diff --git a/doc/capture_screenshots.png b/doc/capture_screenshots.png new file mode 100644 index 0000000000000000000000000000000000000000..a5f5089d788888d38217b5d225f4b06f082ff152 Binary files /dev/null and b/doc/capture_screenshots.png differ diff --git a/doc/ipd_select_variants.png b/doc/ipd_select_variants.png new file mode 100644 index 0000000000000000000000000000000000000000..2ac52c07781ff0957601f27e9b0bdf44f6c2c2eb Binary files /dev/null and b/doc/ipd_select_variants.png differ diff --git a/doc/user-manual.md b/doc/user-manual.md new file mode 100644 index 0000000000000000000000000000000000000000..eca92cb2232b6c1b92053ea2b37d5d1954854f46 --- /dev/null +++ b/doc/user-manual.md @@ -0,0 +1,38 @@ +## Internal Notes (remove or move to different location before publication) +### Create Screenshots +For the sake of consistency, screenshots of the complete cortado-window should have the same size. Therefore, start the backend and the frontend and open the frontend in Google Chrome at `http://localhost:4444/`. Open the google chrome developer tools (shortcut `F12`). Follow the next four steps, which are also depicted in the screenshot below: +1. Open the device toolbar +2. Set resolution to 2000 x 1000 +3. Open the context menu +4. Click `Capture screenshot` + + + +# Incremental Process Discovery +In this section, you learn how to incrementally improve your current process model by selecting (additional) behavior to be considered in the model. + +## Initial Model +The incremental process discovery starts with an initial model. You have multiple options to create an initial model: + +1. Click `Files` → `Import process tree (.ptml)` to import an existing process tree from a file. +2. Use the process tree editor to create a model by hand. +3. Select variants by checking their checkboxes in the variant explorer and click `discover initial model`. The model is discovered using the behavior in the selected variants. + +## Incrememtal Discovery +To increase the current model's language, select additional variants by checking their checkboxes in the variant explorer. Then, click `add variant(s) to model` to add the variants to the model. + +> **_NOTE:_** Selected variants are guaranteed to be in the models language after clicking `add variant(s) to model`. They are guaranteed to stay in the model's language as long as they are selected. Unselcting a variant removes this guarantee. + +> **_EXAMPLE:_** Open cortado and select the top variant of the variant explorer, i.e., check its corresponding checkbox. Click `discover initial model`. Now, you see the same process tree as depicted in the process tree editor in the screenshot below. Select additional variants, e.g., the third and fourth variant as in the screenshot. Click `add variant(s) to model`. Afterward, the model is adjusted. + + +# Variant Explorer +The variant explorer visualizes the variants, i.e., the unique behavior, of the currently loaded event data. It consists of three different views, focusing on different persepectives of process mining: + +1. Standard view: Visualizes variants by using different colors per activity label. +2. Performance view: Visualizes performance information by coloring the chvrons based on time information. +3. Conformance view: Visualizes to which extend the behavior represented by the variants is present in the current process model. + +In the variant explorer, you can perform various actions. + +## \ No newline at end of file diff --git a/src/backend/.DS_Store b/src/backend/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..10b404014fd30fd8b8d4dc68d6ab2da8d4b403a1 Binary files /dev/null and b/src/backend/.DS_Store differ diff --git a/src/backend/__init__.py b/src/backend/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/api/__init__.py b/src/backend/api/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/api/routes/__init__.py b/src/backend/api/routes/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/api/routes/api.py b/src/backend/api/routes/api.py new file mode 100644 index 0000000000000000000000000000000000000000..aae45fc1b24a0f342d99bc8bdec2301f878ae4c0 --- /dev/null +++ b/src/backend/api/routes/api.py @@ -0,0 +1,46 @@ +"""Import routes here +""" + +from fastapi import APIRouter + +from api.websocket import main as websocket +from api.routes.configuration import configuration +from api.routes.conformance import treeConformance +from api.routes.input_output import exporting, importing +from api.routes.log import log, modifyLog +from api.routes.performance import ( + subvariantPerformance, + treePerformance, + variantPerformance, +) +from api.routes.process_tree import discoverTree, modifyTree, treeString +from api.routes.variants import ( + variants, + queryVariant, + subvariantMining, + sequentializer, + lpmMiner, +) +from api.websocket import main + +router = APIRouter() +router.include_router(log.router) +router.include_router(modifyLog.router) +router.include_router(exporting.router) +router.include_router(importing.router) +router.include_router(configuration.router) + +router.include_router(main.router) +router.include_router(treeConformance.router) +router.include_router(treePerformance.router) +router.include_router(subvariantPerformance.router) +router.include_router(variantPerformance.router) +router.include_router(discoverTree.router) +router.include_router(modifyTree.router) +router.include_router(treeString.router) +router.include_router(variants.router) +router.include_router(queryVariant.router) +router.include_router(subvariantMining.router) +router.include_router(sequentializer.router) +router.include_router(lpmMiner.router) +router.include_router(websocket.router) diff --git a/src/backend/api/routes/configuration/__init__.py b/src/backend/api/routes/configuration/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/api/routes/configuration/configuration.py b/src/backend/api/routes/configuration/configuration.py new file mode 100644 index 0000000000000000000000000000000000000000..3c68c971bdf86d227807498224594df5605e7d09 --- /dev/null +++ b/src/backend/api/routes/configuration/configuration.py @@ -0,0 +1,59 @@ +from backend_utilities.configuration.repository import ( + Configuration as DomainConfiguration, +) +from backend_utilities.configuration.repository import ( + ConfigurationRepository, + ConfigurationRepositoryFactory, +) +from fastapi import APIRouter, Depends +from pydantic import ConfigDict, BaseModel, Field + +router = APIRouter(tags=["config"], prefix="/config") + + +def get_config_repo(): + return ConfigurationRepositoryFactory.get_config_repository() + + +class Configuration(BaseModel): + timeout_cvariant_alignment_computation: int = Field( + alias="timeoutCVariantAlignmentComputation" + ) + min_traces_variant_detection_mp: int = Field( + alias="minTracesVariantDetectionMultiprocessing" + ) + number_of_sequentializations_per_variant: int = Field( + alias="numberOfSequentializationsPerVariant" + ) + is_n_sequentialization_reduction_enabled: bool = Field( + alias="isNSequentializationReductionEnabled" + ) + model_config = ConfigDict(populate_by_name=True) + + +@router.post("/saveConfiguration") +async def save_configuration( + config_dto: Configuration, + config_repository: ConfigurationRepository = Depends(get_config_repo), +): + config = DomainConfiguration( + timeout_cvariant_alignment_computation=config_dto.timeout_cvariant_alignment_computation, + min_traces_variant_detection_mp=config_dto.min_traces_variant_detection_mp, + is_n_sequentialization_reduction_enabled=config_dto.is_n_sequentialization_reduction_enabled, + number_of_sequentializations_per_variant=config_dto.number_of_sequentializations_per_variant, + ) + config_repository.save_configuration(config) + + +@router.get("/getConfiguration") +async def get_configuration( + config_repo: ConfigurationRepository = Depends(get_config_repo), +): + config = config_repo.get_configuration() + config_dto = Configuration( + timeout_cvariant_alignment_computation=config.timeout_cvariant_alignment_computation, + min_traces_variant_detection_mp=config.min_traces_variant_detection_mp, + is_n_sequentialization_reduction_enabled=config.is_n_sequentialization_reduction_enabled, + number_of_sequentializations_per_variant=config.number_of_sequentializations_per_variant, + ) + return config_dto diff --git a/src/backend/api/routes/conformance/__init__.py b/src/backend/api/routes/conformance/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/api/routes/conformance/treeConformance.py b/src/backend/api/routes/conformance/treeConformance.py new file mode 100644 index 0000000000000000000000000000000000000000..956333f7233ed80ce77d0fe7cc5baa3ba2be4b47 --- /dev/null +++ b/src/backend/api/routes/conformance/treeConformance.py @@ -0,0 +1,137 @@ +from typing import List, Optional +from typing_extensions import TypedDict +from collections import defaultdict +from fastapi import APIRouter +from pydantic import BaseModel +from cortado_core.utils.process_tree import convert_tree +from cortado_core.utils.sequentializations import generate_variants +from cortado_core.utils.split_graph import Group +from pm4py.objects.process_tree.obj import ProcessTree + +from cache import cache + +from backend_utilities.process_tree_conversion import ( + dict_to_process_tree, + process_tree_to_dict, +) +from endpoints.alignments import InfixType, calculate_alignment + +router = APIRouter(tags=["treeConformance"], prefix="/treeConformance") + + +class ConformanceVariant(TypedDict): + variant: dict + count: int + infixType: InfixType + + +class InputCalculateConformance(BaseModel): + pt: dict + variants: List[ConformanceVariant] + + +@router.post("/calculateVariantsConformance") +async def calculate_tree_conformance(d: InputCalculateConformance): + pt, _ = dict_to_process_tree(d.pt) + pt = convert_tree(pt) + variants_tree_conformance = [] + all_conf_stats = [] + + for c_variant in d.variants: + # calc alignment + c_variant_group = Group.deserialize(c_variant["variant"]) + variants = generate_variants(c_variant_group) + variant_tree_conformances = [] + for variant in variants: + alignment = calculate_alignment(variant, pt, c_variant["infixType"]) + + conf_stats = defaultdict(lambda: {"value": None, "weight": 0}) + for log_move, model_move in alignment["alignment"]: + if isinstance(model_move, ProcessTree): + model_move = model_move.label + + if model_move == ">>": + continue + + if conf_stats[model_move.full]["value"] is None: + conf_stats[model_move.full]["value"] = 0 + + conf_stats[model_move.full]["weight"] += 1 + + # when move is properly aligned + if log_move == model_move or ( + # when model move only is tau + log_move == ">>" + and model_move == None + ): + conf_stats[model_move.full]["value"] += 1 + + for key, conf_stat in conf_stats.items(): + conf_stats[key] = { + "weighted_equally": { + "value": conf_stat["value"] / conf_stat["weight"], + "weight": conf_stat["weight"], + }, + "weighted_by_counts": None, + } + + variant_tree_conformances.append(conf_stats) + + variant_conf_stats = merge_conf_stats(variant_tree_conformances) + all_conf_stats.append(variant_conf_stats) + variants_tree_conformance.append( + process_tree_to_dict(pt, conformance=variant_conf_stats) + ) + + return { + "merged_conformance_tree": process_tree_to_dict( + pt, + conformance=merge_conf_stats( + all_conf_stats, list(map(lambda x: x["count"], d.variants)) + ), + ), + "variants_tree_conformance": variants_tree_conformance, + } + + +def merge_conf_stats(conf_stats: List[dict], counts=None): + merged_stats = {} + if len(conf_stats) >= 1: + keys = set([key for conf_stat in conf_stats for key in conf_stat.keys()]) + for key in keys: + values = [] + equal_weights = [] + count_weights = [] + for index, stats in enumerate(conf_stats): + if key in stats: + values.append(stats[key]["weighted_equally"]["value"]) + equal_weights.append(stats[key]["weighted_equally"]["weight"]) + if counts is not None: + count_weights.append( + stats[key]["weighted_equally"]["weight"] * counts[index] + ) + merged_stats[key] = { + "weighted_equally": { + "value": sum( + [value * weight for value, weight in zip(values, equal_weights)] + ) + / sum(equal_weights), + "weight": sum(equal_weights), + }, + "weighted_by_counts": ( + { + "value": sum( + [ + value * weight + for value, weight in zip(values, count_weights) + ] + ) + / sum(count_weights), + "weight": sum(count_weights), + } + if counts is not None + else None + ), + } + return merged_stats + return None diff --git a/src/backend/api/routes/conformance/variantConformance.py b/src/backend/api/routes/conformance/variantConformance.py new file mode 100644 index 0000000000000000000000000000000000000000..b9fd7eae9c0833770aa2abe636e3134a84b4cf45 --- /dev/null +++ b/src/backend/api/routes/conformance/variantConformance.py @@ -0,0 +1,130 @@ +import asyncio +from collections import Counter +from cortado_core.utils.sequentializations import generate_sequentializations +from cortado_core.utils.split_graph import Group +from cortado_core.utils.process_tree import LabelWithIndex +from starlette.websockets import WebSocketState + +from backend_utilities.configuration.repository import ConfigurationRepositoryFactory +from backend_utilities.timeout.helper_functions import ( + TimeoutException, + execute_with_timeout, +) +from backend_utilities.process_tree_conversion import dict_to_process_tree +from endpoints.alignments import InfixType +from endpoints.alignments import calculate_alignment as calculate_alignment_endpoint +from fastapi import WebSocket + + +def calculate_alignment_intern_with_timeout( + pt: dict, c_variant: dict, infix_type: InfixType, timeout: int +): + try: + return execute_with_timeout( + calculate_alignment_intern, timeout, args=(pt, c_variant, infix_type) + ) + except TimeoutException: + return {"isTimeout": True} + + +def calculate_alignment_intern(pt: dict, c_variant: dict, infix_type: InfixType): + def index_leafs(variant, indices=None): + if indices is None: + indices = Counter() + if "follows" in variant: + res = {"follows": []} + for v in variant["follows"]: + childs = index_leafs(v, indices) + res["follows"].append(childs) + return res + elif "parallel" in variant: + res = {"parallel": []} + for v in variant["parallel"]: + childs = index_leafs(v, indices) + res["parallel"].append(childs) + return res + else: + leafs = [] + for activity in variant["leaf"]: + leafs.append(LabelWithIndex(activity, indices[activity])) + indices[activity] += 1 + return {"leaf": leafs} + + c_variant_indexed = index_leafs(c_variant) + + config = ( + ConfigurationRepositoryFactory().get_config_repository().get_configuration() + ) + n_sequentializations = ( + -1 + if not config.is_n_sequentialization_reduction_enabled + else config.number_of_sequentializations_per_variant + ) + all_variants = generate_sequentializations( + Group.deserialize(c_variant_indexed), n_sequentializations=n_sequentializations + ) + index_alignments_mapping = Counter() + total_cost = 0 + deviations = 0 + for variant in all_variants: + alignment = calculate_alignment_endpoint( + variant, dict_to_process_tree(pt)[0], infix_type + ) + total_cost += alignment["cost"] + deviations += alignment["deviation"] + for log_move, model_move in alignment["alignment"]: + if log_move == ">>": + continue + index_alignments_mapping[log_move.full] += str(log_move) == str(model_move) + + if len(all_variants) > 1: + index_alignments_mapping = { + k: v / len(all_variants) for k, v in index_alignments_mapping.items() + } + + return { + "cost": total_cost / len(all_variants), + "deviations": deviations / len(all_variants), + "alignment": project_alignments_on_cvariant( + index_alignments_mapping, c_variant_indexed + ), + "pt": pt, + } + + +def project_alignments_on_cvariant(mapping, variant): + if "follows" in variant: + res = {"follows": []} + for v in variant["follows"]: + childs = project_alignments_on_cvariant(mapping, v) + res["follows"].append(childs) + return res + elif "parallel" in variant: + res = {"parallel": []} + for v in variant["parallel"]: + childs = project_alignments_on_cvariant(mapping, v) + res["parallel"].append(childs) + return res + else: + return {"leaf": [(str(act), mapping[act.full]) for act in variant["leaf"]]} + + +def get_alignment_callback(idx: str, alignType, websocket: WebSocket): + def callback(result): + data = { + "id": idx, + "isTimeout": False, + "cost": 0, + "type": alignType, + "deviation": False, + } + for key, value in result.items(): + data[key] = value + + try: + if websocket.application_state == WebSocketState.CONNECTED: + asyncio.run(websocket.send_json(data)) + except: + print("Error while sending conformance result") + + return callback diff --git a/src/backend/api/routes/input_output/__init__.py b/src/backend/api/routes/input_output/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/api/routes/input_output/exporting.py b/src/backend/api/routes/input_output/exporting.py new file mode 100644 index 0000000000000000000000000000000000000000..e229a7186dc3cfc782437108cade13aba919d092 --- /dev/null +++ b/src/backend/api/routes/input_output/exporting.py @@ -0,0 +1,96 @@ +import itertools +from typing import List + +import cache.cache as cache +from backend_utilities.process_tree_conversion import dict_to_process_tree +from backend_utilities.variant_trace_conversion import variant_to_trace +from fastapi import APIRouter, Response +from pm4py.objects.bpmn.exporter.variants.etree import ( + get_xml_string as generate_bpmn_xml, +) +from pm4py.objects.conversion.process_tree.converter import ( + Variants as ptConverterVariant, +) +from pm4py.objects.conversion.process_tree.converter import apply as convert_pt +from pm4py.objects.log.exporter.xes.variants.etree_xes_exp import ( + export_log_as_string as generate_xes_xml, +) +from pm4py.objects.log.obj import EventLog +from pm4py.objects.petri_net.exporter.variants.pnml import ( + export_petri_as_string as generate_pnml_xml, +) +from pm4py.objects.process_tree.exporter.variants.ptml import ( + export_tree_as_string as generate_ptml_xml, +) +from pm4py.objects.process_tree.obj import ProcessTree +from pm4py.objects.log.util.interval_lifecycle import to_lifecycle +from cortado_core.utils.sequentializations import generate_sequentializations +from cortado_core.utils.split_graph import Group +from pydantic import BaseModel + +router = APIRouter(tags=["exporting"], prefix="/exporting") + + +class ConvertPtToX(BaseModel): + pt: dict + + +@router.post("/convertPtToBPMN") +async def download_ptml(d: ConvertPtToX): + pt: ProcessTree + pt, _ = dict_to_process_tree(d.pt) + bpmn = convert_pt(pt, variant=ptConverterVariant.TO_BPMN) + + return Response(content=generate_bpmn_xml(bpmn), media_type="application/xml") + + +@router.post("/convertPtToPTML") +async def download_ptml(d: ConvertPtToX): + pt: ProcessTree + pt, _ = dict_to_process_tree(d.pt) + + return Response(content=generate_ptml_xml(pt), media_type="application/xml") + + +@router.post("/convertPtToPNML") +async def download_pnml(d: ConvertPtToX): + pt: ProcessTree + pt, _ = dict_to_process_tree(d.pt) + net, im, fm = convert_pt(pt) + return Response( + content=generate_pnml_xml(net, im, fm), media_type="application/xml" + ) + + +class ExportLogXes(BaseModel): + bids: list + sequentializeVariants: bool + exportAsIntervalLog: bool + includeOriginalLogInfo: bool + + +@router.post("/exportLogVariants") +async def download_xes(d: ExportLogXes): + variants_to_traces = { + variant: traces + for bid, (variant, traces, _, _) in cache.variants.items() + if bid in d.bids + } + + exported_traces = [] + for cvariant, traces in variants_to_traces.items(): + if d.sequentializeVariants or len(traces) == 0: + sequentializations = generate_sequentializations(cvariant) + traces = [variant_to_trace(seq) for seq in sequentializations] + exported_traces += traces + + log = EventLog( + exported_traces, + **cache.parameters["log_info"] if d.includeOriginalLogInfo else {} + ) + + if not d.exportAsIntervalLog: + log = to_lifecycle(log) + + # TODO Perserve the Loaded Log Attributes via Variables + return Response(content=generate_xes_xml(log), media_type="application/xml") diff --git a/src/backend/api/routes/input_output/importing.py b/src/backend/api/routes/input_output/importing.py new file mode 100644 index 0000000000000000000000000000000000000000..178a958c1d3dae08a18a635be58a5b290ddf5480 --- /dev/null +++ b/src/backend/api/routes/input_output/importing.py @@ -0,0 +1,89 @@ +from collections import defaultdict +from cortado_core.utils.collapse_variants import collapse_variant +import cache.cache as cache +import pm4py.objects.log.importer.xes.importer as xes_importer +import pm4py.objects.process_tree.importer.importer as ptml_importer +from backend_utilities.configuration.repository import ( + ConfigurationRepository, + ConfigurationRepositoryFactory, +) +from backend_utilities.process_tree_conversion import process_tree_to_dict +from endpoints.load_event_log import calculate_event_log_properties +from fastapi import APIRouter, Depends, File, HTTPException, UploadFile +from pydantic import BaseModel + +router = APIRouter(tags=["importing"], prefix="/importing") + + +def get_config_repo(): + return ConfigurationRepositoryFactory.get_config_repository() + + +@router.post("/loadEventLogFromFile") +async def load_event_log_from_file( + file: UploadFile = File(...), + config_repo: ConfigurationRepository = Depends(get_config_repo), +): + cache.pcache = {} + + content = "".join([line.decode("UTF-8") for line in file.file]) + event_log = xes_importer.deserialize(content) + use_mp = ( + len(event_log) > config_repo.get_configuration().min_traces_variant_detection_mp + ) + info = calculate_event_log_properties(event_log, use_mp=use_mp) + return info + + +class FilePathInput(BaseModel): + file_path: str + + +@router.post("/loadEventLogFromFilePath") +async def load_event_log_from_file_path( + d: FilePathInput, config_repo: ConfigurationRepository = Depends(get_config_repo) +): + cache.pcache = {} + try: + event_log = xes_importer.apply(d.file_path) + except FileNotFoundError as e: + raise HTTPException( + status_code=404, detail=f"Event log not found ({d.file_path})" + ) + + use_mp = ( + len(event_log) > config_repo.get_configuration().min_traces_variant_detection_mp + ) + info = calculate_event_log_properties(event_log, use_mp=use_mp) + return info + + +@router.post("/loadProcessTreeFromPtmlFile") +async def load_process_tree_from_ptml_file(file: UploadFile = File(...)): + cache.pcache = {} + + content = "".join([line.decode("UTF-8") for line in file.file]) + pt = ptml_importer.deserialize(content) + res = process_tree_to_dict(pt) + return res + + +@router.post("/loadProcessTreeFromPtmlFilePath") +async def load_process_tree_from_ptml_file_path(d: FilePathInput): + pt = ptml_importer.apply(d.file_path) + res = process_tree_to_dict(pt) + return res + + +@router.get("/collapsedVariants") +async def load_loop_collapsed_variants(): + collapsed_variants = defaultdict(list) + + for bid, (variant, _, _, info) in cache.variants.items(): + collapsed_variant = collapse_variant(variant) + collapsed_variants[(collapsed_variant, info.infix_type)].append(bid) + + return [ + {"variant": v.serialize(), "ids": bids} + for (v, _), bids in collapsed_variants.items() + ] diff --git a/src/backend/api/routes/log/__init__.py b/src/backend/api/routes/log/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/api/routes/log/log.py b/src/backend/api/routes/log/log.py new file mode 100644 index 0000000000000000000000000000000000000000..859c8657fc6ca5dce0cde3fdcaa3d7f32fdf557a --- /dev/null +++ b/src/backend/api/routes/log/log.py @@ -0,0 +1,42 @@ +import itertools +import pickle +from typing import Optional + +import cache.cache as cache +from cortado_core.utils.timestamp_utils import TimeUnit + +from endpoints.load_event_log import calculate_event_log_properties +from fastapi import APIRouter +from pm4py.objects.log.obj import EventLog +from pydantic import BaseModel, Field +import sys + +router = APIRouter(tags=["Log"], prefix="/log") + + +class PropertiesParams(BaseModel): + time_granularity: Optional[TimeUnit] = Field(None, alias="timeGranularity") + + +@router.post("/properties") +async def get_event_log_properties(params: PropertiesParams): + traces = list(itertools.chain(*[ts for _, (_, ts, _, _) in cache.variants.items()])) + log = EventLog(traces, **cache.parameters["log_info"]) + + properties = calculate_event_log_properties(log, params.time_granularity) + return properties + + +@router.get("/granularity") +async def get_event_log(): + return cache.parameters["cur_time_granularity"] + + +@router.get("/resetLogCache") +async def reset_log_cache(): + if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"): + cache.variants = pickle.load(open("./_internal/resources/variants.p", "rb")) + cache.parameters = pickle.load(open("./_internal/resources/parameters.p", "rb")) + else: + cache.variants = pickle.load(open("./resources/variants.p", "rb")) + cache.parameters = pickle.load(open("./resources/parameters.p", "rb")) diff --git a/src/backend/api/routes/log/modifyLog.py b/src/backend/api/routes/log/modifyLog.py new file mode 100644 index 0000000000000000000000000000000000000000..f312c7c77a278d856de2bf0be8af45dda5b0f4cf --- /dev/null +++ b/src/backend/api/routes/log/modifyLog.py @@ -0,0 +1,130 @@ +from typing import List, Any + +from cortado_core.utils.split_graph import Group, create_graph_for_cvariant +from fastapi import Response, status + +import cache.cache +from api.routes.variants.variants import VariantInformation +from endpoints.alignments import InfixType +from endpoints.transform_event_log import ( + cache_current_data, + remove_activities, + remove_variant, + rename_activities, + reset_last_transaction, +) +from fastapi import APIRouter +from pydantic import BaseModel + +router = APIRouter(tags=["Log"], prefix="/modifylog") + + +class ChangeActivityName(BaseModel): + mergeList: List[List[int]] + renameList: List[int] + activityName: str + newActivityName: str + + +@router.post("/changeActivityName") +async def change_activity_name_in_log(d: ChangeActivityName): + cache_current_data() + + update_map = rename_activities( + d.mergeList, d.renameList, d.activityName, d.newActivityName + ) + + # TODO Return an Error if needed + return update_map + + +class removeActivityName(BaseModel): + activityName: str + fallthrough: List[int] + delete_member_list: List[int] + merge_list: List[List[int]] + delete_variant_list: List[int] + + +@router.post("/deleteActivity") +async def remove_activity_name_in_log(d: removeActivityName): + cache_current_data() + + res = remove_activities( + d.activityName, + d.fallthrough, + d.delete_member_list, + d.merge_list, + d.delete_variant_list, + ) + + return res + + +class removeVariants(BaseModel): + bids: List[int] + + +@router.post("/deleteVariants") +async def delete_variants(d: removeVariants): + cache_current_data() + + res = remove_variant(d.bids) + + return res + + +@router.post("/revertLastChange") +async def revert_last_change(): + res = reset_last_transaction() + + return res + + +class userDefinedVariant(BaseModel): + variant: Any = None + bid: int + + +@router.post("/addUserDefinedVariant", status_code=201) +async def add_user_defined_variant(request: userDefinedVariant, response: Response): + v = Group.deserialize(request.variant) + v.graphs[create_graph_for_cvariant(v)] = 1 + + if request.bid in cache.cache.variants: + response.status_code = status.HTTP_400_BAD_REQUEST + return + + cache.cache.variants[request.bid] = ( + v, + [], + dict(), + VariantInformation(infix_type=InfixType.NOT_AN_INFIX, is_user_defined=True), + ) + return + + +class userDefinedInfix(BaseModel): + variant: Any = None + bid: int + infixType: int + + +@router.post("/addUserDefinedInfix", status_code=201) +async def add_user_defined_infix(request: userDefinedInfix, response: Response): + infix_type = InfixType(request.infixType) + v = Group.deserialize(request.variant) + v.infix_type = InfixType(request.infixType) + v.graphs[create_graph_for_cvariant(v)] = 1 + + if request.bid in cache.cache.variants: + response.status_code = status.HTTP_400_BAD_REQUEST + return + + cache.cache.variants[request.bid] = ( + v, + [], + dict(), + VariantInformation(infix_type=infix_type, is_user_defined=True), + ) + return diff --git a/src/backend/api/routes/performance/__init__.py b/src/backend/api/routes/performance/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/api/routes/performance/subvariantPerformance.py b/src/backend/api/routes/performance/subvariantPerformance.py new file mode 100644 index 0000000000000000000000000000000000000000..046dce78b1b3c5d0253cc4960f9e73c26031c65e --- /dev/null +++ b/src/backend/api/routes/performance/subvariantPerformance.py @@ -0,0 +1,34 @@ +import cache.cache as cache +from cortado_core.performance.subvariant_performance import ( + calculate_subvariant_performance, +) +from fastapi import APIRouter +from pydantic import BaseModel, Field +from cortado_core.utils.cvariants import get_detailed_variants + +router = APIRouter(tags=["subvariantPerformance"], prefix="/subvariantPerformance") + + +class InputPerformanceSubvariant(BaseModel): + bid: int + + +@router.post("/subvariants") +async def get_subvariants(data: InputPerformanceSubvariant): + sub_variants = cache.variants[data.bid][2] + result = [] + + total_sub_traces = sum(len(sub_variants[v]) for v in sub_variants) + + for subvariant, traces in sub_variants.items(): + subvariant_performance = calculate_subvariant_performance( + subvariant, traces, cache.parameters["cur_time_granularity"] + ) + subvariant_response = { + "variant": subvariant_performance, + "count": len(traces), + "percentage": round(len(traces) / total_sub_traces * 100, 2), + } + result.append(subvariant_response) + + return sorted(result, key=lambda x: x["count"], reverse=True) diff --git a/src/backend/api/routes/performance/treePerformance.py b/src/backend/api/routes/performance/treePerformance.py new file mode 100644 index 0000000000000000000000000000000000000000..5eef15116d379470c86123d82061f88ad3f3acd8 --- /dev/null +++ b/src/backend/api/routes/performance/treePerformance.py @@ -0,0 +1,203 @@ +from typing import List, Optional + +import cache.cache as cache +from backend_utilities.process_tree_conversion import ( + dict_to_process_tree, + process_tree_to_dict, +) +from cortado_core.performance import tree_performance +from cortado_core.performance import utils as performance_utils +from cortado_core.performance.aggregators import avg, noop, stats +from cortado_core.utils.process_tree import CortadoProcessTree, convert_tree +from fastapi import APIRouter +from pm4py.algo.conformance.alignments.petri_net import algorithm as net_alignment +from pm4py.objects.log.obj import EventLog +from cortado_core.process_tree_utils.miscellaneous import is_tau_leaf +from pydantic import BaseModel + +router = APIRouter(tags=["treePerformance"], prefix="/treePerformance") + + +def merge_performance(all_performances): + merged = {} + for performance in all_performances: + for tree in performance: + p = merged.get(tree, []) + if performance[tree]: + p.extend(performance[tree]) + merged[tree] = p + return merged + + +class InputCalculatePerformance(BaseModel): + pt: dict + variants: List[int] + delete: Optional[List[int]] = None + + +pcache = {} + + +def tau_0_values(tree_nodes, perf_stats): + for t in [t for t in tree_nodes if is_tau_leaf(t)]: + perf_stats[str(t)] = { + "service_time": stats([0]), + "cycle_time": stats([0]), + "waiting_time": stats([0]), + "idle_time": stats([0]), + } + + +def get_merged_performances(pt: CortadoProcessTree): + tree_nodes = performance_utils.get_all_nodes(pt) + tree_cache_key = str(pt) + + all_service_times = [ + cache.pcache[tree_cache_key][k]["service_times"] + for k in cache.pcache[tree_cache_key] + ] + all_waiting_times = [ + cache.pcache[tree_cache_key][k]["waiting_times"] + for k in cache.pcache[tree_cache_key] + ] + all_cycle_times = [ + cache.pcache[tree_cache_key][k]["cycle_times"] + for k in cache.pcache[tree_cache_key] + ] + all_idle_times = [ + cache.pcache[tree_cache_key][k]["idle_times"] + for k in cache.pcache[tree_cache_key] + ] + + merged_service_times = merge_performance(all_service_times) + merged_waiting_times = merge_performance(all_waiting_times) + merged_cycle_times = merge_performance(all_cycle_times) + merged_idle_times = merge_performance(all_idle_times) + + merged_performances = { + str(t): { + "service_time": ( + stats(merged_service_times[t]) if t in merged_service_times else None + ), + "cycle_time": ( + stats(merged_cycle_times[t]) if t in merged_cycle_times else None + ), + "waiting_time": ( + stats(merged_waiting_times[t]) if t in merged_waiting_times else None + ), + "idle_time": ( + stats(merged_idle_times[t]) if t in merged_idle_times else None + ), + } + for t in tree_nodes + } + tau_0_values(tree_nodes, merged_performances) + pt_dict = process_tree_to_dict(pt, performance=merged_performances) + return pt_dict + + +@router.post("/calculateVariantsPerformance") +async def calculate_variant_performance(d: InputCalculatePerformance): + pt, _ = dict_to_process_tree(d.pt) + pt = convert_tree(pt) + tree_nodes = performance_utils.get_all_nodes(pt) + variants_tree_performance = [] + + tree_cache_key = str(pt) + variants_fitness = [] + + if d.delete: + for bid in d.delete: + if tree_cache_key in pcache and bid in cache.pcache[tree_cache_key]: + del cache.pcache[tree_cache_key][bid] + + for bid in d.variants: + (_, traces, _, info) = cache.variants[bid] + if info.is_user_defined: + continue + if tree_cache_key in cache.pcache and bid in cache.pcache[tree_cache_key]: + p_values = cache.pcache[tree_cache_key][bid] + service_times_aggregated = p_values["service_times"] + idle_times_aggregated = p_values["idle_times"] + waiting_times_aggregated = p_values["waiting_times"] + cycle_times_aggregated = p_values["cycle_times"] + mean_fitness = p_values["mean_fitness"] + + else: + test_log = traces + test_log = EventLog(test_log) + + ( + service_times, + idle_times, + waiting_times, + cycle_times, + ), mean_fitness = tree_performance.get_tree_performance_intervals( + pt, + test_log, + alignment_variant=net_alignment.Variants.VERSION_STATE_EQUATION_A_STAR, + ) + + service_times_aggregated = tree_performance.apply_aggregation( + service_times, noop, avg, avg + ) + idle_times_aggregated = tree_performance.apply_aggregation( + idle_times, noop, avg, avg + ) + waiting_times_aggregated = tree_performance.apply_aggregation( + waiting_times, noop, avg, avg + ) + cycle_times_aggregated = tree_performance.apply_aggregation( + cycle_times, noop, avg, avg + ) + + perf_stats = { + str(t): { + "service_time": ( + stats(service_times_aggregated[t]) + if t in service_times_aggregated + else None + ), + "cycle_time": ( + stats(cycle_times_aggregated[t]) + if t in cycle_times_aggregated + else None + ), + "waiting_time": ( + stats(waiting_times_aggregated[t]) + if t in waiting_times_aggregated + else None + ), + "idle_time": ( + stats(idle_times_aggregated[t]) + if t in idle_times_aggregated + else None + ), + } + for t in tree_nodes + } + + tau_0_values(tree_nodes, perf_stats) + + pt_dict_variant = process_tree_to_dict(pt, performance=perf_stats) + variants_tree_performance.append(pt_dict_variant) + variants_fitness.append(mean_fitness) + + if tree_cache_key not in cache.pcache: + cache.pcache[tree_cache_key] = {} + + cache.pcache[tree_cache_key][bid] = { + "service_times": service_times_aggregated, + "idle_times": idle_times_aggregated, + "cycle_times": cycle_times_aggregated, + "waiting_times": waiting_times_aggregated, + "mean_fitness": mean_fitness, + } + + pt_dict = get_merged_performances(pt) + + return { + "merged_performance_tree": pt_dict, + "variants_tree_performance": variants_tree_performance, + "fitness_values": variants_fitness, + } diff --git a/src/backend/api/routes/performance/variantPerformance.py b/src/backend/api/routes/performance/variantPerformance.py new file mode 100644 index 0000000000000000000000000000000000000000..cf54d14769f9de40499da32acb4ab6099d58c296 --- /dev/null +++ b/src/backend/api/routes/performance/variantPerformance.py @@ -0,0 +1,25 @@ +from cortado_core.performance.variant_performance import assign_variants_performances +from fastapi import APIRouter +from pydantic import BaseModel + +from cache import cache + +router = APIRouter(tags=["variantPerformance"], prefix="/variantPerformance") + + +class InputLogBasedVariantPerformance(BaseModel): + start: int + end: int + + +@router.post("/logBasedVariantPerformance") +async def calculate_log_based_performance(data: InputLogBasedVariantPerformance): + variants = { + bid: var for bid, var in cache.variants.items() if data.start <= bid <= data.end + } + + assign_variants_performances(variants) + + return { + bid: v[0].serialize(include_performance=True) for bid, v in variants.items() + } diff --git a/src/backend/api/routes/process_tree/__init__.py b/src/backend/api/routes/process_tree/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/api/routes/process_tree/discoverTree.py b/src/backend/api/routes/process_tree/discoverTree.py new file mode 100644 index 0000000000000000000000000000000000000000..79297659991d14e19d8aa523206d26a7158e12c8 --- /dev/null +++ b/src/backend/api/routes/process_tree/discoverTree.py @@ -0,0 +1,113 @@ +from typing import Any, List + +from cortado_core.models.infix_type import InfixType +from cortado_core.process_tree_utils.reduction import apply_reduction_rules +from cortado_core.utils.sequentializations import generate_sequentializations +from cortado_core.utils.split_graph import Group +from cortado_core.utils.trace import TypedTrace + +from backend_utilities.configuration.repository import ConfigurationRepositoryFactory +from backend_utilities.multiprocessing.pool_factory import PoolFactory +from backend_utilities.process_tree_conversion import ( + dict_to_process_tree, + process_tree_to_dict, +) +from backend_utilities.variant_trace_conversion import variant_to_trace +from cortado_core.utils.alignment_utils import typed_trace_fits_process_tree +from endpoints.add_variants_to_process_model import add_variants_to_process_model +from fastapi import APIRouter +from pm4py.discovery import discover_process_tree_inductive +from pm4py.objects.log.obj import Event, EventLog, Trace +from pm4py.objects.process_tree.obj import ProcessTree +from pydantic import BaseModel + +router = APIRouter(tags=["discoverTree"], prefix="/discoverTree") + + +class InputDiscoverProcessModelFromVariants(BaseModel): + variants: List[Any] + + +def discover_process_model_from_variants(traces): + # TODO decide how to handle initial process discovery + log = EventLog([t.trace for t in traces if t.infix_type == InfixType.NOT_AN_INFIX]) + pt: ProcessTree = discover_process_tree_inductive(log) + apply_reduction_rules(pt) + res = process_tree_to_dict(pt) + return res + + +@router.post("/discoverProcessModelFromConcurrencyVariants") +async def discover_process_model_from_cvariants( + d: InputDiscoverProcessModelFromVariants, +): + all_traces = get_traces_from_variants(d.variants) + print(f"nVariants: {len(all_traces)}") + res = discover_process_model_from_variants(all_traces) + return res + + +class InputAddVariantsToProcessModel(BaseModel): + fitting_variants: List[Any] + variants_to_add: List[Any] + pt: dict + + +@router.post("/addConcurrencyVariantsToProcessModel") +async def add_cvariants_to_process_model(d: InputAddVariantsToProcessModel): + fitting_variants = get_traces_from_variants(d.fitting_variants) + to_add = get_traces_from_variants(d.variants_to_add) + return add_variants_to_process_model( + d.pt, fitting_variants, to_add, PoolFactory.instance().get_pool() + ) + + +class InputAddVariantsToProcessModelUnknownConformance(BaseModel): + selected_variants: List[Any] + pt: dict + + +@router.post("/addConcurrencyVariantsToProcessModelUnknownConformance") +async def add_cvariants_to_process_model_unknown_conformance( + d: InputAddVariantsToProcessModelUnknownConformance, +): + selected_variants = get_traces_from_variants(d.selected_variants) + + fitting_traces = set() + traces_to_add = set() + process_tree, _ = dict_to_process_tree(d.pt) + for selected_variant in selected_variants: + if typed_trace_fits_process_tree(selected_variant, process_tree): + fitting_traces.add(selected_variant) + else: + traces_to_add.add(selected_variant) + + return add_variants_to_process_model( + d.pt, + list(fitting_traces), + list(traces_to_add), + PoolFactory.instance().get_pool(), + ) + + +def get_traces_from_variants(variants): + config = ( + ConfigurationRepositoryFactory().get_config_repository().get_configuration() + ) + n_sequentializations = ( + -1 + if not config.is_n_sequentialization_reduction_enabled + else config.number_of_sequentializations_per_variant + ) + traces = [] + + for cvariant, infix_type in variants: + sequentializations = generate_sequentializations( + Group.deserialize(cvariant), n_sequentializations=n_sequentializations + ) + traces += [ + TypedTrace(variant_to_trace(seq), InfixType(infix_type)) + for seq in sequentializations + ] + + return traces diff --git a/src/backend/api/routes/process_tree/modifyTree.py b/src/backend/api/routes/process_tree/modifyTree.py new file mode 100644 index 0000000000000000000000000000000000000000..3b21684b5604706382853e66873681ce23c91a19 --- /dev/null +++ b/src/backend/api/routes/process_tree/modifyTree.py @@ -0,0 +1,19 @@ +from backend_utilities.process_tree_conversion import ( + dict_to_process_tree, + process_tree_to_dict, +) +from cortado_core.freezing.reinsert_frozen_subtrees import post_process_tree +from fastapi import APIRouter +from pydantic import BaseModel + +router = APIRouter(tags=["modifyTree"], prefix="/modifyTree") + + +class ReduceData(BaseModel): + pt: dict + + +@router.post("/applyReductionRulesToTree") +async def applyTreeReductionRules(d: ReduceData): + pt, frozen_subtrees = dict_to_process_tree(d.pt) + return process_tree_to_dict(post_process_tree(pt, frozen_subtrees), frozen_subtrees) diff --git a/src/backend/api/routes/process_tree/treeString.py b/src/backend/api/routes/process_tree/treeString.py new file mode 100644 index 0000000000000000000000000000000000000000..f466d7bcac13996eb4f1e372049084243dc875c0 --- /dev/null +++ b/src/backend/api/routes/process_tree/treeString.py @@ -0,0 +1,38 @@ +from backend_utilities.process_tree_conversion import ( + dict_to_process_tree, + process_tree_to_dict, +) +from fastapi import APIRouter +from pm4py.objects.process_tree.utils.generic import parse +from pydantic import BaseModel + +router = APIRouter(tags=["treeSting"], prefix="/treeSting") + + +class InputTreeStringFromTree(BaseModel): + pt: dict + + +@router.post("/computeTreeStringFromTree") +async def computeTreeStringFromTree(d: InputTreeStringFromTree): + res = str(dict_to_process_tree(d.pt)[0]) + return res + + +class InputTreeFromTreeString(BaseModel): + pt_string: str + + +@router.post("/parseStringToPT") +async def parseStringToPT(d: InputTreeFromTreeString): + res = dict() + try: + d.pt_string = d.pt_string.replace("*tau*", "τ") + pt = parse(d.pt_string) + res["tree"] = process_tree_to_dict(pt) + res["errors"] = None + except: + res["tree"] = None + res["errors"] = "Error occurred during backend parsing" + + return res diff --git a/src/backend/api/routes/variants/__init__.py b/src/backend/api/routes/variants/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/api/routes/variants/lpmMiner.py b/src/backend/api/routes/variants/lpmMiner.py new file mode 100644 index 0000000000000000000000000000000000000000..e75224cb18439aa63d52d2e707ce2b0b1c81630d --- /dev/null +++ b/src/backend/api/routes/variants/lpmMiner.py @@ -0,0 +1,104 @@ +from typing import Any + +from cortado_core.eventually_follows_pattern_mining.local_process_models.clustering.edit_dist_aggl_with_preclustering import ( + EditDistanceAgglomerativeClustererWithPreclustering, +) +from cortado_core.eventually_follows_pattern_mining.local_process_models.discovery.inductive_miner import ( + InductiveMiner, +) +from cortado_core.eventually_follows_pattern_mining.local_process_models.lpm_discoverer import ( + LpmDiscoverer, +) +from cortado_core.eventually_follows_pattern_mining.local_process_models.metrics import ( + calculate_metrics, +) +from cortado_core.eventually_follows_pattern_mining.obj import group_to_ef_pattern +from cortado_core.utils.split_graph import Group +from fastapi import APIRouter +from pm4py.objects.log.obj import EventLog +from pydantic import BaseModel + +import cache.cache +from api.routes.variants.subvariantMining import serialize_pattern +from backend_utilities.process_tree_conversion import ( + process_tree_to_dict, + dict_to_process_tree, +) + +router = APIRouter(tags=["lpmMiner"], prefix="/lpmMining") + + +class LpmMiningInput(BaseModel): + patterns: list + + +class LpmStatisticsInput(BaseModel): + lpm: Any = None + + +@router.post("/lpmMining") +def mineLocalProcessModels(config: LpmMiningInput): + patterns = __deserialize_patterns(config.patterns) + lpm_discoverer = LpmDiscoverer( + EditDistanceAgglomerativeClustererWithPreclustering( + max_distance=2, + preclustering_type="label_vector", + precalculated_distance_matrix=None, + ), + discoverer=InductiveMiner(), + ) + local_process_models = lpm_discoverer.discover_lpms(patterns) + + res = [] + for lpm, patterns in local_process_models: + res.append( + { + "lpm": process_tree_to_dict(lpm), + "patterns": [serialize_pattern(p) for p in patterns], + } + ) + + return res + + +@router.post("/lpmStatistics") +def mineLocalProcessModels(config: LpmStatisticsInput): + tree, _ = dict_to_process_tree(config.lpm) + log = [] + for _, traces, _, _ in cache.cache.variants.values(): + log += traces + log = EventLog(log) + ( + support_tax, + support_trans, + support_occ, + confidence, + precision, + coverage, + simplicity, + n_transitions, + skip_precision, + mean_range, + min_range, + max_range, + ) = calculate_metrics(tree, log, is_place_net_algorithm=False) + + res = { + "support": support_tax, + "supportTrans": support_trans, + "supportOcc": support_occ, + "confidence": confidence, + "precision": precision, + "coverage": coverage, + "simplicity": simplicity, + "skipPrecision": skip_precision, + "meanRange": mean_range.item(), + "minRange": min_range.item(), + "maxRange": max_range.item(), + } + + return res + + +def __deserialize_patterns(patterns): + return [group_to_ef_pattern(Group.deserialize(p)) for p in patterns] diff --git a/src/backend/api/routes/variants/models.py b/src/backend/api/routes/variants/models.py new file mode 100644 index 0000000000000000000000000000000000000000..04d146f4e5949db658816af22d96675d576f9576 --- /dev/null +++ b/src/backend/api/routes/variants/models.py @@ -0,0 +1,27 @@ +import dataclasses +from enum import Enum +from typing import Dict +from pydantic import BaseModel + +from endpoints.alignments import InfixType + + +class VariantFragment(BaseModel): + fragment: dict + infixType: str + + +class ClusteringAlgorithm(str, Enum): + AGGLOMERATIVE_EDIT_DISTANCE_CLUSTERING = "AGGLOMERATIVE_EDIT_DISTANCE_CLUSTERING" + LABEL_VECTOR_CLUSTERING = "LABEL_VECTOR_CLUSTERING" + + +class ClusteringParameters(BaseModel): + algorithm: ClusteringAlgorithm + params: Dict + + +@dataclasses.dataclass +class VariantInformation: + infix_type: InfixType + is_user_defined: bool diff --git a/src/backend/api/routes/variants/queryVariant.py b/src/backend/api/routes/variants/queryVariant.py new file mode 100644 index 0000000000000000000000000000000000000000..8878aca161b833aa65334ed33eab41c08ab30573 --- /dev/null +++ b/src/backend/api/routes/variants/queryVariant.py @@ -0,0 +1,22 @@ +import cache.cache as cache +from endpoints.query_variant import evaluate_query_against_variant_graphs +from fastapi import APIRouter +from pydantic import BaseModel + +router = APIRouter(tags=["variantQuery"], prefix="/variantQuery") + + +class variantQuery(BaseModel): + queryString: str + + +@router.post("/variant-query") +def variant_query(query: variantQuery): + res = evaluate_query_against_variant_graphs( + query, cache.variants, cache.parameters["activites"] + ) + + for bid in res["ids"]: + print(cache.variants[bid][0]) + + return res diff --git a/src/backend/api/routes/variants/sequentializer.py b/src/backend/api/routes/variants/sequentializer.py new file mode 100644 index 0000000000000000000000000000000000000000..2903c813af18847be52906f5d91fbf8f49b62d75 --- /dev/null +++ b/src/backend/api/routes/variants/sequentializer.py @@ -0,0 +1,279 @@ +from typing import Any +from cortado_core.utils.split_graph import ( + Group, + SequenceGroup, + ParallelGroup, + FallthroughGroup, + ChoiceGroup, + LoopGroup, + LeafGroup, +) +from collections import defaultdict + +from cortado_core.subprocess_discovery.concurrency_trees.cTrees import cTreeOperator +from cortado_core.sequentializer.algorithm import apply_sequentializer_on_variants +from cortado_core.sequentializer.pattern import ( + parse_sequentializer_pattern, + SequentializerPattern, + WILDCARD_MATCH, +) +from cortado_core.sequentializer.two_plus_two_free_check import get_wildcard_node +from fastapi import APIRouter, HTTPException +from pydantic import BaseModel + +import cache.cache +from api.routes.variants.variants import VariantInformation + +# from endpoints.alignments import InfixType +from cortado_core.models.infix_type import InfixType +from endpoints.load_event_log import ( + create_variant_object, + compute_log_stats, + variants_to_variant_objects, +) + +from cortado_core.subprocess_discovery.concurrency_trees.cTrees import ( + ConcurrencyTree, + cTreeOperator, + cTreeFromcGroup, +) + +router = APIRouter(tags=["Sequentializer"], prefix="/sequentializer") + + +class SequentializerPatterns(BaseModel): + sourcePattern: Any = None + targetPattern: Any = None + + +@router.post("/apply") +def apply_sequentializer(payload: SequentializerPatterns): + source_pattern = parse_pattern_from_variant( + Group.deserialize(payload.sourcePattern) + ) + target_pattern = parse_pattern_from_variant( + Group.deserialize(payload.targetPattern) + ) + + validate_patterns(source_pattern, target_pattern) + + variants = cache.cache.variants + + new_variants = { + InfixType.NOT_AN_INFIX: defaultdict(list), + InfixType.PROPER_INFIX: defaultdict(list), + InfixType.PREFIX: defaultdict(list), + InfixType.POSTFIX: defaultdict(list), + } + + n_traces = 0 + for _, (variant, traces, _, info) in variants.items(): + new_variants[info.infix_type][variant] += traces + n_traces += len(traces) + + print("SOURCE PATTERN:", str(source_pattern)) + print("TARGET PATTERN:", str(target_pattern)) + + cache_variants = dict() + cache_max_bid = 0 + res_variants = [] + + for infix_type, var in new_variants.items(): # var: dict, key(variant) value(trace) + new_variants = apply_sequentializer_on_variants( + var, source_pattern, target_pattern + ) + + res_vars, new_cache_variants = variants_to_variant_objects( + new_variants, + cache.cache.parameters["cur_time_granularity"], + n_traces, + lambda ts: generate_variant_info(infix_type, ts), + ) + res_variants += res_vars + + for bid, variant in new_cache_variants.items(): + cache_variants[bid + cache_max_bid] = variant + + cache_max_bid = max(cache_variants.keys()) + + cache.cache.variants = cache_variants + + start_activities, end_activities, nActivities = compute_log_stats( + cache.cache.variants + ) + + cache.cache.parameters["activites"] = set(nActivities.keys()) + + res = { + "startActivities": start_activities, + "endActivities": end_activities, + "activities": nActivities, + "variants": res_variants, + "performanceInfoAvailable": cache.cache.parameters["lifecycle_available"], + "timeGranularity": cache.cache.parameters["cur_time_granularity"], + } + + return res + + +def generate_variant_info(infix_type, traces): + user_defined = len(traces) == 0 + + return VariantInformation(infix_type=infix_type, is_user_defined=user_defined) + + +def validate_string_pattern(pattern: str) -> bool: + return pattern.count("(") == pattern.count(")") + + +def validate_patterns( + source_pattern: SequentializerPattern, target_pattern: SequentializerPattern +): + activities = cache.cache.parameters["activites"] + source_activities = get_activities_in_pattern(source_pattern) + target_activities = get_activities_in_pattern(target_pattern) + + for source_activity in source_activities: + if source_activity not in activities: + raise HTTPException( + status_code=400, + detail=f"Source pattern contains invalid activity '{source_activity}'", + ) + + for target_activity in target_activities: + if target_activity not in activities: + raise HTTPException( + status_code=400, + detail=f"Target pattern contains invalid activity '{target_activity}'", + ) + + source_labeled_nodes = [ + set(p.labels) for p in get_activity_nodes_in_pattern(source_pattern) + ] + target_labeled_nodes = [ + set(p.labels) for p in get_activity_nodes_in_pattern(target_pattern) + ] + + for source_labeled_node in source_labeled_nodes: + try: + target_labeled_nodes.remove(source_labeled_node) + except ValueError: + raise HTTPException( + status_code=400, + detail=f"Node with labels {source_labeled_node} is present in source pattern, but not in target pattern", + ) + + if len(target_labeled_nodes) > 0: + raise HTTPException( + status_code=400, + detail=f"Node with labels {target_labeled_nodes[0]} is present in target pattern, but not in source pattern", + ) + + source_wc_node = get_wildcard_node(source_pattern) + target_wc_node = get_wildcard_node(target_pattern) + + if source_wc_node is None and target_wc_node is not None: + raise HTTPException( + status_code=400, + detail=f"Target pattern has wildcard (...), which is not present in source pattern", + ) + + if source_wc_node is not None and target_wc_node is None: + raise HTTPException( + status_code=400, + detail=f"Source pattern has wildcard (...), which is not present in target pattern", + ) + + if source_pattern.operator != cTreeOperator.Concurrent: + raise HTTPException( + status_code=400, + detail=f"Source pattern without concurrent operator at highest level", + ) + + for child in source_pattern.children: + if child.operator is not None and child.operator != WILDCARD_MATCH: + raise HTTPException( + status_code=400, detail=f"Source pattern cannot have nested operators" + ) + + +def get_activities_in_pattern(pattern: SequentializerPattern): + activities = set(pattern.labels) + + for child in pattern.children: + activities = activities.union(get_activities_in_pattern(child)) + + return activities + + +def get_activity_nodes_in_pattern(pattern: SequentializerPattern): + nodes = set() + + if len(pattern.labels) > 0: + nodes.add(pattern) + + for child in pattern.children: + nodes = nodes.union(get_activity_nodes_in_pattern(child)) + + return nodes + + +def parse_pattern_from_variant(variant): + root_node = parse_pattern_from_variant_recursive(variant, None) + if ( + len(root_node.children) == 1 + and root_node.children[0].operator == cTreeOperator.Concurrent + ): + return root_node.children[0] + else: + return root_node + + +def parse_pattern_from_variant_recursive(variant, parent): + operator = None + node = None + if isinstance(variant, SequenceGroup): + operator = cTreeOperator.Sequential + elif isinstance(variant, ParallelGroup): + operator = cTreeOperator.Concurrent + + elif isinstance(variant, FallthroughGroup): + operator = cTreeOperator.Fallthrough + + elif isinstance(variant, LeafGroup) and sorted([activity for activity in variant])[ + 0 + ].startswith("..."): + operator = WILDCARD_MATCH + + if operator is not None and operator != WILDCARD_MATCH: + node = SequentializerPattern(operator=operator, parent=parent, children=None) + if parent is not None: + parent.children.append(node) + if operator != cTreeOperator.Fallthrough: + for child in variant: + parse_pattern_from_variant_recursive(child, node) + else: + fallthrough_leaf = LeafGroup( + [[activity for activity in leaf][0] for leaf in variant] + ) + parse_pattern_from_variant_recursive(fallthrough_leaf, node) + elif operator is not None and operator == WILDCARD_MATCH: + node = SequentializerPattern(operator=operator, parent=parent, children=None) + if parent is not None: + parent.children.append(node) + else: + labels = [] + if isinstance(variant, ChoiceGroup): + labels = [[activity for activity in leaf][0] for leaf in variant] + match_multiple = True + else: + labels = [activity for activity in variant] + match_multiple = False + + node = SequentializerPattern( + labels=labels, parent=parent, match_multiple=match_multiple + ) + if parent is not None: + parent.children.append(node) + + return node diff --git a/src/backend/api/routes/variants/subvariantMining.py b/src/backend/api/routes/variants/subvariantMining.py new file mode 100644 index 0000000000000000000000000000000000000000..f9c7d75bca1cf33343edefce0571fbb7ca9f2148 --- /dev/null +++ b/src/backend/api/routes/variants/subvariantMining.py @@ -0,0 +1,316 @@ +import asyncio +from collections import defaultdict +from cortado_core.eventually_follows_pattern_mining.algorithm import ( + generate_eventually_follows_patterns_from_groups, +) +from cortado_core.eventually_follows_pattern_mining.blanket_mining.algorithm import ( + postprocess_closed_patterns, + postprocess_maximal_patterns, +) +from cortado_core.eventually_follows_pattern_mining.obj import ( + EventuallyFollowsPattern, + SubPattern, +) +from cortado_core.eventually_follows_pattern_mining.util.pattern import flatten_patterns +from cortado_core.variant_pattern_replications.repetition_mining import ( + create_pair, + pair_unions, +) +from cortado_core.subprocess_discovery.concurrency_trees.cTrees import ConcurrencyTree +from cortado_core.utils.split_graph import ( + LeafGroup, + LoopGroup, + ParallelGroup, + SequenceGroup, + SkipGroup, + Group, +) + +from fastapi import APIRouter +from pydantic import BaseModel + +from cortado_core.subprocess_discovery.subtree_mining.treebank import ( + create_treebank_from_cv_variants, +) +from cortado_core.subprocess_discovery.subtree_mining.right_most_path_extension.min_sub_mining import ( + min_sub_mining, +) +from cortado_core.subprocess_discovery.subtree_mining.obj import ( + FrequencyCountingStrategy, +) +from cortado_core.subprocess_discovery.subtree_mining.maximal_connected_components.maximal_connected_check import ( + set_maximaly_closed_patterns, +) +from cortado_core.subprocess_discovery.subtree_mining.output import ( + dataframe_from_k_patterns, +) +from cortado_core.subprocess_discovery.subtree_mining.blanket_mining.cm_grow import ( + cm_min_sub_mining, +) +from cortado_core.subprocess_discovery.subtree_mining.folding_label import fold_loops +from starlette.websockets import WebSocket, WebSocketDisconnect, WebSocketState + +import cache.cache as cache +import numpy as np + +from cortado_core.variant_pattern_replications.repetition_mining import ( + generate_and_filter_patterns, + filter_maximal_patterns, +) + +from backend_utilities.configuration.repository import ConfigurationRepositoryFactory +from backend_utilities.multiprocessing.pool_factory import PoolFactory +from endpoints.transform_event_log import remove_activitiy_from_group + +router = APIRouter(tags=["subvariantMining"], prefix="/subvariantMining") + + +class VariantMinerConfig(BaseModel): + size: int + min_sup: int + strat: int + algo: int + loop: int + algo_type: int + artifical_start: bool + + +class FilterParams(BaseModel): + activitiesToInclude: list[str] = [] + + +class RepetitionsMiningConfig(BaseModel): + bids: list[int] + filters: FilterParams + + +freq_strat_mapping = { + 1: FrequencyCountingStrategy.TraceTransaction, + 2: FrequencyCountingStrategy.VariantTransaction, + 3: FrequencyCountingStrategy.TraceOccurence, + 4: FrequencyCountingStrategy.VariantOccurence, +} + + +def postProcessFrequentTrees(k_patterns: defaultdict[any, set]): + set_maximaly_closed_patterns(k_patterns) + + df = dataframe_from_k_patterns(k_patterns) + + if not df.empty: + df = df[df.valid] + + df["bids"] = df.obj.apply(lambda x: set(x.rmo.keys())) + + df.obj = df.obj.apply( + lambda x: replace_loops_by_loop_group(x.to_concurrency_group()).serialize( + include_performance=False + ) + ) + df = df.replace({np.nan: None}) + + df_dict = df.to_dict(orient="records") + + else: + df_dict = False + return df_dict + + +@router.post("/frequentSubtreeMining") +def mineFrequentSubtrees(config: VariantMinerConfig): + print(config) + + print("K:", config.size) + print("min_sup:", config.min_sup) + print("Strat:", freq_strat_mapping[config.strat]) + print("Mining Algo:", config.algo) + print("Loop", config.loop) + print("Artif. Start", config.artifical_start) + + variants = { + v: ts + for _, (v, ts, _, info) in cache.variants.items() + if not info.is_user_defined + } + + if config.algo == 3: + return get_eventually_follows_patterns( + variants, config.min_sup, freq_strat_mapping[config.strat], config.size + ) + + treeBank = create_treebank_from_cv_variants(variants, config.artifical_start) + + if config.loop: + print("Folding Loops...") + fold_loops(treeBank, config.loop) + + print() + + if config.algo == 1: + print("Mining K Patterns...") + k_patterns, _ = min_sub_mining( + treeBank, + frequency_counting_strat=freq_strat_mapping[config.strat], + k_it=config.size, + min_sup=config.min_sup, + ) + + else: + print("Mining CM K Patterns...") + k_patterns = cm_min_sub_mining( + treeBank, + frequency_counting_strat=freq_strat_mapping[config.strat], + k_it=config.size, + min_sup=config.min_sup, + ) + + print() + print("Post-Processing...") + return postProcessFrequentTrees(k_patterns) + + +def replace_loops_by_loop_group(group): + result = group + if isinstance(group, LeafGroup): + if group.number_of_activities() == 1 and group[0].endswith("_LOOP"): + result = LoopGroup([LeafGroup([group[0][:-5]])]) + + return result + + if isinstance(group, ParallelGroup): + return ParallelGroup([replace_loops_by_loop_group(g) for g in group]) + + if isinstance(group, SequenceGroup): + return SequenceGroup([replace_loops_by_loop_group(g) for g in group]) + + raise Exception("Group type is unknown") + + +def get_eventually_follows_patterns( + variants, min_support, frequency_counting_strategy, max_size +): + patterns = generate_eventually_follows_patterns_from_groups( + variants, min_support, frequency_counting_strategy, max_size=max_size + ) + flat_patterns = set(flatten_patterns(patterns)) + closed = postprocess_closed_patterns(flat_patterns) + maximal = postprocess_maximal_patterns(flat_patterns) + + result = [] + for pattern in flat_patterns: + result.append( + { + "bids": [], + "k": sum([len(sp) for sp in pattern.sub_patterns]), + "obj": serialize_pattern(pattern), + "sup": pattern.support, + "child_parent_confidence": None, + "subpattern_confidence": None, + "cross_support_confidence": None, + "valid": True, + "maximal": pattern in maximal, + "closed": pattern in closed, + } + ) + + return result + + +def serialize_pattern(pattern: EventuallyFollowsPattern): + return SkipGroup( + [sub_pattern_to_ctree(sp).to_concurrency_group() for sp in pattern.sub_patterns] + ).serialize() + + +def sub_pattern_to_ctree(pattern: SubPattern, parent=None): + t = ConcurrencyTree(parent=parent, op=pattern.operator, label=pattern.label) + t.children = [sub_pattern_to_ctree(child, t) for child in pattern.children] + return t + + +def serialize_result(data): + result = {} + for key, value in data.items(): + if key == "pairs": + result[key] = {k: [p.serialize() for p in v] for k, v in value.items()} + else: + result[key] = value + return result + + +def mine_repetition_patterns_with_timeout( + config: RepetitionsMiningConfig, cached_variants, cached_activities, timeout: int +): + result = {} + + filter_activities = len(config.filters.activitiesToInclude) > 0 and len( + config.filters.activitiesToInclude + ) != len(cached_activities) + + activities_to_exclude = [] + + if filter_activities: + activities_to_exclude = list( + filter( + lambda x: x not in config.filters.activitiesToInclude, + cached_activities, + ) + ) + + maximal_size, maximal_length = 1, 1 + + for bid in config.bids: + if bid in cached_variants: + v, ts, _, _ = cached_variants[bid] + else: + continue + + if filter_activities: + v = remove_activitiy_from_group( + v, activities_to_exclude, replace_with_random=True + ) + v.assign_dfs_ids() + + tree_bank = create_treebank_from_cv_variants({v: ts}, False) + + ( + pairs_filtered, + kpatterns_filtered, + ks, + single_act_pairs, + ) = generate_and_filter_patterns(tree_bank) + + pairs_from_kpatterns, maximal_size, maximal_length = filter_maximal_patterns( + kpatterns_filtered, pairs_filtered, ks, tree_bank[0] + ) + + combined_pairs = pair_unions(pairs_from_kpatterns, single_act_pairs) + + result.update( + { + bid: sorted( + combined_pairs, + key=lambda x: x.positions.bfs[1] - x.positions.bfs[0], + reverse=True, + ) + } + ) + + return { + "pairs": result, + "maximal_values": {"size": maximal_size, "length": maximal_length}, + } + + +def get_repetition_mining_callback(websocket: WebSocket): + def send_response(data): + result = serialize_result(data) + + try: + if websocket.application_state == WebSocketState.CONNECTED: + asyncio.run(websocket.send_json(result)) + + except Exception as e: + print("Error while sending arc diagrams computation result: ", e) + + return send_response diff --git a/src/backend/api/routes/variants/utils.py b/src/backend/api/routes/variants/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..01affdb99680b1ba14b067c2ddbc8404967c11a5 --- /dev/null +++ b/src/backend/api/routes/variants/utils.py @@ -0,0 +1,92 @@ +from typing import List, Mapping, Tuple + +from cortado_core.clustering.agglomerative_edit_distance_clusterer import ( + AgglomerativeEditDistanceClusterer, +) +from cortado_core.clustering.clusterer import Clusterer +from cortado_core.clustering.label_vector_clusterer import LabelVectorClusterer +from cortado_core.utils.split_graph import ConcurrencyGroup, Group, SequenceGroup +from pm4py.objects.log.obj import Trace + +from api.routes.variants.models import ( + ClusteringAlgorithm, + ClusteringParameters, + VariantInformation, +) +from cache import cache, cache_util +from endpoints.alignments import InfixType +from endpoints.load_event_log import create_variant_object + + +def count_fragment_occurrences(variant, fragment: Group, infixType: InfixType, idx): + # extract group from variant + group: Group = variant[1][0] + + # We always need a sequence group as the root of the tree + # because we use this assumption to check the prefix/postfix + if not isinstance(group, SequenceGroup): + group = SequenceGroup(lst=[group]) + + return group.countInfixOccurrences(fragment, infixType=infixType, isRootNode=True) + + +def get_trace_counts( + variants: Mapping[int, Tuple[ConcurrencyGroup, Trace, List, VariantInformation]] +): + return list(map(lambda variant: len(variant[1][1]), variants.items())) + + +def get_fragment_counts( + variants: Mapping[int, Tuple[ConcurrencyGroup, Trace, List, VariantInformation]], + fragment: Group, + infixType: InfixType, +): + return list( + map( + lambda variant: count_fragment_occurrences( + variant, fragment, infixType, variant[0] + ), + variants.items(), + ) + ) + + +def get_clusterer(params: ClusteringParameters) -> Clusterer: + if params.algorithm == ClusteringAlgorithm.AGGLOMERATIVE_EDIT_DISTANCE_CLUSTERING: + max_distance = params.params["maxDistance"] + clusterer: Clusterer = AgglomerativeEditDistanceClusterer( + max_distance=max_distance + ) + elif params.algorithm == ClusteringAlgorithm.LABEL_VECTOR_CLUSTERING: + n_clusters = params.params["nClusters"] + clusterer: Clusterer = LabelVectorClusterer(n_clusters=n_clusters) + + return clusterer + + +def map_clusters(clusters): + result = [] + + for idx, cluster in enumerate(clusters): + cluster_result = [] # list of variants for a single cluster + for group in cluster: + variant_id, variant = cache_util.map_group_to_cached_variant( + group + ) # get the cached version + + print(cache.parameters) + # create object that structure that can be handled by the frontend + variant, _ = create_variant_object( + cache.parameters["cur_time_granularity"], + cache_util.get_log_length(), + variant_id, + cache_util.get_variant(variant), + cache_util.get_traces(variant), + cache_util.get_variant_info(variant), + ) + variant["clusterId"] = idx + cluster_result.append(variant) + + result.append(cluster_result) + + return result diff --git a/src/backend/api/routes/variants/variants.py b/src/backend/api/routes/variants/variants.py new file mode 100644 index 0000000000000000000000000000000000000000..eecd1fef97377f7ce81a430c6c43d0b98f17eadf --- /dev/null +++ b/src/backend/api/routes/variants/variants.py @@ -0,0 +1,176 @@ +from pydantic import BaseModel +import functools +import operator +from typing import List, Mapping, Tuple +from typing import Any +import numpy as np +from cortado_core.clustering.clusterer import Clusterer +from cortado_core.clustering.variant_clusterer_adapter import calculate_clusters +from cortado_core.models.infix_type import InfixType +from cortado_core.utils.split_graph import ConcurrencyGroup, Group +from pm4py.objects.log.obj import Trace +from fastapi import APIRouter + +import cache.cache as cache +from api.routes.variants.models import ( + ClusteringParameters, + VariantFragment, + VariantInformation, +) +from api.routes.variants.utils import ( + get_clusterer, + get_fragment_counts, + get_trace_counts, + map_clusters, +) +from cache import cache_util + +# i think its better to have one prefix for everything which +# is related to variants instead of defining a prefix for +# every endpoint. +# e.g. /variantQuery should be /variant/query +# because otherwise the generated api docs are not really convenient +router = APIRouter(tags=["Variants"], prefix="/variant") + + +@router.post("/countFragmentOccurrences") +def count_fragment_occurrences(payload: VariantFragment): + fragment: Group = Group.deserialize(payload.fragment) + + variants: Mapping[int, Tuple[ConcurrencyGroup, Trace, List, VariantInformation]] = ( + cache.variants + ) + variants = {k: v for k, v in variants.items() if not v[3].is_user_defined} + + infixType = InfixType[payload.infixType] + + trace_counts = get_trace_counts(variants) + fragment_counts = get_fragment_counts(variants, fragment, infixType) + + # number of pattern occurrences among all variants + total_variant_occurrences = functools.reduce(operator.add, fragment_counts) + # number of variants having at least once the pattern + variant_occurrences = np.count_nonzero(fragment_counts) + # number traces having at least once the pattern + trace_occurrences = np.sum( + np.array(trace_counts)[np.nonzero(fragment_counts)] + ).item() + + # number of pattern occurrences among all traces + total_trace_occurrences = np.sum( + np.array(trace_counts) * np.array(fragment_counts) + ).item() + + return { + "totalOccurrences": total_variant_occurrences, + "variantOccurrences": variant_occurrences, + "traceOccurrences": trace_occurrences, + "totalTraceOccurrences": total_trace_occurrences, + "variantOccurrencesFraction": round(variant_occurrences / len(variants), 4), + "traceOccurrencesFraction": round(trace_occurrences / np.sum(trace_counts), 4), + } + + +class GroupToSort(BaseModel): + variants: Any = None + + +class IdQuery(BaseModel): + index: Any = None + + +class caseQuery(BaseModel): + index: Any = None + caseId: Any = None + + +@router.post("/sortvariant") +def sort_variant(payload: GroupToSort): + sorted_variant = Group.deserialize(payload.variants).sort().serialize() + res = { + "variants": sorted_variant, + } + return res + + +@router.post("/cluster") +def cluster(params: ClusteringParameters): + variants: List[Group] = cache_util.get_variant_list(True) + clusterer: Clusterer = get_clusterer(params) + clusters: List[List[Group]] = calculate_clusters( + variants=variants, clusterer=clusterer + ) + result = map_clusters(clusters) + return result + + +@router.post("/caseStatistics") +def calculateStatistics(query: IdQuery): + index = int(query.index) + traces = cache.variants[index][1] + trace_statistics = [] + for trace in traces: + statistics_temp = {} + statistics_temp["case_id"] = trace.attributes["concept:name"] + statistics_temp["activity_num"] = len(trace) + earliest_time = min( + min([act["start_timestamp"] for act in trace]), + max([act["time:timestamp"] for act in trace]), + ) + statistics_temp["earliest_time"] = earliest_time.strftime( + "%Y-%m-%d %H:%M:%S" + ) # there might not be a start + latest_time = max([act["time:timestamp"] for act in trace]) + statistics_temp["latest_time"] = latest_time.strftime("%Y-%m-%d %H:%M:%S") + duration = latest_time - earliest_time + statistics_temp["total_duration"] = ( + f"{duration.days} days, {duration.seconds // 3600:02}:{(duration.seconds % 3600) // 60:02}:{duration.seconds % 60:02}" + ) + trace_statistics.append(statistics_temp) + + res = { + "statistics": trace_statistics, + } + return res + + +@router.post("/caseActivities") +def getCaseActivities(query: caseQuery): + index = int(query.index) + id = str(query.caseId) + traces = cache.variants[index][1] + case_activities = [] + key_set = set() + for trace in traces: + key_set = key_set.union(list(trace[0].keys())) + for trace in traces: + if trace.attributes["concept:name"] == id: + for act in trace: + activities_temp = {} + activities_temp["act_id"] = act["concept:name"] + activities_temp["end_timestamp"] = act["time:timestamp"].strftime( + "%Y-%m-%d %H:%M:%S" + ) + activities_temp["start_timestamp"] = act["start_timestamp"].strftime( + "%Y-%m-%d %H:%M:%S" + ) + duration = act["time:timestamp"] - act["start_timestamp"] + activities_temp["duration"] = ( + f"{duration.days} days, {duration.seconds // 3600:02}:{(duration.seconds % 3600) // 60:02}:{duration.seconds % 60:02}" + ) + activities_temp["property"] = act + case_activities.append(activities_temp) + break + key_set.difference_update( + { + "cortado_activity_instance", + "concept:name", + "time:timestamp", + "start_timestamp", + } + ) + res = { + "statistics": case_activities, + "keys": key_set, + } + return res diff --git a/src/backend/api/websocket/__init__.py b/src/backend/api/websocket/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/api/websocket/main.py b/src/backend/api/websocket/main.py new file mode 100644 index 0000000000000000000000000000000000000000..394356f5bf9bcd03cdc81451ad8839a870ef7bc6 --- /dev/null +++ b/src/backend/api/websocket/main.py @@ -0,0 +1,111 @@ +from fastapi.routing import APIRouter +from typing import Callable +from starlette.websockets import WebSocket, WebSocketState, WebSocketDisconnect + +from api.routes.conformance.variantConformance import ( + calculate_alignment_intern_with_timeout, + get_alignment_callback, +) +from api.routes.variants.subvariantMining import ( + mine_repetition_patterns_with_timeout, + RepetitionsMiningConfig, + get_repetition_mining_callback, +) +from backend_utilities.configuration.repository import ConfigurationRepositoryFactory +from backend_utilities.multiprocessing.pool_factory import PoolFactory +from cache import cache +from endpoints.alignments import InfixType + +router = APIRouter(tags=["websocket"], prefix="/ws") + + +class WebSocketService: + def __init__( + self, websocket: WebSocket, callback: Callable, timeout: int, name: str + ): + self.websocket = websocket + self.callback = callback + self.pool = PoolFactory.instance().get_pool() + self.timeout = timeout + self.name = name + + async def start_service(self): + await self.websocket.accept() + + try: + while True: + data = await self.websocket.receive_json() + + if "isCancellationRequested" in data: + await self.websocket.close(1000) + PoolFactory.instance().restart_pool() + return + + try: + if "timeout" in data and data["timeout"] != 0: + self.timeout = data["timeout"] + + await self.callback(data, self.timeout) + + except Exception as e: + if self.websocket.application_state == WebSocketState.CONNECTED: + await self.websocket.send_json({"error": str(e)}) + + except WebSocketDisconnect as d: + print(d) + print("websocket disconnected") + + +class ConformanceWebsocketHandler(WebSocketService): + def __init__(self, websocket: WebSocket, timeout: int): + super().__init__( + websocket, self.handle_message, timeout, "conformance checking" + ) + + async def handle_message(self, data, timeout: int): + self.pool.apply_async( + calculate_alignment_intern_with_timeout, + ( + data["pt"], + data["variant"], + InfixType(data["infixType"]), + timeout, + ), + callback=get_alignment_callback( + data["id"], data["alignType"], self.websocket + ), + ) + + +class ArcDiagramWebsocketHandler(WebSocketService): + def __init__(self, websocket: WebSocket, timeout: int = None): + super().__init__(websocket, self.handle_message, timeout, "arc diagrams") + + async def handle_message(self, data, timeout: int): + self.pool.apply_async( + mine_repetition_patterns_with_timeout, + ( + RepetitionsMiningConfig(**data), + cache.variants, + cache.parameters["activites"], + timeout, + ), + callback=get_repetition_mining_callback(self.websocket), + ) + + +@router.websocket("/conformance") +async def websocket_conformance(websocket: WebSocket): + ws_handler = ConformanceWebsocketHandler( + websocket, + ConfigurationRepositoryFactory.get_config_repository() + .get_configuration() + .timeout_cvariant_alignment_computation, + ) + await ws_handler.start_service() + + +@router.websocket("/repetitionsMining") +async def websocket_repetitions_mining(websocket: WebSocket): + ws_handler = ArcDiagramWebsocketHandler(websocket) + await ws_handler.start_service() diff --git a/src/backend/backend_utilities/__init__.py b/src/backend/backend_utilities/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/backend_utilities/configuration/__init__.py b/src/backend/backend_utilities/configuration/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/backend_utilities/configuration/repository.py b/src/backend/backend_utilities/configuration/repository.py new file mode 100644 index 0000000000000000000000000000000000000000..7e977becc6b4ec01571c0b9ba55c53b4e44d9a3b --- /dev/null +++ b/src/backend/backend_utilities/configuration/repository.py @@ -0,0 +1,131 @@ +import abc +import json +from pathlib import Path +from appdirs import user_config_dir +import os +import errno + +CONFIG_FILENAME = "config.json" +DEFAULT_TIMEOUT = 2 +DEFAULT_MIN_TRACES_VARIANT_DETECTION_MULTIPROCESSING = 1000 +DEFAULT_NUMBER_OF_SEQUENTIALIZATIONS = 10 +APP_NAME = "cortado" +COMPANY_NAME = "Fraunhofer" + + +class Configuration: + timeout_cvariant_alignment_computation: int + min_traces_variant_detection_mp: int + + def __init__( + self, + timeout_cvariant_alignment_computation=DEFAULT_TIMEOUT, + min_traces_variant_detection_mp=DEFAULT_MIN_TRACES_VARIANT_DETECTION_MULTIPROCESSING, + is_n_sequentialization_reduction_enabled=True, + number_of_sequentializations_per_variant=DEFAULT_NUMBER_OF_SEQUENTIALIZATIONS, + ): + self.timeout_cvariant_alignment_computation = ( + timeout_cvariant_alignment_computation + ) + self.min_traces_variant_detection_mp = min_traces_variant_detection_mp + self.is_n_sequentialization_reduction_enabled = ( + is_n_sequentialization_reduction_enabled + ) + self.number_of_sequentializations_per_variant = ( + number_of_sequentializations_per_variant + ) + + def __getitem__(self, key): + return self[key] + + +class ConfigurationRepository(abc.ABC): + @abc.abstractmethod + def save_configuration(self, config: Configuration): + raise NotImplementedError + + @abc.abstractmethod + def get_configuration(self) -> Configuration: + raise NotImplementedError + + +class FileBasedConfigurationRepository(ConfigurationRepository): + def save_configuration(self, config: Configuration): + directory = user_config_dir(APP_NAME, COMPANY_NAME) + filename = os.path.join(directory, CONFIG_FILENAME) + self.__create_dir_if_not_exists(filename) + + with open(filename, "w+", encoding="utf-8") as f: + json.dump(config.__dict__, f, ensure_ascii=False, indent=4) + + def get_configuration(self) -> Configuration: + directory = user_config_dir(APP_NAME, COMPANY_NAME) + if not Path(os.path.join(directory, CONFIG_FILENAME)).is_file(): + return Configuration(timeout_cvariant_alignment_computation=DEFAULT_TIMEOUT) + + with open(os.path.join(directory, CONFIG_FILENAME), "r", encoding="utf-8") as f: + data = json.load(f) + + min_traces_variant_detection_mp = ( + data["min_traces_variant_detection_mp"] + if "min_traces_variant_detection_mp" in data + else DEFAULT_MIN_TRACES_VARIANT_DETECTION_MULTIPROCESSING + ) + + timeout_cvariant_alignment_computation = ( + data["timeout_cvariant_alignment_computation"] + if "timeout_cvariant_alignment_computation" in data + else DEFAULT_TIMEOUT + ) + + is_n_sequentialization_reduction_enabled = ( + data["is_n_sequentialization_reduction_enabled"] + if "is_n_sequentialization_reduction_enabled" in data + else True + ) + number_of_sequentializations_per_variant = ( + data["number_of_sequentializations_per_variant"] + if "number_of_sequentializations_per_variant" in data + else DEFAULT_NUMBER_OF_SEQUENTIALIZATIONS + ) + + return Configuration( + timeout_cvariant_alignment_computation=timeout_cvariant_alignment_computation, + min_traces_variant_detection_mp=min_traces_variant_detection_mp, + is_n_sequentialization_reduction_enabled=is_n_sequentialization_reduction_enabled, + number_of_sequentializations_per_variant=number_of_sequentializations_per_variant, + ) + + # see https://stackoverflow.com/questions/12517451/automatically-creating-directories-with-file-output + @staticmethod + def __create_dir_if_not_exists(filename: str): + if not os.path.exists(os.path.dirname(filename)): + try: + os.makedirs(os.path.dirname(filename)) + except OSError as exc: # Guard against race condition + if exc.errno != errno.EEXIST: + raise + + +class ConfigurationRepositoryCacheProxy(ConfigurationRepository): + def __init__(self, config_repo: ConfigurationRepository): + self.config_repo = config_repo + self.cached_config = None + + def save_configuration(self, config: Configuration): + self.config_repo.save_configuration(config) + self.cached_config = config + + def get_configuration(self) -> Configuration: + if self.cached_config is None: + self.cached_config = self.config_repo.get_configuration() + + return self.cached_config + + +class ConfigurationRepositoryFactory: + repo = ConfigurationRepositoryCacheProxy(FileBasedConfigurationRepository()) + + @staticmethod + def get_config_repository() -> ConfigurationRepository: + return ConfigurationRepositoryFactory.repo diff --git a/src/backend/backend_utilities/multiprocessing/__init__.py b/src/backend/backend_utilities/multiprocessing/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/backend_utilities/multiprocessing/pool_factory.py b/src/backend/backend_utilities/multiprocessing/pool_factory.py new file mode 100644 index 0000000000000000000000000000000000000000..07b493b4a17ab935b187f63c1262ef311a0968f5 --- /dev/null +++ b/src/backend/backend_utilities/multiprocessing/pool_factory.py @@ -0,0 +1,18 @@ +import multiprocessing + +from backend_utilities.multiprocessing.singleton import Singleton + + +@Singleton +class PoolFactory: + def __init__(self): + self.pool = multiprocessing.Pool() + + def get_pool(self): + return self.pool + + def restart_pool(self): + self.pool.terminate() + self.pool.join() + + self.pool = multiprocessing.Pool() diff --git a/src/backend/backend_utilities/multiprocessing/singleton.py b/src/backend/backend_utilities/multiprocessing/singleton.py new file mode 100644 index 0000000000000000000000000000000000000000..15e3900fa807c9d878422a7d5a0906eeba8be73b --- /dev/null +++ b/src/backend/backend_utilities/multiprocessing/singleton.py @@ -0,0 +1,23 @@ +import threading + + +class Singleton: + def __init__(self, decorated): + self._decorated = decorated + self._lock = threading.Lock() + self._instance = None + + def instance(self): + if self._instance is None: + with self._lock: + # double check because other thread could have generated the instance in the meantime + if self._instance is None: + self._instance = self._decorated() + + return self._instance + + def __call__(self): + raise TypeError("Singletons must be accessed through `instance()`.") + + def __instancecheck__(self, inst): + return isinstance(inst, self._decorated) diff --git a/src/backend/backend_utilities/process_tree_conversion.py b/src/backend/backend_utilities/process_tree_conversion.py new file mode 100644 index 0000000000000000000000000000000000000000..9d8de271565108f2fe9eb29ebd567410c1fa8024 --- /dev/null +++ b/src/backend/backend_utilities/process_tree_conversion.py @@ -0,0 +1,248 @@ +from typing import List, Tuple + +from cortado_core.process_tree_utils.miscellaneous import ( + subtree_is_part_of_tree_based_on_obj_id, +) +from pm4py.objects.process_tree.obj import Operator, ProcessTree + +SEQUENCE_CHAR = "\u2794" +CHOICE_CHAR = "\u2715" +LOOP_CHAR = "\u21BA" +PARALLELISM_CHAR = "\u2227" +TAU_CHAR = "\u03C4" + + +def process_tree_to_dict( + pt: ProcessTree, + frozen_subtrees: List[ProcessTree] = [], + performance={}, + conformance=None, +) -> dict: + return process_tree_to_dict_rec( + pt, + frozen_subtrees=frozen_subtrees, + performance=performance, + conformance=conformance, + ) + + +def process_tree_to_dict_rec( + pt: ProcessTree, + frozen_subtrees: List[ProcessTree] = [], + performance={}, + conformance=None, +) -> dict: + pt_frozen = False + for frozen_subtree in frozen_subtrees: + if subtree_is_part_of_tree_based_on_obj_id(pt, frozen_subtree): + pt_frozen = True + res = { + "operator": __get_root_operator_string_for_frontend(pt), + "label": ( + None + if __get_root_node_label(pt) is None + else str(__get_root_node_label(pt)) + ), + "id": id(pt), + "children": [], + "frozen": pt_frozen, + "performance": performance.get(str(pt), None), + "conformance": None, + } + for c in pt.children: + res["children"].append( + process_tree_to_dict_rec(c, frozen_subtrees, performance, conformance) + ) + if conformance: + if res["children"]: + child_conformance = [ + child["conformance"] + for child in res["children"] + if child["conformance"] is not None + ] + if len(child_conformance) > 0: + equal_weight_sum = sum( + list( + map( + lambda conf: conf["weighted_equally"]["weight"], + child_conformance, + ) + ) + ) + equal_weight_value = [] + + count_weight_sum = sum( + list( + map( + lambda conf: ( + 0 + if conf["weighted_by_counts"] is None + else conf["weighted_by_counts"]["weight"] + ), + child_conformance, + ) + ) + ) + count_weight_value = [] + + for child in child_conformance: + equal_weight_value.append( + child["weighted_equally"]["value"] + * child["weighted_equally"]["weight"] + ) + if child["weighted_by_counts"] is not None: + count_weight_value.append( + child["weighted_by_counts"]["value"] + * child["weighted_by_counts"]["weight"] + ) + + equal_weight_value = ( + None + if equal_weight_sum == 0 + else sum(equal_weight_value) / equal_weight_sum + ) + count_weight_value = ( + None + if count_weight_sum == 0 + else sum(count_weight_value) / count_weight_sum + ) + + res["conformance"] = { + "weighted_equally": { + "value": equal_weight_value, + "weight": equal_weight_sum, + }, + "weighted_by_counts": ( + { + "value": count_weight_value, + "weight": count_weight_sum, + } + if count_weight_sum > 0 + else None + ), + } + elif str(pt) in conformance: + res["conformance"] = conformance[str(pt)] + return res + + +def __get_root_operator_string_for_frontend(pt: ProcessTree) -> str: + if pt.operator == Operator.XOR: + return CHOICE_CHAR + if pt.operator == Operator.SEQUENCE: + return SEQUENCE_CHAR + if pt.operator == Operator.LOOP: + return LOOP_CHAR + if pt.operator == Operator.PARALLEL: + return PARALLELISM_CHAR + return None + + +def __convert_operator_string_from_frontend_for_pm4py_core(operator: str) -> str: + if operator == CHOICE_CHAR: + return Operator.XOR + if operator == SEQUENCE_CHAR: + return Operator.SEQUENCE + if operator == LOOP_CHAR: + return Operator.LOOP + if operator == PARALLELISM_CHAR: + return Operator.PARALLEL + return None + + +def __convert_label_string_from_frontend_for_pm4py_core(label: str) -> str: + if label == TAU_CHAR: + return None + else: + return label + + +def __get_root_node_label(pt: ProcessTree) -> str: + if not pt.label and not pt.operator: + return TAU_CHAR + else: + return pt.label + + +def dict_to_process_tree( + pt: dict, res=None, frozen_subtrees=None +) -> Tuple[ProcessTree, List[ProcessTree]]: + if frozen_subtrees is None: + frozen_subtrees = [] + if not res: + res = ProcessTree( + operator=__convert_operator_string_from_frontend_for_pm4py_core( + pt["operator"] + ), + label=__convert_label_string_from_frontend_for_pm4py_core(pt["label"]), + ) + else: + subtree = ProcessTree( + operator=__convert_operator_string_from_frontend_for_pm4py_core( + pt["operator"] + ), + label=__convert_label_string_from_frontend_for_pm4py_core(pt["label"]), + parent=res, + ) + res.children.append(subtree) + res = subtree + if pt["frozen"]: + current_node_already_considered = False + for frozen_tree in frozen_subtrees: + if subtree_is_part_of_tree_based_on_obj_id(subtree, frozen_tree): + current_node_already_considered = True + break + if not current_node_already_considered: + frozen_subtrees.append(subtree) + if pt["children"]: + for c in pt["children"]: + dict_to_process_tree(c, res, frozen_subtrees) + + return res, frozen_subtrees + + +if __name__ == "__main__": + test = { + "label": None, + "operator": "➔", + "children": [ + {"label": "A_SUBMITTED", "operator": None, "children": [], "frozen": False}, + { + "label": "A_PARTLYSUBMITTED", + "operator": None, + "children": [], + "frozen": False, + }, + { + "label": None, + "operator": "✕", + "children": [ + {"label": "τ", "operator": None, "children": [], "frozen": True}, + { + "label": "A_Completeren aanvraag", + "operator": None, + "children": [], + "frozen": True, + }, + ], + "frozen": True, + }, + { + "label": None, + "operator": "✕", + "children": [ + {"label": "τ", "operator": None, "children": [], "frozen": True}, + { + "label": "W_Completeren aanvraag", + "operator": None, + "children": [], + "frozen": True, + }, + ], + "frozen": True, + }, + ], + "frozen": False, + } + + res_tree, res_frozen_subtrees = dict_to_process_tree(test) diff --git a/src/backend/backend_utilities/timeout/__init__.py b/src/backend/backend_utilities/timeout/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/backend_utilities/timeout/helper_functions.py b/src/backend/backend_utilities/timeout/helper_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..7128ebeec44c34fba4a272a42ea69ca47fa79a1a --- /dev/null +++ b/src/backend/backend_utilities/timeout/helper_functions.py @@ -0,0 +1,44 @@ +import threading +import ctypes + + +class TimeoutException(BaseException): + pass + + +def execute_with_timeout(func, timeout, args=()): + result = [] + exception = [] + + def func_wrapper(*args_wrapper): + try: + result.append(func(*args_wrapper)) + except Exception as e: + exception.append(e) + + t = threading.Thread(target=func_wrapper, args=args) + t.start() + t.join(timeout=timeout) + + if t.is_alive(): + raise_in_thread(t, TimeoutException()) + + if len(result) != 0: + return result[0] + + if len(exception) != 0: + raise exception[0] + + raise TimeoutException() + + +def raise_in_thread(thread, exception): + # see https://stackoverflow.com/questions/36484151/throw-an-exception-into-another-thread + ret = ctypes.pythonapi.PyThreadState_SetAsyncExc( + ctypes.c_long(thread.ident), ctypes.py_object(exception) + ) + if ret == 0: + raise ValueError("Invalid thread ID") + elif ret > 1: + ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None) + raise SystemError("PyThreadState_SetAsyncExc failed") diff --git a/src/backend/backend_utilities/util.py b/src/backend/backend_utilities/util.py new file mode 100644 index 0000000000000000000000000000000000000000..ab4c35fe3f7745f799d7afe1ca5f272e6fe3ba69 --- /dev/null +++ b/src/backend/backend_utilities/util.py @@ -0,0 +1,13 @@ +import traceback + +from fastapi.responses import JSONResponse + + +def get_trace(e): + return "".join(traceback.format_exception(e, value=e, tb=e.__traceback__)) + + +def build_json_error_rsp(detail, stack_trace, status_code): + return JSONResponse( + {"detail": detail, "stack_trace": stack_trace}, status_code=status_code + ) diff --git a/src/backend/backend_utilities/variant_trace_conversion.py b/src/backend/backend_utilities/variant_trace_conversion.py new file mode 100644 index 0000000000000000000000000000000000000000..693931118828670694a9e7221445c2fec76b28eb --- /dev/null +++ b/src/backend/backend_utilities/variant_trace_conversion.py @@ -0,0 +1,24 @@ +from pm4py.objects.log.obj import Trace, Event +import datetime + +from pm4py.util.xes_constants import ( + DEFAULT_START_TIMESTAMP_KEY, + DEFAULT_TIMESTAMP_KEY, + DEFAULT_NAME_KEY, +) + + +def variant_to_trace(variant: any) -> Trace: + t = Trace() + trace_starttime = datetime.datetime.fromtimestamp(0) + for i, e in enumerate(variant): + assert type(e) == str + event = Event() + event[DEFAULT_NAME_KEY] = e + event[DEFAULT_START_TIMESTAMP_KEY] = trace_starttime + datetime.timedelta( + seconds=i + ) + event[DEFAULT_TIMESTAMP_KEY] = trace_starttime + datetime.timedelta(seconds=i) + t.append(event) + + return t diff --git a/src/backend/cache/__init__.py b/src/backend/cache/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/cache/cache.py b/src/backend/cache/cache.py new file mode 100644 index 0000000000000000000000000000000000000000..937eb32d7d9a9a3348559e0503f2476ad5296220 --- /dev/null +++ b/src/backend/cache/cache.py @@ -0,0 +1,15 @@ +from typing import List, Mapping, Tuple +from pm4py.objects.log.obj import EventLog, Trace +from cortado_core.utils.split_graph import ConcurrencyGroup + +# raw event log +from api.routes.variants.models import VariantInformation + +# raw event log +event_log: EventLog = None +# performance statistics +pcache: Mapping = {} + +parameters: Mapping = {} + +variants: Mapping[int, Tuple[ConcurrencyGroup, Trace, List, VariantInformation]] = {} diff --git a/src/backend/cache/cache_util.py b/src/backend/cache/cache_util.py new file mode 100644 index 0000000000000000000000000000000000000000..d963c9954f1a6531dfd49f61de4eed8d7ac876fd --- /dev/null +++ b/src/backend/cache/cache_util.py @@ -0,0 +1,71 @@ +import itertools +from typing import Dict, List, Mapping, Tuple +from cortado_core.utils.split_graph import Group +from pm4py.objects.log.obj import EventLog, Trace +from cache import cache +from api.routes.variants.variants import VariantInformation + + +def get_variant(variant: Tuple[Group, List[Trace], List, VariantInformation]) -> Group: + return variant[0] + + +def get_traces( + variant: Tuple[Group, List[Trace], List, VariantInformation] +) -> List[Trace]: + return variant[1] + + +def get_variant_info( + variant: Tuple[Group, List[Trace], List, VariantInformation] +) -> List[Trace]: + return variant[3] + + +def get_id_to_group_mapping(include_user_defined=False) -> Dict: + variants: Mapping[int, Tuple[Group, Trace, List, VariantInformation]] = ( + cache.variants + ) + variants = { + k: v[0] + for k, v in variants.items() + if (v[3].is_user_defined and include_user_defined) or (not v[3].is_user_defined) + } + + return variants + + +def get_variant_list(include_user_defined=False) -> List[Group]: + return list( + get_id_to_group_mapping(include_user_defined=include_user_defined).values() + ) + + +def get_group_hash_to_id_mapping(include_user_defined=False) -> Dict[str, int]: + variants: Mapping[int, Group] = get_id_to_group_mapping( + include_user_defined=include_user_defined + ) + return {hash(v): k for k, v in variants.items()} + + +def map_group_to_cached_variant(group: Group): + variants: Mapping[str, int] = get_group_hash_to_id_mapping( + include_user_defined=True + ) + + variant_id = variants.get(hash(group)) + return variant_id, cache.variants.get(variant_id) + + +def get_event_log() -> EventLog: + traces = get_all_traces() + log = EventLog(traces, **cache.parameters["log_info"]) + return log + + +def get_all_traces() -> List["Trace"]: + return list(itertools.chain(*[ts for _, (_, ts, _, _) in cache.variants.items()])) + + +def get_log_length(): + return len(get_all_traces()) diff --git a/src/backend/core/__init__.py b/src/backend/core/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/core/events.py b/src/backend/core/events.py new file mode 100644 index 0000000000000000000000000000000000000000..3e5b33fe29241c36e6f00a84df0ecf98fd9d870f --- /dev/null +++ b/src/backend/core/events.py @@ -0,0 +1,40 @@ +import logging +import pickle +from typing import Callable +import cache.cache as cache +from backend_utilities.multiprocessing.pool_factory import PoolFactory +from fastapi import FastAPI +import sys + +logger = logging.getLogger("uvicorn") + + +def create_start_app_handler( + app: FastAPI, +) -> Callable: + async def start_app() -> None: + logger.info("---------- Handling startup ----------") + cache.pcache = {} + + if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"): + cache.variants = pickle.load(open("./_internal/resources/variants.p", "rb")) + cache.parameters = pickle.load( + open("./_internal/resources/parameters.p", "rb") + ) + else: + cache.variants = pickle.load(open("./resources/variants.p", "rb")) + cache.parameters = pickle.load(open("./resources/parameters.p", "rb")) + + # create process pool + PoolFactory.instance() + + print("loaded parameters", cache.parameters) + + return start_app + + +def create_stop_app_handler(app: FastAPI) -> Callable: + async def stop_app() -> None: + logger.info("-------- Handling application stop -----------") + + return stop_app diff --git a/src/backend/cortado-backend-macos.spec b/src/backend/cortado-backend-macos.spec new file mode 100644 index 0000000000000000000000000000000000000000..75eb7fbb13b41cea881109af8abb7cafcbf6a562 --- /dev/null +++ b/src/backend/cortado-backend-macos.spec @@ -0,0 +1,72 @@ +# -*- mode: python ; coding: utf-8 -*- +block_cipher = None + +import sys +import glob +sys.setrecursionlimit(sys.getrecursionlimit() * 5) + +# https://stackoverflow.com/a/48068640 +import importlib + +datas = [] +if glob.glob('./resources/*.p'): + print('Adding Resources') + datas.append(( './resources/*.p', 'resources' )) + +if glob.glob('./*.ini'): + datas.append(( './*.ini', '.' )) + +cwd = os.getcwd() +a = Analysis(['main.py'], + pathex=[cwd], + hiddenimports=['uvicorn.logging', + 'uvicorn.loops', + 'uvicorn.loops.auto', + 'uvicorn.protocols', + 'uvicorn.protocols.http', + 'uvicorn.protocols.http.auto', + 'uvicorn.protocols.websockets', + 'uvicorn.protocols.websockets.auto', + 'uvicorn.lifespan', + 'uvicorn.lifespan.on', + 'pkg_resources.extern', + 'scipy._lib.array_api_compat.numpy.fft', + 'scipy.special._special_ufuncs', + 'OpenBLAS', + 'sklearn.neighbors._partition_nodes', + 'encodings', + 'main'], + binaries=[], + datas=datas, + hookspath=[], + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + noarchive=False) +pyz = PYZ(a.pure, a.zipped_data, + cipher=block_cipher) +exe = EXE(pyz, + a.scripts, + [], + exclude_binaries=True, + name='cortado-backend', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=True, + icon=os.path.join(os.path.dirname(SPEC), 'icon', 'cortado_icon_colorful_transparent.ico')) +coll = COLLECT(exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + upx_exclude=[], + name='cortado-backend') +app = BUNDLE(exe, + name='cortado-backend.app', + icon=None, + bundle_identifier=None) diff --git a/src/backend/cortado-backend.spec b/src/backend/cortado-backend.spec new file mode 100644 index 0000000000000000000000000000000000000000..1bf7ec61a4e66ac5545abfe4ee6fb87c3d5948e6 --- /dev/null +++ b/src/backend/cortado-backend.spec @@ -0,0 +1,84 @@ +# -*- mode: python ; coding: utf-8 -*- +block_cipher = None + +import sys +import glob +sys.setrecursionlimit(sys.getrecursionlimit() * 5) + +# https://stackoverflow.com/a/48068640 +import importlib +packages_datas = [ + ['cvxopt', [('*', '.')]] +] + +datas = [] +for package, files in packages_datas: + proot = os.path.dirname(importlib.import_module(package).__file__) + print(proot) + datas.extend((os.path.join(proot, source), os.path.join(package, target)) for (source, target) in files) + + +if glob.glob('./resources/*.p'): + print('Adding Resources') + datas.append(( './resources/*.p', 'resources' )) + +if glob.glob('./*.ini'): + datas.append(( './*.ini', '.' )) + +packages_binaries = ['cvxopt'] +binaries = [] +for package in packages_binaries: + proot = os.path.dirname(importlib.import_module(package).__file__) + print(proot) + binaries.append((proot, package)) + +cwd = os.getcwd() +a = Analysis(['main.py'], + pathex=[cwd], + hiddenimports=['uvicorn.logging', + 'uvicorn.loops', + 'uvicorn.loops.auto', + 'uvicorn.protocols', + 'uvicorn.protocols.http', + 'uvicorn.protocols.http.auto', + 'uvicorn.protocols.websockets', + 'uvicorn.protocols.websockets.auto', + 'uvicorn.lifespan', + 'uvicorn.lifespan.on', + 'pkg_resources.extern', + 'scipy._lib.array_api_compat.numpy.fft', + 'scipy.special._special_ufuncs', + 'OpenBLAS', + 'sklearn.neighbors._partition_nodes', + 'encodings', + 'main'], + binaries=binaries, + datas=datas, + hookspath=[], + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + noarchive=False) +pyz = PYZ(a.pure, a.zipped_data, + cipher=block_cipher) +exe = EXE(pyz, + a.scripts, + [], + exclude_binaries=True, + name='cortado-backend', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=True, + icon=os.path.join(os.path.dirname(SPEC), 'icon', 'cortado_icon_colorful_transparent.ico')) +coll = COLLECT(exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + upx_exclude=[], + name='cortado-backend') diff --git a/src/backend/endpoints/__init__.py b/src/backend/endpoints/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/endpoints/add_variants_to_process_model.py b/src/backend/endpoints/add_variants_to_process_model.py new file mode 100644 index 0000000000000000000000000000000000000000..eb0aa9e6024bbe250fbb908aec99f8b3d764d368 --- /dev/null +++ b/src/backend/endpoints/add_variants_to_process_model.py @@ -0,0 +1,50 @@ +import multiprocessing.pool +from typing import List + +from cortado_core.models.infix_type import InfixType +from cortado_core.utils.trace import TypedTrace +from pm4py.objects.log.obj import EventLog + +from backend_utilities.process_tree_conversion import ( + dict_to_process_tree, + process_tree_to_dict, +) +from cortado_core.freezing.apply import add_trace_to_pt_language_with_freezing +from cortado_core.lca_approach import add_trace_to_pt_language +from pm4py.objects.process_tree.obj import ProcessTree +from tqdm import tqdm + + +def add_variants_to_process_model( + pt_dict: dict, + fitting_traces: List[TypedTrace], + traces_to_be_added: List[TypedTrace], + pool: multiprocessing.pool.Pool, +): + pt: ProcessTree + frozen_subtrees: List[ProcessTree] + pt, frozen_subtrees = dict_to_process_tree(pt_dict) + + frozen_subtrees_are_present = len(frozen_subtrees) > 0 + + description = "adding variants to process tree without frozen subtrees" + if frozen_subtrees_are_present: + description = "adding variants to process tree including frozen subtrees" + + for t in tqdm(traces_to_be_added, desc=description): + if not frozen_subtrees_are_present: + pt = add_trace_to_pt_language( + pt, fitting_traces, t, try_pulling_lca_down=True, pool=pool + ) + else: + pt, frozen_subtrees = add_trace_to_pt_language_with_freezing( + pt, + frozen_subtrees, + fitting_traces, + t, + try_pulling_lca_down=True, + pool=pool, + ) + fitting_traces.append(t) + res = process_tree_to_dict(pt, frozen_subtrees) + return res diff --git a/src/backend/endpoints/alignments.py b/src/backend/endpoints/alignments.py new file mode 100644 index 0000000000000000000000000000000000000000..523b613ff5927c0a57777ed33528e0e8b605d842 --- /dev/null +++ b/src/backend/endpoints/alignments.py @@ -0,0 +1,60 @@ +from typing import List +from enum import Enum + +from pm4py.objects.log.obj import Trace, Event +from pm4py.objects.petri_net.utils.align_utils import STD_MODEL_LOG_MOVE_COST +from pm4py.objects.process_tree.obj import ProcessTree +from pm4py.algo.conformance.alignments.process_tree.variants import ( + search_graph_pt as tree_alignment, +) +from cortado_core.alignments.infix_alignments import algorithm as infix_alignments +from cortado_core.alignments.prefix_alignments import algorithm as prefix_alignments +from cortado_core.alignments.suffix_alignments import algorithm as suffix_alignments + + +class InfixType(Enum): + PROPER_INFIX = 1 + PREFIX = 2 + POSTFIX = 3 + NOT_AN_INFIX = 4 + + +# @lru_cache(maxsize=None) + + +def calculate_alignment(variant, pt: ProcessTree, infix_type: InfixType): + # this function uses the specific tree alignment calculation + trace = Trace() + for a in variant: + e = Event() + e["concept:name"] = a + trace.append(e) + + if infix_type == InfixType.PROPER_INFIX: + align = infix_alignments.calculate_optimal_infix_alignment( + trace, + pt, + infix_alignments.VARIANT_TREE_BASED_PREPROCESSING, + naive=False, + use_dijkstra=True, + ) + elif infix_type == InfixType.PREFIX: + align = prefix_alignments.calculate_optimal_prefix_alignment( + trace, pt, use_dijkstra=True + ) + elif infix_type == InfixType.POSTFIX: + align = suffix_alignments.calculate_optimal_suffix_alignment( + trace, pt, naive=False, use_dijkstra=True + ) + else: + align = tree_alignment.apply_from_variants_list([tuple(variant)], pt) + align = align[0] + align["deviation"] = align["cost"] > 0 + + if infix_type != InfixType.NOT_AN_INFIX: + align["deviation"] = align["cost"] >= STD_MODEL_LOG_MOVE_COST + + # remove non essential information + res = {k: align[k] for k in ["alignment", "cost", "deviation"]} + + return res diff --git a/src/backend/endpoints/load_event_log.py b/src/backend/endpoints/load_event_log.py new file mode 100644 index 0000000000000000000000000000000000000000..43030a21bdeb7537e00544f040128efc761a09a2 --- /dev/null +++ b/src/backend/endpoints/load_event_log.py @@ -0,0 +1,170 @@ +from collections import Counter +from typing import Mapping, Tuple, Callable + +import cache.cache as cache +from cortado_core.models.infix_type import InfixType +from cortado_core.utils.cvariants import get_concurrency_variants, get_detailed_variants +from cortado_core.utils.split_graph import Group +from cortado_core.utils.timestamp_utils import TimeUnit +from api.routes.variants.models import VariantInformation +from pm4py.objects.log.obj import EventLog, Trace +from pm4py.objects.log.util.interval_lifecycle import to_interval +from pm4py.util.xes_constants import DEFAULT_START_TIMESTAMP_KEY, DEFAULT_TRANSITION_KEY +from backend_utilities.multiprocessing.pool_factory import PoolFactory + + +def calculate_event_log_properties( + event_log: EventLog, time_granularity: TimeUnit = None, use_mp: bool = False +): + if time_granularity is None: + time_granularity = min(TimeUnit) + + cache.parameters["cur_time_granularity"] = time_granularity + + cache.parameters["log_info"] = { + "extensions": event_log._get_extensions(), + # 'omni_present' : event_log._get_omni(), + # 'attributes' : event_log._get_attributes(), + "classifiers": event_log._get_classifiers(), + "properties": event_log._get_properties(), + } + + cache.parameters["lifecycle_available"] = False + + # TODO: maybe implement more robust check if lifecycle/interval information is available + if ( + DEFAULT_TRANSITION_KEY not in event_log[0][0] + and DEFAULT_START_TIMESTAMP_KEY not in event_log[0][0] + ): + event_log = to_interval(event_log) + else: + cache.parameters["lifecycle_available"] = True + + res_variants, cache.variants = get_c_variants(event_log, use_mp, time_granularity) + + start_activities, end_activities, nActivities = compute_log_stats(cache.variants) + + cache.parameters["activites"] = set(nActivities.keys()) + + res = { + "startActivities": start_activities, + "endActivities": end_activities, + "activities": nActivities, + "variants": res_variants, + "performanceInfoAvailable": cache.parameters["lifecycle_available"], + "timeGranularity": time_granularity, + } + + cache.parameters["nBids"] = len(cache.variants.keys()) + + # pickle.dump(cache.variants, open( "./resources/variants.p", "wb" )) + # pickle.dump(cache.parameters, open( "./resources/parameters.p", "wb" )) + + return res + + +def compute_log_stats(variants: Mapping[int, Tuple[Group, Trace]]): + start_activities = set() + end_activities = set() + activites = [] + + for v, _, _, _ in variants.values(): + for g, ts in v.graphs.items(): + start_activities.update(g.start_activities.keys()) + end_activities.update(g.end_activities.keys()) + + for k, ls in g.events.items(): + activites.append(Counter({k: (len(ls) * ts)})) + + nActivities = sum(activites, Counter()) + return start_activities, end_activities, nActivities + + +def get_c_variants( + event_log: EventLog, + use_mp: bool = False, + time_granularity: TimeUnit = min(TimeUnit), +): + variants: dict[Group, list[Trace]] = get_concurrency_variants( + event_log, use_mp, time_granularity, PoolFactory.instance().get_pool() + ) + + total_traces: int = len(event_log) + info_generator: Callable[[list[Trace]], VariantInformation] = ( + lambda _: VariantInformation( + infix_type=InfixType.NOT_AN_INFIX, is_user_defined=False + ) + ) + + return variants_to_variant_objects( + variants, time_granularity, total_traces, info_generator + ) + + +def variants_to_variant_objects( + variants: dict[Group, list[Trace]], + time_granularity: TimeUnit, + total_traces: int, + info_generator: Callable[[list[Trace]], VariantInformation], +): + res_variants = [] + + cache_variants = dict() + + for bid, (v, ts) in enumerate( + sorted(list(variants.items()), key=lambda e: len(e[1]), reverse=True) + ): + info: VariantInformation = info_generator(ts) + v.infix_type = info.infix_type + + v.assign_dfs_ids() + + variant, sub_vars = create_variant_object( + time_granularity, total_traces, bid, v, ts, info + ) + + res_variants.append(variant) + cache_variants[bid] = (v, ts, sub_vars, info) + + return ( + sorted(res_variants, key=lambda variant: variant["count"], reverse=True), + cache_variants, + ) + + +def create_variant_object( + time_granularity: TimeUnit, + total_traces: int, + bid: int, + v: Group, + ts: list[Trace], + info: VariantInformation, +): + sub_variants = create_subvariants(ts, time_granularity) + # v.assign_dfs_ids() + + # Default value of clusterId in a variant = -1 + variant = { + "count": len(ts), + "variant": v.serialize(), + "bid": bid, + "length": len(v), + "number_of_activities": v.number_of_activities(), + "percentage": round(len(ts) / total_traces * 100, 2), + "nSubVariants": len(sub_variants.keys()), + "userDefined": info.is_user_defined, + "infixType": info.infix_type.value, + "clusterId": -1, + } + + # If the variant is only a single activity leaf, wrap it up as a sequence + if "leaf" in variant["variant"].keys() or "parallel" in variant["variant"].keys(): + variant["variant"] = {"follows": [variant["variant"]]} + + return variant, sub_variants + + +def create_subvariants(ts: list[Trace], time_granularity: TimeUnit): + sub_vars = get_detailed_variants(ts, time_granularity=time_granularity) + + return sub_vars diff --git a/src/backend/endpoints/query_variant.py b/src/backend/endpoints/query_variant.py new file mode 100644 index 0000000000000000000000000000000000000000..adc3b6d1981faa877ea5911515f6724a9ff7aba2 --- /dev/null +++ b/src/backend/endpoints/query_variant.py @@ -0,0 +1,30 @@ +from cortado_core.variant_query_language.check_query_tree_against_graph import ( + check_query_tree, +) +from cortado_core.variant_query_language.error_handling import LexerError, ParseError +from cortado_core.variant_query_language.parse_query import parse_query_to_query_tree + + +def evaluate_query_against_variant_graphs(query, variants, activities): + ids = [] + + try: + qt = parse_query_to_query_tree(query.queryString) + + for bid, (variant, _, _, info) in variants.items(): + for g in variant.graphs.keys(): + b = check_query_tree(qt, g, activities, True) + + if b: + ids.append(bid) + break + + except ParseError as PE: + res = {"error": PE.msg, "error_index": PE.column} + return res + + except LexerError as LE: + res = {"error": LE.msg, "error_index": LE.column} + return res + + return {"ids": ids} diff --git a/src/backend/endpoints/transform_event_log.py b/src/backend/endpoints/transform_event_log.py new file mode 100644 index 0000000000000000000000000000000000000000..b86ed7f7290d48ec9376cebaddc2a9cf35af82df --- /dev/null +++ b/src/backend/endpoints/transform_event_log.py @@ -0,0 +1,732 @@ +import os.path +import pickle +import random +import string +from collections import Counter, defaultdict +from typing import List, Mapping, Set, Tuple + +import cache.cache as cache +from cortado_core.utils.cgroups_graph import cgroups_graph +from cortado_core.utils.cvariants import ( + get_concurrency_variants, + get_detailed_variants, + SubvariantNode, +) +from cortado_core.utils.split_graph import ( + ConcurrencyGroup, + LeafGroup, + ParallelGroup, + SequenceGroup, +) +from pm4py.objects.log.obj import EventLog, Trace +from pm4py.util.xes_constants import DEFAULT_NAME_KEY +from cortado_core.utils.cvariants import ACTIVITY_INSTANCE_KEY + +from endpoints.load_event_log import compute_log_stats, create_variant_object + + +def cache_current_data(): + if not os.path.isdir("./tmp"): + os.mkdir("./tmp") + + pickle.dump(cache.parameters, open("tmp/parameters_cache.p", "wb")) + pickle.dump(cache.variants, open("tmp/variants_cache.p", "wb")) + + +def reset_last_transaction(): + cache.variants = pickle.load(open("tmp/variants_cache.p", "rb")) + cache.parameters = pickle.load(open("tmp/parameters_cache.p", "rb")) + + total_traces = sum([len(ts) for (_, ts, _, _) in cache.variants.values()]) + res_variants = [] + + for bid, (v, ts, sv, info) in cache.variants.items(): + # Default value of clusterId in a variant = -1 + variant = { + "count": len(ts), + "variant": v.serialize(), + "bid": bid, + "length": len(v), + "number_of_activities": v.number_of_activities(), + "percentage": round(len(ts) / total_traces * 100, 2), + "nSubVariants": len(sv), + "userDefined": info.is_user_defined, + "infixType": info.infix_type.value, + "clusterId": -1, + } + + # If the variant is only a single activity leaf, wrap it up as a sequence + if ( + "leaf" in variant["variant"].keys() + or "parallel" in variant["variant"].keys() + ): + variant["variant"] = {"follows": [variant["variant"]]} + + res_variants.append(variant) + + res_variants = sorted( + res_variants, key=lambda variant: variant["count"], reverse=True + ) + + start_activities, end_activities, nActivities = compute_log_stats(cache.variants) + + cache.parameters["activites"] = set(nActivities.keys()) + res = { + "startActivities": start_activities, + "endActivities": end_activities, + "activities": nActivities, + "variants": res_variants, + "performanceInfoAvailable": cache.parameters["lifecycle_available"], + "timeGranularity": cache.parameters["cur_time_granularity"], + } + + print(res) + + return res + + +def rename_merge_activities_in_graph( + graph: ConcurrencyGroup, oldActivityName, newActivityName +): + graph.events[newActivityName] = graph.events.pop(oldActivityName, set()).union( + graph.events.get(oldActivityName, set()) + ) + graph.start_activities[newActivityName] = graph.start_activities.pop( + oldActivityName, set() + ).union(graph.start_activities.get(oldActivityName, set())) + graph.end_activities[newActivityName] = graph.end_activities.pop( + newActivityName, set() + ).union(graph.end_activities.get(oldActivityName, set())) + + new_df = {} + + for x, y in graph.directly_follows: + if x != oldActivityName and y != oldActivityName: + new_df[(x, y)] = new_df.get((x, y), set()).union( + graph.directly_follows.get((x, y)) + ) + + else: + if x == oldActivityName and y == oldActivityName: + new_df[(newActivityName, newActivityName)] = graph.directly_follows.get( + (x, y) + ).union( + graph.directly_follows.get( + (newActivityName, newActivityName), set() + ) + ) + + elif x == oldActivityName: + new_df[(newActivityName, y)] = graph.directly_follows.get((x, y)).union( + graph.directly_follows.get((newActivityName, y), set()) + ) + + elif y == oldActivityName: + new_df[(x, newActivityName)] = graph.directly_follows.get((x, y)).union( + graph.directly_follows.get((x, newActivityName), set()) + ) + + graph.directly_follows = new_df + + new_ef = {} + + for x, y in graph.follows: + if x != oldActivityName and y != oldActivityName: + new_ef[(x, y)] = new_ef.get((x, y), set()).union(graph.follows.get((x, y))) + + else: + if x == oldActivityName and y == oldActivityName: + new_ef[(newActivityName, newActivityName)] = graph.follows.get( + (x, y) + ).union(graph.follows.get((newActivityName, newActivityName), set())) + + elif x == oldActivityName: + new_ef[(newActivityName, y)] = graph.follows.get((x, y)).union( + graph.follows.get((newActivityName, y), set()) + ) + + elif y == oldActivityName: + new_ef[(x, newActivityName)] = graph.follows.get((x, y)).union( + graph.follows.get((x, newActivityName), set()) + ) + + graph.follows = new_ef + + new_cc = {} + + for x, y in graph.concurrency_pairs: + if x != oldActivityName and y != oldActivityName: + new_cc[(x, y)] = new_cc.get((x, y), set()).union( + graph.concurrency_pairs.get((x, y)) + ) + + else: + if x == oldActivityName and y == oldActivityName: + pair = (newActivityName, newActivityName) + + new_cc[pair] = graph.concurrency_pairs.get((x, y)).union( + graph.concurrency_pairs.get(pair, set()) + ) + + elif x == oldActivityName: + pair = tuple(sorted((newActivityName, y))) + + new_cc[pair] = graph.concurrency_pairs.get((x, y)).union( + graph.concurrency_pairs.get(pair, set()) + ) + + elif y == oldActivityName: + pair = tuple(sorted((x, newActivityName))) + + new_cc[pair] = graph.concurrency_pairs.get((x, y)).union( + graph.concurrency_pairs.get(pair, set()) + ) + + graph.concurrency_pairs = new_cc + + return graph + + +def rename_activities_in_trace( + trace, oldActivityName, newActivityName, instanceDict=None +): + if not instanceDict: + instanceDict = __get_instance_dict(trace, oldActivityName, newActivityName) + + for event in trace: + if event[DEFAULT_NAME_KEY] == newActivityName: + event[ACTIVITY_INSTANCE_KEY] = instanceDict[ + event[DEFAULT_NAME_KEY], event[ACTIVITY_INSTANCE_KEY] + ] + + if event[DEFAULT_NAME_KEY] == oldActivityName: + event[ACTIVITY_INSTANCE_KEY] = instanceDict[ + event[DEFAULT_NAME_KEY], event[ACTIVITY_INSTANCE_KEY] + ] + event[DEFAULT_NAME_KEY] = newActivityName + + return trace + + +def rename_activities_in_variant_group(group, oldActivityName, newActivityName): + if isinstance(group, LeafGroup): + lst = group[:] + if oldActivityName in group: + lst.remove(oldActivityName) + lst.append(newActivityName) + lst.sort() + + return LeafGroup(lst) + + else: + children = [ + rename_activities_in_variant_group(child, oldActivityName, newActivityName) + for child in group + ] + + if isinstance(group, ParallelGroup): + return ParallelGroup(sorted(children)) + + else: + return SequenceGroup(children) + + +def __get_instance_dict(trace, activityName, newActivityName): + instanceDict = {} + + # Compute the number of instances of both activites + nInstances = 0 + actInstance = 0 + newInstance = 0 + + for e in trace: + if e["concept:name"] == activityName: + instanceDict[(activityName, actInstance)] = nInstances + actInstance += 1 + nInstances += 1 + + if e["concept:name"] == newActivityName: + instanceDict[(newActivityName, newInstance)] = nInstances + newInstance += 1 + nInstances += 1 + + return instanceDict + + +def rename_activites_in_subvariant(subvariants, activityName, newActivityName): + new_subvariants = defaultdict(list) + + for sv, ts in subvariants.items(): + new_variant = [] + + instanceDict = __get_instance_dict(ts[0], activityName, newActivityName) + + for node in sv: + node: Tuple[SubvariantNode] + + for svNode in node: + if svNode.activity == newActivityName: + svNode.activity_instance = instanceDict[ + (svNode.activity, svNode.activity_instance) + ] + + if svNode.activity == activityName: + svNode.activity_instance = instanceDict[ + (svNode.activity, svNode.activity_instance) + ] + svNode.activity = newActivityName + + new_variant.append(node) + + new_subvariants[tuple(new_variant)] += [ + rename_activities_in_trace( + trace, activityName, newActivityName, instanceDict + ) + for trace in ts + ] + + return new_subvariants + + +def rename_activities(mergeList, renameList, activityName, newActivityName): + if cache.parameters["activites"].discard(activityName): + cache.parameters["activites"].add(newActivityName) + + new_variant_dict = {} + update_res_variants = {} + + new_variant_dict, update_res_variants = handle_rename_single_variant( + renameList, activityName, newActivityName, new_variant_dict, update_res_variants + ) + + new_variant_dict, update_res_variants = handle_rename_merge_variants( + mergeList, activityName, newActivityName, new_variant_dict, update_res_variants + ) + + flat_list = lambda lss: [x for ls in lss for x in ls] + + no_update = set(cache.variants.keys()).difference( + set(flat_list(mergeList) + renameList) + ) + + for bid in no_update: + new_variant_dict[bid] = cache.variants[bid] + + cache.variants = new_variant_dict + + activities: Set = cache.parameters["activites"] + activities.discard(activityName) + activities.add(newActivityName) + + cache.parameters["activites"] = activities + + return update_res_variants + + +def handle_rename_merge_variants( + mergeList, activityName, newActivityName, new_variant_dict, update_res_variants +): + for ls in mergeList: + (variant, _, _, info) = cache.variants[ls[0]] + renamed_variant = rename_activities_in_variant_group( + variant, activityName, newActivityName + ) + + graphs = {} + + for graph, ts in variant.graphs.items(): + new_graph = rename_merge_activities_in_graph( + graph, activityName, newActivityName + ) + graphs[new_graph] = graphs.get(new_graph, 0) + ts + + renamed_variant.graphs = graphs + + renamed_subvariants = defaultdict(list) + renamed_traces = [] + are_all_user_defined = True + + for bid in ls: + (_, traces, sv, info) = cache.variants[bid] + + are_all_user_defined &= info.is_user_defined + + if info.is_user_defined: + new_sv = dict() + else: + new_sv = rename_activites_in_subvariant( + sv, activityName, newActivityName + ) + + renamed_traces += [ + rename_activities_in_trace(trace, activityName, newActivityName) + for trace in traces + ] + + for s, tr in new_sv.items(): + renamed_subvariants[s] += tr + + new_variant_dict[min(ls)] = ( + renamed_variant, + renamed_traces, + renamed_subvariants, + info, + ) + + update_res_variants[min(ls)] = {"nSubVariants": len(renamed_subvariants.keys())} + + return new_variant_dict, update_res_variants + + +def handle_rename_single_variant( + renameList, activityName, newActivityName, new_variant_dict, update_res_variants +): + for bid in renameList: + (variant, traces, subvariants, info) = cache.variants[bid] + + renamed_variant = rename_activities_in_variant_group( + variant, activityName, newActivityName + ) + + graphs = {} + + if not info.is_user_defined: + for graph, ts in variant.graphs.items(): + new_graph = rename_merge_activities_in_graph( + graph, activityName, newActivityName + ) + graphs[new_graph] = graphs.get(new_graph, 0) + ts + + renamed_variant.graphs = graphs + + if info.is_user_defined: + renamed_subvariants = dict() + else: + renamed_subvariants = rename_activites_in_subvariant( + subvariants, activityName, newActivityName + ) + + renamed_traces = [ + rename_activities_in_trace(trace, activityName, newActivityName) + for trace in traces + ] + + update_res_variants[bid] = {"nSubVariants": len(renamed_subvariants.keys())} + new_variant_dict[bid] = ( + renamed_variant, + renamed_traces, + renamed_subvariants, + info, + ) + + return new_variant_dict, update_res_variants + + +def remove_activity_from_trace(trace, activityName): + for event in trace: + if event[DEFAULT_NAME_KEY] == activityName: + del event + + return trace + + +def random_activity(curr_name: str, length=4): + letters = string.ascii_lowercase + # joining with the current name to retain the order of acts + return curr_name + "".join(random.choice(letters) for _ in range(length)) + + +def remove_activitiy_from_group( + group, activity_names: list[str] | str, replace_with_random=False +): + if isinstance(group, LeafGroup): + if isinstance(activity_names, str): + activity_names = [activity_names] + + if replace_with_random: + group_minus = [ + random_activity(act) if act in activity_names else act for act in group + ] + else: + group_minus = [act for act in group if act not in activity_names] + + if len(group_minus) == 0: + return None + + return LeafGroup(group_minus) + + else: + children = [ + remove_activitiy_from_group(child, activity_names, replace_with_random) + for child in group + ] + children = [child for child in children if child] + + tmp = [] + + for child in children: + if type(child) == type(group): + for cchild in child: + tmp.append(cchild) + + else: + tmp.append(child) + + children = tmp + + if len(children) > 1: + if isinstance(group, ParallelGroup): + return ParallelGroup( + children if replace_with_random else sorted(children) + ) # to retain the order of acts + + else: + return SequenceGroup(children) + + elif len(children) == 1: + return children[0] + + else: + return None + + +def create_new_graph(trace): + c = Counter() + activity_map = {} + unique_trace = trace.__deepcopy__() + + for event in unique_trace: + activity = event[DEFAULT_NAME_KEY] + new_name = activity + str(c[activity]) + event[DEFAULT_NAME_KEY] = new_name + activity_map[new_name] = activity + c[activity] += 1 + + graph = cgroups_graph(unique_trace, cache.parameters["cur_time_granularity"]) + id_name_map = {name: id for id, name in enumerate(activity_map.keys())} + graph.restore_names(activity_map, id_name_map) + + return graph + + +def apply_filter_copy(trace, activityName): + new_attributes = {} + for k, v in trace.attributes.items(): + new_attributes[k] = v + + ctrace = Trace(attributes=new_attributes) + for ev in trace._list: + if ev[DEFAULT_NAME_KEY] != activityName: + ctrace.append(ev) + + return ctrace + + +def remove_activitiy_from_subvariant(subvariants, activityName): + new_subvariants = defaultdict(list) + for sv, ts in subvariants.items(): + new_variant = [] + + for node in sv: + node: Tuple[SubvariantNode] + + tup = [svNode for svNode in node if not svNode.activity == activityName] + + if len(tup) > 0: + new_variant.append(tuple(tup)) + + ts = [apply_filter_copy(trace, activityName) for trace in ts] + new_subvariants[tuple(new_variant)] += ts + + return new_subvariants + + +def remove_activities( + activityName, fallthrough, delete_member_list, merge_list, delete_variant_list +): + new_variants: Mapping[int, Tuple[ConcurrencyGroup, List]] = {} + update_res_variants = {} + + new_variants, update_res_variants = handle_delete_member( + activityName, delete_member_list, new_variants, update_res_variants + ) + + new_variants, update_res_variants = handle_merge_members( + activityName, merge_list, new_variants, update_res_variants + ) + + flat_list = lambda lss: [x for ls in lss for x in ls] + + no_update = set(cache.variants.keys()).difference( + set( + flat_list(merge_list) + + fallthrough + + delete_member_list + + delete_variant_list + ) + ) + + for bid in no_update: + new_variants[bid] = cache.variants[bid] + + new_variants, new_res_variants, update_res_variants = handle_fallthrough( + activityName, fallthrough, new_variants, update_res_variants + ) + + for _, v in new_variants.items(): + v[0].assign_dfs_ids() + + start_activities, end_activities, _ = compute_log_stats(new_variants) + + res = { + "startActivities": list(start_activities), + "endActivities": list(end_activities), + "new_variants": new_res_variants, + "update_variants": update_res_variants, + } + + cache.variants = new_variants + + activities: Set = cache.parameters["activites"] + activities.discard(activityName) + + cache.parameters["activites"] = activities + + return res + + +def handle_merge_members(activityName, merge_list, new_variants, update_res_variants): + for ls in merge_list: + (variant, _, _, _) = cache.variants[ls[0]] + new_variant = remove_activitiy_from_group(variant, activityName) + + new_traces = [] + new_subvariants = defaultdict(list) + + for bid in ls: + (_, traces, sv, info) = cache.variants[bid] + new_traces += [apply_filter_copy(trace, activityName) for trace in traces] + new_sv = remove_activitiy_from_subvariant(sv, activityName) + + for s, tr in new_sv.items(): + new_subvariants[s] += tr + + graphs = {} + + for trace in new_traces: + g = create_new_graph(trace) + graphs[g] = graphs.get(g, 0) + 1 + + new_variant.graphs = graphs + + new_variants[min(ls)] = (new_variant, new_traces, new_subvariants, info) + update_res_variants[min(ls)] = { + "count": len(new_traces), + "nSubVariants": len(new_subvariants.keys()), + } + + return new_variants, update_res_variants + + +def handle_delete_member( + activityName, delete_member_list, new_variants, update_res_variants +): + for bid in delete_member_list: + variant, traces, subvariants, info = cache.variants[bid] + + new_variant = remove_activitiy_from_group(variant, activityName) + ts = [apply_filter_copy(trace, activityName) for trace in traces] + + graphs = {} + + for trace in ts: + g = create_new_graph(trace) + graphs[g] = graphs.get(g, 0) + 1 + + new_variant.graphs = graphs + + new_subvariant = remove_activitiy_from_subvariant(subvariants, activityName) + + new_variants[bid] = (new_variant, ts, new_subvariant, info) + + update_res_variants[bid] = { + "count": len(ts), + "nSubVariants": len(new_subvariant.keys()), + } + + return new_variants, update_res_variants + + +def handle_fallthrough(activityName, fallthrough, new_variants, update_res_variants): + mergeVariants = [] + newVariants = [] + + if len(fallthrough) > 0: + cLog = [] + for bid in fallthrough: + (_, traces, _, _) = cache.variants[bid] + cLog.extend([apply_filter_copy(trace, activityName) for trace in traces]) + + log = EventLog(cLog) + + c_variants = get_concurrency_variants( + log, False, cache.parameters["cur_time_granularity"] + ) + + for c_variant, c_traces in c_variants.items(): + foundMatch = False + for n_bid, (n_variant, n_traces, _, n_info) in new_variants.items(): + if str(n_variant) == str(c_variant): + mergeVariants.append((n_bid, c_variant, n_traces + c_traces)) + foundMatch = True + break + + if foundMatch: + new_variants[n_bid] = (n_variant, n_traces + c_traces, None, n_info) + + else: + newVariants.append((cache.parameters["nBids"] + 1, c_variant, c_traces)) + cache.parameters["nBids"] = cache.parameters["nBids"] + 1 + + new_res_variants = [] + + for bid, v, ts, info in newVariants: + variant, subvar = create_variant_object( + cache.parameters["cur_time_granularity"], 1, bid, v, ts, info + ) + + new_variants[bid] = (v, ts, subvar, info) + new_res_variants.append(variant) + + for bid, v, ts, info in mergeVariants: + subvars = get_detailed_variants( + ts, time_granularity=cache.parameters["cur_time_granularity"] + ) + + new_variants[bid] = (v, ts, subvars, info) + update_res_variants[bid] = { + "count": len(ts), + "nSubVariants": len(subvars.keys()), + } + + return new_variants, new_res_variants, update_res_variants + + +def remove_variant(bids): + cache.variants = { + bid: (v, t, sv, info) + for bid, (v, t, sv, info) in cache.variants.items() + if bid not in bids + } + + start_activities, end_activities, nActivities = compute_log_stats(cache.variants) + + res = { + "startActivities": list(start_activities), + "endActivities": list(end_activities), + "activities": nActivities, + } + + cache.parameters["activites"] = set(nActivities.keys()) + + return res diff --git a/src/backend/error_handlers.py b/src/backend/error_handlers.py new file mode 100644 index 0000000000000000000000000000000000000000..76f86dc84d95e849349d2b2e4abb3e0feebb4bee --- /dev/null +++ b/src/backend/error_handlers.py @@ -0,0 +1,16 @@ +from fastapi import HTTPException, Request +from fastapi.exceptions import RequestValidationError + +from backend_utilities.util import build_json_error_rsp, get_trace + + +async def http_exception_handler(request: Request, exc: HTTPException): + return build_json_error_rsp(exc.detail, get_trace(exc), exc.status_code) + + +async def exception_handler(request: Request, exc: Exception): + return build_json_error_rsp(str(exc), get_trace(exc), 500) + + +async def validation_exception_handler(request, exc: RequestValidationError): + return build_json_error_rsp(exc.errors(), get_trace(exc), status_code=422) diff --git a/src/backend/icon/cortado_icon_colorful_transparent.ico b/src/backend/icon/cortado_icon_colorful_transparent.ico new file mode 100644 index 0000000000000000000000000000000000000000..d7e1e65f114f5070174966c3e3d8c31410fc32ef Binary files /dev/null and b/src/backend/icon/cortado_icon_colorful_transparent.ico differ diff --git a/src/backend/icon/cortado_icon_colorful_transparent.png b/src/backend/icon/cortado_icon_colorful_transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..4f5db230f74133cc57c8f52d53591b06149399b8 Binary files /dev/null and b/src/backend/icon/cortado_icon_colorful_transparent.png differ diff --git a/src/backend/log.xes b/src/backend/log.xes new file mode 100644 index 0000000000000000000000000000000000000000..7d0edae8f73f5a609fe11c59f15df9579e7f9160 --- /dev/null +++ b/src/backend/log.xes @@ -0,0 +1,31337 @@ +<?xml version="1.0" encoding="utf-8" ?> +<log> + <string key="origin" value="csv" /> + <trace> + <string key="concept:name" value="0" /> + <event> + <int key="case" value="0" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2000-03-19 16:06:48" /> + </event> + <event> + <int key="case" value="0" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-03-19 16:06:48" /> + </event> + </trace> + <trace> + <string key="concept:name" value="1" /> + <event> + <int key="case" value="1" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-04-08 09:08:30" /> + </event> + <event> + <int key="case" value="1" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2000-04-14 22:29:04" /> + </event> + <event> + <int key="case" value="1" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2000-04-14 22:29:04" /> + </event> + <event> + <int key="case" value="1" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-04-14 22:29:04" /> + </event> + <event> + <int key="case" value="1" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2000-04-14 22:29:04" /> + </event> + <event> + <int key="case" value="1" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-04-14 22:29:04" /> + </event> + <event> + <int key="case" value="1" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-04-14 22:29:04" /> + </event> + <event> + <int key="case" value="1" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-04-21 11:49:38" /> + </event> + </trace> + <trace> + <string key="concept:name" value="2" /> + <event> + <int key="case" value="2" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2000-05-11 03:51:20" /> + </event> + <event> + <int key="case" value="2" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-05-11 03:51:20" /> + </event> + </trace> + <trace> + <string key="concept:name" value="3" /> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2000-05-30 19:53:02" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-05-30 19:53:02" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-06-06 09:13:36" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2000-06-12 22:34:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2000-06-12 22:34:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-06-12 22:34:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2000-06-12 22:34:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-06-12 22:34:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-06-12 22:34:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2000-06-12 22:34:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-06-12 22:34:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2000-06-12 22:34:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2000-06-12 22:34:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2000-06-19 11:54:44" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-06-19 11:54:44" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-06-19 11:54:44" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2000-06-19 11:54:44" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2000-06-26 01:15:18" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2000-06-26 01:15:18" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-06-26 01:15:18" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2000-06-26 01:15:18" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2000-07-02 14:35:52" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2000-07-02 14:35:52" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-07-02 14:35:52" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-07-02 14:35:52" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2000-07-02 14:35:52" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2000-07-09 03:56:26" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-07-09 03:56:26" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2000-07-15 17:17:00" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-07-15 17:17:00" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-07-15 17:17:00" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2000-07-15 17:17:00" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2000-07-22 06:37:34" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2000-07-22 06:37:34" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-07-22 06:37:34" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2000-07-28 19:58:08" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2000-07-28 19:58:08" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-07-28 19:58:08" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-07-28 19:58:08" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2000-07-28 19:58:08" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2000-08-04 09:18:42" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-08-04 09:18:42" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2000-08-10 22:39:16" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-08-10 22:39:16" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2000-08-10 22:39:16" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2000-08-17 11:59:50" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2000-08-17 11:59:50" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2000-08-17 11:59:50" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2000-08-17 11:59:50" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-08-17 11:59:50" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-08-17 11:59:50" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2000-08-24 01:20:24" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2000-08-24 01:20:24" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-08-24 01:20:24" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2000-08-24 01:20:24" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-08-24 01:20:24" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2000-08-30 14:40:58" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-08-30 14:40:58" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-08-30 14:40:58" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2000-09-06 04:01:32" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2000-09-06 04:01:32" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-09-06 04:01:32" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2000-09-12 17:22:06" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2000-09-12 17:22:06" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-09-12 17:22:06" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2000-09-12 17:22:06" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-09-12 17:22:06" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2000-09-19 06:42:40" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2000-09-19 06:42:40" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2000-09-19 06:42:40" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2000-09-19 06:42:40" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2000-09-19 06:42:40" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-09-19 06:42:40" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-09-19 06:42:40" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-09-19 06:42:40" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2000-09-19 06:42:40" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-09-19 06:42:40" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-09-19 06:42:40" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2000-09-19 06:42:40" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2000-09-25 20:03:14" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2000-09-25 20:03:14" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2000-09-25 20:03:14" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-09-25 20:03:14" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-09-25 20:03:14" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2000-09-25 20:03:14" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-09-25 20:03:14" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-09-25 20:03:14" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-09-25 20:03:14" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2000-10-02 09:23:48" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-10-02 09:23:48" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-10-02 09:23:48" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2000-10-08 22:44:22" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-10-08 22:44:22" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-10-08 22:44:22" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-10-08 22:44:22" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2000-10-08 22:44:22" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2000-10-15 12:04:56" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-10-15 12:04:56" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2000-10-15 12:04:56" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-10-15 12:04:56" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-10-15 12:04:56" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-10-22 01:25:30" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2000-10-28 14:46:04" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2000-10-28 14:46:04" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-10-28 14:46:04" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-10-28 14:46:04" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-10-28 14:46:04" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2000-11-04 03:06:38" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-11-04 03:06:38" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-11-04 03:06:38" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2000-11-04 03:06:38" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2000-11-04 03:06:38" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2000-11-04 03:06:38" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2000-11-10 16:27:12" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2000-11-10 16:27:12" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-11-10 16:27:12" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2000-11-10 16:27:12" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-11-10 16:27:12" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2000-11-10 16:27:12" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2000-11-10 16:27:12" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2000-11-17 05:47:46" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2000-11-17 05:47:46" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2000-11-17 05:47:46" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2000-11-17 05:47:46" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-11-17 05:47:46" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-11-17 05:47:46" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2000-11-17 05:47:46" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-11-17 05:47:46" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-11-17 05:47:46" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2000-11-17 05:47:46" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2000-11-23 19:08:20" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2000-11-23 19:08:20" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2000-11-23 19:08:20" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-11-23 19:08:20" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2000-11-23 19:08:20" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-11-23 19:08:20" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2000-11-23 19:08:20" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2000-11-23 19:08:20" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-11-23 19:08:20" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2000-11-23 19:08:20" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2000-11-30 08:28:54" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2000-11-30 08:28:54" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2000-11-30 08:28:54" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-11-30 08:28:54" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2000-11-30 08:28:54" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-11-30 08:28:54" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2000-11-30 08:28:54" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2000-12-06 21:49:28" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-12-06 21:49:28" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-12-06 21:49:28" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2000-12-06 21:49:28" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2000-12-13 11:10:02" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2000-12-13 11:10:02" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-12-13 11:10:02" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-12-13 11:10:02" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2000-12-13 11:10:02" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2000-12-20 00:30:36" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2000-12-26 13:51:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-12-26 13:51:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2000-12-26 13:51:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2000-12-26 13:51:10" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-01-02 03:11:44" /> + </event> + <event> + <int key="case" value="3" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2001-01-08 16:32:18" /> + </event> + </trace> + <trace> + <string key="concept:name" value="4" /> + <event> + <int key="case" value="4" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2001-01-15 05:52:52" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-01-15 05:52:52" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2001-01-21 19:13:26" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2001-01-21 19:13:26" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-01-21 19:13:26" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2001-01-21 19:13:26" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2001-01-28 08:34:00" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2001-01-28 08:34:00" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-01-28 08:34:00" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-01-28 08:34:00" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-02-03 21:54:34" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2001-02-03 21:54:34" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2001-02-10 11:15:08" /> + </event> + <event> + <int key="case" value="4" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-02-10 11:15:08" /> + </event> + </trace> + <trace> + <string key="concept:name" value="5" /> + <event> + <int key="case" value="5" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-03-08 16:37:24" /> + </event> + <event> + <int key="case" value="5" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2001-03-15 05:57:58" /> + </event> + <event> + <int key="case" value="5" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2001-03-15 05:57:58" /> + </event> + <event> + <int key="case" value="5" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2001-03-21 19:18:32" /> + </event> + </trace> + <trace> + <string key="concept:name" value="6" /> + <event> + <int key="case" value="6" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-03-28 09:39:06" /> + </event> + <event> + <int key="case" value="6" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-04-03 22:59:40" /> + </event> + </trace> + <trace> + <string key="concept:name" value="7" /> + <event> + <int key="case" value="7" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-05-13 07:03:04" /> + </event> + </trace> + <trace> + <string key="concept:name" value="8" /> + <event> + <int key="case" value="8" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-06-21 15:06:28" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2001-06-28 04:27:02" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2001-06-28 04:27:02" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2001-06-28 04:27:02" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2001-07-04 17:47:36" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-07-04 17:47:36" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-07-04 17:47:36" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2001-07-04 17:47:36" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2001-07-11 07:08:10" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-07-11 07:08:10" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-07-11 07:08:10" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2001-07-17 20:28:44" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2001-07-17 20:28:44" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2001-07-17 20:28:44" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-07-17 20:28:44" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2001-07-17 20:28:44" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2001-07-17 20:28:44" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2001-07-17 20:28:44" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2001-07-17 20:28:44" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2001-07-24 09:49:18" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2001-07-24 09:49:18" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-07-24 09:49:18" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2001-07-24 09:49:18" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2001-07-24 09:49:18" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2001-07-30 23:09:52" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2001-07-30 23:09:52" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-07-30 23:09:52" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2001-07-30 23:09:52" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2001-08-06 12:30:26" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2001-08-06 12:30:26" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-08-06 12:30:26" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2001-08-06 12:30:26" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2001-08-13 01:51:00" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-08-13 01:51:00" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2001-08-13 01:51:00" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2001-08-19 15:11:34" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-08-19 15:11:34" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2001-08-26 04:32:08" /> + </event> + <event> + <int key="case" value="8" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2001-08-26 04:32:08" /> + </event> + </trace> + <trace> + <string key="concept:name" value="9" /> + <event> + <int key="case" value="9" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2001-09-14 20:33:50" /> + </event> + <event> + <int key="case" value="9" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-09-14 20:33:50" /> + </event> + <event> + <int key="case" value="9" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-09-14 20:33:50" /> + </event> + <event> + <int key="case" value="9" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2001-09-21 09:54:24" /> + </event> + <event> + <int key="case" value="9" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-09-21 09:54:24" /> + </event> + <event> + <int key="case" value="9" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-09-27 23:14:58" /> + </event> + <event> + <int key="case" value="9" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2001-09-27 23:14:58" /> + </event> + <event> + <int key="case" value="9" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-10-04 12:35:32" /> + </event> + </trace> + <trace> + <string key="concept:name" value="10" /> + <event> + <int key="case" value="10" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2001-10-17 15:16:40" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2001-10-17 15:16:40" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-10-17 15:16:40" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2001-10-17 15:16:40" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2001-10-17 15:16:40" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2001-10-24 04:37:14" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-10-30 16:57:48" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2001-11-06 06:18:22" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2001-11-06 06:18:22" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2001-11-06 06:18:22" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2001-11-06 06:18:22" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2001-11-06 06:18:22" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2001-11-06 06:18:22" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2001-11-12 19:38:56" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2001-11-12 19:38:56" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2001-11-12 19:38:56" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2001-11-12 19:38:56" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2001-11-12 19:38:56" /> + </event> + <event> + <int key="case" value="10" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2001-11-19 08:59:30" /> + </event> + </trace> + <trace> + <string key="concept:name" value="11" /> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2001-12-02 11:40:38" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2001-12-02 11:40:38" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2001-12-02 11:40:38" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2001-12-02 11:40:38" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2001-12-09 01:01:12" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2001-12-09 01:01:12" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2001-12-09 01:01:12" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2001-12-09 01:01:12" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2001-12-15 14:21:46" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2001-12-15 14:21:46" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2001-12-15 14:21:46" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2001-12-15 14:21:46" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2001-12-22 03:42:20" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2001-12-22 03:42:20" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2001-12-22 03:42:20" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2001-12-28 17:02:54" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2001-12-28 17:02:54" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2001-12-28 17:02:54" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2001-12-28 17:02:54" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2001-12-28 17:02:54" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2002-01-04 06:23:28" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2002-01-04 06:23:28" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2002-01-04 06:23:28" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2002-01-04 06:23:28" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-01-04 06:23:28" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-01-04 06:23:28" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-01-04 06:23:28" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2002-01-04 06:23:28" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-01-04 06:23:28" /> + </event> + <event> + <int key="case" value="11" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-01-10 19:44:02" /> + </event> + </trace> + <trace> + <string key="concept:name" value="12" /> + <event> + <int key="case" value="12" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2002-01-17 09:04:36" /> + </event> + </trace> + <trace> + <string key="concept:name" value="13" /> + <event> + <int key="case" value="13" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2002-01-23 22:25:10" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2002-01-30 11:45:44" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2002-01-30 11:45:44" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2002-01-30 11:45:44" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-01-30 11:45:44" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-01-30 11:45:44" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-01-30 11:45:44" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-01-30 11:45:44" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2002-01-30 11:45:44" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-01-30 11:45:44" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2002-01-30 11:45:44" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-01-30 11:45:44" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2002-02-06 01:06:18" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2002-02-06 01:06:18" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2002-02-06 01:06:18" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-02-06 01:06:18" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-02-06 01:06:18" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-02-06 01:06:18" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2002-02-06 01:06:18" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-02-06 01:06:18" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2002-02-12 14:26:52" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-02-12 14:26:52" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-02-12 14:26:52" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2002-02-12 14:26:52" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2002-02-19 03:47:26" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-02-19 03:47:26" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2002-02-19 03:47:26" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2002-02-25 17:08:00" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-02-25 17:08:00" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2002-03-04 06:28:34" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2002-03-04 06:28:34" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-03-04 06:28:34" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-03-04 06:28:34" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / enter" /> + <string key="timestamp" value="2002-03-04 06:28:34" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-03-04 06:28:34" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2002-03-10 19:49:08" /> + </event> + <event> + <int key="case" value="13" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2002-03-17 09:09:42" /> + </event> + </trace> + <trace> + <string key="concept:name" value="14" /> + <event> + <int key="case" value="14" /> + <string key="activity" value="Send for Credit Collection / High / exec" /> + <string key="timestamp" value="2002-04-06 02:11:24" /> + </event> + </trace> + <trace> + <string key="concept:name" value="15" /> + <event> + <int key="case" value="15" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-04-19 04:52:32" /> + </event> + <event> + <int key="case" value="15" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2002-04-25 18:13:06" /> + </event> + <event> + <int key="case" value="15" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2002-04-25 18:13:06" /> + </event> + <event> + <int key="case" value="15" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2002-04-25 18:13:06" /> + </event> + <event> + <int key="case" value="15" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2002-04-25 18:13:06" /> + </event> + <event> + <int key="case" value="15" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2002-05-02 07:33:40" /> + </event> + <event> + <int key="case" value="15" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-05-02 07:33:40" /> + </event> + <event> + <int key="case" value="15" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-05-02 07:33:40" /> + </event> + <event> + <int key="case" value="15" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2002-05-08 20:54:14" /> + </event> + <event> + <int key="case" value="15" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-05-15 10:14:48" /> + </event> + </trace> + <trace> + <string key="concept:name" value="16" /> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2002-06-04 02:16:30" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-06-04 02:16:30" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-06-04 02:16:30" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2002-06-04 02:16:30" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2002-06-04 02:16:30" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2002-06-10 15:37:04" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-06-10 15:37:04" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-06-17 04:57:38" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-06-17 04:57:38" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-06-23 18:18:12" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-06-23 18:18:12" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-06-23 18:18:12" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2002-06-30 07:38:46" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2002-06-30 07:38:46" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-06-30 07:38:46" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-06-30 07:38:46" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2002-06-30 07:38:46" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2002-06-30 07:38:46" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2002-07-06 20:59:20" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-07-06 20:59:20" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-07-06 20:59:20" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-07-13 10:19:54" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2002-07-19 23:40:28" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-07-19 23:40:28" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-07-19 23:40:28" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-07-19 23:40:28" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2002-07-26 13:01:02" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2002-07-26 13:01:02" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-07-26 13:01:02" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-07-26 13:01:02" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-07-26 13:01:02" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2002-07-26 13:01:02" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2002-07-26 13:01:02" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2002-08-02 02:21:36" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-08-02 02:21:36" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-08-02 02:21:36" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-08-02 02:21:36" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2002-08-02 02:21:36" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2002-08-08 15:42:10" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-08-08 15:42:10" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-08-08 15:42:10" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-08-08 15:42:10" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-08-08 15:42:10" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2002-08-15 05:02:44" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2002-08-15 05:02:44" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2002-08-15 05:02:44" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-08-15 05:02:44" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-08-15 05:02:44" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-08-15 05:02:44" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2002-08-21 18:23:18" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-08-21 18:23:18" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2002-08-21 18:23:18" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-08-28 07:43:52" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2002-09-03 21:04:26" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2002-09-03 21:04:26" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-09-03 21:04:26" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-09-03 21:04:26" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2002-09-03 21:04:26" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2002-09-03 21:04:26" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2002-09-03 21:04:26" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-09-10 10:25:00" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2002-09-16 23:45:34" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2002-09-16 23:45:34" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2002-09-16 23:45:34" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-09-16 23:45:34" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-09-16 23:45:34" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2002-09-16 23:45:34" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-09-16 23:45:34" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2002-09-23 13:06:08" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2002-09-23 13:06:08" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-09-23 13:06:08" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-09-23 13:06:08" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-09-30 02:26:42" /> + </event> + <event> + <int key="case" value="16" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-10-06 15:47:16" /> + </event> + </trace> + <trace> + <string key="concept:name" value="17" /> + <event> + <int key="case" value="17" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2002-10-13 05:07:50" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2002-10-13 05:07:50" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-10-13 05:07:50" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2002-10-13 05:07:50" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2002-10-19 18:28:24" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-10-19 18:28:24" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2002-10-19 18:28:24" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2002-10-19 18:28:24" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2002-10-26 07:48:58" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-10-26 07:48:58" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2002-11-01 20:09:32" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2002-11-01 20:09:32" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-11-01 20:09:32" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-11-01 20:09:32" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2002-11-01 20:09:32" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-11-01 20:09:32" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2002-11-08 09:30:06" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2002-11-08 09:30:06" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2002-11-08 09:30:06" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-11-08 09:30:06" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-11-08 09:30:06" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-11-08 09:30:06" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-11-08 09:30:06" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2002-11-08 09:30:06" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2002-11-08 09:30:06" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-11-08 09:30:06" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2002-11-14 22:50:40" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2002-11-14 22:50:40" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-11-14 22:50:40" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-11-14 22:50:40" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-11-14 22:50:40" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2002-11-14 22:50:40" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-11-21 12:11:14" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-11-21 12:11:14" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2002-11-28 01:31:48" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2002-11-28 01:31:48" /> + </event> + <event> + <int key="case" value="17" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2002-11-28 01:31:48" /> + </event> + </trace> + <trace> + <string key="concept:name" value="18" /> + <event> + <int key="case" value="18" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-12-04 14:52:22" /> + </event> + <event> + <int key="case" value="18" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2002-12-11 04:12:56" /> + </event> + <event> + <int key="case" value="18" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / enter" /> + <string key="timestamp" value="2002-12-11 04:12:56" /> + </event> + <event> + <int key="case" value="18" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2002-12-11 04:12:56" /> + </event> + </trace> + <trace> + <string key="concept:name" value="19" /> + <event> + <int key="case" value="19" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2002-12-24 06:54:04" /> + </event> + <event> + <int key="case" value="19" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-12-24 06:54:04" /> + </event> + <event> + <int key="case" value="19" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2002-12-24 06:54:04" /> + </event> + <event> + <int key="case" value="19" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2002-12-24 06:54:04" /> + </event> + <event> + <int key="case" value="19" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2002-12-30 20:14:38" /> + </event> + <event> + <int key="case" value="19" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2002-12-30 20:14:38" /> + </event> + <event> + <int key="case" value="19" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2002-12-30 20:14:38" /> + </event> + <event> + <int key="case" value="19" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2002-12-30 20:14:38" /> + </event> + <event> + <int key="case" value="19" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2003-01-06 09:35:12" /> + </event> + <event> + <int key="case" value="19" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2003-01-06 09:35:12" /> + </event> + </trace> + <trace> + <string key="concept:name" value="20" /> + <event> + <int key="case" value="20" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2003-01-12 22:55:46" /> + </event> + <event> + <int key="case" value="20" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2003-01-12 22:55:46" /> + </event> + <event> + <int key="case" value="20" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2003-01-19 12:16:20" /> + </event> + <event> + <int key="case" value="20" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-01-19 12:16:20" /> + </event> + <event> + <int key="case" value="20" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2003-01-26 01:36:54" /> + </event> + <event> + <int key="case" value="20" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2003-01-26 01:36:54" /> + </event> + </trace> + <trace> + <string key="concept:name" value="21" /> + <event> + <int key="case" value="21" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-02-01 14:57:28" /> + </event> + <event> + <int key="case" value="21" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2003-02-08 04:18:02" /> + </event> + <event> + <int key="case" value="21" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-02-08 04:18:02" /> + </event> + </trace> + <trace> + <string key="concept:name" value="22" /> + <event> + <int key="case" value="22" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2003-02-14 17:38:36" /> + </event> + <event> + <int key="case" value="22" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2003-02-14 17:38:36" /> + </event> + </trace> + <trace> + <string key="concept:name" value="23" /> + <event> + <int key="case" value="23" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2003-02-27 20:19:44" /> + </event> + <event> + <int key="case" value="23" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2003-02-27 20:19:44" /> + </event> + <event> + <int key="case" value="23" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2003-02-27 20:19:44" /> + </event> + <event> + <int key="case" value="23" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2003-02-27 20:19:44" /> + </event> + <event> + <int key="case" value="23" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2003-02-27 20:19:44" /> + </event> + <event> + <int key="case" value="23" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2003-03-06 09:40:18" /> + </event> + <event> + <int key="case" value="23" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2003-03-06 09:40:18" /> + </event> + <event> + <int key="case" value="23" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2003-03-06 09:40:18" /> + </event> + </trace> + <trace> + <string key="concept:name" value="24" /> + <event> + <int key="case" value="24" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-03-12 23:00:52" /> + </event> + <event> + <int key="case" value="24" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2003-03-19 12:21:26" /> + </event> + <event> + <int key="case" value="24" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2003-03-19 12:21:26" /> + </event> + <event> + <int key="case" value="24" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2003-03-19 12:21:26" /> + </event> + <event> + <int key="case" value="24" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2003-03-19 12:21:26" /> + </event> + <event> + <int key="case" value="24" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2003-03-19 12:21:26" /> + </event> + <event> + <int key="case" value="24" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2003-03-26 01:42:00" /> + </event> + <event> + <int key="case" value="24" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2003-03-26 01:42:00" /> + </event> + <event> + <int key="case" value="24" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / enter" /> + <string key="timestamp" value="2003-03-26 01:42:00" /> + </event> + <event> + <int key="case" value="24" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2003-03-26 01:42:00" /> + </event> + <event> + <int key="case" value="24" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2003-04-01 16:02:34" /> + </event> + </trace> + <trace> + <string key="concept:name" value="25" /> + <event> + <int key="case" value="25" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2003-04-14 18:43:42" /> + </event> + <event> + <int key="case" value="25" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2003-04-21 08:04:16" /> + </event> + <event> + <int key="case" value="25" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2003-04-21 08:04:16" /> + </event> + <event> + <int key="case" value="25" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / enter" /> + <string key="timestamp" value="2003-04-21 08:04:16" /> + </event> + <event> + <int key="case" value="25" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2003-04-21 08:04:16" /> + </event> + <event> + <int key="case" value="25" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2003-04-27 21:24:50" /> + </event> + <event> + <int key="case" value="25" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / enter" /> + <string key="timestamp" value="2003-04-27 21:24:50" /> + </event> + <event> + <int key="case" value="25" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2003-05-04 10:45:24" /> + </event> + <event> + <int key="case" value="25" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2003-05-04 10:45:24" /> + </event> + </trace> + <trace> + <string key="concept:name" value="26" /> + <event> + <int key="case" value="26" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2003-05-17 13:26:32" /> + </event> + <event> + <int key="case" value="26" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2003-05-17 13:26:32" /> + </event> + <event> + <int key="case" value="26" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2003-05-24 02:47:06" /> + </event> + <event> + <int key="case" value="26" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2003-05-24 02:47:06" /> + </event> + <event> + <int key="case" value="26" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-05-24 02:47:06" /> + </event> + <event> + <int key="case" value="26" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2003-05-24 02:47:06" /> + </event> + <event> + <int key="case" value="26" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2003-05-24 02:47:06" /> + </event> + <event> + <int key="case" value="26" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-05-24 02:47:06" /> + </event> + <event> + <int key="case" value="26" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-05-24 02:47:06" /> + </event> + <event> + <int key="case" value="26" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2003-05-30 16:07:40" /> + </event> + </trace> + <trace> + <string key="concept:name" value="27" /> + <event> + <int key="case" value="27" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2003-06-19 08:09:22" /> + </event> + <event> + <int key="case" value="27" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2003-06-19 08:09:22" /> + </event> + </trace> + <trace> + <string key="concept:name" value="28" /> + <event> + <int key="case" value="28" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2003-07-02 10:50:30" /> + </event> + </trace> + <trace> + <string key="concept:name" value="29" /> + <event> + <int key="case" value="29" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2003-07-22 02:52:12" /> + </event> + <event> + <int key="case" value="29" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2003-07-22 02:52:12" /> + </event> + <event> + <int key="case" value="29" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2003-07-22 02:52:12" /> + </event> + <event> + <int key="case" value="29" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2003-07-28 16:12:46" /> + </event> + <event> + <int key="case" value="29" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2003-08-04 05:33:20" /> + </event> + <event> + <int key="case" value="29" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2003-08-10 18:53:54" /> + </event> + <event> + <int key="case" value="29" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2003-08-10 18:53:54" /> + </event> + <event> + <int key="case" value="29" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2003-08-10 18:53:54" /> + </event> + <event> + <int key="case" value="29" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2003-08-17 08:14:28" /> + </event> + </trace> + <trace> + <string key="concept:name" value="30" /> + <event> + <int key="case" value="30" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2003-09-06 00:16:10" /> + </event> + </trace> + <trace> + <string key="concept:name" value="31" /> + <event> + <int key="case" value="31" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2003-09-12 13:36:44" /> + </event> + <event> + <int key="case" value="31" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2003-09-12 13:36:44" /> + </event> + <event> + <int key="case" value="31" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2003-09-19 02:57:18" /> + </event> + <event> + <int key="case" value="31" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-09-19 02:57:18" /> + </event> + <event> + <int key="case" value="31" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-09-19 02:57:18" /> + </event> + <event> + <int key="case" value="31" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2003-09-25 16:17:52" /> + </event> + <event> + <int key="case" value="31" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-09-25 16:17:52" /> + </event> + <event> + <int key="case" value="31" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2003-09-25 16:17:52" /> + </event> + <event> + <int key="case" value="31" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-09-25 16:17:52" /> + </event> + <event> + <int key="case" value="31" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-10-02 05:38:26" /> + </event> + <event> + <int key="case" value="31" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-10-08 18:59:00" /> + </event> + <event> + <int key="case" value="31" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-10-15 08:19:34" /> + </event> + </trace> + <trace> + <string key="concept:name" value="32" /> + <event> + <int key="case" value="32" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2003-10-28 10:00:42" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2003-10-28 10:00:42" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2003-11-03 23:21:16" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-11-03 23:21:16" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2003-11-03 23:21:16" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-11-03 23:21:16" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2003-11-10 12:41:50" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2003-11-10 12:41:50" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-11-10 12:41:50" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-11-10 12:41:50" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2003-11-10 12:41:50" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-11-10 12:41:50" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2003-11-10 12:41:50" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2003-11-17 02:02:24" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2003-11-17 02:02:24" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-11-17 02:02:24" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-11-17 02:02:24" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2003-11-17 02:02:24" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-11-17 02:02:24" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2003-11-23 15:22:58" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2003-11-23 15:22:58" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2003-11-23 15:22:58" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2003-11-23 15:22:58" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2003-11-23 15:22:58" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-11-23 15:22:58" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-11-23 15:22:58" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-11-23 15:22:58" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2003-11-23 15:22:58" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2003-11-23 15:22:58" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-11-23 15:22:58" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-11-23 15:22:58" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2003-11-30 04:43:32" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-11-30 04:43:32" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2003-11-30 04:43:32" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2003-11-30 04:43:32" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2003-11-30 04:43:32" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-12-06 18:04:06" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2003-12-13 07:24:40" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2003-12-13 07:24:40" /> + </event> + <event> + <int key="case" value="32" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2003-12-13 07:24:40" /> + </event> + </trace> + <trace> + <string key="concept:name" value="33" /> + <event> + <int key="case" value="33" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-01-01 23:26:22" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-01-01 23:26:22" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2004-01-08 12:46:56" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2004-01-08 12:46:56" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2004-01-08 12:46:56" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-01-08 12:46:56" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-01-08 12:46:56" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-01-08 12:46:56" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2004-01-08 12:46:56" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-01-08 12:46:56" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2004-01-08 12:46:56" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-01-08 12:46:56" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2004-01-15 02:07:30" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2004-01-15 02:07:30" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-01-15 02:07:30" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-01-15 02:07:30" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2004-01-15 02:07:30" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2004-01-15 02:07:30" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2004-01-15 02:07:30" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2004-01-15 02:07:30" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-01-15 02:07:30" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2004-01-21 15:28:04" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2004-01-21 15:28:04" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2004-01-21 15:28:04" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2004-01-21 15:28:04" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2004-01-28 04:48:38" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2004-01-28 04:48:38" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2004-02-03 18:09:12" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2004-02-03 18:09:12" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2004-02-10 07:29:46" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2004-02-10 07:29:46" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2004-02-16 20:50:20" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2004-02-16 20:50:20" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2004-02-16 20:50:20" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2004-02-16 20:50:20" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2004-02-16 20:50:20" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2004-02-23 10:10:54" /> + </event> + <event> + <int key="case" value="33" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2004-02-23 10:10:54" /> + </event> + </trace> + <trace> + <string key="concept:name" value="34" /> + <event> + <int key="case" value="34" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2004-02-29 23:31:28" /> + </event> + </trace> + <trace> + <string key="concept:name" value="35" /> + <event> + <int key="case" value="35" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2004-03-27 04:53:44" /> + </event> + <event> + <int key="case" value="35" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2004-03-27 04:53:44" /> + </event> + </trace> + <trace> + <string key="concept:name" value="36" /> + <event> + <int key="case" value="36" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2004-05-12 03:17:42" /> + </event> + <event> + <int key="case" value="36" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2004-05-12 03:17:42" /> + </event> + <event> + <int key="case" value="36" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2004-05-18 16:38:16" /> + </event> + </trace> + <trace> + <string key="concept:name" value="37" /> + <event> + <int key="case" value="37" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2004-05-31 19:19:24" /> + </event> + <event> + <int key="case" value="37" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2004-05-31 19:19:24" /> + </event> + <event> + <int key="case" value="37" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2004-05-31 19:19:24" /> + </event> + <event> + <int key="case" value="37" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2004-06-07 08:39:58" /> + </event> + <event> + <int key="case" value="37" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2004-06-07 08:39:58" /> + </event> + </trace> + <trace> + <string key="concept:name" value="38" /> + <event> + <int key="case" value="38" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2004-06-20 11:21:06" /> + </event> + <event> + <int key="case" value="38" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-06-20 11:21:06" /> + </event> + <event> + <int key="case" value="38" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2004-06-20 11:21:06" /> + </event> + <event> + <int key="case" value="38" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2004-06-20 11:21:06" /> + </event> + </trace> + <trace> + <string key="concept:name" value="39" /> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2004-07-03 14:02:14" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2004-07-03 14:02:14" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2004-07-03 14:02:14" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2004-07-10 03:22:48" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2004-07-10 03:22:48" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2004-07-10 03:22:48" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2004-07-10 03:22:48" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2004-07-10 03:22:48" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2004-07-16 16:43:22" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2004-07-16 16:43:22" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2004-07-16 16:43:22" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2004-07-16 16:43:22" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2004-07-23 06:03:56" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2004-07-23 06:03:56" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2004-07-23 06:03:56" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2004-07-29 19:24:30" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2004-07-29 19:24:30" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2004-07-29 19:24:30" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2004-07-29 19:24:30" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2004-08-05 08:45:04" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2004-08-05 08:45:04" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2004-08-05 08:45:04" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2004-08-11 22:05:38" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2004-08-11 22:05:38" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2004-08-11 22:05:38" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2004-08-18 11:26:12" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2004-08-18 11:26:12" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2004-08-18 11:26:12" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2004-08-25 00:46:46" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2004-08-25 00:46:46" /> + </event> + <event> + <int key="case" value="39" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2004-08-31 14:07:20" /> + </event> + </trace> + <trace> + <string key="concept:name" value="40" /> + <event> + <int key="case" value="40" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2004-09-26 19:29:36" /> + </event> + </trace> + <trace> + <string key="concept:name" value="41" /> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2004-11-05 02:33:00" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2004-11-05 02:33:00" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2004-11-11 15:53:34" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-11-11 15:53:34" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2004-11-11 15:53:34" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-11-11 15:53:34" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2004-11-18 05:14:08" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2004-11-18 05:14:08" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2004-11-18 05:14:08" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2004-11-24 18:34:42" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-11-24 18:34:42" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2004-11-24 18:34:42" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2004-11-24 18:34:42" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-11-24 18:34:42" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-12-01 07:55:16" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-12-01 07:55:16" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2004-12-01 07:55:16" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-12-01 07:55:16" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2004-12-07 21:15:50" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-12-07 21:15:50" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-12-07 21:15:50" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-12-07 21:15:50" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2004-12-07 21:15:50" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2004-12-07 21:15:50" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-12-07 21:15:50" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2004-12-07 21:15:50" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2004-12-14 10:36:24" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-12-14 10:36:24" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2004-12-14 10:36:24" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2004-12-20 23:56:58" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-12-20 23:56:58" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2004-12-20 23:56:58" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2004-12-27 13:17:32" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2004-12-27 13:17:32" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-12-27 13:17:32" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2004-12-27 13:17:32" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2004-12-27 13:17:32" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2005-01-03 02:38:06" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-01-03 02:38:06" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-03 02:38:06" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2005-01-03 02:38:06" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-03 02:38:06" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-03 02:38:06" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-01-09 15:58:40" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2005-01-16 05:19:14" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-16 05:19:14" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-01-16 05:19:14" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-16 05:19:14" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-01-16 05:19:14" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-01-16 05:19:14" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2005-01-22 18:39:48" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2005-01-22 18:39:48" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2005-01-22 18:39:48" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2005-01-22 18:39:48" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-22 18:39:48" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-01-22 18:39:48" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-01-22 18:39:48" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-22 18:39:48" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-01-22 18:39:48" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-22 18:39:48" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-22 18:39:48" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2005-01-29 08:00:22" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2005-01-29 08:00:22" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2005-01-29 08:00:22" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2005-01-29 08:00:22" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-29 08:00:22" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-01-29 08:00:22" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / enter" /> + <string key="timestamp" value="2005-01-29 08:00:22" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-29 08:00:22" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-01-29 08:00:22" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-01-29 08:00:22" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2005-01-29 08:00:22" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2005-01-29 08:00:22" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2005-02-04 21:20:56" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2005-02-04 21:20:56" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-02-04 21:20:56" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-02-04 21:20:56" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-02-04 21:20:56" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-02-04 21:20:56" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-02-04 21:20:56" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-02-04 21:20:56" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2005-02-04 21:20:56" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-02-04 21:20:56" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2005-02-11 10:41:30" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-02-11 10:41:30" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-02-11 10:41:30" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-02-11 10:41:30" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2005-02-11 10:41:30" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2005-02-18 00:02:04" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-02-18 00:02:04" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2005-02-18 00:02:04" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2005-02-24 13:22:38" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-02-24 13:22:38" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-02-24 13:22:38" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-02-24 13:22:38" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2005-02-24 13:22:38" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2005-03-03 02:43:12" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2005-03-03 02:43:12" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-03-03 02:43:12" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-03-03 02:43:12" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-03-03 02:43:12" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2005-03-09 16:03:46" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2005-03-09 16:03:46" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2005-03-09 16:03:46" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2005-03-09 16:03:46" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2005-03-09 16:03:46" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / enter" /> + <string key="timestamp" value="2005-03-09 16:03:46" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-03-09 16:03:46" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-03-09 16:03:46" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2005-03-09 16:03:46" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-03-09 16:03:46" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2005-03-09 16:03:46" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2005-03-09 16:03:46" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2005-03-16 05:24:20" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2005-03-16 05:24:20" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2005-03-16 05:24:20" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2005-03-16 05:24:20" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2005-03-22 18:44:54" /> + </event> + <event> + <int key="case" value="41" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2005-03-22 18:44:54" /> + </event> + </trace> + <trace> + <string key="concept:name" value="42" /> + <event> + <int key="case" value="42" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2005-04-04 22:26:02" /> + </event> + <event> + <int key="case" value="42" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2005-04-04 22:26:02" /> + </event> + <event> + <int key="case" value="42" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2005-04-04 22:26:02" /> + </event> + <event> + <int key="case" value="42" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2005-04-04 22:26:02" /> + </event> + </trace> + <trace> + <string key="concept:name" value="43" /> + <event> + <int key="case" value="43" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2005-04-18 01:07:10" /> + </event> + <event> + <int key="case" value="43" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2005-04-18 01:07:10" /> + </event> + </trace> + <trace> + <string key="concept:name" value="44" /> + <event> + <int key="case" value="44" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2005-04-24 14:27:44" /> + </event> + </trace> + <trace> + <string key="concept:name" value="45" /> + <event> + <int key="case" value="45" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2005-05-01 03:48:18" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2005-05-01 03:48:18" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2005-05-07 17:08:52" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2005-05-07 17:08:52" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-05-07 17:08:52" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2005-05-14 06:29:26" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-05-14 06:29:26" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2005-05-14 06:29:26" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2005-05-20 19:50:00" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2005-05-27 09:10:34" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-05-27 09:10:34" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-06-02 22:31:08" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2005-06-09 11:51:42" /> + </event> + <event> + <int key="case" value="45" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2005-06-09 11:51:42" /> + </event> + </trace> + <trace> + <string key="concept:name" value="46" /> + <event> + <int key="case" value="46" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-06-22 14:32:50" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2005-06-22 14:32:50" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-06-29 03:53:24" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2005-06-29 03:53:24" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-07-05 17:13:58" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2005-07-05 17:13:58" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-07-05 17:13:58" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2005-07-05 17:13:58" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2005-07-05 17:13:58" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-07-12 06:34:32" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2005-07-12 06:34:32" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2005-07-12 06:34:32" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2005-07-12 06:34:32" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-07-18 19:55:06" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2005-07-18 19:55:06" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2005-07-18 19:55:06" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2005-07-18 19:55:06" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2005-07-18 19:55:06" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2005-07-18 19:55:06" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2005-07-25 09:15:40" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2005-07-25 09:15:40" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-07-31 22:36:14" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2005-07-31 22:36:14" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2005-07-31 22:36:14" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-07-31 22:36:14" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2005-07-31 22:36:14" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2005-07-31 22:36:14" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2005-07-31 22:36:14" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-07-31 22:36:14" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-08-07 11:56:48" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2005-08-07 11:56:48" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2005-08-07 11:56:48" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2005-08-07 11:56:48" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2005-08-07 11:56:48" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-08-14 01:17:22" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2005-08-14 01:17:22" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2005-08-14 01:17:22" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2005-08-14 01:17:22" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-08-20 14:37:56" /> + </event> + <event> + <int key="case" value="46" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-08-20 14:37:56" /> + </event> + </trace> + <trace> + <string key="concept:name" value="47" /> + <event> + <int key="case" value="47" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2005-09-02 17:19:04" /> + </event> + <event> + <int key="case" value="47" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2005-09-09 06:39:38" /> + </event> + <event> + <int key="case" value="47" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2005-09-09 06:39:38" /> + </event> + </trace> + <trace> + <string key="concept:name" value="48" /> + <event> + <int key="case" value="48" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2005-09-15 20:00:12" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2005-09-15 20:00:12" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2005-09-22 09:20:46" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-09-22 09:20:46" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-09-22 09:20:46" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-09-22 09:20:46" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2005-09-22 09:20:46" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2005-09-28 22:41:20" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2005-09-28 22:41:20" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-09-28 22:41:20" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-09-28 22:41:20" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2005-09-28 22:41:20" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-09-28 22:41:20" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2005-09-28 22:41:20" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-09-28 22:41:20" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2005-10-05 12:01:54" /> + </event> + <event> + <int key="case" value="48" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2005-10-05 12:01:54" /> + </event> + </trace> + <trace> + <string key="concept:name" value="49" /> + <event> + <int key="case" value="49" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2005-10-18 14:43:02" /> + </event> + <event> + <int key="case" value="49" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2005-10-18 14:43:02" /> + </event> + <event> + <int key="case" value="49" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-10-18 14:43:02" /> + </event> + <event> + <int key="case" value="49" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2005-10-25 04:03:36" /> + </event> + <event> + <int key="case" value="49" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2005-10-25 04:03:36" /> + </event> + </trace> + <trace> + <string key="concept:name" value="50" /> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2005-11-20 08:25:52" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-11-20 08:25:52" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-11-20 08:25:52" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-11-20 08:25:52" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-11-20 08:25:52" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2005-11-26 21:46:26" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2005-11-26 21:46:26" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2005-11-26 21:46:26" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2005-11-26 21:46:26" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-11-26 21:46:26" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2005-12-03 11:07:00" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2005-12-03 11:07:00" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-12-10 00:27:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-12-16 13:48:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2005-12-16 13:48:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2005-12-16 13:48:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-12-16 13:48:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2005-12-16 13:48:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2005-12-16 13:48:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-12-16 13:48:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2005-12-16 13:48:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2005-12-16 13:48:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-12-23 03:08:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2005-12-23 03:08:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2005-12-23 03:08:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-12-23 03:08:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2005-12-23 03:08:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2005-12-29 16:29:16" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2005-12-29 16:29:16" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2005-12-29 16:29:16" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2005-12-29 16:29:16" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2005-12-29 16:29:16" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2006-01-05 05:49:50" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-01-05 05:49:50" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-01-05 05:49:50" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-01-11 19:10:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-01-11 19:10:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2006-01-11 19:10:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-01-11 19:10:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-01-11 19:10:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-01-11 19:10:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2006-01-11 19:10:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2006-01-11 19:10:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-01-11 19:10:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-01-11 19:10:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-01-18 08:30:58" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-01-18 08:30:58" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-01-18 08:30:58" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-01-24 21:51:32" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-01-24 21:51:32" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-01-24 21:51:32" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-01-31 11:12:06" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-01-31 11:12:06" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-01-31 11:12:06" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2006-02-07 00:32:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-02-07 00:32:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-02-07 00:32:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-02-07 00:32:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2006-02-07 00:32:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2006-02-07 00:32:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-02-07 00:32:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / enter" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-02-13 13:53:14" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-02-20 03:13:48" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2006-02-20 03:13:48" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-02-20 03:13:48" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-02-20 03:13:48" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-02-20 03:13:48" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-02-20 03:13:48" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2006-02-26 16:34:22" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2006-02-26 16:34:22" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-02-26 16:34:22" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2006-02-26 16:34:22" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2006-02-26 16:34:22" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2006-02-26 16:34:22" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-02-26 16:34:22" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-03-05 05:54:56" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2006-03-05 05:54:56" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-03-05 05:54:56" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-03-05 05:54:56" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-03-05 05:54:56" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2006-03-05 05:54:56" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-03-05 05:54:56" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2006-03-11 19:15:30" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-03-11 19:15:30" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2006-03-11 19:15:30" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2006-03-11 19:15:30" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2006-03-11 19:15:30" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-03-11 19:15:30" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-03-18 08:36:04" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2006-03-18 08:36:04" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-03-18 08:36:04" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2006-03-24 21:56:38" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-03-24 21:56:38" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2006-03-24 21:56:38" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2006-03-24 21:56:38" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2006-03-24 21:56:38" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2006-03-24 21:56:38" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-03-24 21:56:38" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2006-03-31 12:17:12" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-03-31 12:17:12" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-03-31 12:17:12" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2006-04-07 01:37:46" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-04-07 01:37:46" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2006-04-07 01:37:46" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2006-04-07 01:37:46" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-04-07 01:37:46" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-04-13 14:58:20" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2006-04-20 04:18:54" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-04-20 04:18:54" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-04-20 04:18:54" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2006-04-20 04:18:54" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2006-04-20 04:18:54" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2006-04-20 04:18:54" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-04-20 04:18:54" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2006-04-26 17:39:28" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2006-04-26 17:39:28" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2006-04-26 17:39:28" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2006-04-26 17:39:28" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-04-26 17:39:28" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-05-03 07:00:02" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2006-05-03 07:00:02" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-05-03 07:00:02" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-05-09 20:20:36" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-05-09 20:20:36" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2006-05-16 09:41:10" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2006-05-16 09:41:10" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-05-16 09:41:10" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-05-22 23:01:44" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2006-05-22 23:01:44" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-05-29 12:22:18" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2006-05-29 12:22:18" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2006-05-29 12:22:18" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-05-29 12:22:18" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-06-05 01:42:52" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2006-06-05 01:42:52" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-06-05 01:42:52" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2006-06-05 01:42:52" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-06-11 15:03:26" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2006-06-11 15:03:26" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2006-06-11 15:03:26" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-06-11 15:03:26" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-06-11 15:03:26" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2006-06-18 04:24:00" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2006-06-18 04:24:00" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2006-06-18 04:24:00" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-06-18 04:24:00" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2006-06-18 04:24:00" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-06-24 17:44:34" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-07-01 07:05:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2006-07-01 07:05:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2006-07-01 07:05:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-07-01 07:05:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2006-07-01 07:05:08" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-07-07 20:25:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2006-07-07 20:25:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2006-07-07 20:25:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2006-07-07 20:25:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2006-07-07 20:25:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2006-07-07 20:25:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-07-07 20:25:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2006-07-07 20:25:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-07-07 20:25:42" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2006-07-14 09:46:16" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2006-07-14 09:46:16" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-07-14 09:46:16" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-07-14 09:46:16" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-07-20 23:06:50" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2006-07-20 23:06:50" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2006-07-20 23:06:50" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-07-20 23:06:50" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2006-07-27 12:27:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2006-07-27 12:27:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-07-27 12:27:24" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2006-08-03 01:47:58" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2006-08-03 01:47:58" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2006-08-03 01:47:58" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-08-03 01:47:58" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2006-08-09 15:08:32" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2006-08-09 15:08:32" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-08-09 15:08:32" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2006-08-16 04:29:06" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2006-08-16 04:29:06" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2006-08-16 04:29:06" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2006-08-16 04:29:06" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / enter" /> + <string key="timestamp" value="2006-08-16 04:29:06" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-08-16 04:29:06" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2006-08-16 04:29:06" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-08-16 04:29:06" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-08-22 17:49:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2006-08-22 17:49:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2006-08-22 17:49:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-08-22 17:49:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2006-08-22 17:49:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / enter" /> + <string key="timestamp" value="2006-08-22 17:49:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-08-22 17:49:40" /> + </event> + <event> + <int key="case" value="50" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2006-08-22 17:49:40" /> + </event> + </trace> + <trace> + <string key="concept:name" value="51" /> + <event> + <int key="case" value="51" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2006-09-04 20:30:48" /> + </event> + <event> + <int key="case" value="51" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2006-09-04 20:30:48" /> + </event> + <event> + <int key="case" value="51" /> + <string key="activity" value="Payment<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-09-04 20:30:48" /> + </event> + <event> + <int key="case" value="51" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-09-04 20:30:48" /> + </event> + <event> + <int key="case" value="51" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2006-09-04 20:30:48" /> + </event> + <event> + <int key="case" value="51" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2006-09-04 20:30:48" /> + </event> + </trace> + <trace> + <string key="concept:name" value="52" /> + <event> + <int key="case" value="52" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-09-17 23:11:56" /> + </event> + <event> + <int key="case" value="52" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-09-17 23:11:56" /> + </event> + </trace> + <trace> + <string key="concept:name" value="53" /> + <event> + <int key="case" value="53" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2006-10-07 15:13:38" /> + </event> + </trace> + <trace> + <string key="concept:name" value="54" /> + <event> + <int key="case" value="54" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-10-14 04:34:12" /> + </event> + <event> + <int key="case" value="54" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-10-20 17:54:46" /> + </event> + <event> + <int key="case" value="54" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2006-10-20 17:54:46" /> + </event> + <event> + <int key="case" value="54" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2006-10-20 17:54:46" /> + </event> + <event> + <int key="case" value="54" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2006-10-20 17:54:46" /> + </event> + <event> + <int key="case" value="54" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-10-20 17:54:46" /> + </event> + <event> + <int key="case" value="54" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2006-10-20 17:54:46" /> + </event> + <event> + <int key="case" value="54" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2006-10-20 17:54:46" /> + </event> + <event> + <int key="case" value="54" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-10-20 17:54:46" /> + </event> + <event> + <int key="case" value="54" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-10-20 17:54:46" /> + </event> + <event> + <int key="case" value="54" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2006-10-27 07:15:20" /> + </event> + </trace> + <trace> + <string key="concept:name" value="55" /> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-11-02 19:35:54" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2006-11-02 19:35:54" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2006-11-02 19:35:54" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-11-09 08:56:28" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2006-11-09 08:56:28" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2006-11-15 22:17:02" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2006-11-15 22:17:02" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2006-11-15 22:17:02" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-11-22 11:37:36" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2006-11-22 11:37:36" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2006-11-22 11:37:36" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-11-22 11:37:36" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-11-22 11:37:36" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2006-11-22 11:37:36" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-11-29 00:58:10" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-11-29 00:58:10" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2006-11-29 00:58:10" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-11-29 00:58:10" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2006-11-29 00:58:10" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2006-11-29 00:58:10" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-12-05 14:18:44" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-12-05 14:18:44" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2006-12-05 14:18:44" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-12-05 14:18:44" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-12-05 14:18:44" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2006-12-05 14:18:44" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2006-12-12 03:39:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2006-12-12 03:39:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2006-12-12 03:39:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-12-12 03:39:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-12-12 03:39:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2006-12-12 03:39:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2006-12-12 03:39:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-12-12 03:39:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2006-12-18 16:59:52" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-12-18 16:59:52" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2006-12-18 16:59:52" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-12-18 16:59:52" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2006-12-18 16:59:52" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2006-12-18 16:59:52" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-12-18 16:59:52" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-12-25 06:20:26" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2006-12-25 06:20:26" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-12-25 06:20:26" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-12-25 06:20:26" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2006-12-31 19:41:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2006-12-31 19:41:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2006-12-31 19:41:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / enter" /> + <string key="timestamp" value="2006-12-31 19:41:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-12-31 19:41:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2006-12-31 19:41:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-01-07 09:01:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-01-07 09:01:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2007-01-07 09:01:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-01-07 09:01:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-01-07 09:01:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-01-07 09:01:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-01-07 09:01:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2007-01-07 09:01:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-01-13 22:22:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2007-01-13 22:22:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-01-13 22:22:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-01-13 22:22:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2007-01-20 11:42:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-01-20 11:42:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2007-01-20 11:42:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-01-20 11:42:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-01-20 11:42:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-01-20 11:42:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2007-01-20 11:42:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-01-20 11:42:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-01-20 11:42:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-01-27 01:03:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-01-27 01:03:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-01-27 01:03:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-01-27 01:03:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-01-27 01:03:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2007-01-27 01:03:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2007-01-27 01:03:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-01-27 01:03:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-02-02 14:23:50" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2007-02-02 14:23:50" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2007-02-02 14:23:50" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-02-02 14:23:50" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-02-02 14:23:50" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2007-02-02 14:23:50" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-02-02 14:23:50" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2007-02-09 03:44:24" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-02-09 03:44:24" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-02-09 03:44:24" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2007-02-09 03:44:24" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-02-09 03:44:24" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2007-02-09 03:44:24" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-02-09 03:44:24" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-02-09 03:44:24" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2007-02-15 17:04:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-02-15 17:04:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-02-15 17:04:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2007-02-15 17:04:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-02-15 17:04:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2007-02-15 17:04:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2007-02-15 17:04:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-02-15 17:04:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-02-15 17:04:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2007-02-22 06:25:32" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-02-22 06:25:32" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-02-22 06:25:32" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2007-02-22 06:25:32" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2007-02-22 06:25:32" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2007-02-22 06:25:32" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2007-02-22 06:25:32" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-02-22 06:25:32" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2007-02-28 19:46:06" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2007-02-28 19:46:06" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-02-28 19:46:06" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2007-02-28 19:46:06" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / enter" /> + <string key="timestamp" value="2007-02-28 19:46:06" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2007-02-28 19:46:06" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2007-02-28 19:46:06" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-02-28 19:46:06" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-02-28 19:46:06" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2007-03-07 09:06:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-03-07 09:06:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2007-03-07 09:06:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-03-07 09:06:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-03-07 09:06:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2007-03-07 09:06:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2007-03-07 09:06:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2007-03-07 09:06:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2007-03-07 09:06:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-03-07 09:06:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2007-03-13 22:27:14" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2007-03-13 22:27:14" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2007-03-13 22:27:14" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-03-13 22:27:14" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-03-20 11:47:48" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2007-03-20 11:47:48" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-03-20 11:47:48" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2007-03-27 02:08:22" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-03-27 02:08:22" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2007-04-02 15:28:56" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-04-02 15:28:56" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2007-04-02 15:28:56" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2007-04-02 15:28:56" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2007-04-02 15:28:56" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-04-02 15:28:56" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2007-04-09 04:49:30" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2007-04-09 04:49:30" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-04-09 04:49:30" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2007-04-09 04:49:30" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-04-09 04:49:30" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2007-04-15 18:10:04" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2007-04-15 18:10:04" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-04-15 18:10:04" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-04-22 07:30:38" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-04-28 20:51:12" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2007-04-28 20:51:12" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / enter" /> + <string key="timestamp" value="2007-04-28 20:51:12" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2007-04-28 20:51:12" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-04-28 20:51:12" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-05-05 10:11:46" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2007-05-11 23:32:20" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2007-05-11 23:32:20" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2007-05-11 23:32:20" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2007-05-11 23:32:20" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2007-05-11 23:32:20" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-05-11 23:32:20" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-05-18 12:52:54" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-05-25 02:13:28" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / enter" /> + <string key="timestamp" value="2007-05-31 15:34:02" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-05-31 15:34:02" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-06-07 04:54:36" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2007-06-07 04:54:36" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-06-07 04:54:36" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-06-07 04:54:36" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-06-13 18:15:10" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-06-13 18:15:10" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-06-20 07:35:44" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2007-06-26 20:56:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2007-06-26 20:56:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2007-06-26 20:56:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2007-06-26 20:56:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2007-06-26 20:56:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2007-06-26 20:56:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-06-26 20:56:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2007-07-03 10:16:52" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2007-07-03 10:16:52" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2007-07-03 10:16:52" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-07-03 10:16:52" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2007-07-09 23:37:26" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2007-07-09 23:37:26" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2007-07-09 23:37:26" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-07-09 23:37:26" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2007-07-16 12:58:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2007-07-16 12:58:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2007-07-16 12:58:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2007-07-16 12:58:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2007-07-16 12:58:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-07-16 12:58:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-07-23 02:18:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2007-07-29 15:39:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2007-07-29 15:39:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2007-07-29 15:39:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-07-29 15:39:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2007-08-05 04:59:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2007-08-05 04:59:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-08-05 04:59:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2007-08-11 18:20:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2007-08-11 18:20:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2007-08-11 18:20:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-08-11 18:20:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2007-08-18 07:40:50" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2007-08-18 07:40:50" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2007-08-18 07:40:50" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-08-18 07:40:50" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2007-08-24 21:01:24" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-08-24 21:01:24" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-08-24 21:01:24" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-08-24 21:01:24" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-08-31 10:21:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-08-31 10:21:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-08-31 10:21:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-08-31 10:21:58" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-09-06 23:42:32" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-09-06 23:42:32" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-09-06 23:42:32" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-09-06 23:42:32" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-09-13 13:03:06" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-09-13 13:03:06" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-09-13 13:03:06" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-09-20 02:23:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-09-20 02:23:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-09-20 02:23:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-09-20 02:23:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-09-20 02:23:40" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-09-26 15:44:14" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2007-09-26 15:44:14" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-09-26 15:44:14" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2007-09-26 15:44:14" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-09-26 15:44:14" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2007-10-03 05:04:48" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-10-03 05:04:48" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2007-10-09 18:25:22" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-10-09 18:25:22" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-10-09 18:25:22" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-10-16 07:45:56" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2007-10-16 07:45:56" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-10-16 07:45:56" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-10-16 07:45:56" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2007-10-22 21:06:30" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2007-10-22 21:06:30" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2007-10-22 21:06:30" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2007-10-22 21:06:30" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-10-22 21:06:30" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-10-29 09:27:04" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2007-10-29 09:27:04" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-10-29 09:27:04" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2007-11-04 22:47:38" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2007-11-04 22:47:38" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-11-04 22:47:38" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2007-11-11 12:08:12" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2007-11-11 12:08:12" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2007-11-11 12:08:12" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2007-11-11 12:08:12" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2007-11-11 12:08:12" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-11-11 12:08:12" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-11-18 01:28:46" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2007-11-24 14:49:20" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2007-11-24 14:49:20" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-11-24 14:49:20" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-11-24 14:49:20" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2007-12-01 04:09:54" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-12-01 04:09:54" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2007-12-07 17:30:28" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2007-12-07 17:30:28" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2007-12-07 17:30:28" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2007-12-07 17:30:28" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2007-12-07 17:30:28" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-12-07 17:30:28" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2007-12-14 06:51:02" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2007-12-14 06:51:02" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-12-14 06:51:02" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-12-14 06:51:02" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-12-20 20:11:36" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2007-12-27 09:32:10" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2007-12-27 09:32:10" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2008-01-02 22:52:44" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2008-01-09 12:13:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2008-01-09 12:13:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2008-01-09 12:13:18" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2008-01-16 01:33:52" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2008-01-22 14:54:26" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2008-01-29 04:15:00" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2008-02-04 17:35:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2008-02-04 17:35:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2008-02-04 17:35:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2008-02-04 17:35:34" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2008-02-11 06:56:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2008-02-11 06:56:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2008-02-11 06:56:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2008-02-11 06:56:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2008-02-11 06:56:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-02-11 06:56:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2008-02-11 06:56:08" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-02-17 20:16:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2008-02-17 20:16:42" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2008-02-24 09:37:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2008-02-24 09:37:16" /> + </event> + <event> + <int key="case" value="55" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2008-02-24 09:37:16" /> + </event> + </trace> + <trace> + <string key="concept:name" value="56" /> + <event> + <int key="case" value="56" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-03-01 22:57:50" /> + </event> + <event> + <int key="case" value="56" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2008-03-01 22:57:50" /> + </event> + <event> + <int key="case" value="56" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-03-08 12:18:24" /> + </event> + </trace> + <trace> + <string key="concept:name" value="57" /> + <event> + <int key="case" value="57" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2008-03-28 04:20:06" /> + </event> + <event> + <int key="case" value="57" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2008-04-03 18:40:40" /> + </event> + </trace> + <trace> + <string key="concept:name" value="58" /> + <event> + <int key="case" value="58" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-04-16 21:21:48" /> + </event> + </trace> + <trace> + <string key="concept:name" value="59" /> + <event> + <int key="case" value="59" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2008-04-23 10:42:22" /> + </event> + </trace> + <trace> + <string key="concept:name" value="60" /> + <event> + <int key="case" value="60" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / enter" /> + <string key="timestamp" value="2008-04-30 00:02:56" /> + </event> + <event> + <int key="case" value="60" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-05-06 13:23:30" /> + </event> + </trace> + <trace> + <string key="concept:name" value="61" /> + <event> + <int key="case" value="61" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2008-05-26 05:25:12" /> + </event> + </trace> + <trace> + <string key="concept:name" value="62" /> + <event> + <int key="case" value="62" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2008-06-01 18:45:46" /> + </event> + <event> + <int key="case" value="62" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2008-06-01 18:45:46" /> + </event> + <event> + <int key="case" value="62" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2008-06-08 08:06:20" /> + </event> + <event> + <int key="case" value="62" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2008-06-08 08:06:20" /> + </event> + <event> + <int key="case" value="62" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-06-08 08:06:20" /> + </event> + <event> + <int key="case" value="62" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2008-06-08 08:06:20" /> + </event> + <event> + <int key="case" value="62" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2008-06-08 08:06:20" /> + </event> + <event> + <int key="case" value="62" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2008-06-08 08:06:20" /> + </event> + </trace> + <trace> + <string key="concept:name" value="63" /> + <event> + <int key="case" value="63" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2008-06-21 10:47:28" /> + </event> + </trace> + <trace> + <string key="concept:name" value="64" /> + <event> + <int key="case" value="64" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2008-06-28 00:08:02" /> + </event> + <event> + <int key="case" value="64" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2008-07-04 13:28:36" /> + </event> + <event> + <int key="case" value="64" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2008-07-04 13:28:36" /> + </event> + </trace> + <trace> + <string key="concept:name" value="65" /> + <event> + <int key="case" value="65" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2008-07-11 02:49:10" /> + </event> + </trace> + <trace> + <string key="concept:name" value="66" /> + <event> + <int key="case" value="66" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2008-07-17 16:09:44" /> + </event> + <event> + <int key="case" value="66" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2008-07-17 16:09:44" /> + </event> + <event> + <int key="case" value="66" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2008-07-17 16:09:44" /> + </event> + </trace> + <trace> + <string key="concept:name" value="67" /> + <event> + <int key="case" value="67" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2008-07-30 18:50:52" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2008-07-30 18:50:52" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2008-07-30 18:50:52" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2008-07-30 18:50:52" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2008-07-30 18:50:52" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2008-07-30 18:50:52" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2008-08-06 08:11:26" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2008-08-06 08:11:26" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2008-08-06 08:11:26" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-08-06 08:11:26" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2008-08-06 08:11:26" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2008-08-06 08:11:26" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-08-06 08:11:26" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2008-08-12 21:32:00" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2008-08-12 21:32:00" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2008-08-12 21:32:00" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2008-08-12 21:32:00" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2008-08-19 10:52:34" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2008-08-19 10:52:34" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2008-08-19 10:52:34" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2008-08-19 10:52:34" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2008-08-19 10:52:34" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2008-08-26 00:13:08" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2008-09-01 13:33:42" /> + </event> + <event> + <int key="case" value="67" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2008-09-01 13:33:42" /> + </event> + </trace> + <trace> + <string key="concept:name" value="68" /> + <event> + <int key="case" value="68" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2008-09-21 05:35:24" /> + </event> + <event> + <int key="case" value="68" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2008-09-27 18:55:58" /> + </event> + <event> + <int key="case" value="68" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2008-09-27 18:55:58" /> + </event> + <event> + <int key="case" value="68" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2008-10-04 08:16:32" /> + </event> + <event> + <int key="case" value="68" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2008-10-04 08:16:32" /> + </event> + <event> + <int key="case" value="68" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-10-04 08:16:32" /> + </event> + <event> + <int key="case" value="68" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2008-10-04 08:16:32" /> + </event> + <event> + <int key="case" value="68" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-10-04 08:16:32" /> + </event> + <event> + <int key="case" value="68" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2008-10-10 21:37:06" /> + </event> + <event> + <int key="case" value="68" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2008-10-10 21:37:06" /> + </event> + <event> + <int key="case" value="68" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2008-10-10 21:37:06" /> + </event> + </trace> + <trace> + <string key="concept:name" value="69" /> + <event> + <int key="case" value="69" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2008-11-06 01:59:22" /> + </event> + <event> + <int key="case" value="69" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2008-11-06 01:59:22" /> + </event> + <event> + <int key="case" value="69" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2008-11-06 01:59:22" /> + </event> + <event> + <int key="case" value="69" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-11-06 01:59:22" /> + </event> + </trace> + <trace> + <string key="concept:name" value="70" /> + <event> + <int key="case" value="70" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2008-11-25 18:01:04" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2008-11-25 18:01:04" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2008-11-25 18:01:04" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2008-12-02 07:21:38" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2008-12-02 07:21:38" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2008-12-02 07:21:38" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2008-12-08 20:42:12" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2008-12-08 20:42:12" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2008-12-08 20:42:12" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2008-12-15 10:02:46" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2008-12-15 10:02:46" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-12-21 23:23:20" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2008-12-21 23:23:20" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2008-12-21 23:23:20" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2008-12-28 12:43:54" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2008-12-28 12:43:54" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-01-04 02:04:28" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-01-10 15:25:02" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-01-10 15:25:02" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2009-01-17 04:45:36" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-01-17 04:45:36" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-01-17 04:45:36" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2009-01-23 18:06:10" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2009-01-23 18:06:10" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2009-01-23 18:06:10" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-01-23 18:06:10" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-01-30 07:26:44" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2009-02-05 20:47:18" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2009-02-05 20:47:18" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-02-05 20:47:18" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2009-02-12 10:07:52" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-02-12 10:07:52" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2009-02-18 23:28:26" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-02-18 23:28:26" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2009-02-18 23:28:26" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-02-18 23:28:26" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2009-02-25 12:49:00" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-02-25 12:49:00" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2009-03-04 02:09:34" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-03-04 02:09:34" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2009-03-10 15:30:08" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-03-10 15:30:08" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / enter" /> + <string key="timestamp" value="2009-03-10 15:30:08" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2009-03-10 15:30:08" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-03-10 15:30:08" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2009-03-17 04:50:42" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-03-17 04:50:42" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-03-17 04:50:42" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Send for Credit Collection / High / exec" /> + <string key="timestamp" value="2009-03-23 18:11:16" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2009-03-23 18:11:16" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2009-03-23 18:11:16" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-03-23 18:11:16" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-03-23 18:11:16" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-03-23 18:11:16" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2009-03-30 08:31:50" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2009-04-05 21:52:24" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-04-05 21:52:24" /> + </event> + <event> + <int key="case" value="70" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2009-04-05 21:52:24" /> + </event> + </trace> + <trace> + <string key="concept:name" value="71" /> + <event> + <int key="case" value="71" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2009-04-25 13:54:06" /> + </event> + <event> + <int key="case" value="71" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2009-04-25 13:54:06" /> + </event> + <event> + <int key="case" value="71" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2009-05-02 03:14:40" /> + </event> + <event> + <int key="case" value="71" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2009-05-02 03:14:40" /> + </event> + <event> + <int key="case" value="71" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2009-05-08 16:35:14" /> + </event> + <event> + <int key="case" value="71" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2009-05-08 16:35:14" /> + </event> + <event> + <int key="case" value="71" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2009-05-08 16:35:14" /> + </event> + </trace> + <trace> + <string key="concept:name" value="72" /> + <event> + <int key="case" value="72" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-05-15 05:55:48" /> + </event> + </trace> + <trace> + <string key="concept:name" value="73" /> + <event> + <int key="case" value="73" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2009-05-21 19:16:22" /> + </event> + <event> + <int key="case" value="73" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-05-21 19:16:22" /> + </event> + </trace> + <trace> + <string key="concept:name" value="74" /> + <event> + <int key="case" value="74" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2009-06-03 21:57:30" /> + </event> + <event> + <int key="case" value="74" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-06-03 21:57:30" /> + </event> + <event> + <int key="case" value="74" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2009-06-03 21:57:30" /> + </event> + <event> + <int key="case" value="74" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-06-03 21:57:30" /> + </event> + <event> + <int key="case" value="74" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2009-06-10 11:18:04" /> + </event> + <event> + <int key="case" value="74" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2009-06-10 11:18:04" /> + </event> + <event> + <int key="case" value="74" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-06-10 11:18:04" /> + </event> + <event> + <int key="case" value="74" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-06-10 11:18:04" /> + </event> + <event> + <int key="case" value="74" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2009-06-10 11:18:04" /> + </event> + </trace> + <trace> + <string key="concept:name" value="75" /> + <event> + <int key="case" value="75" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2009-06-23 13:59:12" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2009-06-23 13:59:12" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2009-06-23 13:59:12" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2009-06-23 13:59:12" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2009-06-23 13:59:12" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2009-06-30 03:19:46" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2009-06-30 03:19:46" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2009-06-30 03:19:46" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2009-07-06 16:40:20" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2009-07-06 16:40:20" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment<-->Send Fine / High / enter" /> + <string key="timestamp" value="2009-07-06 16:40:20" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-07-06 16:40:20" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2009-07-06 16:40:20" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2009-07-13 06:00:54" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2009-07-13 06:00:54" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2009-07-13 06:00:54" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2009-07-13 06:00:54" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2009-07-19 19:21:28" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2009-07-19 19:21:28" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2009-07-19 19:21:28" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-07-19 19:21:28" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2009-07-19 19:21:28" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-07-19 19:21:28" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2009-07-19 19:21:28" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2009-07-19 19:21:28" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2009-07-19 19:21:28" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2009-07-26 08:42:02" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2009-07-26 08:42:02" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2009-07-26 08:42:02" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2009-07-26 08:42:02" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2009-07-26 08:42:02" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-07-26 08:42:02" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2009-07-26 08:42:02" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2009-07-26 08:42:02" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2009-08-01 22:02:36" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2009-08-01 22:02:36" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2009-08-01 22:02:36" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2009-08-01 22:02:36" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-08-01 22:02:36" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2009-08-01 22:02:36" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-08-01 22:02:36" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2009-08-01 22:02:36" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-08-01 22:02:36" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2009-08-01 22:02:36" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2009-08-01 22:02:36" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-08-01 22:02:36" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2009-08-08 11:23:10" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2009-08-08 11:23:10" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2009-08-08 11:23:10" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2009-08-08 11:23:10" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-08-08 11:23:10" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-08-08 11:23:10" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2009-08-08 11:23:10" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2009-08-15 00:43:44" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2009-08-15 00:43:44" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-08-15 00:43:44" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2009-08-15 00:43:44" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2009-08-21 14:04:18" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2009-08-21 14:04:18" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2009-08-21 14:04:18" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2009-08-28 03:24:52" /> + </event> + <event> + <int key="case" value="75" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-08-28 03:24:52" /> + </event> + </trace> + <trace> + <string key="concept:name" value="76" /> + <event> + <int key="case" value="76" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2009-09-03 16:45:26" /> + </event> + </trace> + <trace> + <string key="concept:name" value="77" /> + <event> + <int key="case" value="77" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-09-16 19:26:34" /> + </event> + </trace> + <trace> + <string key="concept:name" value="78" /> + <event> + <int key="case" value="78" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2009-09-23 08:47:08" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2009-09-23 08:47:08" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2009-09-29 22:07:42" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2009-09-29 22:07:42" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2009-09-29 22:07:42" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2009-09-29 22:07:42" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-09-29 22:07:42" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2009-09-29 22:07:42" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / enter" /> + <string key="timestamp" value="2009-09-29 22:07:42" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2009-09-29 22:07:42" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2009-09-29 22:07:42" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-09-29 22:07:42" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-09-29 22:07:42" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-10-06 11:28:16" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2009-10-06 11:28:16" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / enter" /> + <string key="timestamp" value="2009-10-13 00:48:50" /> + </event> + <event> + <int key="case" value="78" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2009-10-13 00:48:50" /> + </event> + </trace> + <trace> + <string key="concept:name" value="79" /> + <event> + <int key="case" value="79" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-11-01 15:50:32" /> + </event> + </trace> + <trace> + <string key="concept:name" value="80" /> + <event> + <int key="case" value="80" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2009-11-14 18:31:40" /> + </event> + </trace> + <trace> + <string key="concept:name" value="81" /> + <event> + <int key="case" value="81" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2009-11-21 07:52:14" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2009-11-27 21:12:48" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2009-11-27 21:12:48" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-11-27 21:12:48" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-11-27 21:12:48" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2009-11-27 21:12:48" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2009-11-27 21:12:48" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2009-11-27 21:12:48" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-11-27 21:12:48" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2009-12-04 10:33:22" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-12-04 10:33:22" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2009-12-04 10:33:22" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2009-12-04 10:33:22" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2009-12-10 23:53:56" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2009-12-10 23:53:56" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2009-12-10 23:53:56" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-12-10 23:53:56" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2009-12-10 23:53:56" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2009-12-17 13:14:30" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2009-12-17 13:14:30" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2009-12-24 02:35:04" /> + </event> + <event> + <int key="case" value="81" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2009-12-24 02:35:04" /> + </event> + </trace> + <trace> + <string key="concept:name" value="82" /> + <event> + <int key="case" value="82" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2010-01-12 18:36:46" /> + </event> + <event> + <int key="case" value="82" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2010-01-12 18:36:46" /> + </event> + <event> + <int key="case" value="82" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2010-01-12 18:36:46" /> + </event> + <event> + <int key="case" value="82" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / enter" /> + <string key="timestamp" value="2010-01-19 07:57:20" /> + </event> + </trace> + <trace> + <string key="concept:name" value="83" /> + <event> + <int key="case" value="83" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2010-01-25 21:17:54" /> + </event> + <event> + <int key="case" value="83" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2010-02-01 10:38:28" /> + </event> + <event> + <int key="case" value="83" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2010-02-07 23:59:02" /> + </event> + <event> + <int key="case" value="83" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2010-02-07 23:59:02" /> + </event> + <event> + <int key="case" value="83" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2010-02-07 23:59:02" /> + </event> + <event> + <int key="case" value="83" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2010-02-07 23:59:02" /> + </event> + <event> + <int key="case" value="83" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2010-02-07 23:59:02" /> + </event> + <event> + <int key="case" value="83" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2010-02-07 23:59:02" /> + </event> + <event> + <int key="case" value="83" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2010-02-07 23:59:02" /> + </event> + <event> + <int key="case" value="83" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2010-02-14 13:19:36" /> + </event> + <event> + <int key="case" value="83" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2010-02-21 02:40:10" /> + </event> + <event> + <int key="case" value="83" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2010-02-21 02:40:10" /> + </event> + <event> + <int key="case" value="83" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2010-02-21 02:40:10" /> + </event> + </trace> + <trace> + <string key="concept:name" value="84" /> + <event> + <int key="case" value="84" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2010-03-06 05:21:18" /> + </event> + <event> + <int key="case" value="84" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2010-03-06 05:21:18" /> + </event> + <event> + <int key="case" value="84" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2010-03-06 05:21:18" /> + </event> + <event> + <int key="case" value="84" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2010-03-12 18:41:52" /> + </event> + </trace> + <trace> + <string key="concept:name" value="85" /> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2010-03-19 08:02:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-03-19 08:02:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-03-25 21:23:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-04-01 11:43:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2010-04-08 01:04:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2010-04-08 01:04:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-04-08 01:04:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2010-04-14 14:24:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2010-04-14 14:24:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-04-14 14:24:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2010-04-21 03:45:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-04-21 03:45:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2010-04-27 17:05:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-04-27 17:05:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2010-05-04 06:26:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2010-05-04 06:26:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2010-05-04 06:26:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-05-04 06:26:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-05-04 06:26:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-05-10 19:46:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-05-10 19:46:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-05-17 09:07:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-05-17 09:07:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / enter" /> + <string key="timestamp" value="2010-05-23 22:28:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-05-23 22:28:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-05-23 22:28:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-05-30 11:48:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-05-30 11:48:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-06-06 01:09:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-06-06 01:09:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-06-12 14:29:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-06-12 14:29:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2010-06-19 03:50:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge / High / exec" /> + <string key="timestamp" value="2010-06-19 03:50:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2010-06-19 03:50:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / enter" /> + <string key="timestamp" value="2010-06-19 03:50:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-06-19 03:50:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-06-19 03:50:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2010-06-25 17:10:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-06-25 17:10:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-06-25 17:10:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2010-07-02 06:31:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-07-02 06:31:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-07-02 06:31:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2010-07-08 19:52:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2010-07-08 19:52:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2010-07-08 19:52:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2010-07-08 19:52:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-07-08 19:52:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-07-15 09:12:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2010-07-21 22:33:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-07-21 22:33:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-07-28 11:53:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-08-04 01:14:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-08-10 14:34:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2010-08-17 03:55:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2010-08-17 03:55:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-08-17 03:55:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-08-23 17:16:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-08-30 06:36:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2010-09-05 19:57:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2010-09-05 19:57:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2010-09-05 19:57:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-09-05 19:57:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2010-09-12 09:17:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2010-09-12 09:17:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-09-12 09:17:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2010-09-18 22:38:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2010-09-18 22:38:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-09-18 22:38:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2010-09-25 11:58:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2010-09-25 11:58:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-09-25 11:58:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-09-25 11:58:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2010-10-02 01:19:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2010-10-02 01:19:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-10-02 01:19:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-10-02 01:19:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-10-08 14:40:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2010-10-08 14:40:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-10-08 14:40:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2010-10-15 04:00:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-10-15 04:00:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2010-10-15 04:00:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-10-15 04:00:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-10-21 17:21:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2010-10-21 17:21:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-10-21 17:21:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-10-28 06:41:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-10-28 06:41:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2010-11-03 19:02:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-11-03 19:02:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2010-11-10 08:22:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2010-11-10 08:22:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2010-11-10 08:22:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2010-11-10 08:22:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2010-11-10 08:22:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2010-11-10 08:22:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-11-10 08:22:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-11-10 08:22:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2010-11-16 21:43:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-11-16 21:43:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-11-16 21:43:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2010-11-23 11:03:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2010-11-23 11:03:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2010-11-23 11:03:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2010-11-23 11:03:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-11-23 11:03:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-11-23 11:03:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2010-11-30 00:24:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2010-11-30 00:24:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2010-11-30 00:24:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2010-11-30 00:24:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-11-30 00:24:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-11-30 00:24:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2010-12-06 13:45:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-12-06 13:45:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-12-06 13:45:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2010-12-13 03:05:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-12-13 03:05:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-12-13 03:05:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2010-12-19 16:26:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2010-12-19 16:26:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2010-12-19 16:26:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-12-19 16:26:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-12-19 16:26:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2010-12-26 05:46:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-12-26 05:46:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2010-12-26 05:46:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-01-01 19:07:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-01-01 19:07:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-01-01 19:07:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2011-01-08 08:27:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2011-01-08 08:27:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-01-08 08:27:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-01-08 08:27:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-01-08 08:27:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-01-14 21:48:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-01-14 21:48:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-01-14 21:48:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-01-21 11:09:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-01-21 11:09:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-01-21 11:09:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / enter" /> + <string key="timestamp" value="2011-01-28 00:29:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2011-01-28 00:29:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-01-28 00:29:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-01-28 00:29:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-01-28 00:29:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-02-03 13:50:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-02-03 13:50:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-02-03 13:50:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-02-10 03:10:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-02-10 03:10:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-02-10 03:10:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-02-16 16:31:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-02-16 16:31:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-02-16 16:31:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / enter" /> + <string key="timestamp" value="2011-02-23 05:51:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-02-23 05:51:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-02-23 05:51:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-02-23 05:51:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-02-23 05:51:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-03-01 19:12:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-03-01 19:12:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-03-01 19:12:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-03-01 19:12:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-03-08 08:33:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-03-08 08:33:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-03-08 08:33:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-03-08 08:33:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-03-14 21:53:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2011-03-14 21:53:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2011-03-14 21:53:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-03-14 21:53:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-03-14 21:53:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-03-14 21:53:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-03-21 11:14:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-03-21 11:14:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-03-21 11:14:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-03-28 01:34:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-03-28 01:34:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-03-28 01:34:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-04-03 14:55:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-04-03 14:55:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-04-03 14:55:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-04-10 04:15:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-04-10 04:15:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-04-10 04:15:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2011-04-16 17:36:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-04-16 17:36:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-04-16 17:36:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-04-16 17:36:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-04-23 06:57:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-04-23 06:57:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-04-23 06:57:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-04-29 20:17:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-04-29 20:17:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-04-29 20:17:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-05-06 09:38:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-05-06 09:38:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-05-06 09:38:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-05-12 22:58:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-05-12 22:58:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-05-12 22:58:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-05-19 12:19:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-05-19 12:19:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-05-19 12:19:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-05-26 01:39:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-05-26 01:39:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-05-26 01:39:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-06-01 15:00:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-06-01 15:00:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-06-01 15:00:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-06-08 04:20:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-06-08 04:20:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-06-08 04:20:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2011-06-14 17:41:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-06-14 17:41:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-06-14 17:41:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-06-14 17:41:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-06-21 07:02:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-06-21 07:02:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-06-21 07:02:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-06-27 20:22:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-06-27 20:22:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-06-27 20:22:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2011-07-04 09:43:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-07-04 09:43:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-07-04 09:43:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2011-07-10 23:03:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-07-10 23:03:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-07-10 23:03:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-07-10 23:03:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2011-07-17 12:24:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2011-07-17 12:24:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2011-07-17 12:24:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2011-07-17 12:24:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-07-17 12:24:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-07-17 12:24:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2011-07-24 01:44:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2011-07-24 01:44:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-07-24 01:44:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-07-24 01:44:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2011-07-30 15:05:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2011-07-30 15:05:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-07-30 15:05:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2011-08-06 04:26:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2011-08-06 04:26:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-08-06 04:26:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2011-08-12 17:46:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine / High / exec" /> + <string key="timestamp" value="2011-08-12 17:46:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / enter" /> + <string key="timestamp" value="2011-08-12 17:46:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2011-08-12 17:46:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-08-12 17:46:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2011-08-19 07:07:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-08-19 07:07:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2011-08-25 20:27:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2011-08-25 20:27:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-08-25 20:27:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-09-01 09:48:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-09-01 09:48:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-09-01 09:48:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-09-07 23:08:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-09-07 23:08:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2011-09-14 12:29:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2011-09-14 12:29:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2011-09-14 12:29:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-09-14 12:29:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-09-14 12:29:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2011-09-21 01:50:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-09-21 01:50:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-09-21 01:50:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-09-27 15:10:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2011-09-27 15:10:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2011-09-27 15:10:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-09-27 15:10:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-09-27 15:10:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2011-10-04 04:31:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-10-04 04:31:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-10-04 04:31:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-10-10 17:51:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification / High / exec" /> + <string key="timestamp" value="2011-10-10 17:51:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2011-10-10 17:51:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2011-10-10 17:51:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2011-10-10 17:51:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2011-10-10 17:51:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-10-10 17:51:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-10-10 17:51:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2011-10-10 17:51:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-10-17 07:12:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2011-10-17 07:12:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-10-17 07:12:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2011-10-17 07:12:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-10-23 20:32:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-10-23 20:32:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2011-10-23 20:32:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2011-10-23 20:32:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / enter" /> + <string key="timestamp" value="2011-10-23 20:32:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-10-23 20:32:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-10-23 20:32:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2011-10-23 20:32:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2011-10-30 08:53:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-10-30 08:53:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-10-30 08:53:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2011-10-30 08:53:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-11-05 22:14:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2011-11-05 22:14:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2011-11-05 22:14:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-11-05 22:14:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-11-05 22:14:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-11-05 22:14:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2011-11-05 22:14:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2011-11-12 11:34:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-11-12 11:34:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2011-11-12 11:34:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2011-11-12 11:34:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2011-11-12 11:34:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / enter" /> + <string key="timestamp" value="2011-11-12 11:34:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2011-11-12 11:34:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-11-12 11:34:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2011-11-12 11:34:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2011-11-19 00:55:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2011-11-19 00:55:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2011-11-19 00:55:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-11-19 00:55:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2011-11-19 00:55:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2011-11-19 00:55:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-11-25 14:15:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-11-25 14:15:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2011-11-25 14:15:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2011-11-25 14:15:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2011-11-25 14:15:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2011-11-25 14:15:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-11-25 14:15:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2011-11-25 14:15:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-12-02 03:36:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2011-12-02 03:36:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2011-12-02 03:36:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2011-12-02 03:36:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-12-02 03:36:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2011-12-02 03:36:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2011-12-08 16:56:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2011-12-08 16:56:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2011-12-08 16:56:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2011-12-08 16:56:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-12-08 16:56:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2011-12-08 16:56:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-12-15 06:17:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / enter" /> + <string key="timestamp" value="2011-12-15 06:17:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2011-12-15 06:17:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2011-12-15 06:17:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2011-12-15 06:17:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2011-12-15 06:17:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty / High / exec" /> + <string key="timestamp" value="2011-12-21 19:37:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2011-12-21 19:37:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2011-12-21 19:37:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2011-12-21 19:37:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2011-12-21 19:37:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-12-21 19:37:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2011-12-28 08:58:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2011-12-28 08:58:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2011-12-28 08:58:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2011-12-28 08:58:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2012-01-03 22:19:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2012-01-03 22:19:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-01-03 22:19:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-01-03 22:19:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-01-03 22:19:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-01-03 22:19:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2012-01-10 11:39:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2012-01-10 11:39:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2012-01-10 11:39:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2012-01-10 11:39:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-01-10 11:39:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-01-10 11:39:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-01-10 11:39:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-01-10 11:39:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2012-01-17 01:00:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2012-01-17 01:00:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-01-17 01:00:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-01-17 01:00:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-01-17 01:00:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-01-17 01:00:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-01-17 01:00:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-01-17 01:00:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2012-01-23 14:20:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-01-23 14:20:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-01-23 14:20:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-01-23 14:20:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-01-23 14:20:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-01-23 14:20:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2012-01-30 03:41:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2012-01-30 03:41:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-01-30 03:41:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-01-30 03:41:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-01-30 03:41:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-01-30 03:41:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-01-30 03:41:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-01-30 03:41:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-02-05 17:01:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / enter" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-12 06:22:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / enter" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-18 19:43:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-02-25 09:03:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-02 22:24:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-09 11:44:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-16 01:05:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-22 14:25:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-03-29 04:46:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-04 18:07:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-11 07:27:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-17 20:48:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-24 10:08:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / enter" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-04-30 23:29:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-07 12:49:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-14 02:10:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-20 15:31:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-05-27 04:51:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-02 18:12:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-09 07:32:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-15 20:53:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-22 10:13:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-06-28 23:34:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-05 12:54:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-12 02:15:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-18 15:36:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-25 04:56:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-07-31 18:17:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-07 07:37:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / enter" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-13 20:58:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-20 10:18:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-08-26 23:39:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-02 13:00:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-09 02:20:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment / High / exec" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-15 15:41:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-22 05:01:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-09-28 18:22:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-05 07:42:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-11 21:03:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-18 10:24:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-24 23:44:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-10-31 12:05:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-07 01:25:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-13 14:46:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-20 04:06:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-11-26 17:27:26" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-03 06:48:00" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-09 20:08:34" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-16 09:29:08" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-22 22:49:42" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2012-12-29 12:10:16" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-05 01:30:50" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-11 14:51:24" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-18 04:11:58" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-24 17:32:32" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-01-31 06:53:06" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-06 20:13:40" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / enter" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-13 09:34:14" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-19 22:54:48" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-02-26 12:15:22" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-05 01:35:56" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture / High / exec" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-11 14:56:30" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-18 04:17:04" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-24 17:37:38" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / enter" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-03-31 07:58:12" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-06 21:18:46" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-13 10:39:20" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / enter" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-19 23:59:54" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture / High / exec" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-04-26 13:20:28" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-03 02:41:02" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender / High / exec" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Notify Result Appeal to Offender / High / enter" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Add penalty / High / enter" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Add penalty / High / enter" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-09 16:01:36" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-16 05:22:10" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-22 18:42:44" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-05-29 08:03:18" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine / High / exec" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Payment / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Payment / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Payment / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Payment / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Payment / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Fine Notification<-->Add penalty / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Notify Result Appeal to Offender<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Insert Fine Notification / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send for Credit Collection<-->Send Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Fine<-->Appeal to Judge / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Insert Date Appeal to Prefecture<-->Send Fine / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Send for Credit Collection / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Create Fine<-->Payment / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Appeal to Judge<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Send Appeal to Prefecture<-->Receive Result Appeal from Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Receive Result Appeal from Prefecture<-->Notify Result Appeal to Offender / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Payment<-->Payment / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + <event> + <int key="case" value="85" /> + <string key="activity" value="Add penalty<-->Insert Date Appeal to Prefecture / High / wt" /> + <string key="timestamp" value="2013-06-04 21:23:52" /> + </event> + </trace> +</log> diff --git a/src/backend/main.py b/src/backend/main.py new file mode 100644 index 0000000000000000000000000000000000000000..a17a38ea7b80ef64fed60d814a1cf11ad838f6da --- /dev/null +++ b/src/backend/main.py @@ -0,0 +1,98 @@ +import os +from multiprocessing import cpu_count, freeze_support + +import uvicorn +from fastapi import FastAPI, HTTPException +from fastapi.exceptions import RequestValidationError +from fastapi.middleware.cors import CORSMiddleware + +from error_handlers import ( + http_exception_handler, + validation_exception_handler, + exception_handler, +) +from api.routes.api import router as api_router +from core.events import create_start_app_handler, create_stop_app_handler +from error_handlers import http_exception_handler, validation_exception_handler +from middleware.http_middleware import http_middleware +import argparse + +CORTADO_DEBUG = os.getenv("CORTADO_DEBUG", "0") == "1" + + +def get_application(): + app = FastAPI() + add_event_handlers(app) + add_middleware(app) + add_exception_handlers(app) + app.include_router(api_router) + return app + + +def add_event_handlers(app: FastAPI): + app.add_event_handler( + "startup", + create_start_app_handler(app), + ) + app.add_event_handler( + "shutdown", + create_stop_app_handler(app), + ) + + +def add_middleware(app: FastAPI): + app.middleware("http")(http_middleware) + origins = ["http://localhost", "http://localhost:8080", "http://localhost:4444"] + + app.add_middleware( + CORSMiddleware, + allow_origins=origins, + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], + ) + + +def add_exception_handlers(app: FastAPI): + app.add_exception_handler(HTTPException, http_exception_handler) + app.add_exception_handler(RequestValidationError, validation_exception_handler) + app.add_exception_handler(Exception, exception_handler) + + +app = get_application() + + +@app.get("/info") +async def get_info(): + return {} + + +# Using FastAPI instance +@app.get("/url-list") +def get_all_urls(): + url_list = [{"path": route.path, "name": route.name} for route in app.routes] + return url_list + + +if __name__ == "__main__": + # IMPORTANT: No other code between the `if __name__ == '__main__'` and freeze_support() + freeze_support() + parser = argparse.ArgumentParser() + parser.add_argument( + "--WEBSERVER_PORT", + default="40000", + type=int, + help="Specify the webserver port, defaults to 40000", + ) + args = parser.parse_args() + + # print(DEFAULT_LP_SOLVER_VARIANT) + uvicorn.run( + "main:app", + host="0.0.0.0", + port=args.WEBSERVER_PORT, + workers=1, + reload=CORTADO_DEBUG, + ) + # dev mode + # uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True) diff --git a/src/backend/middleware/__init__.py b/src/backend/middleware/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/middleware/http_middleware.py b/src/backend/middleware/http_middleware.py new file mode 100644 index 0000000000000000000000000000000000000000..df0d27a3c32d3f32a0cad3261fbde7045404b63b --- /dev/null +++ b/src/backend/middleware/http_middleware.py @@ -0,0 +1,19 @@ +import logging +import traceback + +from fastapi import Request + +from backend_utilities.util import build_json_error_rsp, get_trace + +logger = logging.getLogger("uvicorn") + + +async def http_middleware(request: Request, call_next): + try: + response = await call_next(request) + return response + except Exception as e: + logger.error( + "".join(traceback.format_exception(e, value=e, tb=e.__traceback__)) + ) + return build_json_error_rsp(str(e), get_trace(e), 500) diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..80bb299756c8875bd711e27889f1032c3deb1ffb --- /dev/null +++ b/src/backend/requirements.txt @@ -0,0 +1,12 @@ +fastapi +pydantic>=2.0.0 +uvicorn +cycler~=0.11.0 +networkx==3.0rc1 +python-multipart +pm4py==2.4.1 +appdirs +websockets +git+https://github.com/cortado-tool/cortado-core@main#egg=cortado_core +cvxopt +pyinstaller~=6.6.0 diff --git a/src/backend/resources/__init__.py b/src/backend/resources/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/resources/parameters.p b/src/backend/resources/parameters.p new file mode 100644 index 0000000000000000000000000000000000000000..a6032078e5ca9ae0917c53f1649c23f8a5aa4036 Binary files /dev/null and b/src/backend/resources/parameters.p differ diff --git a/src/backend/resources/sample_log.p b/src/backend/resources/sample_log.p new file mode 100644 index 0000000000000000000000000000000000000000..0dc963e85ea6e82715cfcd4fccb966608a616ba6 Binary files /dev/null and b/src/backend/resources/sample_log.p differ diff --git a/src/backend/resources/variants.p b/src/backend/resources/variants.p new file mode 100644 index 0000000000000000000000000000000000000000..3d1bb93cb942ee4266463696745dd2e82ca09631 Binary files /dev/null and b/src/backend/resources/variants.p differ diff --git a/src/backend/setup_cx_freeze.py b/src/backend/setup_cx_freeze.py new file mode 100644 index 0000000000000000000000000000000000000000..89754640431064b63e603df9f67ab78a95a9ca3f --- /dev/null +++ b/src/backend/setup_cx_freeze.py @@ -0,0 +1,32 @@ +import sys +import os +import opcode + +from cx_Freeze import setup, Executable + +print("SYSPATH: \n" + str(sys.path)) +distutils_path = os.path.join(os.path.dirname(opcode.__file__), "distutils") +print("distutils_path: \n" + str(distutils_path)) + +# Dependencies are automatically detected, but it might need fine tuning. +build_exe_options = { + "packages": ["os", "pulp"], + "excludes": ["tkinter"], + "include_files": [(distutils_path, "distutils")], +} + +# GUI applications require a different base on Windows (the default is for +# a console application). +base = None +if sys.platform == "win32": + base = "Win32GUI" + +# Run the application freezing. + +setup( + name="cortado-backend", + version="0.1", + description="My GUI application!", + options={"build_exe": build_exe_options}, + executables=[Executable("main.py", base=base)], +) diff --git a/src/backend/tests/__init__.py b/src/backend/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/backend/tests/test_timeout.py b/src/backend/tests/test_timeout.py new file mode 100644 index 0000000000000000000000000000000000000000..be6e904175d10c7325f44908a403590cdcfdd0f9 --- /dev/null +++ b/src/backend/tests/test_timeout.py @@ -0,0 +1,48 @@ +import time +import unittest + +from backend.backend_utilities.timeout.helper_functions import ( + TimeoutException, + execute_with_timeout, +) + + +class TimeoutTest(unittest.TestCase): + def test_raise_exception_when_timeout_occurs(self): + def test_func(): + try: + time.sleep(5) + except TimeoutException as t: + self.assertIsInstance(t, TimeoutException) + + try: + execute_with_timeout(test_func, 1) + except TimeoutException as t: + self.assertIsInstance(t, TimeoutException) + + def test_return_result_if_timeout_does_not_occur(self): + def test_func() -> int: + return 5 + + result = execute_with_timeout(test_func, 10) + self.assertEqual(result, 5) + + def test_raise_exception_from_inner_func_if_timeout_does_not_occur_before(self): + def test_func() -> int: + raise Exception("inner_exception") + + try: + execute_with_timeout(test_func, 10) + except Exception as e: + self.assertEqual(str(e), "inner_exception") + + def test_can_handle_function_with_arguments(self): + def test_func(a: int, b: int) -> int: + return a + b + + result = execute_with_timeout(test_func, 5, args=(2, 6)) + self.assertEqual(result, 8) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/backend/tmp/.gitkeep b/src/backend/tmp/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/.editorconfig b/src/frontend/.editorconfig new file mode 100644 index 0000000000000000000000000000000000000000..59d9a3a3e73ffc640517ef488f6f89d6270195d1 --- /dev/null +++ b/src/frontend/.editorconfig @@ -0,0 +1,16 @@ +# Editor configuration, see https://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.ts] +quote_type = single + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/src/frontend/.eslintignore b/src/frontend/.eslintignore new file mode 100644 index 0000000000000000000000000000000000000000..e4182f23228f4b871a7b215abf92ab8a6857b7e9 --- /dev/null +++ b/src/frontend/.eslintignore @@ -0,0 +1,4 @@ +node_modules +dist +app-dist +e2e diff --git a/src/frontend/.eslintrc.json b/src/frontend/.eslintrc.json new file mode 100644 index 0000000000000000000000000000000000000000..9dd13e37db74a29b37b2c19fe89fa3d04f523895 --- /dev/null +++ b/src/frontend/.eslintrc.json @@ -0,0 +1,76 @@ +{ + "root": true, + "ignorePatterns": [ + "projects/**/*" + ], + "overrides": [ + { + "files": [ + "*.ts", + "*.js" + ], + "parserOptions": { + "project": [ + "tsconfig.json", + "e2e/tsconfig.json" + ], + "createDefaultProgram": true + }, + "extends": [ + "plugin:@angular-eslint/recommended", + "plugin:@angular-eslint/template/process-inline-templates", + "plugin:prettier/recommended" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ], + "prettier/prettier": [ + "error", + { + "endOfLine": "auto" + } + ] + } + }, + { + "files": [ + "*.html" + ], + "extends": [ + "plugin:@angular-eslint/template/recommended" + ], + "rules": {} + }, + { + "files": [ + "*.component.html" + ], + "extends": [ + "plugin:prettier/recommended" + ], + "rules": {} + } + ], + "parserOptions": { + "ecmaVersion": 2017, + "sourceType": "module", + "allowImportExportEverywhere": true + }, + "env": { + "es6": true + } +} diff --git a/src/frontend/.gitignore b/src/frontend/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..87e939eedb79c6d4cab18d80457ae9db935ffe32 --- /dev/null +++ b/src/frontend/.gitignore @@ -0,0 +1,50 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/tmp +/out-tsc +# Only exists if Bazel was run +/bazel-out + +# dependencies +/node_modules + +# profiling files +chrome-profiler-events*.json +speed-measure-plugin*.json + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history/* + +# misc +/.angular/cache +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +yarn-error.log +testem.log +/typings + +# System Files +.DS_Store +Thumbs.db +/cortado-linux-x64/ +/cortado-win32-x64/ +/debug.log diff --git a/src/frontend/.htmlhintrc b/src/frontend/.htmlhintrc new file mode 100644 index 0000000000000000000000000000000000000000..a8eeab26158e2f1df7a6d4e28aee82e181d8c468 --- /dev/null +++ b/src/frontend/.htmlhintrc @@ -0,0 +1,22 @@ +{ + "attr-lowercase": false, // cannot handle - `<ng-template [ngIf]="isVisible">` + "attr-no-duplication": true, + "attr-unsafe-chars": true, + "attr-value-double-quotes": true, + "doctype-first": false, // Unable to handle HTML templates for components + "doctype-html5": true, + "id-class-ad-disabled": true, + "id-class-value": true, // but cannot handle - `<div class="{{card.css}}"></div>` + "id-unique": false, // cannot handle - + // <li *ngIf="isEdit"> <a id="id1">id1</a> </li> + // <li *ngIf="!isEdit"> <span id="id1">id1</span> </li> + "inline-style-disabled": false, + "space-tab-mixed-disabled": "space2", + "spec-char-escape": true, + "src-not-empty": true, + "style-disabled": true, + "tag-pair": true, + "tag-self-close": true, + "tagname-lowercase": true, + "title-require": true +} diff --git a/src/frontend/.stylelintignore b/src/frontend/.stylelintignore new file mode 100644 index 0000000000000000000000000000000000000000..1521c8b7652b1eec8ed4fe50877aae880c758ee3 --- /dev/null +++ b/src/frontend/.stylelintignore @@ -0,0 +1 @@ +dist diff --git a/src/frontend/.stylelintrc.json b/src/frontend/.stylelintrc.json new file mode 100644 index 0000000000000000000000000000000000000000..738f882687e864d305dec3639681e8e28f113547 --- /dev/null +++ b/src/frontend/.stylelintrc.json @@ -0,0 +1,10 @@ +{ + "extends": "stylelint-config-standard-scss", + "rules": { + "no-empty-source": null, + "selector-pseudo-element-no-unknown": [ + true, + { "ignorePseudoElements": ["ng-deep"] } + ] + } +} diff --git a/src/frontend/angular.json b/src/frontend/angular.json new file mode 100644 index 0000000000000000000000000000000000000000..7db1bdc4b6c877cf06db20df8063c543f3f83aec --- /dev/null +++ b/src/frontend/angular.json @@ -0,0 +1,159 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "cli": { + "analytics": false, + "schematicCollections": ["@angular-eslint/schematics"] + }, + "version": 1, + "newProjectRoot": "projects", + "projects": { + "interactive-process-mining-angular-app": { + "projectType": "application", + "schematics": {}, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-builders/custom-webpack:browser", + "options": { + "outputPath": "dist", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "tsconfig.app.json", + "assets": [ + "src/assets", + { + "glob": "**/*", + "input": "node_modules/monaco-editor", + "output": "assets/monaco-editor/" + } + ], + "styles": [ + "./node_modules/golden-layout/dist/css/goldenlayout-base.css", + "./node_modules/golden-layout/dist/css/themes/goldenlayout-borderless-dark-theme.css", + "src/styles.scss" + ], + "scripts": [ + "node_modules/jquery/dist/jquery.min.js", + "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js", + "node_modules/gumshoejs/dist/gumshoe.polyfills.min.js" + ], + "vendorChunk": true, + "extractLicenses": false, + "buildOptimizer": false, + "sourceMap": true, + "optimization": false, + "namedChunks": true, + "customWebpackConfig": { + "path": "./custom-webpack.config.js", + "mergeRules": { + "externals": "replace" + } + } + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "namedChunks": false, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "8mb", + "maximumError": "10mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb", + "maximumError": "10kb" + } + ] + }, + "browser": { + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.browser.ts" + } + ] + } + }, + "defaultConfiguration": "" + }, + "serve": { + "builder": "@angular-builders/custom-webpack:dev-server", + "options": { + "browserTarget": "interactive-process-mining-angular-app:build" + }, + "configurations": { + "production": { + "browserTarget": "interactive-process-mining-angular-app:build:production" + }, + "browser": { + "browserTarget": "interactive-process-mining-angular-app:build:browser" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "interactive-process-mining-angular-app:build" + } + }, + "test": { + "builder": "@angular-builders/custom-webpack:karma", + "options": { + "main": "src/test.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "tsconfig.spec.json", + "karmaConfig": "karma.conf.js", + "assets": ["src/favicon.ico", "src/assets"], + "styles": ["src/styles.scss"], + "scripts": [], + "customWebpackConfig": { + "path": "./custom-webpack.config.js" + } + } + }, + "e2e": { + "builder": "@angular-devkit/build-angular:protractor", + "options": { + "protractorConfig": "e2e/protractor.conf.js", + "devServerTarget": "interactive-process-mining-angular-app:serve" + }, + "configurations": { + "production": { + "devServerTarget": "interactive-process-mining-angular-app:serve:production" + } + } + }, + "lint": { + "builder": "@angular-eslint/builder:lint", + "options": { + "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"] + } + } + } + } + }, + "schematics": { + "@angular-eslint/schematics:application": { + "setParserOptionsProject": true + }, + "@angular-eslint/schematics:library": { + "setParserOptionsProject": true + } + } +} diff --git a/src/frontend/build-hooks/afterAllArtifactBuild.js b/src/frontend/build-hooks/afterAllArtifactBuild.js new file mode 100644 index 0000000000000000000000000000000000000000..aae426fe75964431ff97d51abceb1003d373328a --- /dev/null +++ b/src/frontend/build-hooks/afterAllArtifactBuild.js @@ -0,0 +1,16 @@ +exports.default = () => { + const fs = require("fs"); + const process = require("process"); + const path = require("path"); + let appBuildDir = "app-dist"; + if (fs.existsSync(path.join(__dirname, "..", appBuildDir, "win-unpacked"))) { + appOutDir = "win-unpacked"; + } else if ( + fs.existsSync(path.join(__dirname, "..", appBuildDir, "linux-unpacked")) + ) { + appOutDir = "linux-unpacked"; + } else { + // ignore for macos build + return; + } +}; diff --git a/src/frontend/build/VC_redist.x64.exe b/src/frontend/build/VC_redist.x64.exe new file mode 100644 index 0000000000000000000000000000000000000000..faa9a1b92c58684ed4f3875de5e736cdafdba8ef Binary files /dev/null and b/src/frontend/build/VC_redist.x64.exe differ diff --git a/src/frontend/build/installer.nsh b/src/frontend/build/installer.nsh new file mode 100644 index 0000000000000000000000000000000000000000..307ef276466143a00bdd089dc8d5bbd1f9be7671 --- /dev/null +++ b/src/frontend/build/installer.nsh @@ -0,0 +1,4 @@ +!macro customInstall + File /oname=$PLUGINSDIR\VC_redist.x64.exe "${BUILD_RESOURCES_DIR}\VC_redist.x64.exe" + ExecWait "$PLUGINSDIR\VC_redist.x64.exe" +!macroend diff --git a/src/frontend/custom-webpack.config.js b/src/frontend/custom-webpack.config.js new file mode 100644 index 0000000000000000000000000000000000000000..3714d411e7ebc0eff36b606ed6f8bee228ac1b68 --- /dev/null +++ b/src/frontend/custom-webpack.config.js @@ -0,0 +1,29 @@ +const webpack = require("webpack"); +const path = require("path"); +const MONACO_DIR = path.join(__dirname, "", "node_modules/monaco-editor"); + +/** + * Using this custom webpack config to load the css files + * in monaco editor library. More information here: + * https://github.com/microsoft/monaco-editor/issues/886 + */ + +module.exports = { + module: { + rules: [ + { + test: /\.css$/, + include: MONACO_DIR, + use: [ + "style-loader", + { + loader: "css-loader", + options: { + url: false, + }, + }, + ], + }, + ], + }, +}; diff --git a/src/frontend/e2e/protractor.conf.js b/src/frontend/e2e/protractor.conf.js new file mode 100644 index 0000000000000000000000000000000000000000..f238c0bbebe93459d152a88a40da7aa0eeb8e91b --- /dev/null +++ b/src/frontend/e2e/protractor.conf.js @@ -0,0 +1,36 @@ +// @ts-check +// Protractor configuration file, see link for more information +// https://github.com/angular/protractor/blob/master/lib/config.ts + +const { SpecReporter, StacktraceOption } = require('jasmine-spec-reporter'); + +/** + * @type { import("protractor").Config } + */ +exports.config = { + allScriptsTimeout: 11000, + specs: [ + './src/**/*.e2e-spec.ts' + ], + capabilities: { + browserName: 'chrome' + }, + directConnect: true, + baseUrl: 'http://localhost:4200/', + framework: 'jasmine', + jasmineNodeOpts: { + showColors: true, + defaultTimeoutInterval: 30000, + print: function() {} + }, + onPrepare() { + require('ts-node').register({ + project: require('path').join(__dirname, './tsconfig.json') + }); + jasmine.getEnv().addReporter(new SpecReporter({ + spec: { + displayStacktrace: StacktraceOption.PRETTY + } + })); + } +}; \ No newline at end of file diff --git a/src/frontend/e2e/src/app.e2e-spec.ts b/src/frontend/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..efcb8d731a0a343fd44bff1111b8c74ba428c204 --- /dev/null +++ b/src/frontend/e2e/src/app.e2e-spec.ts @@ -0,0 +1,27 @@ +import { AppPage } from './app.po'; +import { browser, logging } from 'protractor'; + +describe('workspace-project App', () => { + let page: AppPage; + + beforeEach(() => { + page = new AppPage(); + }); + + it('should display welcome message', () => { + page.navigateTo(); + expect(page.getTitleText()).toEqual( + 'interactive-process-mining-angular-app app is running!' + ); + }); + + afterEach(async () => { + // Assert that there are no errors emitted from the browser + const logs = await browser.manage().logs().get(logging.Type.BROWSER); + expect(logs).not.toContain( + jasmine.objectContaining({ + level: logging.Level.SEVERE, + } as logging.Entry) + ); + }); +}); diff --git a/src/frontend/e2e/src/app.po.ts b/src/frontend/e2e/src/app.po.ts new file mode 100644 index 0000000000000000000000000000000000000000..c63155bc62fcdc0bc87ccc560a5a7c28d95db57c --- /dev/null +++ b/src/frontend/e2e/src/app.po.ts @@ -0,0 +1,13 @@ +import { browser, by, element } from 'protractor'; + +export class AppPage { + navigateTo(): Promise<unknown> { + return browser.get(browser.baseUrl) as Promise<unknown>; + } + + getTitleText(): Promise<string> { + return element( + by.css('app-root .content span') + ).getText() as Promise<string>; + } +} diff --git a/src/frontend/e2e/tsconfig.json b/src/frontend/e2e/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..426058ef0fbe764d66b4c48429e3ab988de21aee --- /dev/null +++ b/src/frontend/e2e/tsconfig.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/e2e", + "module": "commonjs", + "target": "es2018", + "types": [ + "jasmine", + "jasminewd2", + "node" + ] + } +} diff --git a/src/frontend/karma.conf.js b/src/frontend/karma.conf.js new file mode 100644 index 0000000000000000000000000000000000000000..64a7fb97377d2abff7694cf8712ead0302f4e990 --- /dev/null +++ b/src/frontend/karma.conf.js @@ -0,0 +1,35 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: "", + frameworks: ["jasmine", "@angular-devkit/build-angular"], + plugins: [ + require("karma-jasmine"), + require("karma-chrome-launcher"), + require("karma-jasmine-html-reporter"), + require("karma-coverage-istanbul-reporter"), + require("@angular-devkit/build-angular/plugins/karma"), + ], + client: { + clearContext: false, // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require("path").join( + __dirname, + "./coverage/interactive-process-mining-angular-app" + ), + reports: ["html", "lcovonly", "text-summary"], + fixWebpackSourcePaths: true, + }, + reporters: ["progress", "kjhtml"], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ["Chrome"], + singleRun: false, + restartOnFileChange: true, + }); +}; diff --git a/src/frontend/main-electron.js b/src/frontend/main-electron.js new file mode 100644 index 0000000000000000000000000000000000000000..a7be4d8adf4c9b58bb905d91ff879d30d49c8634 --- /dev/null +++ b/src/frontend/main-electron.js @@ -0,0 +1,213 @@ +const { app, BrowserWindow, dialog, ipcMain, shell } = require("electron"); +var fs = require("fs"); +const { + showSaveDialog, + saveToUserFolder, + readFromUserFolder, +} = require("./util"); +const nativeImage = require("electron").nativeImage; +const url = require("url"); +const path = require("path"); +const kill = require("tree-kill"); +const ChildProcess = require("child_process"); +const Store = require("electron-store"); +const executablePath = app.getPath("exe"); +const downloadFolder = app.getPath("downloads"); +const backendWorkDir = path.join( + path.dirname(executablePath), + process.platform === "darwin" ? ".." : "", // electron-builder puts the executable in `MacOS/` folder, + // so must move one level up to find `cortado-backend` + "cortado-backend" +); +const rawBackendExecutablePath = path.join( + backendWorkDir, + process.platform === "win32" ? "cortado-backend.exe" : "cortado-backend" +); + +const backendExecutablePath = `"${rawBackendExecutablePath}"`; + +const lastAcceptedVersionKey = "lastAcceptedVersion"; +const isDevelopment = process.env.NODE_ENV === "development"; + +let mainCortadoWin; +let backendProcess; + +let closeAttempts = 0; +let lastCloseAttempt = 0; +const closeAttemptThresholdInMs = 3000; + +WS_PORT = 40000; +const portfinder = require("portfinder"); + +function startBackend() { + let portArgument = "--WEBSERVER_PORT " + WS_PORT; + return ChildProcess.spawn(backendExecutablePath, [portArgument], { + shell: true, + detached: true, + windowsHide: false, + cwd: backendWorkDir, + }); +} + +ipcMain.on("restartBackend", () => { + if (isDevelopment) { + console.log( + "DEV: Backend restart requested but backend is not managed while in development mode." + ); + } else { + console.log("Restarting Backend"); + killBackendProcess(); + backendProcess = startBackend(); + } +}); + +ipcMain.handle( + "showSaveDialog", + (_, fileName, fileExtension, base64File, buttonLabel, title) => + showSaveDialog( + downloadFolder, + dialog, + fs, + mainCortadoWin, + fileName, + fileExtension, + base64File, + buttonLabel, + title + ) +); + +function createMainApplicationWindow() { + mainCortadoWin = new BrowserWindow({ + minHeight: 600, + minWidth: 900, + width: 1000, + height: 800, + frame: true, + webPreferences: { + preload: path.join(__dirname, "preload.js"), + nodeIntegration: true, + contextIsolation: true, + }, + darkTheme: true, + }); + mainCortadoWin.removeMenu(); + + //mainCortadoWin.webContents.openDevTools() + //mainCortadoWin.loadURL('data:text/html;charset=utf-8,' + backendExecutablePathWindows); + + if (isDevelopment) { + mainCortadoWin.loadURL("http://localhost:4444"); + mainCortadoWin.webContents.openDevTools(); + } else { + mainCortadoWin.loadFile("dist/index.html"); + } + + mainCortadoWin.on("closed", function () { + mainCortadoWin = null; + app.quit(); + }); + + mainCortadoWin.on("close", async (e) => { + const now = Date.now(); + if (now - lastCloseAttempt > closeAttemptThresholdInMs) closeAttempts = 0; + if (closeAttempts < 2) { + e.preventDefault(); // Prevents default close behavior + // ask projectService for unsaved Changes + // response on "unsaved-changes" + mainCortadoWin.webContents.send("check-unsaved-changes"); + closeAttempts++; + lastCloseAttempt = now; + } + }); + + // prevent external links from being opened in an electron window + mainCortadoWin.webContents.setWindowOpenHandler(({ url }) => { + shell.openExternal(url); + return { action: "deny" }; + }); +} + +function killBackendProcess() { + if (backendProcess) { + if (process.platform == "win32") { + kill(backendProcess.pid); + } else { + ChildProcess.execSync("killall -9 cortado-backend", { shell: "/bin/sh" }); + } + } +} + +app.whenReady().then(function () { + if (!isDevelopment) { + // Find free port + portfinder.getPort( + { + port: 40000, // minimum port + stopPort: 49999, // maximum port + }, + function (err, port) { + WS_PORT = port; + createMainApplicationWindow(); + backendProcess = startBackend(); + } + ); + } else { + createMainApplicationWindow(); + } +}); + +app.on("quit", function () { + if (!isDevelopment) { + killBackendProcess(); + } +}); + +app.on("window-all-closed", function () { + //On macOS specific close process + if (process.platform !== "darwin") { + app.quit(); + } +}); + +app.on("activate", function () { + //macOS specific + if (mainCortadoWin === null) { + createMainApplicationWindow(); + } +}); + +ipcMain.on("unsaved-changes", async (_event, res) => { + if (!res) mainCortadoWin.destroy(); + else { + const { response } = await dialog.showMessageBox(mainCortadoWin, { + type: "warning", + title: "Save Project?", + message: "Save Cortado project before closing?", + detail: "All progress will be lost if you don't save it.", + buttons: ["Don't Save", "Cancel", "Save"], + defaultId: 2, + }); + + if (response === 0) mainCortadoWin.destroy(); + else if (response === 2) { + mainCortadoWin.webContents.send("save-project"); + } + } +}); + +ipcMain.on("saveToUserFolder", (_, fileName, fileExtension, data) => + saveToUserFolder(app.getPath("userData"), fileName, fileExtension, data) +); + +ipcMain.handle("readFromUserFolder", (_, fileName, fileExtension) => + readFromUserFolder(app.getPath("userData"), fileName, fileExtension) +); + +ipcMain.handle("getWSPort", (_) => { + return WS_PORT; +}); + +ipcMain.on("quit", () => { + mainCortadoWin.destroy(); +}); diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..fea6f79fe08854ce5a06d4b0fa013226e8743948 --- /dev/null +++ b/src/frontend/package-lock.json @@ -0,0 +1,37752 @@ +{ + "name": "Cortado", + "version": "1.12.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "Cortado", + "version": "1.12.1", + "dependencies": { + "@monaco-editor/loader": "^1.3.2", + "@perfectmemory/ngx-contextmenu": "^16.0.2", + "class-transformer": "^0.5.1", + "copy-webpack-plugin": "^11.0.0", + "d3": "~7.9.0", + "electron-store": "^8.2.0", + "gumshoejs": "^5.1.2", + "humanize-duration-ts": "^2.1.1", + "jquery": "^3.7.1", + "lodash": "^4.17.21", + "monaco-editor": "^0.34.0", + "monaco-editor-webpack-plugin": "^7.1.0", + "ngx-clipboard": "^16.0.0", + "ngx-color-picker": "^16.0.0", + "ngx-file-drop": "^16.0.0", + "ngx-markdown": "^16.0.0", + "ngx-slider-v2": "^16.0.2", + "object-hash": "^2.2.0", + "portfinder": "^1.0.32", + "reflect-metadata": "^0.1.14", + "svgo": "^3.2.0", + "tree-kill": "^1.2.2" + }, + "devDependencies": { + "@angular-builders/custom-webpack": "^16.0.1", + "@angular-devkit/build-angular": "^16.2.13", + "@angular-eslint/builder": "16.3.1", + "@angular-eslint/eslint-plugin": "16.3.1", + "@angular-eslint/eslint-plugin-template": "16.3.1", + "@angular-eslint/schematics": "16.3.1", + "@angular-eslint/template-parser": "16.3.1", + "@angular/animations": "^16.2.12", + "@angular/cdk": "^16.2.14", + "@angular/cli": "^16.2.13", + "@angular/common": "^16.2.12", + "@angular/compiler": "^16.2.12", + "@angular/compiler-cli": "^16.2.12", + "@angular/core": "^16.2.12", + "@angular/forms": "^16.2.12", + "@angular/platform-browser": "^16.2.12", + "@angular/platform-browser-dynamic": "^16.2.12", + "@angular/router": "^16.2.12", + "@ng-bootstrap/ng-bootstrap": "^15.1.2", + "@sweetalert2/ngx-sweetalert2": "^11.0.0", + "@types/bootstrap": "^5.2.10", + "@types/d3": "^7.4.3", + "@types/electron": "^1.6.10", + "@types/jasmine": "~5.1.4", + "@types/jasminewd2": "~2.0.13", + "@types/jquery": "^3.5.29", + "@types/lodash": "^4.17.0", + "@types/node": "^20.11.30", + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", + "bootstrap": "5.2", + "bootstrap-icons": "^1.11.3", + "codelyzer": "^6.0.2", + "concurrently": "^6.4.0", + "cross-env": "^7.0.3", + "css-loader": "^6.10.0", + "d3-flextree": "^2.1.2", + "electron": "~29.1.5 ", + "electron-builder": "^24.13.3", + "electron-packager": "^17.1.2", + "eslint": "^8.57.0", + "eslint-config-prettier": "^8.3.0", + "eslint-formatter-codeframe": "^7.32.1", + "eslint-plugin-prettier": "^4.0.0", + "eslint-summary": "^1.0.0", + "file-saver": "^2.0.5", + "golden-layout": "^2.4.0", + "htmlhint": "^1.1.4", + "jasmine-core": "~3.10.0", + "jasmine-spec-reporter": "~7.0.0", + "karma": "^6.4.3", + "karma-chrome-launcher": "~3.1.0", + "karma-coverage-istanbul-reporter": "~3.0.2", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", + "nice-try": "^3.0.0", + "protractor": "~7.0.0", + "rxjs": "~6.6.0", + "style-loader": "^3.3.4", + "stylelint": "^15.11.0", + "stylelint-config-standard": "^34.0.0", + "stylelint-config-standard-scss": "^10.0.0", + "ts-node": "~8.3.0", + "tslib": "^2.6.2", + "typescript": "5.1.6", + "wait-on": "^5.3.0", + "yargs-parser": "^21.0.0", + "zone.js": "~0.13.3" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@angular-builders/custom-webpack": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@angular-builders/custom-webpack/-/custom-webpack-16.0.1.tgz", + "integrity": "sha512-C6INC8UOYDcp8LJwNhE0m66yp+nZX50JdgGI8oRn7fqw3gO58qhDgXrR/8BCrSeC8eOx8WxSuvBJ6u+9dozhyw==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": ">=0.1600.0 < 0.1700.0", + "@angular-devkit/build-angular": "^16.0.0", + "@angular-devkit/core": "^16.0.0", + "lodash": "^4.17.15", + "ts-node": "^10.0.0", + "tsconfig-paths": "^4.1.0", + "webpack-merge": "^5.7.3" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^16.0.0" + } + }, + "node_modules/@angular-builders/custom-webpack/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/architect": { + "version": "0.1602.13", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.13.tgz", + "integrity": "sha512-ejrOYoXgbhDYjdaW4B2SyWeb6AqR8vqqzMyvCq2JX7fo08IhLnVu1fcl0fwr161l37TuzgPNWrHSciOzzmZDkw==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.2.13", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/architect/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@angular-devkit/build-angular": { + "version": "16.2.13", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.13.tgz", + "integrity": "sha512-2G8gnBpBKcu+/jJH5DJZyMgn2RwDFPgiNSkcLKFg5DdqVFVT3CCoZAobfpAEMndrysfMmoUPGuAmsgCfdczQjg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "2.2.1", + "@angular-devkit/architect": "0.1602.13", + "@angular-devkit/build-webpack": "0.1602.13", + "@angular-devkit/core": "16.2.13", + "@babel/core": "7.22.9", + "@babel/generator": "7.22.9", + "@babel/helper-annotate-as-pure": "7.22.5", + "@babel/helper-split-export-declaration": "7.22.6", + "@babel/plugin-proposal-async-generator-functions": "7.20.7", + "@babel/plugin-transform-async-to-generator": "7.22.5", + "@babel/plugin-transform-runtime": "7.22.9", + "@babel/preset-env": "7.22.9", + "@babel/runtime": "7.22.6", + "@babel/template": "7.22.5", + "@discoveryjs/json-ext": "0.5.7", + "@ngtools/webpack": "16.2.13", + "@vitejs/plugin-basic-ssl": "1.0.1", + "ansi-colors": "4.1.3", + "autoprefixer": "10.4.14", + "babel-loader": "9.1.3", + "babel-plugin-istanbul": "6.1.1", + "browserslist": "^4.21.5", + "chokidar": "3.5.3", + "copy-webpack-plugin": "11.0.0", + "critters": "0.0.20", + "css-loader": "6.8.1", + "esbuild-wasm": "0.18.17", + "fast-glob": "3.3.1", + "guess-parser": "0.4.22", + "https-proxy-agent": "5.0.1", + "inquirer": "8.2.4", + "jsonc-parser": "3.2.0", + "karma-source-map-support": "1.4.0", + "less": "4.1.3", + "less-loader": "11.1.0", + "license-webpack-plugin": "4.0.2", + "loader-utils": "3.2.1", + "magic-string": "0.30.1", + "mini-css-extract-plugin": "2.7.6", + "mrmime": "1.0.1", + "open": "8.4.2", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "7.0.0", + "picomatch": "2.3.1", + "piscina": "4.0.0", + "postcss": "8.4.31", + "postcss-loader": "7.3.3", + "resolve-url-loader": "5.0.0", + "rxjs": "7.8.1", + "sass": "1.64.1", + "sass-loader": "13.3.2", + "semver": "7.5.4", + "source-map-loader": "4.0.1", + "source-map-support": "0.5.21", + "terser": "5.19.2", + "text-table": "0.2.0", + "tree-kill": "1.2.2", + "tslib": "2.6.1", + "vite": "4.5.2", + "webpack": "5.88.2", + "webpack-dev-middleware": "6.1.2", + "webpack-dev-server": "4.15.1", + "webpack-merge": "5.9.0", + "webpack-subresource-integrity": "5.1.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "optionalDependencies": { + "esbuild": "0.18.17" + }, + "peerDependencies": { + "@angular/compiler-cli": "^16.0.0", + "@angular/localize": "^16.0.0", + "@angular/platform-server": "^16.0.0", + "@angular/service-worker": "^16.0.0", + "jest": "^29.5.0", + "jest-environment-jsdom": "^29.5.0", + "karma": "^6.3.0", + "ng-packagr": "^16.0.0", + "protractor": "^7.0.0", + "tailwindcss": "^2.0.0 || ^3.0.0", + "typescript": ">=4.9.3 <5.2" + }, + "peerDependenciesMeta": { + "@angular/localize": { + "optional": true + }, + "@angular/platform-server": { + "optional": true + }, + "@angular/service-worker": { + "optional": true + }, + "jest": { + "optional": true + }, + "jest-environment-jsdom": { + "optional": true + }, + "karma": { + "optional": true + }, + "ng-packagr": { + "optional": true + }, + "protractor": { + "optional": true + }, + "tailwindcss": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/core": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", + "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.8", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/generator": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", + "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/template": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/css-loader": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", + "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.3", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/es-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/schema-utils/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/terser": { + "version": "5.19.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz", + "integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/tslib": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack": { + "version": "5.88.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", + "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack-merge": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", + "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@angular-devkit/build-webpack": { + "version": "0.1602.13", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.13.tgz", + "integrity": "sha512-H7CqnC0kvWR0Q45ZXsCO3M9lGd4dOajEmkCVmq7vVptU3nJRbCqJ0ZScj9bH5YSlcdO0jPbOdcTELWyEZ3BMFQ==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1602.13", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "webpack": "^5.30.0", + "webpack-dev-server": "^4.0.0" + } + }, + "node_modules/@angular-devkit/build-webpack/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@angular-devkit/core": { + "version": "16.2.13", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.13.tgz", + "integrity": "sha512-6jTlYOIeYsOF/Vw/hBNusjoCmKJBByoyGS1Fu2Yav8ltxYK04aDtI73l9JJB/5Cpzhc4YELrMqBMH7in5Vowaw==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "picomatch": "2.3.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/core/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@angular-devkit/schematics": { + "version": "16.2.13", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.13.tgz", + "integrity": "sha512-uhhJZpppaeuT/2V6RiCheJKzS4bAZADL+Gw59VJaojqS8ssdG1UzvqRJokIzFzP7+MhHWylZBWUvWLQxuUvtsA==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.2.13", + "jsonc-parser": "3.2.0", + "magic-string": "0.30.1", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@angular-eslint/builder": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.3.1.tgz", + "integrity": "sha512-PmIOnRwqdOW1bvZtpTGBTDcOq/Czm3D+IPC/k90yIMs1VsAtcxqUmUtELje+ylJeb2LPeEZavekSnEpcatM4HQ==", + "dev": true, + "dependencies": { + "@nx/devkit": "16.5.1", + "nx": "16.5.1" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/bundled-angular-compiler": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-16.3.1.tgz", + "integrity": "sha512-m4WP1xwS9XLcC/3n6lIcG5HZoai/5eb5W3xm48GVcv//0qE2p7S96RSgKPgGHvif5pF8O9xAqEWs3gDEG45+7A==", + "dev": true + }, + "node_modules/@angular-eslint/eslint-plugin": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-16.3.1.tgz", + "integrity": "sha512-kSc8ESfoy8TUSthbq0Lpq9e17I+3Smy4rHoNpKCFEGuJgPs0+OssZMxB6a5EawGbv2EKTPEtrxzFm1WsLR0U9Q==", + "dev": true, + "dependencies": { + "@angular-eslint/utils": "16.3.1", + "@typescript-eslint/utils": "5.62.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/eslint-plugin-template": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-16.3.1.tgz", + "integrity": "sha512-+RcFEWqNiRt3+5jXvmlIDlXtP9+vjdmgmVL6tt8yDbqdjBOewtyMu4pE4YaR4sFboyxgME9PbO2WrOyPXh6xjg==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "16.3.1", + "@angular-eslint/utils": "16.3.1", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "aria-query": "5.3.0", + "axobject-query": "4.0.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/schematics": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-16.3.1.tgz", + "integrity": "sha512-cqrdobdtRY2XjLa6PhuGOQ7UhTRk2AvWS01sKeGjZ94nQJm5NUtEUyf6u3deIPYllW7gSAWjYzKUObKcTW/R+g==", + "dev": true, + "dependencies": { + "@angular-eslint/eslint-plugin": "16.3.1", + "@angular-eslint/eslint-plugin-template": "16.3.1", + "@nx/devkit": "16.5.1", + "ignore": "5.2.4", + "nx": "16.5.1", + "strip-json-comments": "3.1.1", + "tmp": "0.2.1" + }, + "peerDependencies": { + "@angular/cli": ">= 16.0.0 < 17.0.0" + } + }, + "node_modules/@angular-eslint/template-parser": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-16.3.1.tgz", + "integrity": "sha512-9+SxUtxB2iOnm0ldS2ow0stMxe02rB/TxeMIe8fxsLFHZdw8RQvs/p3HLvVHXzv6gUblMHebIb/ubUmwEVb2SA==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "16.3.1", + "eslint-scope": "^7.0.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/template-parser/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@angular-eslint/template-parser/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@angular-eslint/utils": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-16.3.1.tgz", + "integrity": "sha512-tEBcce0rG+DmcPO8jhRffUFDioGw3G4cUAE15XlRctY1J3QzOBH9HdUOTDt0mMjBgpWCzh0YVT1Moh2bPXU9Xg==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "16.3.1", + "@typescript-eslint/utils": "5.62.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular/animations": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-16.2.12.tgz", + "integrity": "sha512-MD0ElviEfAJY8qMOd6/jjSSvtqER2RDAi0lxe6EtUacC1DHCYkaPrKW4vLqY+tmZBg1yf+6n+uS77pXcHHcA3w==", + "devOptional": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/core": "16.2.12" + } + }, + "node_modules/@angular/cdk": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-16.2.14.tgz", + "integrity": "sha512-n6PrGdiVeSTEmM/HEiwIyg6YQUUymZrb5afaNLGFRM5YL0Y8OBqd+XhCjb0OfD/AfgCUtedVEPwNqrfW8KzgGw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "optionalDependencies": { + "parse5": "^7.1.2" + }, + "peerDependencies": { + "@angular/common": "^16.0.0 || ^17.0.0", + "@angular/core": "^16.0.0 || ^17.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/cli": { + "version": "16.2.13", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.13.tgz", + "integrity": "sha512-Zs/IHV0qeQBlRYp3XTJP96KKMFrOVd4gFWEXyt8xVbma9W7UCWr/0C6D8HRFjheiT40TSa2Suwpk6Hppm+9ESA==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1602.13", + "@angular-devkit/core": "16.2.13", + "@angular-devkit/schematics": "16.2.13", + "@schematics/angular": "16.2.13", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.3", + "ini": "4.1.1", + "inquirer": "8.2.4", + "jsonc-parser": "3.2.0", + "npm-package-arg": "10.1.0", + "npm-pick-manifest": "8.0.1", + "open": "8.4.2", + "ora": "5.4.1", + "pacote": "15.2.0", + "resolve": "1.22.2", + "semver": "7.5.4", + "symbol-observable": "4.0.0", + "yargs": "17.7.2" + }, + "bin": { + "ng": "bin/ng.js" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@angular/common": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-16.2.12.tgz", + "integrity": "sha512-B+WY/cT2VgEaz9HfJitBmgdk4I333XG/ybC98CMC4Wz8E49T8yzivmmxXB3OD6qvjcOB6ftuicl6WBqLbZNg2w==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/core": "16.2.12", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/compiler": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-16.2.12.tgz", + "integrity": "sha512-6SMXUgSVekGM7R6l1Z9rCtUGtlg58GFmgbpMCsGf+VXxP468Njw8rjT2YZkf5aEPxEuRpSHhDYjqz7n14cwCXQ==", + "dev": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/core": "16.2.12" + }, + "peerDependenciesMeta": { + "@angular/core": { + "optional": true + } + } + }, + "node_modules/@angular/compiler-cli": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-16.2.12.tgz", + "integrity": "sha512-pWSrr152562ujh6lsFZR8NfNc5Ljj+zSTQO44DsuB0tZjwEpnRcjJEgzuhGXr+CoiBf+jTSPZKemtSktDk5aaA==", + "dev": true, + "dependencies": { + "@babel/core": "7.23.2", + "@jridgewell/sourcemap-codec": "^1.4.14", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "reflect-metadata": "^0.1.2", + "semver": "^7.0.0", + "tslib": "^2.3.0", + "yargs": "^17.2.1" + }, + "bin": { + "ng-xi18n": "bundles/src/bin/ng_xi18n.js", + "ngc": "bundles/src/bin/ngc.js", + "ngcc": "bundles/ngcc/index.js" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/compiler": "16.2.12", + "typescript": ">=4.9.3 <5.2" + } + }, + "node_modules/@angular/core": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-16.2.12.tgz", + "integrity": "sha512-GLLlDeke/NjroaLYOks0uyzFVo6HyLl7VOm0K1QpLXnYvW63W9Ql/T3yguRZa7tRkOAeFZ3jw+1wnBD4O8MoUA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.13.0" + } + }, + "node_modules/@angular/forms": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-16.2.12.tgz", + "integrity": "sha512-1Eao89hlBgLR3v8tU91vccn21BBKL06WWxl7zLpQmG6Hun+2jrThgOE4Pf3os4fkkbH4Apj0tWL2fNIWe/blbw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": "16.2.12", + "@angular/core": "16.2.12", + "@angular/platform-browser": "16.2.12", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/localize": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-16.2.12.tgz", + "integrity": "sha512-sNIHDlZKENPQqx64qGF99g2sOCy9i9O4VOmjKD/FZbeE8O5qBbaQlkwOlFoQIt35/cnvtAtf7oQF6tqmiVtS2w==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "7.23.2", + "fast-glob": "3.3.0", + "yargs": "^17.2.1" + }, + "bin": { + "localize-extract": "tools/bundles/src/extract/cli.js", + "localize-migrate": "tools/bundles/src/migrate/cli.js", + "localize-translate": "tools/bundles/src/translate/cli.js" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/compiler": "16.2.12", + "@angular/compiler-cli": "16.2.12" + } + }, + "node_modules/@angular/localize/node_modules/fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "dev": true, + "peer": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@angular/platform-browser": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-16.2.12.tgz", + "integrity": "sha512-NnH7ju1iirmVEsUq432DTm0nZBGQsBrU40M3ZeVHMQ2subnGiyUs3QyzDz8+VWLL/T5xTxWLt9BkDn65vgzlIQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/animations": "16.2.12", + "@angular/common": "16.2.12", + "@angular/core": "16.2.12" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } + } + }, + "node_modules/@angular/platform-browser-dynamic": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-16.2.12.tgz", + "integrity": "sha512-ya54jerNgreCVAR278wZavwjrUWImMr2F8yM5n9HBvsMBbFaAQ83anwbOEiHEF2BlR+gJiEBLfpuPRMw20pHqw==", + "dev": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": "16.2.12", + "@angular/compiler": "16.2.12", + "@angular/core": "16.2.12", + "@angular/platform-browser": "16.2.12" + } + }, + "node_modules/@angular/router": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-16.2.12.tgz", + "integrity": "sha512-aU6QnYSza005V9P3W6PpkieL56O0IHps96DjqI1RS8yOJUl3THmokqYN4Fm5+HXy4f390FN9i6ftadYQDKeWmA==", + "dev": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": "16.2.12", + "@angular/core": "16.2.12", + "@angular/platform-browser": "16.2.12", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@assemblyscript/loader": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", + "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", + "dev": true + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz", + "integrity": "sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", + "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.8.tgz", + "integrity": "sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.23.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-unicode-property-regex instead.", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz", + "integrity": "sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", + "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", + "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz", + "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.3", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.23.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.9.tgz", + "integrity": "sha512-9KjBH61AGJetCPYp/IEyLEp47SyybZb0nDRpBvmtEkm+rUIwxdlKpyNHI1TmsGkeuLclJdleQHRZ8XLBnnh8CQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.4", + "babel-plugin-polyfill-corejs3": "^0.8.2", + "babel-plugin-polyfill-regenerator": "^0.5.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.9.tgz", + "integrity": "sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.5", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.22.7", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.22.5", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.5", + "@babel/plugin-transform-classes": "^7.22.6", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.22.5", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.5", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.5", + "@babel/plugin-transform-for-of": "^7.22.5", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.5", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.5", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.5", + "@babel/plugin-transform-modules-systemjs": "^7.22.5", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.5", + "@babel/plugin-transform-numeric-separator": "^7.22.5", + "@babel/plugin-transform-object-rest-spread": "^7.22.5", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.6", + "@babel/plugin-transform-parameters": "^7.22.5", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.5", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.5", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.5", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.4", + "babel-plugin-polyfill-corejs3": "^0.8.2", + "babel-plugin-polyfill-regenerator": "^0.5.1", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz", + "integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@braintree/sanitize-url": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", + "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==", + "optional": true + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.1.tgz", + "integrity": "sha512-ubEkAaTfVZa+WwGhs5jbo5Xfqpeaybr/RvWzvFxRs4jfq16wH8l8Ty/QEEpINxll4xhuGfdMbipRyz5QZh9+FA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^2.2.4" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.4.tgz", + "integrity": "sha512-PuWRAewQLbDhGeTvFuq2oClaSCKPIBmHyIobCV39JHRYN0byDcUWJl5baPeNUcqrjtdMNqFooE0FGl31I3JOqw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.9.tgz", + "integrity": "sha512-qqGuFfbn4rUmyOB0u8CVISIp5FfJ5GAR3mBrZ9/TKndHakdnm6pY0L/fbLcpPnrzwCyyTEZl1nUcXAYHEWneTA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.2.tgz", + "integrity": "sha512-RpHaZ1h9LE7aALeQXmXrJkRG84ZxIsctEN2biEUmFyKpzFM3zZ35eUMcIzZFsw/2olQE6v69+esEqU2f1MKycg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.13" + } + }, + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "dependencies": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@develar/schema-utils/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@develar/schema-utils/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@develar/schema-utils/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@electron/asar": { + "version": "3.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "chromium-pickle-js": "^0.2.0", + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + }, + "optionalDependencies": { + "@types/glob": "^7.1.1" + } + }, + "node_modules/@electron/asar/node_modules/commander": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@electron/get/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@electron/get/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/get/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@electron/get/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@electron/notarize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz", + "integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/osx-sign": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", + "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", + "dev": true, + "dependencies": { + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@electron/osx-sign/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@electron/universal": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", + "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", + "dev": true, + "dependencies": { + "@electron/asar": "^3.2.1", + "@malept/cross-spawn-promise": "^1.1.0", + "debug": "^4.3.1", + "dir-compare": "^3.0.0", + "fs-extra": "^9.0.1", + "minimatch": "^3.0.4", + "plist": "^3.0.4" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.17.tgz", + "integrity": "sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz", + "integrity": "sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.17.tgz", + "integrity": "sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz", + "integrity": "sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz", + "integrity": "sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz", + "integrity": "sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz", + "integrity": "sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz", + "integrity": "sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz", + "integrity": "sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz", + "integrity": "sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz", + "integrity": "sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz", + "integrity": "sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz", + "integrity": "sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz", + "integrity": "sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz", + "integrity": "sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz", + "integrity": "sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz", + "integrity": "sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz", + "integrity": "sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz", + "integrity": "sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz", + "integrity": "sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.17.tgz", + "integrity": "sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz", + "integrity": "sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz", + "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", + "dev": true + }, + "node_modules/@malept/cross-spawn-promise": { + "version": "1.1.1", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "license": "Apache-2.0", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@monaco-editor/loader": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "state-local": "^1.0.6" + }, + "peerDependencies": { + "monaco-editor": ">= 0.21.0 < 1" + } + }, + "node_modules/@ng-bootstrap/ng-bootstrap": { + "version": "15.1.2", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-15.1.2.tgz", + "integrity": "sha512-mM2yiGnt9o7KZLIFp8K1vjfmVfu7HR3d8dhH5SszfArbgn9DvvQ4P5D5TDGygzyBSzeyZe18p7I8rX8vgA6DKw==", + "dev": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^16.0.0", + "@angular/core": "^16.0.0", + "@angular/forms": "^16.0.0", + "@angular/localize": "^16.0.0", + "@popperjs/core": "^2.11.6", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@ngtools/webpack": { + "version": "16.2.13", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.13.tgz", + "integrity": "sha512-P5OiVp9MeMwVxihtC9NB4mx1Zlbup2DLMAWYAl8/kcFdRrRW+1YDQn93tlFToQDHGpPxkqW7cnFUPnA+QwQMYA==", + "dev": true, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^16.0.0", + "typescript": ">=4.9.3 <5.2", + "webpack": "^5.54.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", + "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", + "dev": true, + "dependencies": { + "@npmcli/promise-spawn": "^6.0.0", + "lru-cache": "^7.4.4", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", + "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", + "dev": true, + "dependencies": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "lib/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", + "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", + "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", + "dev": true, + "dependencies": { + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", + "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", + "dev": true, + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/promise-spawn": "^6.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^3.0.0", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script/node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@nrwl/devkit": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-16.5.1.tgz", + "integrity": "sha512-NB+DE/+AFJ7lKH/WBFyatJEhcZGj25F24ncDkwjZ6MzEiSOGOJS0LaV/R+VUsmS5EHTPXYOpn3zHWWAcJhyOmA==", + "dev": true, + "dependencies": { + "@nx/devkit": "16.5.1" + } + }, + "node_modules/@nrwl/tao": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-16.5.1.tgz", + "integrity": "sha512-x+gi/fKdM6uQNIti9exFlm3V5LBP3Y8vOEziO42HdOigyrXa0S0HD2WMpccmp6PclYKhwEDUjKJ39xh5sdh4Ig==", + "dev": true, + "dependencies": { + "nx": "16.5.1" + }, + "bin": { + "tao": "index.js" + } + }, + "node_modules/@nx/devkit": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-16.5.1.tgz", + "integrity": "sha512-T1acZrVVmJw/sJ4PIGidCBYBiBqlg/jT9e8nIGXLSDS20xcLvfo4zBQf8UZLrmHglnwwpDpOWuVJCp2rYA5aDg==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "16.5.1", + "ejs": "^3.1.7", + "ignore": "^5.0.4", + "semver": "7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "nx": ">= 15 <= 17" + } + }, + "node_modules/@nx/devkit/node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/nx-darwin-arm64": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-16.5.1.tgz", + "integrity": "sha512-q98TFI4B/9N9PmKUr1jcbtD4yAFs1HfYd9jUXXTQOlfO9SbDjnrYJgZ4Fp9rMNfrBhgIQ4x1qx0AukZccKmH9Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-darwin-x64": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-16.5.1.tgz", + "integrity": "sha512-j9HmL1l8k7EVJ3eOM5y8COF93gqrydpxCDoz23ZEtsY+JHY77VAiRQsmqBgEx9GGA2dXi9VEdS67B0+1vKariw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-freebsd-x64": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-16.5.1.tgz", + "integrity": "sha512-CXSPT01aVS869tvCCF2tZ7LnCa8l41wJ3mTVtWBkjmRde68E5Up093hklRMyXb3kfiDYlfIKWGwrV4r0eH6x1A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-16.5.1.tgz", + "integrity": "sha512-BhrumqJSZCWFfLFUKl4CAUwR0Y0G2H5EfFVGKivVecEQbb+INAek1aa6c89evg2/OvetQYsJ+51QknskwqvLsA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm64-gnu": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-16.5.1.tgz", + "integrity": "sha512-x7MsSG0W+X43WVv7JhiSq2eKvH2suNKdlUHEG09Yt0vm3z0bhtym1UCMUg3IUAK7jy9hhLeDaFVFkC6zo+H/XQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm64-musl": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-16.5.1.tgz", + "integrity": "sha512-J+/v/mFjOm74I0PNtH5Ka+fDd+/dWbKhpcZ2R1/6b9agzZk+Ff/SrwJcSYFXXWKbPX+uQ4RcJoytT06Zs3s0ow==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-x64-gnu": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-16.5.1.tgz", + "integrity": "sha512-igooWJ5YxQ94Zft7IqgL+Lw0qHaY15Btw4gfK756g/YTYLZEt4tTvR1y6RnK/wdpE3sa68bFTLVBNCGTyiTiDQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-x64-musl": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-16.5.1.tgz", + "integrity": "sha512-zF/exnPqFYbrLAduGhTmZ7zNEyADid2bzNQiIjJkh8Y6NpDwrQIwVIyvIxqynsjMrIs51kBH+8TUjKjj2Jgf5A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-win32-arm64-msvc": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-16.5.1.tgz", + "integrity": "sha512-qtqiLS9Y9TYyAbbpq58kRoOroko4ZXg5oWVqIWFHoxc5bGPweQSJCROEqd1AOl2ZDC6BxfuVHfhDDop1kK05WA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-win32-x64-msvc": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-16.5.1.tgz", + "integrity": "sha512-kUJBLakK7iyA9WfsGGQBVennA4jwf5XIgm0lu35oMOphtZIluvzItMt0EYBmylEROpmpEIhHq0P6J9FA+WH0Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.4.tgz", + "integrity": "sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^3.2.1", + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher/node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true + }, + "node_modules/@perfectmemory/ngx-contextmenu": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/@perfectmemory/ngx-contextmenu/-/ngx-contextmenu-16.0.2.tgz", + "integrity": "sha512-uZsI1dJmz0Xp2l9OQvSBXIU0p9u9gHEGHCimwin+A/NGrkRvChWSjACHjmtX7jO0C7Vz5uMo6FgwWiz2OHC4BQ==", + "dependencies": { + "tslib": "^2.3.1" + }, + "peerDependencies": { + "@angular/cdk": "^16.0.0", + "@angular/common": "^16.0.0", + "@angular/core": "^16.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.6", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@schematics/angular": { + "version": "16.2.13", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.13.tgz", + "integrity": "sha512-SFE9e7X/CEtzwGEqHUqXriAm4J4uTjcfoRXslc7BuqOKABM8RXPphGQsVG4xOt3n25kXXGkFO2dvDRHuLTP1fQ==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.2.13", + "@angular-devkit/schematics": "16.2.13", + "jsonc-parser": "3.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.4", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "dev": true + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@sigstore/bundle": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", + "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/protobuf-specs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", + "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", + "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "make-fetch-happen": "^11.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sigstore/sign/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sigstore/sign/node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/@sigstore/sign/node_modules/minipass-fetch/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/@sigstore/tuf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", + "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0", + "tuf-js": "^1.1.7" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", + "dev": true + }, + "node_modules/@sweetalert2/ngx-sweetalert2": { + "version": "11.0.0", + "dev": true, + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": ">=12.0.0", + "@angular/core": ">=12.0.0", + "sweetalert2": "^11.0.0" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "node_modules/@tufjs/canonical-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", + "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz", + "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==", + "dev": true, + "dependencies": { + "@tufjs/canonical-json": "1.0.0", + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@tufjs/models/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/bootstrap": { + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.10.tgz", + "integrity": "sha512-F2X+cd6551tep0MvVZ6nM8v7XgGN/twpdNDjqS1TUM7YFNEtQYWk+dKAnH+T1gr6QgCoGMPl487xw/9hXooa2g==", + "dev": true, + "dependencies": { + "@popperjs/core": "^2.9.2" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "dev": true, + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "2.12.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-axis": { + "version": "2.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-selection": "^2" + } + }, + "node_modules/@types/d3-brush": { + "version": "2.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-selection": "^2" + } + }, + "node_modules/@types/d3-chord": { + "version": "2.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "2.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-contour": { + "version": "2.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-array": "^2", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "5.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-dispatch": { + "version": "2.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-drag": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-selection": "^2" + } + }, + "node_modules/@types/d3-dsv": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-fetch": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-dsv": "^2" + } + }, + "node_modules/@types/d3-force": { + "version": "2.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-format": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-color": "^2" + } + }, + "node_modules/@types/d3-path": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-polygon": { + "version": "2.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-quadtree": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-random": { + "version": "2.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "3.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-time": "^2" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "2.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-selection": { + "version": "2.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "2.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-path": "^2" + } + }, + "node_modules/@types/d3-time": { + "version": "2.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-time-format": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "2.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-selection": "^2" + } + }, + "node_modules/@types/d3-zoom": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "^2", + "@types/d3-selection": "^2" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/electron": { + "version": "1.6.10", + "dev": true, + "license": "MIT", + "dependencies": { + "electron": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.4.10", + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.51", + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.43", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz", + "integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/geojson": { + "version": "7946.0.10", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/jasmine": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-5.1.4.tgz", + "integrity": "sha512-px7OMFO/ncXxixDe1zR13V1iycqWae0MxTaw62RpFlksUi5QuNWgQJFkTQjIOvrmutJbI7Fp2Y2N1F6D2R4G6w==", + "dev": true + }, + "node_modules/@types/jasminewd2": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.13.tgz", + "integrity": "sha512-aJ3wj8tXMpBrzQ5ghIaqMisD8C3FIrcO6sDKHqFbuqAsI7yOxj0fA7MrRCPLZHIVUjERIwsMmGn/vB0UQ9u0Hg==", + "dev": true, + "dependencies": { + "@types/jasmine": "*" + } + }, + "node_modules/@types/jquery": { + "version": "3.5.29", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.29.tgz", + "integrity": "sha512-oXQQC9X9MOPRrMhPHHOsXqeQDnWeCDT3PelUIg/Oy8FAbzSZtFHRjc7IpbfFVmpLtJ+UOoywpRsuO5Jxjybyeg==", + "dev": true, + "dependencies": { + "@types/sizzle": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", + "dev": true + }, + "node_modules/@types/marked": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.3.2.tgz", + "integrity": "sha512-a79Yc3TOk6dGdituy8hmTTJXjOkZ7zsFYV10L337ttq/rec8lRMDBpV7fL3uLx6TgbFCa5DU/h8FmIBQPSbU0w==", + "peer": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "node_modules/@types/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/q": { + "version": "0.0.32", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/qs": { + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.14.tgz", + "integrity": "sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true + }, + "node_modules/@types/selenium-webdriver": { + "version": "3.0.20", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/sizzle": { + "version": "2.3.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/verror": { + "version": "1.10.10", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.10.tgz", + "integrity": "sha512-l4MM0Jppn18hb9xmM6wwD1uTdShpf9Pn80aXTStnK1C94gtPvJcV2FrDmbOQUAQfJ1cKZHktkQUDwEqaAKXMMg==", + "dev": true, + "optional": true + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yauzl": { + "version": "2.10.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitejs/plugin-basic-ssl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.0.1.tgz", + "integrity": "sha512-pcub+YbFtFhaGRTo1832FQHQSHvMrlb43974e2eS8EKleR3p1cDdkJFPci1UhwkEf1J9Bz+wKBSzqpKp7nNj2A==", + "dev": true, + "engines": { + "node": ">=14.6.0" + }, + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "license": "MIT", + "peer": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@wessberg/ts-evaluator": { + "version": "0.0.27", + "resolved": "https://registry.npmjs.org/@wessberg/ts-evaluator/-/ts-evaluator-0.0.27.tgz", + "integrity": "sha512-7gOpVm3yYojUp/Yn7F4ZybJRxyqfMNf0LXK5KJiawbPfL0XTsJV+0mgrEDjOIR6Bi0OYk2Cyg4tjFu1r8MCZaA==", + "deprecated": "this package has been renamed to ts-evaluator. Please install ts-evaluator instead", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "jsdom": "^16.4.0", + "object-path": "^0.11.5", + "tslib": "^2.0.3" + }, + "engines": { + "node": ">=10.1.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/wessberg/ts-evaluator?sponsor=1" + }, + "peerDependencies": { + "typescript": ">=3.2.x || >= 4.x" + } + }, + "node_modules/@wessberg/ts-evaluator/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@wessberg/ts-evaluator/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@wessberg/ts-evaluator/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@wessberg/ts-evaluator/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@wessberg/ts-evaluator/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wessberg/ts-evaluator/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "license": "Apache-2.0" + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/@yarnpkg/parsers": { + "version": "3.0.0-rc.46", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", + "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", + "dev": true, + "dependencies": { + "js-yaml": "^3.10.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=14.15.0" + } + }, + "node_modules/@zkochan/js-yaml": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", + "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@zkochan/js-yaml/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/7zip-bin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", + "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", + "dev": true + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals/node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { + "version": "2.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dev": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/app-builder-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", + "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "dev": true + }, + "node_modules/app-builder-lib": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz", + "integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==", + "dev": true, + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/notarize": "2.2.1", + "@electron/osx-sign": "1.0.5", + "@electron/universal": "1.5.1", + "@malept/flatpak-bundler": "^0.4.0", + "@types/fs-extra": "9.0.13", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.4", + "ejs": "^3.1.8", + "electron-publish": "24.13.1", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", + "is-ci": "^3.0.0", + "isbinaryfile": "^5.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^5.1.1", + "read-config-file": "6.3.2", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.8", + "tar": "^6.1.12", + "temp-file": "^3.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "dmg-builder": "24.13.3", + "electron-builder-squirrel-windows": "24.13.3" + } + }, + "node_modules/app-builder-lib/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/app-builder-lib/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/app-builder-lib/node_modules/isbinaryfile": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.2.tgz", + "integrity": "sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg==", + "dev": true, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/app-builder-lib/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/app-builder-lib/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/app-root-path": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "node_modules/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "dev": true, + "peer": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "peer": true, + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/argparse/node_modules/sprintf-js": { + "version": "1.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "dev": true, + "license": "ISC" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/atomically": { + "version": "1.7.0", + "license": "MIT", + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/author-regex": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.14", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], + "dependencies": { + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/autoprefixer/node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "dev": true, + "license": "MIT" + }, + "node_modules/axios": { + "version": "0.21.4", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/axobject-query": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", + "integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/babel-loader": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", + "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "dev": true, + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.7.tgz", + "integrity": "sha512-LidDk/tEGDfuHW2DWh/Hgo4rmnw3cduK6ZkOI1NPFceSK3n/yAGeOsNT7FLnSGHkXj3RHGSEVkN3FsCTY6w2CQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.4", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", + "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.4", + "core-js-compat": "^3.33.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.4.tgz", + "integrity": "sha512-S/x2iOCvDaCASLYsOOgWOq4bCfKYVqvO/uxjkaYyZ3rVsVE3CeAI/c84NpyuBBymEgNvHgjEot3a9/Z/kXvqsg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.4" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/blocking-proxy": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "blocking-proxy": "built/lib/bin.js" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "dev": true, + "license": "MIT" + }, + "node_modules/bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/boolean": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/bootstrap": { + "version": "5.2.3", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peerDependencies": { + "@popperjs/core": "^2.11.6" + } + }, + "node_modules/bootstrap-icons": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz", + "integrity": "sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ] + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/browserstack": { + "version": "1.6.1", + "dev": true, + "license": "MIT", + "dependencies": { + "https-proxy-agent": "^2.2.1" + } + }, + "node_modules/browserstack/node_modules/agent-base": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "es6-promisify": "^5.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/browserstack/node_modules/debug": { + "version": "3.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/browserstack/node_modules/https-proxy-agent": { + "version": "2.2.4", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", + "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", + "dev": true, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "license": "MIT" + }, + "node_modules/builder-util": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz", + "integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==", + "dev": true, + "dependencies": { + "@types/debug": "^4.1.6", + "7zip-bin": "~5.2.0", + "app-builder-bin": "4.0.0", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "debug": "^4.3.4", + "fs-extra": "^10.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz", + "integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/builder-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/builder-util/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/builder-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/builder-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/builder-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/builder-util/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/builder-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/builder-util/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/builder-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "dev": true, + "dependencies": { + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001576", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz", + "integrity": "sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/caseless": { + "version": "0.12.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/chokidar": { + "version": "3.5.3", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/chromium-pickle-js": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.7.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "optional": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/clipboard": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", + "optional": true, + "dependencies": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/codelyzer": { + "version": "6.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular/compiler": "9.0.0", + "@angular/core": "9.0.0", + "app-root-path": "^3.0.0", + "aria-query": "^3.0.0", + "axobject-query": "2.0.2", + "css-selector-tokenizer": "^0.7.1", + "cssauron": "^1.4.0", + "damerau-levenshtein": "^1.0.4", + "rxjs": "^6.5.3", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.1.2", + "tslib": "^1.10.0", + "zone.js": "~0.10.3" + }, + "peerDependencies": { + "@angular/compiler": ">=2.3.1 <13.0.0 || ^12.0.0-next || ^12.1.0-next || ^12.2.0-next", + "@angular/core": ">=2.3.1 <13.0.0 || ^12.0.0-next || ^12.1.0-next || ^12.2.0-next", + "tslint": "^5.0.0 || ^6.0.0" + } + }, + "node_modules/codelyzer/node_modules/@angular/compiler": { + "version": "9.0.0", + "dev": true, + "license": "MIT", + "peerDependencies": { + "tslib": "^1.10.0" + } + }, + "node_modules/codelyzer/node_modules/@angular/core": { + "version": "9.0.0", + "dev": true, + "license": "MIT", + "peerDependencies": { + "rxjs": "^6.5.3", + "tslib": "^1.10.0", + "zone.js": "~0.10.2" + } + }, + "node_modules/codelyzer/node_modules/aria-query": { + "version": "3.0.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, + "node_modules/codelyzer/node_modules/axobject-query": { + "version": "2.0.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "ast-types-flow": "0.0.7" + } + }, + "node_modules/codelyzer/node_modules/commander": { + "version": "2.20.3", + "dev": true, + "license": "MIT" + }, + "node_modules/codelyzer/node_modules/source-map": { + "version": "0.5.7", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/codelyzer/node_modules/tslib": { + "version": "1.14.1", + "dev": true, + "license": "0BSD" + }, + "node_modules/codelyzer/node_modules/zone.js": { + "version": "0.10.3", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "7.2.0", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true + }, + "node_modules/compare-version": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/compress-commons": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", + "dev": true, + "peer": true, + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/concurrently": { + "version": "6.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "date-fns": "^2.16.1", + "lodash": "^4.17.21", + "rxjs": "^6.6.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^8.1.0", + "tree-kill": "^1.2.2", + "yargs": "^16.2.0" + }, + "bin": { + "concurrently": "bin/concurrently.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/concurrently/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/concurrently/node_modules/cliui": { + "version": "7.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/concurrently/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/concurrently/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/concurrently/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/concurrently/node_modules/supports-color": { + "version": "8.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/yargs": { + "version": "16.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/concurrently/node_modules/yargs-parser": { + "version": "20.2.9", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/conf": { + "version": "10.2.0", + "license": "MIT", + "dependencies": { + "ajv": "^8.6.3", + "ajv-formats": "^2.1.1", + "atomically": "^1.7.0", + "debounce-fn": "^4.0.0", + "dot-prop": "^6.0.1", + "env-paths": "^2.2.1", + "json-schema-typed": "^7.0.3", + "onetime": "^5.1.2", + "pkg-up": "^3.1.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/config-file-ts": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", + "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", + "dev": true, + "dependencies": { + "glob": "^10.3.10", + "typescript": "^5.3.3" + } + }, + "node_modules/config-file-ts/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/config-file-ts/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/config-file-ts/node_modules/typescript": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/connect": { + "version": "3.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "dependencies": { + "is-what": "^3.14.1" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "license": "MIT", + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "13.1.2", + "license": "MIT", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-js-compat": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.0.tgz", + "integrity": "sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==", + "dev": true, + "dependencies": { + "browserslist": "^4.22.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat/node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "optional": true, + "dependencies": { + "layout-base": "^1.0.0" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "optional": true, + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "peer": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "dev": true, + "peer": true, + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/critters": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.20.tgz", + "integrity": "sha512-CImNRorKOl5d8TWcnAz5n5izQ6HFsvz29k327/ELy6UFcmbiZNOsinaKvzv16WZR0P6etfSWYzE47C4/56B3Uw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "css-select": "^5.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.2", + "htmlparser2": "^8.0.2", + "postcss": "^8.4.23", + "pretty-bytes": "^5.3.0" + } + }, + "node_modules/critters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/critters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/critters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/critters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/critters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/critters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn-windows-exe": { + "version": "1.2.0", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-cross-spawn-windows-exe?utm_medium=referral&utm_source=npm_fund" + } + ], + "license": "Apache-2.0", + "dependencies": { + "@malept/cross-spawn-promise": "^1.1.0", + "is-wsl": "^2.2.0", + "which": "^2.0.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/css-functions-list": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.1.tgz", + "integrity": "sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==", + "dev": true, + "engines": { + "node": ">=12 || >=16" + } + }, + "node_modules/css-loader": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.10.0.tgz", + "integrity": "sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.4", + "postcss-modules-scope": "^3.1.1", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-loader/node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-selector-tokenizer": { + "version": "0.7.3", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssauron": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "through": "X.X.X" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + }, + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/custom-event": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/cytoscape": { + "version": "3.28.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.28.1.tgz", + "integrity": "sha512-xyItz4O/4zp9/239wCcH8ZcFuuZooEeF8KHRmzjDfGdXsj3OG9MFSMA0pJE0uX3uCN/ygof6hHf4L7lst+JaDg==", + "optional": true, + "dependencies": { + "heap": "^0.2.6", + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "optional": true, + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "optional": true, + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "optional": true, + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "optional": true + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.0", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.0", + "license": "ISC", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.2", + "license": "ISC", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "license": "ISC", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "license": "ISC", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-flextree": { + "version": "2.1.2", + "dev": true, + "license": "WTFPL", + "dependencies": { + "d3-hierarchy": "^1.1.5" + } + }, + "node_modules/d3-flextree/node_modules/d3-hierarchy": { + "version": "1.1.9", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/d3-force": { + "version": "3.0.0", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.0.1", + "license": "ISC", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.0.1", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.0.0", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.1.0", + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.0.0", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.9.tgz", + "integrity": "sha512-rYR4QfVmy+sR44IBDvVtcAmOReGBvRCWDpO2QjYwqgh9yijw6eSHBqaPG/LIOEy7aBsniLvtMW6pg19qJhq60w==", + "optional": true, + "dependencies": { + "d3": "^7.8.2", + "lodash-es": "^4.17.21" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/data-urls/node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true, + "engines": { + "node": ">=10.4" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/date-fns": { + "version": "2.29.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/date-format": { + "version": "4.0.14", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "optional": true + }, + "node_modules/debounce-fn": { + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "mimic-fn": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "2.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/array-union": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/globby": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/pify": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/rimraf": { + "version": "2.7.1", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/delaunator": { + "version": "5.0.0", + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "optional": true + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "node_modules/depd": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-it": { + "version": "4.0.1", + "license": "MIT" + }, + "node_modules/detect-node": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-passive-events": { + "version": "2.0.3", + "license": "MIT", + "dependencies": { + "detect-it": "^4.0.1" + } + }, + "node_modules/di": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/diff": { + "version": "4.0.2", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-compare": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", + "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", + "dev": true, + "dependencies": { + "buffer-equal": "^1.0.0", + "minimatch": "^3.0.4" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dmg-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", + "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", + "dev": true, + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "fs-extra": "^10.1.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.11" + } + }, + "node_modules/dmg-builder/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/dmg-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmg-builder/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "bin": { + "dmg-license": "bin/dmg-license.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dmg-license/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "optional": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/dmg-license/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "optional": true + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-serialize": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz", + "integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ==", + "optional": true + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-prop": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron": { + "version": "29.1.5", + "resolved": "https://registry.npmjs.org/electron/-/electron-29.1.5.tgz", + "integrity": "sha512-1uWGRw/ffA62lcrklxGUgVxVtOHojsg/nwsYr+/F9cVjipZJn8iPv/ABGIIexhmUqWcho8BqfTJ4osCBa29gBg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^20.9.0", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz", + "integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==", + "dev": true, + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "dmg-builder": "24.13.3", + "fs-extra": "^10.1.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.3.2", + "simple-update-notifier": "2.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/electron-builder-squirrel-windows": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-24.13.3.tgz", + "integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==", + "dev": true, + "peer": true, + "dependencies": { + "app-builder-lib": "24.13.3", + "archiver": "^5.3.1", + "builder-util": "24.13.1", + "fs-extra": "^10.1.0" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/electron-builder/node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/electron-builder/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/electron-builder/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-builder/node_modules/fs-extra": { + "version": "10.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-builder/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-packager": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-17.1.2.tgz", + "integrity": "sha512-XofXdikjYI7MVBcnXeoOvRR+yFFFHOLs3J7PF5KYQweigtgLshcH4W660PsvHr4lYZ03JBpLyEcUB8DzHZ+BNw==", + "deprecated": "Please use @electron/packager moving forward. There is no API change, just a package name change", + "dev": true, + "dependencies": { + "@electron/asar": "^3.2.1", + "@electron/get": "^2.0.0", + "@electron/notarize": "^1.2.3", + "@electron/osx-sign": "^1.0.5", + "@electron/universal": "^1.3.2", + "cross-spawn-windows-exe": "^1.2.0", + "debug": "^4.0.1", + "extract-zip": "^2.0.0", + "filenamify": "^4.1.0", + "fs-extra": "^11.1.0", + "galactus": "^1.0.0", + "get-package-info": "^1.0.0", + "junk": "^3.1.0", + "parse-author": "^2.0.0", + "plist": "^3.0.0", + "rcedit": "^3.0.1", + "resolve": "^1.1.6", + "semver": "^7.1.3", + "yargs-parser": "^21.1.1" + }, + "bin": { + "electron-packager": "bin/electron-packager.js" + }, + "engines": { + "node": ">= 14.17.5" + }, + "funding": { + "url": "https://github.com/electron/electron-packager?sponsor=1" + } + }, + "node_modules/electron-packager/node_modules/@electron/notarize": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-1.2.4.tgz", + "integrity": "sha512-W5GQhJEosFNafewnS28d3bpQ37/s91CDWqxVchHfmv2dQSTWpOzNlUVQwYzC1ay5bChRV/A9BTL68yj0Pa+TSg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-packager/node_modules/@electron/notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/electron-packager/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/electron-publish": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz", + "integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==", + "dev": true, + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "fs-extra": "^10.1.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "node_modules/electron-publish/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/electron-publish/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/electron-publish/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/electron-publish/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/electron-publish/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-publish/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-publish/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-store": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-8.2.0.tgz", + "integrity": "sha512-ukLL5Bevdil6oieAOXz3CMy+OgaItMiVBg701MNlG6W5RaC0AHN7rvlqTCmeb6O7jP0Qa1KKYTE0xV0xbhF4Hw==", + "dependencies": { + "conf": "^10.2.0", + "type-fest": "^2.17.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.630", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.630.tgz", + "integrity": "sha512-osHqhtjojpCsACVnuD11xO5g9xaCyw7Qqn/C2KParkMv42i8jrJJgx3g7mkHfpxwhy9MnOJr8+pKOdZ7qzgizg==" + }, + "node_modules/elkjs": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz", + "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==", + "optional": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/emoji-toolkit": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/emoji-toolkit/-/emoji-toolkit-7.0.1.tgz", + "integrity": "sha512-l5aJyAhpC5s4mDuoVuqt4SzVjwIsIvakPh4ZGJJE4KWuWFCEHaXacQFkStVdD9zbRR+/BbRXob7u99o0lQFr8A==", + "optional": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "dev": true, + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "license": "MIT", + "peer": true + }, + "node_modules/es6-error": { + "version": "4.1.1", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "dev": true, + "license": "MIT" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, + "node_modules/esbuild": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.17.tgz", + "integrity": "sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.17", + "@esbuild/android-arm64": "0.18.17", + "@esbuild/android-x64": "0.18.17", + "@esbuild/darwin-arm64": "0.18.17", + "@esbuild/darwin-x64": "0.18.17", + "@esbuild/freebsd-arm64": "0.18.17", + "@esbuild/freebsd-x64": "0.18.17", + "@esbuild/linux-arm": "0.18.17", + "@esbuild/linux-arm64": "0.18.17", + "@esbuild/linux-ia32": "0.18.17", + "@esbuild/linux-loong64": "0.18.17", + "@esbuild/linux-mips64el": "0.18.17", + "@esbuild/linux-ppc64": "0.18.17", + "@esbuild/linux-riscv64": "0.18.17", + "@esbuild/linux-s390x": "0.18.17", + "@esbuild/linux-x64": "0.18.17", + "@esbuild/netbsd-x64": "0.18.17", + "@esbuild/openbsd-x64": "0.18.17", + "@esbuild/sunos-x64": "0.18.17", + "@esbuild/win32-arm64": "0.18.17", + "@esbuild/win32-ia32": "0.18.17", + "@esbuild/win32-x64": "0.18.17" + } + }, + "node_modules/esbuild-wasm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.18.17.tgz", + "integrity": "sha512-9OHGcuRzy+I8ziF9FzjfKLWAPbvi0e/metACVg9k6bK+SI4FFxeV6PcZsz8RIVaMD4YNehw+qj6UMR3+qj/EuQ==", + "dev": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.5.0", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-formatter-codeframe": { + "version": "7.32.1", + "resolved": "https://registry.npmjs.org/eslint-formatter-codeframe/-/eslint-formatter-codeframe-7.32.1.tgz", + "integrity": "sha512-DK/3Q3+zVKq/7PdSYiCxPrsDF8H/TRMK5n8Hziwr4IMkMy+XiKSwbpj25AdajS63I/B61Snetq4uVvX9fOLyAg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/eslint-formatter-codeframe/node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/eslint-formatter-codeframe/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint-formatter-codeframe/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint-formatter-codeframe/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint-formatter-codeframe/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint-formatter-codeframe/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-formatter-codeframe/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-summary": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-summary/-/eslint-summary-1.0.0.tgz", + "integrity": "sha512-cHr5WiNFhu2guLQykhQV8O7BQcnpFLR6GdLjbQfDDL0yGy9U7dXC6zMUtwoxYgJRC/Wk3yZMc+I6Q15Z7r4j9Q==", + "dev": true, + "dependencies": { + "chalk": "^1.0.0", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-summary/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-summary/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-summary/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-summary/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-summary/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter-asyncresource": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz", + "integrity": "sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==", + "dev": true + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/express/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/external-editor/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastparse": { + "version": "1.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.13.0", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-saver": { + "version": "2.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/finalhandler/node_modules/on-finished": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "dev": true, + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/flora-colossus": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flora-colossus/-/flora-colossus-2.0.0.tgz", + "integrity": "sha512-dz4HxH6pOvbUzZpZ/yXhafjbR2I8cenK5xL0KtBFb7U2ADsR+OwXifnxZjij/pZWF775uSCMzWVd+jDik2H2IA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/flora-colossus/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", + "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/galactus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/galactus/-/galactus-1.0.0.tgz", + "integrity": "sha512-R1fam6D4CyKQGNlvJne4dkNF+PvUUl7TAJInvTGa9fti9qAv95quQz29GXapA4d8Ec266mJJxFVh82M4GIIGDQ==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "flora-colossus": "^2.0.0", + "fs-extra": "^10.1.0" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/galactus/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-info": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.1.1", + "debug": "^2.2.0", + "lodash.get": "^4.0.0", + "read-pkg-up": "^2.0.0" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/get-package-info/node_modules/debug": { + "version": "2.6.9", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/get-package-info/node_modules/ms": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "license": "BSD-2-Clause" + }, + "node_modules/global-agent": { + "version": "3.0.0", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, + "node_modules/golden-layout": { + "version": "2.6.0", + "dev": true, + "license": "MIT" + }, + "node_modules/good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", + "optional": true, + "dependencies": { + "delegate": "^3.1.2" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/guess-parser": { + "version": "0.4.22", + "resolved": "https://registry.npmjs.org/guess-parser/-/guess-parser-0.4.22.tgz", + "integrity": "sha512-KcUWZ5ACGaBM69SbqwVIuWGoSAgD+9iJnchR9j/IarVI1jHVeXv+bUXBIMeqVMSKt3zrn0Dgf9UpcOEpPBLbSg==", + "dev": true, + "dependencies": { + "@wessberg/ts-evaluator": "0.0.27" + }, + "peerDependencies": { + "typescript": ">=3.7.5" + } + }, + "node_modules/gumshoejs": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/gumshoejs/-/gumshoejs-5.1.2.tgz", + "integrity": "sha512-wIRdZGTNkWMP8dY3po8mtNYmCfiSva41LxXIEek2yEHceETpxRmO7DfW7aUbHsuucC9z2oDPu3alN3+00FUqlw==" + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/har-schema": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/har-validator/node_modules/ajv": { + "version": "6.12.6", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/har-validator/node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, + "node_modules/hdr-histogram-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", + "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", + "dev": true, + "dependencies": { + "@assemblyscript/loader": "^0.10.1", + "base64-js": "^1.2.0", + "pako": "^1.0.3" + } + }, + "node_modules/hdr-histogram-percentiles-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", + "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", + "dev": true + }, + "node_modules/heap": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", + "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", + "optional": true + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/htmlhint": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/htmlhint/-/htmlhint-1.1.4.tgz", + "integrity": "sha512-tSKPefhIaaWDk/vKxAOQbN+QwZmDeJCq3bZZGbJMoMQAfTjepudC+MkuT9MOBbuQI3dLLzDWbmU7fLV3JASC7Q==", + "dev": true, + "dependencies": { + "async": "3.2.3", + "chalk": "^4.1.2", + "commander": "^9.1.0", + "glob": "^7.2.0", + "is-glob": "^4.0.3", + "node-fetch": "^2.6.2", + "strip-json-comments": "3.1.0", + "xml": "1.0.1" + }, + "bin": { + "htmlhint": "bin/htmlhint" + } + }, + "node_modules/htmlhint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/htmlhint/node_modules/async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", + "dev": true + }, + "node_modules/htmlhint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/htmlhint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/htmlhint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/htmlhint/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/htmlhint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/htmlhint/node_modules/strip-json-comments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", + "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/htmlhint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "dev": true, + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize-duration-ts": { + "version": "2.1.1", + "license": "MIT" + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + }, + "engines": { + "node": "^8.11.2 || >=10" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.4.tgz", + "integrity": "sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw==", + "dev": true, + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ignore-walk/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/ignore-walk/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/immutable": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", + "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "dev": true, + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/inquirer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/inquirer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/rxjs": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", + "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/inquirer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/ip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", + "dev": true + }, + "node_modules/ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-cwd": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-in-cwd": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-path-inside": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-in-cwd/node_modules/is-path-inside": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-is-inside": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/isbinaryfile": { + "version": "4.0.10", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "3.0.6", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/istanbul-lib-coverage": { + "version": "2.0.5", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/make-dir": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/pify": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/rimraf": { + "version": "2.7.1", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.5", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jake/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jake/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jake/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jake/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jasmine": { + "version": "2.8.0", + "dev": true, + "license": "MIT", + "dependencies": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.8.0" + }, + "bin": { + "jasmine": "bin/jasmine.js" + } + }, + "node_modules/jasmine-core": { + "version": "3.10.1", + "dev": true, + "license": "MIT" + }, + "node_modules/jasmine-spec-reporter": { + "version": "7.0.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "colors": "1.4.0" + } + }, + "node_modules/jasmine-spec-reporter/node_modules/colors": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/jasmine/node_modules/jasmine-core": { + "version": "2.8.0", + "dev": true, + "license": "MIT" + }, + "node_modules/jasminewd2": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.9.x" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/joi": { + "version": "17.7.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/jsdom/node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdom/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true, + "engines": { + "node": ">=10.4" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsdom/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "license": "MIT" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "dev": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/json-schema-typed": { + "version": "7.0.3", + "license": "BSD-2-Clause" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/jsprim": { + "version": "1.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jsprim/node_modules/core-util-is": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/jsprim/node_modules/extsprintf": { + "version": "1.3.0", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/jsprim/node_modules/verror": { + "version": "1.10.0", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/jszip": { + "version": "3.10.1", + "dev": true, + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/junk": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/karma": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.3.tgz", + "integrity": "sha512-LuucC/RE92tJ8mlCwqEoRWXP38UMAqpnq98vktmS9SznSoUPPUJQbc91dHcxcunROvfQjdORVA/YFviH+Xci9Q==", + "dev": true, + "dependencies": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.7.2", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/karma-chrome-launcher": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "which": "^1.2.1" + } + }, + "node_modules/karma-chrome-launcher/node_modules/which": { + "version": "1.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/karma-coverage-istanbul-reporter": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^3.0.2", + "minimatch": "^3.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/mattlewis92" + } + }, + "node_modules/karma-jasmine": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "jasmine-core": "^3.6.0" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "karma": "*" + } + }, + "node_modules/karma-jasmine-html-reporter": { + "version": "1.7.0", + "dev": true, + "license": "MIT", + "peerDependencies": { + "jasmine-core": ">=3.8", + "karma": ">=0.9", + "karma-jasmine": ">=1.1" + } + }, + "node_modules/karma-source-map-support": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map-support": "^0.5.5" + } + }, + "node_modules/karma/node_modules/cliui": { + "version": "7.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/karma/node_modules/mkdirp": { + "version": "0.5.6", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/karma/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/karma/node_modules/yargs": { + "version": "16.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/karma/node_modules/yargs-parser": { + "version": "20.2.9", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/katex": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz", + "integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "optional": true, + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==", + "optional": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/known-css-properties": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz", + "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==", + "dev": true + }, + "node_modules/launch-editor": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", + "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", + "dev": true, + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "optional": true + }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "dev": true + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "peer": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/less": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", + "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", + "dev": true, + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/less-loader": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", + "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", + "dev": true, + "dependencies": { + "klona": "^2.0.4" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/less/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/less/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/less/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/less/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/less/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/license-webpack-plugin": { + "version": "4.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "webpack-sources": "^3.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-sources": { + "optional": true + } + } + }, + "node_modules/lie": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "optional": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true, + "peer": true + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "dev": true, + "peer": true + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true, + "peer": true + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "peer": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "dev": true, + "peer": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log4js": { + "version": "6.7.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.3" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/magic-string": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.1.tgz", + "integrity": "sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/magic-string/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/make-dir": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "dev": true, + "license": "ISC" + }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/make-fetch-happen/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-fetch-happen/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/make-fetch-happen/node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "peer": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/matcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/meow": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", + "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.2", + "camelcase-keys": "^7.0.0", + "decamelize": "^5.0.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.2", + "read-pkg-up": "^8.0.0", + "redent": "^4.0.0", + "trim-newlines": "^4.0.2", + "type-fest": "^1.2.2", + "yargs-parser": "^20.2.9" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/meow/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/read-pkg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", + "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/read-pkg-up": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", + "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0", + "read-pkg": "^6.0.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/mermaid": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-9.4.3.tgz", + "integrity": "sha512-TLkQEtqhRSuEHSE34lh5bCa94KATCyluAXmFnNI2PRZwOpXFeqiJWwZl+d2CcemE1RS6QbbueSSq9QIg8Uxcyw==", + "optional": true, + "dependencies": { + "@braintree/sanitize-url": "^6.0.0", + "cytoscape": "^3.23.0", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.1.0", + "d3": "^7.4.0", + "dagre-d3-es": "7.0.9", + "dayjs": "^1.11.7", + "dompurify": "2.4.3", + "elkjs": "^0.8.2", + "khroma": "^2.0.0", + "lodash-es": "^4.17.21", + "non-layered-tidy-tree-layout": "^2.0.2", + "stylis": "^4.1.2", + "ts-dedent": "^2.2.0", + "uuid": "^9.0.0", + "web-worker": "^1.2.0" + } + }, + "node_modules/mermaid/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "license": "MIT", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", + "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", + "dev": true, + "dependencies": { + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.7", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minimist-options/node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/minipass": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.0.tgz", + "integrity": "sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/monaco-editor": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.34.1.tgz", + "integrity": "sha512-FKc80TyiMaruhJKKPz5SpJPIjL+dflGvz4CpuThaPMc94AyN7SeC9HQ8hrvaxX7EyHdJcUY5i4D0gNyJj1vSZQ==" + }, + "node_modules/monaco-editor-webpack-plugin": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-7.1.0.tgz", + "integrity": "sha512-ZjnGINHN963JQkFqjjcBtn1XBtUATDZBMgNQhDQwd78w2ukRhFXAPNgWuacaQiDZsUr4h1rWv5Mv6eriKuOSzA==", + "dependencies": { + "loader-utils": "^2.0.2" + }, + "peerDependencies": { + "monaco-editor": ">= 0.31.0", + "webpack": "^4.5.0 || 5.x" + } + }, + "node_modules/monaco-editor-webpack-plugin/node_modules/loader-utils": { + "version": "2.0.4", + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/mrmime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", + "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/needle": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", + "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", + "dev": true, + "optional": true, + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "license": "MIT" + }, + "node_modules/ngx-clipboard": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/ngx-clipboard/-/ngx-clipboard-16.0.0.tgz", + "integrity": "sha512-rZ/Eo1PqiKMiyF8tdjhmUkoUu68f7OzBJ7YH1YFeh2RAaNrerTaW8XfFOzppSckjFQqA1fwGSYuTTJlDhDag5w==", + "dependencies": { + "ngx-window-token": ">=7.0.0", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": ">=13.0.0", + "@angular/core": ">=13.0.0" + } + }, + "node_modules/ngx-color-picker": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/ngx-color-picker/-/ngx-color-picker-16.0.0.tgz", + "integrity": "sha512-Dk2FvcbebD6STZSVzkI5oFHOlTrrNC5bOHh+YVaFgaWuWrVUdVIJm68ocUvTgr/qxTEJjrfcnRnS4wi7BJ2hKg==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": ">=9.0.0", + "@angular/core": ">=9.0.0", + "@angular/forms": ">=9.0.0" + } + }, + "node_modules/ngx-file-drop": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/ngx-file-drop/-/ngx-file-drop-16.0.0.tgz", + "integrity": "sha512-33RPoZBAiMkV110Rzu3iOrzGcG5M20S4sAiwLzNylfJobu9qVw5XR83FhUelSeqJRoaDxXBRKAozYCSnUf2CNw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">= 14.5.0", + "npm": ">= 6.9.0" + }, + "peerDependencies": { + "@angular/common": ">=14.0.0", + "@angular/core": ">=14.0.0" + } + }, + "node_modules/ngx-markdown": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/ngx-markdown/-/ngx-markdown-16.0.0.tgz", + "integrity": "sha512-/rlbXi+HBscJCDdwaTWIUrRkvwJicPnuAgeugOCZa0UbZ4VCWV3U0+uB1Zv6krRDF6FXJNXNLTUrMZV7yH8I6A==", + "dependencies": { + "tslib": "^2.3.0" + }, + "optionalDependencies": { + "clipboard": "^2.0.11", + "emoji-toolkit": "^7.0.0", + "katex": "^0.16.0", + "mermaid": "^9.1.2", + "prismjs": "^1.28.0" + }, + "peerDependencies": { + "@angular/common": "^16.0.0", + "@angular/core": "^16.0.0", + "@angular/platform-browser": "^16.0.0", + "@types/marked": "^4.3.0", + "marked": "^4.3.0", + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.13.0" + } + }, + "node_modules/ngx-slider-v2": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/ngx-slider-v2/-/ngx-slider-v2-16.0.2.tgz", + "integrity": "sha512-Lpl7SlErL+tJJvTRZYdyZoXTThKN8Ro1z3vscJQ1O5azHXwvbv3pnTcsOwY4ltfaP+dpzY27KL1QXyDr6QMaxQ==", + "dependencies": { + "detect-passive-events": "^2.0.3", + "rxjs": "^7.4.0", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^16.0.0", + "@angular/core": "^16.0.0", + "@angular/forms": "^16.0.0" + } + }, + "node_modules/ngx-slider-v2/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/ngx-window-token": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ngx-window-token/-/ngx-window-token-7.0.0.tgz", + "integrity": "sha512-5+XfRVSY7Dciu8xyCNMkOlH2UfwR9W2P1Pirz7caaZgOZDjFbL8aEO2stjfJJm2FFf1D6dlVHNzhLWGk9HGkqA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": ">=13.0.0", + "@angular/core": ">=13.0.0" + } + }, + "node_modules/nice-napi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", + "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "!win32" + ], + "dependencies": { + "node-addon-api": "^3.0.0", + "node-gyp-build": "^4.2.2" + } + }, + "node_modules/nice-napi/node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true, + "optional": true + }, + "node_modules/nice-try": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "optional": true + }, + "node_modules/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-gyp": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", + "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/non-layered-tidy-tree-layout": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==", + "optional": true + }, + "node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "2.8.9", + "dev": true, + "license": "ISC" + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-bundled": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", + "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", + "dev": true, + "dependencies": { + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-install-checks": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", + "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", + "dev": true, + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg/node_modules/hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm-packlist": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", + "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", + "dev": true, + "dependencies": { + "ignore-walk": "^6.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-pick-manifest": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz", + "integrity": "sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==", + "dev": true, + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch": { + "version": "14.0.5", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz", + "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==", + "dev": true, + "dependencies": { + "make-fetch-happen": "^11.0.0", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^10.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm-registry-fetch/node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/npm-registry-fetch/node_modules/minipass-fetch/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "dev": true + }, + "node_modules/nx": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/nx/-/nx-16.5.1.tgz", + "integrity": "sha512-I3hJRE4hG7JWAtncWwDEO3GVeGPpN0TtM8xH5ArZXyDuVeTth/i3TtJzdDzqXO1HHtIoAQN0xeq4n9cLuMil5g==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nrwl/tao": "16.5.1", + "@parcel/watcher": "2.0.4", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.6", + "axios": "^1.0.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^7.0.2", + "dotenv": "~10.0.0", + "enquirer": "~2.3.6", + "fast-glob": "3.2.7", + "figures": "3.2.0", + "flat": "^5.0.2", + "fs-extra": "^11.1.0", + "glob": "7.1.4", + "ignore": "^5.0.4", + "js-yaml": "4.1.0", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "3.0.5", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "semver": "7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "v8-compile-cache": "2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "16.5.1", + "@nx/nx-darwin-x64": "16.5.1", + "@nx/nx-freebsd-x64": "16.5.1", + "@nx/nx-linux-arm-gnueabihf": "16.5.1", + "@nx/nx-linux-arm64-gnu": "16.5.1", + "@nx/nx-linux-arm64-musl": "16.5.1", + "@nx/nx-linux-x64-gnu": "16.5.1", + "@nx/nx-linux-x64-musl": "16.5.1", + "@nx/nx-win32-arm64-msvc": "16.5.1", + "@nx/nx-win32-x64-msvc": "16.5.1" + }, + "peerDependencies": { + "@swc-node/register": "^1.4.2", + "@swc/core": "^1.2.173" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/nx/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/nx/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/nx/node_modules/axios": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/nx/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/nx/node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nx/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/nx/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/nx/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/nx/node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/nx/node_modules/fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nx/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/nx/node_modules/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nx/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nx/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/nx/node_modules/lines-and-columns": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/nx/node_modules/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nx/node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nx/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "2.2.0", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-path": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.8.tgz", + "integrity": "sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==", + "dev": true, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime/node_modules/mimic-fn": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/ora/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pacote": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz", + "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==", + "dev": true, + "dependencies": { + "@npmcli/git": "^4.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^6.0.1", + "@npmcli/run-script": "^6.0.0", + "cacache": "^17.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^5.0.0", + "npm-package-arg": "^10.0.0", + "npm-packlist": "^7.0.0", + "npm-pick-manifest": "^8.0.0", + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^6.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^1.3.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/pacote/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "dev": true, + "license": "(MIT AND Zlib)" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-author": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "author-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "devOptional": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-html-rewriting-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", + "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", + "dev": true, + "dependencies": { + "entities": "^4.3.0", + "parse5": "^7.0.0", + "parse5-sax-parser": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-sax-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", + "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", + "dev": true, + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "dev": true, + "license": "(WTFPL OR MIT)" + }, + "node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/performance-now": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/piscina": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.0.0.tgz", + "integrity": "sha512-641nAmJS4k4iqpNUqfggqUBUMmlw0ZoM5VZKdQkV2e970Inn3Tk9kroCc1wpsYLD07vCwpys5iY0d3xI/9WkTg==", + "dev": true, + "dependencies": { + "eventemitter-asyncresource": "^1.0.0", + "hdr-histogram-js": "^2.0.1", + "hdr-histogram-percentiles-obj": "^3.0.0" + }, + "optionalDependencies": { + "nice-napi": "^1.0.2" + } + }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "dev": true, + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/pkg-dir/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/plist": { + "version": "3.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/portfinder": { + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", + "dependencies": { + "async": "^2.6.4", + "debug": "^3.2.7", + "mkdirp": "^0.5.6" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/portfinder/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-loader": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz", + "integrity": "sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==", + "dev": true, + "dependencies": { + "cosmiconfig": "^8.2.0", + "jiti": "^1.18.2", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.4.tgz", + "integrity": "sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.1.1.tgz", + "integrity": "sha512-uZgqzdTleelWjzJY+Fhti6F3C9iF1JR/dODLs/JDefozYcKTBCdD8BIl6nNPbTbcLnGrk56hzwZC2DaGNvYjzA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "dev": true + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.4.29" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.0", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protractor": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "^3.0.0", + "blocking-proxy": "^1.0.0", + "browserstack": "^1.5.1", + "chalk": "^1.1.3", + "glob": "^7.0.3", + "jasmine": "2.8.0", + "jasminewd2": "^2.1.0", + "q": "1.4.1", + "saucelabs": "^1.5.0", + "selenium-webdriver": "3.6.0", + "source-map-support": "~0.4.0", + "webdriver-js-extender": "2.1.0", + "webdriver-manager": "^12.1.7", + "yargs": "^15.3.1" + }, + "bin": { + "protractor": "bin/protractor", + "webdriver-manager": "bin/webdriver-manager" + }, + "engines": { + "node": ">=10.13.x" + } + }, + "node_modules/protractor/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/ansi-styles": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/chalk": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/cliui": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/protractor/node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/protractor/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/protractor/node_modules/source-map": { + "version": "0.5.7", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/source-map-support": { + "version": "0.4.18", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/protractor/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/supports-color": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/protractor/node_modules/wrap-ansi": { + "version": "6.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/protractor/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/node_modules/y18n": { + "version": "4.0.3", + "dev": true, + "license": "ISC" + }, + "node_modules/protractor/node_modules/yargs": { + "version": "15.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/node_modules/yargs-parser": { + "version": "18.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true + }, + "node_modules/psl": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qjobs": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.9" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rcedit": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn-windows-exe": "^1.1.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/read-config-file": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", + "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", + "dev": true, + "dependencies": { + "config-file-ts": "^0.2.4", + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/read-config-file/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/read-config-file/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/read-package-json": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", + "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", + "dev": true, + "dependencies": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "dev": true, + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", + "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/read-package-json/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/read-package-json/node_modules/hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json/node_modules/json-parse-even-better-errors": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", + "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/read-package-json/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/read-package-json/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/read-package-json/node_modules/normalize-package-data": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", + "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", + "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-pkg": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "1.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-try": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/pify": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "peer": true, + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", + "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", + "dev": true, + "dependencies": { + "indent-string": "^5.0.0", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/redent/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-parser": { + "version": "2.2.11", + "dev": true, + "license": "MIT" + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/request": { + "version": "2.88.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dev": true, + "dependencies": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-url-loader": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.14", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/resolve-url-loader/node_modules/loader-utils": { + "version": "2.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.1", + "license": "Unlicense" + }, + "node_modules/rollup": { + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "license": "BSD-3-Clause" + }, + "node_modules/rxjs": { + "version": "6.6.7", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/rxjs/node_modules/tslib": { + "version": "1.14.1", + "license": "0BSD" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "dev": true, + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sass": { + "version": "1.64.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.64.1.tgz", + "integrity": "sha512-16rRACSOFEE8VN7SCgBu1MpYCyN7urj9At898tyzdXFhC+a+yOX5dXwAR7L8/IdPJ1NB8OYoXmD55DM30B2kEQ==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-loader": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.2.tgz", + "integrity": "sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==", + "dev": true, + "dependencies": { + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/saucelabs": { + "version": "1.5.0", + "dev": true, + "dependencies": { + "https-proxy-agent": "^2.2.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/saucelabs/node_modules/agent-base": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "es6-promisify": "^5.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/saucelabs/node_modules/debug": { + "version": "3.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/saucelabs/node_modules/https-proxy-agent": { + "version": "2.2.4", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/sax": { + "version": "1.2.4", + "dev": true, + "license": "ISC" + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==", + "optional": true + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selenium-webdriver": { + "version": "3.6.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "engines": { + "node": ">= 6.9.0" + } + }, + "node_modules/selenium-webdriver/node_modules/rimraf": { + "version": "2.7.1", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/selenium-webdriver/node_modules/tmp": { + "version": "0.0.30", + "dev": true, + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/semver-dsl": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.3.0" + } + }, + "node_modules/semver-dsl/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-error/node_modules/type-fest": { + "version": "0.13.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "dev": true, + "license": "ISC" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "dev": true, + "license": "ISC" + }, + "node_modules/sigstore": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", + "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "@sigstore/sign": "^1.0.0", + "@sigstore/tuf": "^1.0.3", + "make-fetch-happen": "^11.0.1" + }, + "bin": { + "sigstore": "bin/sigstore.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/sigstore/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/sigstore/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/sigstore/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sigstore/node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/sigstore/node_modules/minipass-fetch/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "optional": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "optional": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "optional": true + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socket.io": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.4.tgz", + "integrity": "sha512-DcotgfP1Zg9iP/dH9zvAQcWrE0TtbMVwXmlV4T4mqsvY+gw+LqUGPfx2AoVyRk0FLME+GQhufDMyacFmw7ksqw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dev": true, + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dev": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dev": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.1.tgz", + "integrity": "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.72.1" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spawn-command": { + "version": "0.0.2-1", + "dev": true, + "license": "MIT" + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.12", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.2", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/sshpk": { + "version": "1.17.0", + "dev": true, + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ssri/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/state-local": { + "version": "1.0.7", + "license": "MIT" + }, + "node_modules/statuses": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/streamroller": { + "version": "3.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/streamroller/node_modules/fs-extra": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/streamroller/node_modules/jsonfile": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/streamroller/node_modules/universalify": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-outer": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strong-log-transformer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", + "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", + "dev": true, + "dependencies": { + "duplexer": "^0.1.1", + "minimist": "^1.2.0", + "through": "^2.3.4" + }, + "bin": { + "sl-log-transformer": "bin/sl-log-transformer.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/style-loader": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true + }, + "node_modules/stylelint": { + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.11.0.tgz", + "integrity": "sha512-78O4c6IswZ9TzpcIiQJIN49K3qNoXTM8zEJzhaTE/xRTCZswaovSEVIa/uwbOltZrk16X4jAxjaOhzz/hTm1Kw==", + "dev": true, + "dependencies": { + "@csstools/css-parser-algorithms": "^2.3.1", + "@csstools/css-tokenizer": "^2.2.0", + "@csstools/media-query-list-parser": "^2.1.4", + "@csstools/selector-specificity": "^3.0.0", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^8.2.0", + "css-functions-list": "^3.2.1", + "css-tree": "^2.3.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.1", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^7.0.0", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^5.2.4", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.29.0", + "mathml-tag-names": "^2.1.3", + "meow": "^10.1.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.28", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.13", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^3.0.0", + "svg-tags": "^1.0.0", + "table": "^6.8.1", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.mjs" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/stylelint-config-standard": { + "version": "34.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-34.0.0.tgz", + "integrity": "sha512-u0VSZnVyW9VSryBG2LSO+OQTjN7zF9XJaAJRX/4EwkmU0R2jYwmBSN10acqZisDitS0CLiEiGjX7+Hrq8TAhfQ==", + "dev": true, + "dependencies": { + "stylelint-config-recommended": "^13.0.0" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "stylelint": "^15.10.0" + } + }, + "node_modules/stylelint-config-standard-scss": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-10.0.0.tgz", + "integrity": "sha512-bChBEo1p3xUVWh/wenJI+josoMk21f2yuLDGzGjmKYcALfl2u3DFltY+n4UHswYiXghqXaA8mRh+bFy/q1hQlg==", + "dev": true, + "dependencies": { + "stylelint-config-recommended-scss": "^12.0.0", + "stylelint-config-standard": "^33.0.0" + }, + "peerDependencies": { + "postcss": "^8.3.3", + "stylelint": "^15.5.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + } + } + }, + "node_modules/stylelint-config-standard-scss/node_modules/stylelint-config-recommended": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-12.0.0.tgz", + "integrity": "sha512-x6x8QNARrGO2sG6iURkzqL+Dp+4bJorPMMRNPScdvaUK8PsynriOcMW7AFDKqkWAS5wbue/u8fUT/4ynzcmqdQ==", + "dev": true, + "peerDependencies": { + "stylelint": "^15.5.0" + } + }, + "node_modules/stylelint-config-standard-scss/node_modules/stylelint-config-recommended-scss": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-12.0.0.tgz", + "integrity": "sha512-5Bb2mlGy6WLa30oNeKpZvavv2lowJUsUJO25+OA68GFTemlwd1zbFsL7q0bReKipOSU3sG47hKneZ6Nd+ctrFA==", + "dev": true, + "dependencies": { + "postcss-scss": "^4.0.6", + "stylelint-config-recommended": "^12.0.0", + "stylelint-scss": "^5.0.0" + }, + "peerDependencies": { + "postcss": "^8.3.3", + "stylelint": "^15.5.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + } + } + }, + "node_modules/stylelint-config-standard-scss/node_modules/stylelint-config-recommended-scss/node_modules/stylelint-scss": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-5.3.2.tgz", + "integrity": "sha512-4LzLaayFhFyneJwLo0IUa8knuIvj+zF0vBFueQs4e3tEaAMIQX8q5th8ziKkgOavr6y/y9yoBe+RXN/edwLzsQ==", + "dev": true, + "dependencies": { + "known-css-properties": "^0.29.0", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-selector-parser": "^6.0.13", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "stylelint": "^14.5.1 || ^15.0.0" + } + }, + "node_modules/stylelint-config-standard-scss/node_modules/stylelint-config-standard": { + "version": "33.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-33.0.0.tgz", + "integrity": "sha512-eyxnLWoXImUn77+ODIuW9qXBDNM+ALN68L3wT1lN2oNspZ7D9NVGlNHb2QCUn4xDug6VZLsh0tF8NyoYzkgTzg==", + "dev": true, + "dependencies": { + "stylelint-config-recommended": "^12.0.0" + }, + "peerDependencies": { + "stylelint": "^15.5.0" + } + }, + "node_modules/stylelint-config-standard/node_modules/stylelint-config-recommended": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-13.0.0.tgz", + "integrity": "sha512-EH+yRj6h3GAe/fRiyaoO2F9l9Tgg50AOFhaszyfov9v6ayXJ1IkSHwTxd7lB48FmOeSGDPLjatjO11fJpmarkQ==", + "dev": true, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "stylelint": "^15.10.0" + } + }, + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "node_modules/stylelint/node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/stylelint/node_modules/file-entry-cache": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-7.0.2.tgz", + "integrity": "sha512-TfW7/1iI4Cy7Y8L6iqNdZQVvdXn0f8B4QcIXmkIbtTIe/Okm/nSlHb4IwGzRVOd3WfSieCgvf5cMzEfySAIl0g==", + "dev": true, + "dependencies": { + "flat-cache": "^3.2.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/stylelint/node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/stylelint/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stylelint/node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/stylis": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", + "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==", + "optional": true + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", + "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/svgo": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.2.0.tgz", + "integrity": "sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/sweetalert2": { + "version": "11.10.4", + "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.10.4.tgz", + "integrity": "sha512-MOVRuEW/yQsyzgkaiHqAJcYKxW3vhtE5o3Skp6vZdyJejCOWo4FOicbjRfvqHAXTyTMuwDHA+0lYbO6BiHl1Gw==", + "dev": true, + "peer": true, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/limonte" + } + }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/table/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/table/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/table/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^4.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/terser": { + "version": "5.16.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", + "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "license": "MIT" + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.1", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser-webpack-plugin/node_modules/terser": { + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz", + "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/through": { + "version": "2.3.8", + "dev": true, + "license": "MIT" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "optional": true + }, + "node_modules/tmp": { + "version": "0.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/trim-newlines": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", + "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "optional": true, + "engines": { + "node": ">=6.10" + } + }, + "node_modules/ts-node": { + "version": "8.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "^3.0.0" + }, + "bin": { + "ts-node": "dist/bin.js" + }, + "engines": { + "node": ">=4.2.0" + }, + "peerDependencies": { + "typescript": ">=2.0" + } + }, + "node_modules/tsconfig-paths": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.1.2.tgz", + "integrity": "sha512-uhxiMgnXQp1IR622dUXI+9Ehnws7i/y6xvpZB9IbUVOPy0muvdvgXeZOn88UcGPiT98Vp3rJPTa8bFoalZ3Qhw==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/tslint": { + "version": "6.1.3", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + } + }, + "node_modules/tslint/node_modules/commander": { + "version": "2.20.3", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/tslint/node_modules/mkdirp": { + "version": "0.5.6", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/tslint/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/tslint/node_modules/tslib": { + "version": "1.14.1", + "dev": true, + "license": "0BSD", + "peer": true + }, + "node_modules/tslint/node_modules/tsutils": { + "version": "2.29.0", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/tsutils": { + "version": "3.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "dev": true, + "license": "0BSD" + }, + "node_modules/tuf-js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", + "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", + "dev": true, + "dependencies": { + "@tufjs/models": "1.0.4", + "debug": "^4.3.4", + "make-fetch-happen": "^11.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/tuf-js/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tuf-js/node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/tuf-js/node_modules/minipass-fetch/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "dev": true, + "license": "Unlicense" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "2.19.0", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-assert": { + "version": "1.0.9", + "dev": true, + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ua-parser-js": { + "version": "0.7.37", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.37.tgz", + "integrity": "sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dev": true, + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "dev": true, + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "optional": true + }, + "node_modules/vite": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", + "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", + "dev": true, + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/void-elements": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", + "dev": true, + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/wait-on": { + "version": "5.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "axios": "^0.21.1", + "joi": "^17.3.0", + "lodash": "^4.17.21", + "minimist": "^1.2.5", + "rxjs": "^6.6.3" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-worker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.3.0.tgz", + "integrity": "sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==", + "optional": true + }, + "node_modules/webdriver-js-extender": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/selenium-webdriver": "^3.0.0", + "selenium-webdriver": "^3.0.1" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/webdriver-manager": { + "version": "12.1.9", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.9.tgz", + "integrity": "sha512-Yl113uKm8z4m/KMUVWHq1Sjtla2uxEBtx2Ue3AmIlnlPAKloDn/Lvmy6pqWCUersVISpdMeVpAaGbNnvMuT2LQ==", + "dev": true, + "dependencies": { + "adm-zip": "^0.5.2", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" + }, + "bin": { + "webdriver-manager": "bin/webdriver-manager" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/webdriver-manager/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webdriver-manager/node_modules/ansi-styles": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webdriver-manager/node_modules/chalk": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webdriver-manager/node_modules/rimraf": { + "version": "2.7.1", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/webdriver-manager/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/webdriver-manager/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webdriver-manager/node_modules/supports-color": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/webpack": { + "version": "5.76.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", + "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.10.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.2.tgz", + "integrity": "sha512-Wu+EHmX326YPYUpQLKmKbTyZZJIB8/n6R09pTmB03kJmnMsVPTo9COzHZFr01txwaCAuZvfBJE4ZCHRcKs5JaQ==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-subresource-integrity": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "typed-assert": "^1.0.8" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "html-webpack-plugin": ">= 5.0.0-beta.1 < 6", + "webpack": "^5.12.0" + }, + "peerDependenciesMeta": { + "html-webpack-plugin": { + "optional": true + } + } + }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "license": "MIT", + "peer": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "license": "MIT", + "peer": true + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.1.1", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wildcard": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", + "dev": true + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "node_modules/xml2js": { + "version": "0.4.23", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zip-stream": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", + "dev": true, + "peer": true, + "dependencies": { + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/archiver-utils": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", + "dev": true, + "peer": true, + "dependencies": { + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/zone.js": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.13.3.tgz", + "integrity": "sha512-MKPbmZie6fASC/ps4dkmIhaT5eonHkEt6eAy80K42tAm0G2W+AahLJjbfi6X9NPdciOE9GRFTTM8u2IiF6O3ww==", + "dependencies": { + "tslib": "^2.3.0" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@ampproject/remapping": { + "version": "2.2.0", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@angular-builders/custom-webpack": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@angular-builders/custom-webpack/-/custom-webpack-16.0.1.tgz", + "integrity": "sha512-C6INC8UOYDcp8LJwNhE0m66yp+nZX50JdgGI8oRn7fqw3gO58qhDgXrR/8BCrSeC8eOx8WxSuvBJ6u+9dozhyw==", + "dev": true, + "requires": { + "@angular-devkit/architect": ">=0.1600.0 < 0.1700.0", + "@angular-devkit/build-angular": "^16.0.0", + "@angular-devkit/core": "^16.0.0", + "lodash": "^4.17.15", + "ts-node": "^10.0.0", + "tsconfig-paths": "^4.1.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } + } + } + }, + "@angular-devkit/architect": { + "version": "0.1602.13", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.13.tgz", + "integrity": "sha512-ejrOYoXgbhDYjdaW4B2SyWeb6AqR8vqqzMyvCq2JX7fo08IhLnVu1fcl0fwr161l37TuzgPNWrHSciOzzmZDkw==", + "dev": true, + "requires": { + "@angular-devkit/core": "16.2.13", + "rxjs": "7.8.1" + }, + "dependencies": { + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + } + } + }, + "@angular-devkit/build-angular": { + "version": "16.2.13", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.13.tgz", + "integrity": "sha512-2G8gnBpBKcu+/jJH5DJZyMgn2RwDFPgiNSkcLKFg5DdqVFVT3CCoZAobfpAEMndrysfMmoUPGuAmsgCfdczQjg==", + "dev": true, + "requires": { + "@ampproject/remapping": "2.2.1", + "@angular-devkit/architect": "0.1602.13", + "@angular-devkit/build-webpack": "0.1602.13", + "@angular-devkit/core": "16.2.13", + "@babel/core": "7.22.9", + "@babel/generator": "7.22.9", + "@babel/helper-annotate-as-pure": "7.22.5", + "@babel/helper-split-export-declaration": "7.22.6", + "@babel/plugin-proposal-async-generator-functions": "7.20.7", + "@babel/plugin-transform-async-to-generator": "7.22.5", + "@babel/plugin-transform-runtime": "7.22.9", + "@babel/preset-env": "7.22.9", + "@babel/runtime": "7.22.6", + "@babel/template": "7.22.5", + "@discoveryjs/json-ext": "0.5.7", + "@ngtools/webpack": "16.2.13", + "@vitejs/plugin-basic-ssl": "1.0.1", + "ansi-colors": "4.1.3", + "autoprefixer": "10.4.14", + "babel-loader": "9.1.3", + "babel-plugin-istanbul": "6.1.1", + "browserslist": "^4.21.5", + "chokidar": "3.5.3", + "copy-webpack-plugin": "11.0.0", + "critters": "0.0.20", + "css-loader": "6.8.1", + "esbuild": "0.18.17", + "esbuild-wasm": "0.18.17", + "fast-glob": "3.3.1", + "guess-parser": "0.4.22", + "https-proxy-agent": "5.0.1", + "inquirer": "8.2.4", + "jsonc-parser": "3.2.0", + "karma-source-map-support": "1.4.0", + "less": "4.1.3", + "less-loader": "11.1.0", + "license-webpack-plugin": "4.0.2", + "loader-utils": "3.2.1", + "magic-string": "0.30.1", + "mini-css-extract-plugin": "2.7.6", + "mrmime": "1.0.1", + "open": "8.4.2", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "7.0.0", + "picomatch": "2.3.1", + "piscina": "4.0.0", + "postcss": "8.4.31", + "postcss-loader": "7.3.3", + "resolve-url-loader": "5.0.0", + "rxjs": "7.8.1", + "sass": "1.64.1", + "sass-loader": "13.3.2", + "semver": "7.5.4", + "source-map-loader": "4.0.1", + "source-map-support": "0.5.21", + "terser": "5.19.2", + "text-table": "0.2.0", + "tree-kill": "1.2.2", + "tslib": "2.6.1", + "vite": "4.5.2", + "webpack": "5.88.2", + "webpack-dev-middleware": "6.1.2", + "webpack-dev-server": "4.15.1", + "webpack-merge": "5.9.0", + "webpack-subresource-integrity": "5.1.0" + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/core": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", + "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.8", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", + "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/template": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "css-loader": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", + "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.3", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + } + }, + "es-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + } + } + }, + "terser": { + "version": "5.19.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz", + "integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } + }, + "tslib": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", + "dev": true + }, + "webpack": { + "version": "5.88.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", + "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + } + }, + "webpack-merge": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", + "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + } + } + }, + "@angular-devkit/build-webpack": { + "version": "0.1602.13", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.13.tgz", + "integrity": "sha512-H7CqnC0kvWR0Q45ZXsCO3M9lGd4dOajEmkCVmq7vVptU3nJRbCqJ0ZScj9bH5YSlcdO0jPbOdcTELWyEZ3BMFQ==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.1602.13", + "rxjs": "7.8.1" + }, + "dependencies": { + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + } + } + }, + "@angular-devkit/core": { + "version": "16.2.13", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.13.tgz", + "integrity": "sha512-6jTlYOIeYsOF/Vw/hBNusjoCmKJBByoyGS1Fu2Yav8ltxYK04aDtI73l9JJB/5Cpzhc4YELrMqBMH7in5Vowaw==", + "dev": true, + "requires": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "picomatch": "2.3.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "dependencies": { + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + } + } + }, + "@angular-devkit/schematics": { + "version": "16.2.13", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.13.tgz", + "integrity": "sha512-uhhJZpppaeuT/2V6RiCheJKzS4bAZADL+Gw59VJaojqS8ssdG1UzvqRJokIzFzP7+MhHWylZBWUvWLQxuUvtsA==", + "dev": true, + "requires": { + "@angular-devkit/core": "16.2.13", + "jsonc-parser": "3.2.0", + "magic-string": "0.30.1", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "dependencies": { + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + } + } + }, + "@angular-eslint/builder": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.3.1.tgz", + "integrity": "sha512-PmIOnRwqdOW1bvZtpTGBTDcOq/Czm3D+IPC/k90yIMs1VsAtcxqUmUtELje+ylJeb2LPeEZavekSnEpcatM4HQ==", + "dev": true, + "requires": { + "@nx/devkit": "16.5.1", + "nx": "16.5.1" + } + }, + "@angular-eslint/bundled-angular-compiler": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-16.3.1.tgz", + "integrity": "sha512-m4WP1xwS9XLcC/3n6lIcG5HZoai/5eb5W3xm48GVcv//0qE2p7S96RSgKPgGHvif5pF8O9xAqEWs3gDEG45+7A==", + "dev": true + }, + "@angular-eslint/eslint-plugin": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-16.3.1.tgz", + "integrity": "sha512-kSc8ESfoy8TUSthbq0Lpq9e17I+3Smy4rHoNpKCFEGuJgPs0+OssZMxB6a5EawGbv2EKTPEtrxzFm1WsLR0U9Q==", + "dev": true, + "requires": { + "@angular-eslint/utils": "16.3.1", + "@typescript-eslint/utils": "5.62.0" + } + }, + "@angular-eslint/eslint-plugin-template": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-16.3.1.tgz", + "integrity": "sha512-+RcFEWqNiRt3+5jXvmlIDlXtP9+vjdmgmVL6tt8yDbqdjBOewtyMu4pE4YaR4sFboyxgME9PbO2WrOyPXh6xjg==", + "dev": true, + "requires": { + "@angular-eslint/bundled-angular-compiler": "16.3.1", + "@angular-eslint/utils": "16.3.1", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "aria-query": "5.3.0", + "axobject-query": "4.0.0" + } + }, + "@angular-eslint/schematics": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-16.3.1.tgz", + "integrity": "sha512-cqrdobdtRY2XjLa6PhuGOQ7UhTRk2AvWS01sKeGjZ94nQJm5NUtEUyf6u3deIPYllW7gSAWjYzKUObKcTW/R+g==", + "dev": true, + "requires": { + "@angular-eslint/eslint-plugin": "16.3.1", + "@angular-eslint/eslint-plugin-template": "16.3.1", + "@nx/devkit": "16.5.1", + "ignore": "5.2.4", + "nx": "16.5.1", + "strip-json-comments": "3.1.1", + "tmp": "0.2.1" + } + }, + "@angular-eslint/template-parser": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-16.3.1.tgz", + "integrity": "sha512-9+SxUtxB2iOnm0ldS2ow0stMxe02rB/TxeMIe8fxsLFHZdw8RQvs/p3HLvVHXzv6gUblMHebIb/ubUmwEVb2SA==", + "dev": true, + "requires": { + "@angular-eslint/bundled-angular-compiler": "16.3.1", + "eslint-scope": "^7.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "@angular-eslint/utils": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-16.3.1.tgz", + "integrity": "sha512-tEBcce0rG+DmcPO8jhRffUFDioGw3G4cUAE15XlRctY1J3QzOBH9HdUOTDt0mMjBgpWCzh0YVT1Moh2bPXU9Xg==", + "dev": true, + "requires": { + "@angular-eslint/bundled-angular-compiler": "16.3.1", + "@typescript-eslint/utils": "5.62.0" + } + }, + "@angular/animations": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-16.2.12.tgz", + "integrity": "sha512-MD0ElviEfAJY8qMOd6/jjSSvtqER2RDAi0lxe6EtUacC1DHCYkaPrKW4vLqY+tmZBg1yf+6n+uS77pXcHHcA3w==", + "devOptional": true, + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/cdk": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-16.2.14.tgz", + "integrity": "sha512-n6PrGdiVeSTEmM/HEiwIyg6YQUUymZrb5afaNLGFRM5YL0Y8OBqd+XhCjb0OfD/AfgCUtedVEPwNqrfW8KzgGw==", + "requires": { + "parse5": "^7.1.2", + "tslib": "^2.3.0" + } + }, + "@angular/cli": { + "version": "16.2.13", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.13.tgz", + "integrity": "sha512-Zs/IHV0qeQBlRYp3XTJP96KKMFrOVd4gFWEXyt8xVbma9W7UCWr/0C6D8HRFjheiT40TSa2Suwpk6Hppm+9ESA==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.1602.13", + "@angular-devkit/core": "16.2.13", + "@angular-devkit/schematics": "16.2.13", + "@schematics/angular": "16.2.13", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.3", + "ini": "4.1.1", + "inquirer": "8.2.4", + "jsonc-parser": "3.2.0", + "npm-package-arg": "10.1.0", + "npm-pick-manifest": "8.0.1", + "open": "8.4.2", + "ora": "5.4.1", + "pacote": "15.2.0", + "resolve": "1.22.2", + "semver": "7.5.4", + "symbol-observable": "4.0.0", + "yargs": "17.7.2" + }, + "dependencies": { + "ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true + } + } + }, + "@angular/common": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-16.2.12.tgz", + "integrity": "sha512-B+WY/cT2VgEaz9HfJitBmgdk4I333XG/ybC98CMC4Wz8E49T8yzivmmxXB3OD6qvjcOB6ftuicl6WBqLbZNg2w==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/compiler": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-16.2.12.tgz", + "integrity": "sha512-6SMXUgSVekGM7R6l1Z9rCtUGtlg58GFmgbpMCsGf+VXxP468Njw8rjT2YZkf5aEPxEuRpSHhDYjqz7n14cwCXQ==", + "dev": true, + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/compiler-cli": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-16.2.12.tgz", + "integrity": "sha512-pWSrr152562ujh6lsFZR8NfNc5Ljj+zSTQO44DsuB0tZjwEpnRcjJEgzuhGXr+CoiBf+jTSPZKemtSktDk5aaA==", + "dev": true, + "requires": { + "@babel/core": "7.23.2", + "@jridgewell/sourcemap-codec": "^1.4.14", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "reflect-metadata": "^0.1.2", + "semver": "^7.0.0", + "tslib": "^2.3.0", + "yargs": "^17.2.1" + } + }, + "@angular/core": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-16.2.12.tgz", + "integrity": "sha512-GLLlDeke/NjroaLYOks0uyzFVo6HyLl7VOm0K1QpLXnYvW63W9Ql/T3yguRZa7tRkOAeFZ3jw+1wnBD4O8MoUA==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/forms": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-16.2.12.tgz", + "integrity": "sha512-1Eao89hlBgLR3v8tU91vccn21BBKL06WWxl7zLpQmG6Hun+2jrThgOE4Pf3os4fkkbH4Apj0tWL2fNIWe/blbw==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/localize": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-16.2.12.tgz", + "integrity": "sha512-sNIHDlZKENPQqx64qGF99g2sOCy9i9O4VOmjKD/FZbeE8O5qBbaQlkwOlFoQIt35/cnvtAtf7oQF6tqmiVtS2w==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "7.23.2", + "fast-glob": "3.3.0", + "yargs": "^17.2.1" + }, + "dependencies": { + "fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "dev": true, + "peer": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + } + } + }, + "@angular/platform-browser": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-16.2.12.tgz", + "integrity": "sha512-NnH7ju1iirmVEsUq432DTm0nZBGQsBrU40M3ZeVHMQ2subnGiyUs3QyzDz8+VWLL/T5xTxWLt9BkDn65vgzlIQ==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/platform-browser-dynamic": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-16.2.12.tgz", + "integrity": "sha512-ya54jerNgreCVAR278wZavwjrUWImMr2F8yM5n9HBvsMBbFaAQ83anwbOEiHEF2BlR+gJiEBLfpuPRMw20pHqw==", + "dev": true, + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/router": { + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-16.2.12.tgz", + "integrity": "sha512-aU6QnYSza005V9P3W6PpkieL56O0IHps96DjqI1RS8yOJUl3THmokqYN4Fm5+HXy4f390FN9i6ftadYQDKeWmA==", + "dev": true, + "requires": { + "tslib": "^2.3.0" + } + }, + "@assemblyscript/loader": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", + "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", + "dev": true + }, + "@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + } + }, + "@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true + }, + "@babel/core": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "requires": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz", + "integrity": "sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "dependencies": { + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", + "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dev": true, + "requires": { + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "dependencies": { + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + } + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + } + }, + "@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + } + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + } + }, + "@babel/helpers": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.8.tgz", + "integrity": "sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + } + }, + "@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "dev": true + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.23.3" + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "requires": {} + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-async-generator-functions": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz", + "integrity": "sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-static-block": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", + "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + } + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.15" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dynamic-import": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-export-namespace-from": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", + "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-json-strings": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-logical-assignment-operators": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz", + "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-transform-numeric-separator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-transform-object-rest-spread": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.23.3", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.23.3" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20" + } + }, + "@babel/plugin-transform-optional-catch-binding": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-transform-optional-chaining": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-methods": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-property-in-object": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.9.tgz", + "integrity": "sha512-9KjBH61AGJetCPYp/IEyLEp47SyybZb0nDRpBvmtEkm+rUIwxdlKpyNHI1TmsGkeuLclJdleQHRZ8XLBnnh8CQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.4", + "babel-plugin-polyfill-corejs3": "^0.8.2", + "babel-plugin-polyfill-regenerator": "^0.5.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-property-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-sets-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/preset-env": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.9.tgz", + "integrity": "sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.5", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.22.7", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.22.5", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.5", + "@babel/plugin-transform-classes": "^7.22.6", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.22.5", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.5", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.5", + "@babel/plugin-transform-for-of": "^7.22.5", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.5", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.5", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.5", + "@babel/plugin-transform-modules-systemjs": "^7.22.5", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.5", + "@babel/plugin-transform-numeric-separator": "^7.22.5", + "@babel/plugin-transform-object-rest-spread": "^7.22.5", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.6", + "@babel/plugin-transform-parameters": "^7.22.5", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.5", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.5", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.5", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.4", + "babel-plugin-polyfill-corejs3": "^0.8.2", + "babel-plugin-polyfill-regenerator": "^0.5.1", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/preset-modules": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz", + "integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "@babel/runtime": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.11" + } + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/traverse": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + } + } + }, + "@babel/types": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@braintree/sanitize-url": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", + "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==", + "optional": true + }, + "@colors/colors": { + "version": "1.5.0", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + } + } + }, + "@csstools/css-parser-algorithms": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.1.tgz", + "integrity": "sha512-ubEkAaTfVZa+WwGhs5jbo5Xfqpeaybr/RvWzvFxRs4jfq16wH8l8Ty/QEEpINxll4xhuGfdMbipRyz5QZh9+FA==", + "dev": true, + "requires": {} + }, + "@csstools/css-tokenizer": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.4.tgz", + "integrity": "sha512-PuWRAewQLbDhGeTvFuq2oClaSCKPIBmHyIobCV39JHRYN0byDcUWJl5baPeNUcqrjtdMNqFooE0FGl31I3JOqw==", + "dev": true + }, + "@csstools/media-query-list-parser": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.9.tgz", + "integrity": "sha512-qqGuFfbn4rUmyOB0u8CVISIp5FfJ5GAR3mBrZ9/TKndHakdnm6pY0L/fbLcpPnrzwCyyTEZl1nUcXAYHEWneTA==", + "dev": true, + "requires": {} + }, + "@csstools/selector-specificity": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.2.tgz", + "integrity": "sha512-RpHaZ1h9LE7aALeQXmXrJkRG84ZxIsctEN2biEUmFyKpzFM3zZ35eUMcIzZFsw/2olQE6v69+esEqU2f1MKycg==", + "dev": true, + "requires": {} + }, + "@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "requires": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } + } + }, + "@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true + }, + "@electron/asar": { + "version": "3.2.2", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "chromium-pickle-js": "^0.2.0", + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "dependencies": { + "commander": { + "version": "5.1.0", + "dev": true + } + } + }, + "@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "global-agent": "^3.0.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "@electron/notarize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz", + "integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + } + }, + "@electron/osx-sign": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", + "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", + "dev": true, + "requires": { + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "@electron/universal": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", + "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", + "dev": true, + "requires": { + "@electron/asar": "^3.2.1", + "@malept/cross-spawn-promise": "^1.1.0", + "debug": "^4.3.1", + "dir-compare": "^3.0.0", + "fs-extra": "^9.0.1", + "minimatch": "^3.0.4", + "plist": "^3.0.4" + } + }, + "@esbuild/android-arm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.17.tgz", + "integrity": "sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz", + "integrity": "sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.17.tgz", + "integrity": "sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz", + "integrity": "sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz", + "integrity": "sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz", + "integrity": "sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz", + "integrity": "sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz", + "integrity": "sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz", + "integrity": "sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz", + "integrity": "sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz", + "integrity": "sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz", + "integrity": "sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz", + "integrity": "sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz", + "integrity": "sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz", + "integrity": "sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz", + "integrity": "sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz", + "integrity": "sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz", + "integrity": "sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz", + "integrity": "sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz", + "integrity": "sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.17.tgz", + "integrity": "sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz", + "integrity": "sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==", + "dev": true, + "optional": true + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true + }, + "@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true + }, + "@hapi/hoek": { + "version": "9.3.0", + "dev": true + }, + "@hapi/topo": { + "version": "5.1.0", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0" + }, + "@jridgewell/set-array": { + "version": "1.1.2" + }, + "@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz", + "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==", + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", + "dev": true + }, + "@malept/cross-spawn-promise": { + "version": "1.1.1", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + } + }, + "@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + } + }, + "@monaco-editor/loader": { + "version": "1.3.2", + "requires": { + "state-local": "^1.0.6" + } + }, + "@ng-bootstrap/ng-bootstrap": { + "version": "15.1.2", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-15.1.2.tgz", + "integrity": "sha512-mM2yiGnt9o7KZLIFp8K1vjfmVfu7HR3d8dhH5SszfArbgn9DvvQ4P5D5TDGygzyBSzeyZe18p7I8rX8vgA6DKw==", + "dev": true, + "requires": { + "tslib": "^2.3.0" + } + }, + "@ngtools/webpack": { + "version": "16.2.13", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.13.tgz", + "integrity": "sha512-P5OiVp9MeMwVxihtC9NB4mx1Zlbup2DLMAWYAl8/kcFdRrRW+1YDQn93tlFToQDHGpPxkqW7cnFUPnA+QwQMYA==", + "dev": true, + "requires": {} + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "dev": true, + "requires": { + "semver": "^7.3.5" + } + }, + "@npmcli/git": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", + "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", + "dev": true, + "requires": { + "@npmcli/promise-spawn": "^6.0.0", + "lru-cache": "^7.4.4", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^3.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "@npmcli/installed-package-contents": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", + "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", + "dev": true, + "requires": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + } + }, + "@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "@npmcli/node-gyp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", + "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", + "dev": true + }, + "@npmcli/promise-spawn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", + "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", + "dev": true, + "requires": { + "which": "^3.0.0" + }, + "dependencies": { + "which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "@npmcli/run-script": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", + "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", + "dev": true, + "requires": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/promise-spawn": "^6.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^3.0.0", + "which": "^3.0.0" + }, + "dependencies": { + "which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "@nrwl/devkit": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-16.5.1.tgz", + "integrity": "sha512-NB+DE/+AFJ7lKH/WBFyatJEhcZGj25F24ncDkwjZ6MzEiSOGOJS0LaV/R+VUsmS5EHTPXYOpn3zHWWAcJhyOmA==", + "dev": true, + "requires": { + "@nx/devkit": "16.5.1" + } + }, + "@nrwl/tao": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-16.5.1.tgz", + "integrity": "sha512-x+gi/fKdM6uQNIti9exFlm3V5LBP3Y8vOEziO42HdOigyrXa0S0HD2WMpccmp6PclYKhwEDUjKJ39xh5sdh4Ig==", + "dev": true, + "requires": { + "nx": "16.5.1" + } + }, + "@nx/devkit": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-16.5.1.tgz", + "integrity": "sha512-T1acZrVVmJw/sJ4PIGidCBYBiBqlg/jT9e8nIGXLSDS20xcLvfo4zBQf8UZLrmHglnwwpDpOWuVJCp2rYA5aDg==", + "dev": true, + "requires": { + "@nrwl/devkit": "16.5.1", + "ejs": "^3.1.7", + "ignore": "^5.0.4", + "semver": "7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0" + }, + "dependencies": { + "semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@nx/nx-darwin-arm64": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-16.5.1.tgz", + "integrity": "sha512-q98TFI4B/9N9PmKUr1jcbtD4yAFs1HfYd9jUXXTQOlfO9SbDjnrYJgZ4Fp9rMNfrBhgIQ4x1qx0AukZccKmH9Q==", + "dev": true, + "optional": true + }, + "@nx/nx-darwin-x64": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-16.5.1.tgz", + "integrity": "sha512-j9HmL1l8k7EVJ3eOM5y8COF93gqrydpxCDoz23ZEtsY+JHY77VAiRQsmqBgEx9GGA2dXi9VEdS67B0+1vKariw==", + "dev": true, + "optional": true + }, + "@nx/nx-freebsd-x64": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-16.5.1.tgz", + "integrity": "sha512-CXSPT01aVS869tvCCF2tZ7LnCa8l41wJ3mTVtWBkjmRde68E5Up093hklRMyXb3kfiDYlfIKWGwrV4r0eH6x1A==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-arm-gnueabihf": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-16.5.1.tgz", + "integrity": "sha512-BhrumqJSZCWFfLFUKl4CAUwR0Y0G2H5EfFVGKivVecEQbb+INAek1aa6c89evg2/OvetQYsJ+51QknskwqvLsA==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-arm64-gnu": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-16.5.1.tgz", + "integrity": "sha512-x7MsSG0W+X43WVv7JhiSq2eKvH2suNKdlUHEG09Yt0vm3z0bhtym1UCMUg3IUAK7jy9hhLeDaFVFkC6zo+H/XQ==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-arm64-musl": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-16.5.1.tgz", + "integrity": "sha512-J+/v/mFjOm74I0PNtH5Ka+fDd+/dWbKhpcZ2R1/6b9agzZk+Ff/SrwJcSYFXXWKbPX+uQ4RcJoytT06Zs3s0ow==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-x64-gnu": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-16.5.1.tgz", + "integrity": "sha512-igooWJ5YxQ94Zft7IqgL+Lw0qHaY15Btw4gfK756g/YTYLZEt4tTvR1y6RnK/wdpE3sa68bFTLVBNCGTyiTiDQ==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-x64-musl": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-16.5.1.tgz", + "integrity": "sha512-zF/exnPqFYbrLAduGhTmZ7zNEyADid2bzNQiIjJkh8Y6NpDwrQIwVIyvIxqynsjMrIs51kBH+8TUjKjj2Jgf5A==", + "dev": true, + "optional": true + }, + "@nx/nx-win32-arm64-msvc": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-16.5.1.tgz", + "integrity": "sha512-qtqiLS9Y9TYyAbbpq58kRoOroko4ZXg5oWVqIWFHoxc5bGPweQSJCROEqd1AOl2ZDC6BxfuVHfhDDop1kK05WA==", + "dev": true, + "optional": true + }, + "@nx/nx-win32-x64-msvc": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-16.5.1.tgz", + "integrity": "sha512-kUJBLakK7iyA9WfsGGQBVennA4jwf5XIgm0lu35oMOphtZIluvzItMt0EYBmylEROpmpEIhHq0P6J9FA+WH0Rg==", + "dev": true, + "optional": true + }, + "@parcel/watcher": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.4.tgz", + "integrity": "sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg==", + "dev": true, + "requires": { + "node-addon-api": "^3.2.1", + "node-gyp-build": "^4.3.0" + }, + "dependencies": { + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true + } + } + }, + "@perfectmemory/ngx-contextmenu": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/@perfectmemory/ngx-contextmenu/-/ngx-contextmenu-16.0.2.tgz", + "integrity": "sha512-uZsI1dJmz0Xp2l9OQvSBXIU0p9u9gHEGHCimwin+A/NGrkRvChWSjACHjmtX7jO0C7Vz5uMo6FgwWiz2OHC4BQ==", + "requires": { + "tslib": "^2.3.1" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "@popperjs/core": { + "version": "2.11.6", + "dev": true + }, + "@schematics/angular": { + "version": "16.2.13", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.13.tgz", + "integrity": "sha512-SFE9e7X/CEtzwGEqHUqXriAm4J4uTjcfoRXslc7BuqOKABM8RXPphGQsVG4xOt3n25kXXGkFO2dvDRHuLTP1fQ==", + "dev": true, + "requires": { + "@angular-devkit/core": "16.2.13", + "@angular-devkit/schematics": "16.2.13", + "jsonc-parser": "3.2.0" + } + }, + "@sideway/address": { + "version": "4.1.4", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "dev": true + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "dev": true + }, + "@sigstore/bundle": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", + "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", + "dev": true, + "requires": { + "@sigstore/protobuf-specs": "^0.2.0" + } + }, + "@sigstore/protobuf-specs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", + "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", + "dev": true + }, + "@sigstore/sign": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", + "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", + "dev": true, + "requires": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "make-fetch-happen": "^11.0.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "requires": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "requires": { + "encoding": "^0.1.13", + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "dependencies": { + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + } + } + } + } + }, + "@sigstore/tuf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", + "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", + "dev": true, + "requires": { + "@sigstore/protobuf-specs": "^0.2.0", + "tuf-js": "^1.1.7" + } + }, + "@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true + }, + "@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", + "dev": true + }, + "@sweetalert2/ngx-sweetalert2": { + "version": "11.0.0", + "dev": true, + "requires": { + "tslib": "^2.0.0" + } + }, + "@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "@tootallnate/once": { + "version": "2.0.0", + "dev": true + }, + "@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "@tufjs/canonical-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", + "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", + "dev": true + }, + "@tufjs/models": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz", + "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==", + "dev": true, + "requires": { + "@tufjs/canonical-json": "1.0.0", + "minimatch": "^9.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/bootstrap": { + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.10.tgz", + "integrity": "sha512-F2X+cd6551tep0MvVZ6nM8v7XgGN/twpdNDjqS1TUM7YFNEtQYWk+dKAnH+T1gr6QgCoGMPl487xw/9hXooa2g==", + "dev": true, + "requires": { + "@popperjs/core": "^2.9.2" + } + }, + "@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "requires": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "dev": true, + "requires": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "@types/d3-array": { + "version": "2.12.3", + "dev": true + }, + "@types/d3-axis": { + "version": "2.1.3", + "dev": true, + "requires": { + "@types/d3-selection": "^2" + } + }, + "@types/d3-brush": { + "version": "2.1.2", + "dev": true, + "requires": { + "@types/d3-selection": "^2" + } + }, + "@types/d3-chord": { + "version": "2.0.3", + "dev": true + }, + "@types/d3-color": { + "version": "2.0.3", + "dev": true + }, + "@types/d3-contour": { + "version": "2.0.4", + "dev": true, + "requires": { + "@types/d3-array": "^2", + "@types/geojson": "*" + } + }, + "@types/d3-delaunay": { + "version": "5.3.1", + "dev": true + }, + "@types/d3-dispatch": { + "version": "2.0.1", + "dev": true + }, + "@types/d3-drag": { + "version": "2.0.2", + "dev": true, + "requires": { + "@types/d3-selection": "^2" + } + }, + "@types/d3-dsv": { + "version": "2.0.2", + "dev": true + }, + "@types/d3-ease": { + "version": "2.0.2", + "dev": true + }, + "@types/d3-fetch": { + "version": "2.0.2", + "dev": true, + "requires": { + "@types/d3-dsv": "^2" + } + }, + "@types/d3-force": { + "version": "2.1.4", + "dev": true + }, + "@types/d3-format": { + "version": "2.0.2", + "dev": true + }, + "@types/d3-geo": { + "version": "2.0.3", + "dev": true, + "requires": { + "@types/geojson": "*" + } + }, + "@types/d3-hierarchy": { + "version": "2.0.2", + "dev": true + }, + "@types/d3-interpolate": { + "version": "2.0.2", + "dev": true, + "requires": { + "@types/d3-color": "^2" + } + }, + "@types/d3-path": { + "version": "2.0.2", + "dev": true + }, + "@types/d3-polygon": { + "version": "2.0.1", + "dev": true + }, + "@types/d3-quadtree": { + "version": "2.0.2", + "dev": true + }, + "@types/d3-random": { + "version": "2.2.1", + "dev": true + }, + "@types/d3-scale": { + "version": "3.3.2", + "dev": true, + "requires": { + "@types/d3-time": "^2" + } + }, + "@types/d3-scale-chromatic": { + "version": "2.0.1", + "dev": true + }, + "@types/d3-selection": { + "version": "2.0.1", + "dev": true + }, + "@types/d3-shape": { + "version": "2.1.3", + "dev": true, + "requires": { + "@types/d3-path": "^2" + } + }, + "@types/d3-time": { + "version": "2.1.1", + "dev": true + }, + "@types/d3-time-format": { + "version": "3.0.1", + "dev": true + }, + "@types/d3-timer": { + "version": "2.0.1", + "dev": true + }, + "@types/d3-transition": { + "version": "2.0.2", + "dev": true, + "requires": { + "@types/d3-selection": "^2" + } + }, + "@types/d3-zoom": { + "version": "2.0.3", + "dev": true, + "requires": { + "@types/d3-interpolate": "^2", + "@types/d3-selection": "^2" + } + }, + "@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "requires": { + "@types/ms": "*" + } + }, + "@types/electron": { + "version": "1.6.10", + "dev": true, + "requires": { + "electron": "*" + } + }, + "@types/eslint": { + "version": "8.4.10", + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.4", + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.51" + }, + "@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.43", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz", + "integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/geojson": { + "version": "7946.0.10", + "dev": true + }, + "@types/glob": { + "version": "7.2.0", + "dev": true, + "optional": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true + }, + "@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/jasmine": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-5.1.4.tgz", + "integrity": "sha512-px7OMFO/ncXxixDe1zR13V1iycqWae0MxTaw62RpFlksUi5QuNWgQJFkTQjIOvrmutJbI7Fp2Y2N1F6D2R4G6w==", + "dev": true + }, + "@types/jasminewd2": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.13.tgz", + "integrity": "sha512-aJ3wj8tXMpBrzQ5ghIaqMisD8C3FIrcO6sDKHqFbuqAsI7yOxj0fA7MrRCPLZHIVUjERIwsMmGn/vB0UQ9u0Hg==", + "dev": true, + "requires": { + "@types/jasmine": "*" + } + }, + "@types/jquery": { + "version": "3.5.29", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.29.tgz", + "integrity": "sha512-oXQQC9X9MOPRrMhPHHOsXqeQDnWeCDT3PelUIg/Oy8FAbzSZtFHRjc7IpbfFVmpLtJ+UOoywpRsuO5Jxjybyeg==", + "dev": true, + "requires": { + "@types/sizzle": "*" + } + }, + "@types/json-schema": { + "version": "7.0.11" + }, + "@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/lodash": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", + "dev": true + }, + "@types/marked": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.3.2.tgz", + "integrity": "sha512-a79Yc3TOk6dGdituy8hmTTJXjOkZ7zsFYV10L337ttq/rec8lRMDBpV7fL3uLx6TgbFCa5DU/h8FmIBQPSbU0w==", + "peer": true + }, + "@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "@types/minimatch": { + "version": "5.1.2", + "dev": true, + "optional": true + }, + "@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true + }, + "@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "dev": true + }, + "@types/node": { + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "@types/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", + "dev": true, + "optional": true, + "requires": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "@types/q": { + "version": "0.0.32", + "dev": true + }, + "@types/qs": { + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.14.tgz", + "integrity": "sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true + }, + "@types/selenium-webdriver": { + "version": "3.0.20", + "dev": true + }, + "@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, + "@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/serve-static": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "dev": true, + "requires": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "@types/sizzle": { + "version": "2.3.3", + "dev": true + }, + "@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/verror": { + "version": "1.10.10", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.10.tgz", + "integrity": "sha512-l4MM0Jppn18hb9xmM6wwD1uTdShpf9Pn80aXTStnK1C94gtPvJcV2FrDmbOQUAQfJ1cKZHktkQUDwEqaAKXMMg==", + "dev": true, + "optional": true + }, + "@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/yauzl": { + "version": "2.10.0", + "dev": true, + "optional": true, + "requires": { + "@types/node": "*" + } + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "@vitejs/plugin-basic-ssl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.0.1.tgz", + "integrity": "sha512-pcub+YbFtFhaGRTo1832FQHQSHvMrlb43974e2eS8EKleR3p1cDdkJFPci1UhwkEf1J9Bz+wKBSzqpKp7nNj2A==", + "dev": true, + "requires": {} + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "peer": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "peer": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "peer": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "peer": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "peer": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "peer": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "peer": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "peer": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "peer": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@wessberg/ts-evaluator": { + "version": "0.0.27", + "resolved": "https://registry.npmjs.org/@wessberg/ts-evaluator/-/ts-evaluator-0.0.27.tgz", + "integrity": "sha512-7gOpVm3yYojUp/Yn7F4ZybJRxyqfMNf0LXK5KJiawbPfL0XTsJV+0mgrEDjOIR6Bi0OYk2Cyg4tjFu1r8MCZaA==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "jsdom": "^16.4.0", + "object-path": "^0.11.5", + "tslib": "^2.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@xtuc/ieee754": { + "version": "1.2.0" + }, + "@xtuc/long": { + "version": "4.2.2" + }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "@yarnpkg/parsers": { + "version": "3.0.0-rc.46", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", + "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", + "dev": true, + "requires": { + "js-yaml": "^3.10.0", + "tslib": "^2.4.0" + } + }, + "@zkochan/js-yaml": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", + "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + } + } + }, + "7zip-bin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", + "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", + "dev": true + }, + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==" + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + } + } + }, + "acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "requires": {} + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "adjust-sourcemap-loader": { + "version": "4.0.0", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.4", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "dev": true + }, + "agent-base": { + "version": "6.0.2", + "dev": true, + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dev": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-formats": { + "version": "2.1.1", + "requires": { + "ajv": "^8.0.0" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.3", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "app-builder-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", + "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "dev": true + }, + "app-builder-lib": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz", + "integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==", + "dev": true, + "requires": { + "@develar/schema-utils": "~2.6.5", + "@electron/notarize": "2.2.1", + "@electron/osx-sign": "1.0.5", + "@electron/universal": "1.5.1", + "@malept/flatpak-bundler": "^0.4.0", + "@types/fs-extra": "9.0.13", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.4", + "ejs": "^3.1.8", + "electron-publish": "24.13.1", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", + "is-ci": "^3.0.0", + "isbinaryfile": "^5.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^5.1.1", + "read-config-file": "6.3.2", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.8", + "tar": "^6.1.12", + "temp-file": "^3.4.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "isbinaryfile": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.2.tgz", + "integrity": "sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "app-root-path": { + "version": "3.1.0", + "dev": true + }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "dev": true, + "peer": true, + "requires": { + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "peer": true, + "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + } + }, + "are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "arg": { + "version": "4.1.3", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "dev": true + } + } + }, + "aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "requires": { + "dequal": "^2.0.3" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "dev": true + }, + "asn1": { + "version": "0.2.6", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "dev": true + }, + "ast-types-flow": { + "version": "0.0.7", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "dev": true + }, + "at-least-node": { + "version": "1.0.0", + "dev": true + }, + "atomically": { + "version": "1.7.0" + }, + "author-regex": { + "version": "1.0.0", + "dev": true + }, + "autoprefixer": { + "version": "10.4.14", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "dev": true, + "requires": { + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "dependencies": { + "browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "dev": true + }, + "aws4": { + "version": "1.11.0", + "dev": true + }, + "axios": { + "version": "0.21.4", + "dev": true, + "requires": { + "follow-redirects": "^1.14.0" + } + }, + "axobject-query": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", + "integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==", + "dev": true, + "requires": { + "dequal": "^2.0.3" + } + }, + "babel-loader": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", + "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "dev": true, + "requires": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.7.tgz", + "integrity": "sha512-LidDk/tEGDfuHW2DWh/Hgo4rmnw3cduK6ZkOI1NPFceSK3n/yAGeOsNT7FLnSGHkXj3RHGSEVkN3FsCTY6w2CQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.4", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", + "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.4.4", + "core-js-compat": "^3.33.1" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.4.tgz", + "integrity": "sha512-S/x2iOCvDaCASLYsOOgWOq4bCfKYVqvO/uxjkaYyZ3rVsVE3CeAI/c84NpyuBBymEgNvHgjEot3a9/Z/kXvqsg==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.4.4" + } + }, + "balanced-match": { + "version": "1.0.2", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "dev": true + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big.js": { + "version": "5.2.2" + }, + "binary-extensions": { + "version": "2.2.0", + "dev": true + }, + "bl": { + "version": "4.1.0", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "blocking-proxy": { + "version": "1.0.1", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "bluebird": { + "version": "3.7.2", + "dev": true + }, + "bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "requires": { + "bluebird": "^3.5.5" + } + }, + "body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ms": { + "version": "2.0.0", + "dev": true + } + } + }, + "bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "boolean": { + "version": "3.2.0", + "dev": true, + "optional": true + }, + "bootstrap": { + "version": "5.2.3", + "dev": true, + "requires": {} + }, + "bootstrap-icons": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz", + "integrity": "sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "peer": true, + "requires": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + } + }, + "browserstack": { + "version": "1.6.1", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + }, + "dependencies": { + "agent-base": { + "version": "4.3.0", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "debug": { + "version": "3.2.7", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + } + } + }, + "buffer": { + "version": "5.7.1", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "dev": true + }, + "buffer-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", + "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", + "dev": true + }, + "buffer-from": { + "version": "1.1.2" + }, + "builder-util": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz", + "integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==", + "dev": true, + "requires": { + "@types/debug": "^4.1.6", + "7zip-bin": "~5.2.0", + "app-builder-bin": "4.0.0", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "debug": "^4.3.4", + "fs-extra": "^10.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "builder-util-runtime": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz", + "integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "sax": "^1.2.4" + } + }, + "builtin-modules": { + "version": "1.1.1", + "dev": true, + "peer": true + }, + "builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "requires": { + "semver": "^7.0.0" + } + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true + }, + "cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "dev": true, + "requires": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + } + } + }, + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true + }, + "cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + } + }, + "call-bind": { + "version": "1.0.2", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "dev": true + }, + "camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "dev": true, + "requires": { + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + } + } + }, + "caniuse-lite": { + "version": "1.0.30001576", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz", + "integrity": "sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==" + }, + "caseless": { + "version": "0.12.0", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "3.5.3", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.3" + }, + "chromium-pickle-js": { + "version": "0.2.0", + "dev": true + }, + "ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true + }, + "class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.7.0", + "dev": true + }, + "cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "optional": true, + "requires": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "clipboard": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", + "optional": true, + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "cliui": { + "version": "8.0.1", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "clone": { + "version": "1.0.4", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "codelyzer": { + "version": "6.0.2", + "dev": true, + "requires": { + "@angular/compiler": "9.0.0", + "@angular/core": "9.0.0", + "app-root-path": "^3.0.0", + "aria-query": "^3.0.0", + "axobject-query": "2.0.2", + "css-selector-tokenizer": "^0.7.1", + "cssauron": "^1.4.0", + "damerau-levenshtein": "^1.0.4", + "rxjs": "^6.5.3", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.1.2", + "tslib": "^1.10.0", + "zone.js": "~0.10.3" + }, + "dependencies": { + "@angular/compiler": { + "version": "9.0.0", + "dev": true, + "requires": {} + }, + "@angular/core": { + "version": "9.0.0", + "dev": true, + "requires": {} + }, + "aria-query": { + "version": "3.0.0", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, + "axobject-query": { + "version": "2.0.2", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7" + } + }, + "commander": { + "version": "2.20.3", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "dev": true + }, + "tslib": { + "version": "1.14.1", + "dev": true + }, + "zone.js": { + "version": "0.10.3", + "dev": true + } + } + }, + "color-convert": { + "version": "1.9.3", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "dev": true + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "7.2.0" + }, + "common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true + }, + "compare-version": { + "version": "0.1.2", + "dev": true + }, + "compress-commons": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", + "dev": true, + "peer": true, + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "concat-map": { + "version": "0.0.1", + "dev": true + }, + "concurrently": { + "version": "6.5.1", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "date-fns": "^2.16.1", + "lodash": "^4.17.21", + "rxjs": "^6.6.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^8.1.0", + "tree-kill": "^1.2.2", + "yargs": "^16.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "cliui": { + "version": "7.0.4", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "yargs": { + "version": "16.2.0", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "dev": true + } + } + }, + "conf": { + "version": "10.2.0", + "requires": { + "ajv": "^8.6.3", + "ajv-formats": "^2.1.1", + "atomically": "^1.7.0", + "debounce-fn": "^4.0.0", + "dot-prop": "^6.0.1", + "env-paths": "^2.2.1", + "json-schema-typed": "^7.0.3", + "onetime": "^5.1.2", + "pkg-up": "^3.1.0", + "semver": "^7.3.5" + } + }, + "config-file-ts": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", + "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", + "dev": true, + "requires": { + "glob": "^10.3.10", + "typescript": "^5.3.3" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + }, + "typescript": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "dev": true + } + } + }, + "connect": { + "version": "3.7.0", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "dev": true + } + } + }, + "connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "requires": { + "safe-buffer": "5.2.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true + }, + "convert-source-map": { + "version": "1.9.0", + "dev": true + }, + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "requires": { + "is-what": "^3.14.1" + } + }, + "copy-webpack-plugin": { + "version": "11.0.0", + "requires": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "6.0.2", + "requires": { + "is-glob": "^4.0.3" + } + }, + "globby": { + "version": "13.1.2", + "requires": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" + } + }, + "slash": { + "version": "4.0.0" + } + } + }, + "core-js-compat": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.0.tgz", + "integrity": "sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==", + "dev": true, + "requires": { + "browserslist": "^4.22.2" + }, + "dependencies": { + "browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + } + } + }, + "core-util-is": { + "version": "1.0.3", + "dev": true + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "optional": true, + "requires": { + "layout-base": "^1.0.0" + } + }, + "cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "requires": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + } + } + }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "optional": true, + "requires": { + "buffer": "^5.1.0" + } + }, + "crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "peer": true + }, + "crc32-stream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "dev": true, + "peer": true, + "requires": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "critters": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.20.tgz", + "integrity": "sha512-CImNRorKOl5d8TWcnAz5n5izQ6HFsvz29k327/ELy6UFcmbiZNOsinaKvzv16WZR0P6etfSWYzE47C4/56B3Uw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "css-select": "^5.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.2", + "htmlparser2": "^8.0.2", + "postcss": "^8.4.23", + "pretty-bytes": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + } + }, + "cross-spawn": { + "version": "7.0.3", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "cross-spawn-windows-exe": { + "version": "1.2.0", + "dev": true, + "requires": { + "@malept/cross-spawn-promise": "^1.1.0", + "is-wsl": "^2.2.0", + "which": "^2.0.2" + } + }, + "css-functions-list": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.1.tgz", + "integrity": "sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==", + "dev": true + }, + "css-loader": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.10.0.tgz", + "integrity": "sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.4", + "postcss-modules-scope": "^3.1.1", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "dependencies": { + "postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "requires": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + } + } + } + }, + "css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + } + }, + "css-selector-tokenizer": { + "version": "0.7.3", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, + "css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "requires": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, + "cssauron": { + "version": "1.4.0", + "dev": true, + "requires": { + "through": "X.X.X" + } + }, + "cssesc": { + "version": "3.0.0", + "dev": true + }, + "csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "requires": { + "css-tree": "~2.2.0" + }, + "dependencies": { + "css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "requires": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + } + }, + "mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + } + } + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, + "custom-event": { + "version": "1.0.1", + "dev": true + }, + "cytoscape": { + "version": "3.28.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.28.1.tgz", + "integrity": "sha512-xyItz4O/4zp9/239wCcH8ZcFuuZooEeF8KHRmzjDfGdXsj3OG9MFSMA0pJE0uX3uCN/ygof6hHf4L7lst+JaDg==", + "optional": true, + "requires": { + "heap": "^0.2.6", + "lodash": "^4.17.21" + } + }, + "cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "optional": true, + "requires": { + "cose-base": "^1.0.0" + } + }, + "cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "optional": true, + "requires": { + "cose-base": "^2.2.0" + }, + "dependencies": { + "cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "optional": true, + "requires": { + "layout-base": "^2.0.0" + } + }, + "layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "optional": true + } + } + }, + "d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "requires": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + } + }, + "d3-array": { + "version": "3.2.0", + "requires": { + "internmap": "1 - 2" + } + }, + "d3-axis": { + "version": "3.0.0" + }, + "d3-brush": { + "version": "3.0.0", + "requires": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + } + }, + "d3-chord": { + "version": "3.0.1", + "requires": { + "d3-path": "1 - 3" + } + }, + "d3-color": { + "version": "3.1.0" + }, + "d3-contour": { + "version": "4.0.0", + "requires": { + "d3-array": "^3.2.0" + } + }, + "d3-delaunay": { + "version": "6.0.2", + "requires": { + "delaunator": "5" + } + }, + "d3-dispatch": { + "version": "3.0.1" + }, + "d3-drag": { + "version": "3.0.0", + "requires": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + } + }, + "d3-dsv": { + "version": "3.0.1", + "requires": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + } + }, + "d3-ease": { + "version": "3.0.1" + }, + "d3-fetch": { + "version": "3.0.1", + "requires": { + "d3-dsv": "1 - 3" + } + }, + "d3-flextree": { + "version": "2.1.2", + "dev": true, + "requires": { + "d3-hierarchy": "^1.1.5" + }, + "dependencies": { + "d3-hierarchy": { + "version": "1.1.9", + "dev": true + } + } + }, + "d3-force": { + "version": "3.0.0", + "requires": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + } + }, + "d3-format": { + "version": "3.1.0" + }, + "d3-geo": { + "version": "3.0.1", + "requires": { + "d3-array": "2.5.0 - 3" + } + }, + "d3-hierarchy": { + "version": "3.1.2" + }, + "d3-interpolate": { + "version": "3.0.1", + "requires": { + "d3-color": "1 - 3" + } + }, + "d3-path": { + "version": "3.0.1" + }, + "d3-polygon": { + "version": "3.0.1" + }, + "d3-quadtree": { + "version": "3.0.1" + }, + "d3-random": { + "version": "3.0.1" + }, + "d3-scale": { + "version": "4.0.2", + "requires": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + } + }, + "d3-scale-chromatic": { + "version": "3.0.0", + "requires": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + } + }, + "d3-selection": { + "version": "3.0.0" + }, + "d3-shape": { + "version": "3.1.0", + "requires": { + "d3-path": "1 - 3" + } + }, + "d3-time": { + "version": "3.0.0", + "requires": { + "d3-array": "2 - 3" + } + }, + "d3-time-format": { + "version": "4.1.0", + "requires": { + "d3-time": "1 - 3" + } + }, + "d3-timer": { + "version": "3.0.1" + }, + "d3-transition": { + "version": "3.0.1", + "requires": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + } + }, + "d3-zoom": { + "version": "3.0.0", + "requires": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + } + }, + "dagre-d3-es": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.9.tgz", + "integrity": "sha512-rYR4QfVmy+sR44IBDvVtcAmOReGBvRCWDpO2QjYwqgh9yijw6eSHBqaPG/LIOEy7aBsniLvtMW6pg19qJhq60w==", + "optional": true, + "requires": { + "d3": "^7.8.2", + "lodash-es": "^4.17.21" + } + }, + "damerau-levenshtein": { + "version": "1.0.8", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "dependencies": { + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + } + } + }, + "date-fns": { + "version": "2.29.3", + "dev": true + }, + "date-format": { + "version": "4.0.14", + "dev": true + }, + "dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "optional": true + }, + "debounce-fn": { + "version": "4.0.0", + "requires": { + "mimic-fn": "^3.0.0" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true + } + } + }, + "decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "requires": { + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true + } + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "requires": { + "execa": "^5.0.0" + } + }, + "defaults": { + "version": "1.0.4", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true + }, + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true + }, + "define-properties": { + "version": "1.1.4", + "dev": true, + "optional": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "del": { + "version": "2.2.2", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "globby": { + "version": "5.0.0", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "delaunator": { + "version": "5.0.0", + "requires": { + "robust-predicates": "^3.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "dev": true + }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "optional": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "depd": { + "version": "2.0.0", + "dev": true + }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true + }, + "destroy": { + "version": "1.2.0", + "dev": true + }, + "detect-it": { + "version": "4.0.1" + }, + "detect-node": { + "version": "2.1.0", + "dev": true + }, + "detect-passive-events": { + "version": "2.0.3", + "requires": { + "detect-it": "^4.0.1" + } + }, + "di": { + "version": "0.0.1", + "dev": true + }, + "diff": { + "version": "4.0.2", + "dev": true + }, + "dir-compare": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", + "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0", + "minimatch": "^3.0.4" + } + }, + "dir-glob": { + "version": "3.0.1", + "requires": { + "path-type": "^4.0.0" + } + }, + "dmg-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", + "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", + "dev": true, + "requires": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "dmg-license": "^1.0.11", + "fs-extra": "^10.1.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + } + } + }, + "dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "optional": true, + "requires": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "optional": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "optional": true + } + } + }, + "dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "requires": { + "@leichtgewicht/ip-codec": "^2.0.1" + } + }, + "doctrine": { + "version": "3.0.0", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-serialize": { + "version": "2.2.1", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true + } + } + }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "requires": { + "domelementtype": "^2.3.0" + } + }, + "dompurify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz", + "integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ==", + "optional": true + }, + "domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + } + }, + "dot-prop": { + "version": "6.0.1", + "requires": { + "is-obj": "^2.0.0" + } + }, + "dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "dev": true + }, + "ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dev": true, + "requires": { + "jake": "^10.8.5" + } + }, + "electron": { + "version": "29.1.5", + "resolved": "https://registry.npmjs.org/electron/-/electron-29.1.5.tgz", + "integrity": "sha512-1uWGRw/ffA62lcrklxGUgVxVtOHojsg/nwsYr+/F9cVjipZJn8iPv/ABGIIexhmUqWcho8BqfTJ4osCBa29gBg==", + "dev": true, + "requires": { + "@electron/get": "^2.0.0", + "@types/node": "^20.9.0", + "extract-zip": "^2.0.1" + } + }, + "electron-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz", + "integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==", + "dev": true, + "requires": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "dmg-builder": "24.13.3", + "fs-extra": "^10.1.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.3.2", + "simple-update-notifier": "2.0.0", + "yargs": "^17.6.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "dev": true + }, + "fs-extra": { + "version": "10.1.0", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "electron-builder-squirrel-windows": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-24.13.3.tgz", + "integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==", + "dev": true, + "peer": true, + "requires": { + "app-builder-lib": "24.13.3", + "archiver": "^5.3.1", + "builder-util": "24.13.1", + "fs-extra": "^10.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "peer": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "electron-packager": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-17.1.2.tgz", + "integrity": "sha512-XofXdikjYI7MVBcnXeoOvRR+yFFFHOLs3J7PF5KYQweigtgLshcH4W660PsvHr4lYZ03JBpLyEcUB8DzHZ+BNw==", + "dev": true, + "requires": { + "@electron/asar": "^3.2.1", + "@electron/get": "^2.0.0", + "@electron/notarize": "^1.2.3", + "@electron/osx-sign": "^1.0.5", + "@electron/universal": "^1.3.2", + "cross-spawn-windows-exe": "^1.2.0", + "debug": "^4.0.1", + "extract-zip": "^2.0.0", + "filenamify": "^4.1.0", + "fs-extra": "^11.1.0", + "galactus": "^1.0.0", + "get-package-info": "^1.0.0", + "junk": "^3.1.0", + "parse-author": "^2.0.0", + "plist": "^3.0.0", + "rcedit": "^3.0.1", + "resolve": "^1.1.6", + "semver": "^7.1.3", + "yargs-parser": "^21.1.1" + }, + "dependencies": { + "@electron/notarize": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-1.2.4.tgz", + "integrity": "sha512-W5GQhJEosFNafewnS28d3bpQ37/s91CDWqxVchHfmv2dQSTWpOzNlUVQwYzC1ay5bChRV/A9BTL68yj0Pa+TSg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "electron-publish": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz", + "integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==", + "dev": true, + "requires": { + "@types/fs-extra": "^9.0.11", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "fs-extra": "^10.1.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "electron-store": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-8.2.0.tgz", + "integrity": "sha512-ukLL5Bevdil6oieAOXz3CMy+OgaItMiVBg701MNlG6W5RaC0AHN7rvlqTCmeb6O7jP0Qa1KKYTE0xV0xbhF4Hw==", + "requires": { + "conf": "^10.2.0", + "type-fest": "^2.17.0" + } + }, + "electron-to-chromium": { + "version": "1.4.630", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.630.tgz", + "integrity": "sha512-osHqhtjojpCsACVnuD11xO5g9xaCyw7Qqn/C2KParkMv42i8jrJJgx3g7mkHfpxwhy9MnOJr8+pKOdZ7qzgizg==" + }, + "elkjs": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz", + "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==", + "optional": true + }, + "emoji-regex": { + "version": "8.0.0", + "dev": true + }, + "emoji-toolkit": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/emoji-toolkit/-/emoji-toolkit-7.0.1.tgz", + "integrity": "sha512-l5aJyAhpC5s4mDuoVuqt4SzVjwIsIvakPh4ZGJJE4KWuWFCEHaXacQFkStVdD9zbRR+/BbRXob7u99o0lQFr8A==", + "optional": true + }, + "emojis-list": { + "version": "3.0.0" + }, + "encodeurl": { + "version": "1.0.2", + "dev": true + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + } + }, + "end-of-stream": { + "version": "1.4.4", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "dev": true, + "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" + } + }, + "engine.io-parser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "dev": true + }, + "enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "ent": { + "version": "2.2.0", + "dev": true + }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + }, + "env-paths": { + "version": "2.2.1" + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-module-lexer": { + "version": "0.9.3", + "peer": true + }, + "es6-error": { + "version": "4.1.1", + "dev": true, + "optional": true + }, + "es6-promise": { + "version": "4.2.8", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "esbuild": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.17.tgz", + "integrity": "sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.18.17", + "@esbuild/android-arm64": "0.18.17", + "@esbuild/android-x64": "0.18.17", + "@esbuild/darwin-arm64": "0.18.17", + "@esbuild/darwin-x64": "0.18.17", + "@esbuild/freebsd-arm64": "0.18.17", + "@esbuild/freebsd-x64": "0.18.17", + "@esbuild/linux-arm": "0.18.17", + "@esbuild/linux-arm64": "0.18.17", + "@esbuild/linux-ia32": "0.18.17", + "@esbuild/linux-loong64": "0.18.17", + "@esbuild/linux-mips64el": "0.18.17", + "@esbuild/linux-ppc64": "0.18.17", + "@esbuild/linux-riscv64": "0.18.17", + "@esbuild/linux-s390x": "0.18.17", + "@esbuild/linux-x64": "0.18.17", + "@esbuild/netbsd-x64": "0.18.17", + "@esbuild/openbsd-x64": "0.18.17", + "@esbuild/sunos-x64": "0.18.17", + "@esbuild/win32-arm64": "0.18.17", + "@esbuild/win32-ia32": "0.18.17", + "@esbuild/win32-x64": "0.18.17" + } + }, + "esbuild-wasm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.18.17.tgz", + "integrity": "sha512-9OHGcuRzy+I8ziF9FzjfKLWAPbvi0e/metACVg9k6bK+SI4FFxeV6PcZsz8RIVaMD4YNehw+qj6UMR3+qj/EuQ==", + "dev": true + }, + "escalade": { + "version": "3.1.1" + }, + "escape-html": { + "version": "1.0.3", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "dev": true + }, + "escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "source-map": "~0.6.1" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "dev": true + }, + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "8.5.0", + "dev": true, + "requires": {} + }, + "eslint-formatter-codeframe": { + "version": "7.32.1", + "resolved": "https://registry.npmjs.org/eslint-formatter-codeframe/-/eslint-formatter-codeframe-7.32.1.tgz", + "integrity": "sha512-DK/3Q3+zVKq/7PdSYiCxPrsDF8H/TRMK5n8Hziwr4IMkMy+XiKSwbpj25AdajS63I/B61Snetq4uVvX9fOLyAg==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "chalk": "^4.0.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "eslint-plugin-prettier": { + "version": "4.2.1", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-summary": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-summary/-/eslint-summary-1.0.0.tgz", + "integrity": "sha512-cHr5WiNFhu2guLQykhQV8O7BQcnpFLR6GdLjbQfDDL0yGy9U7dXC6zMUtwoxYgJRC/Wk3yZMc+I6Q15Z7r4j9Q==", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esprima": { + "version": "4.0.1", + "dev": true + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0" + } + } + }, + "estraverse": { + "version": "4.3.0" + }, + "esutils": { + "version": "2.0.3", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true + }, + "eventemitter-asyncresource": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz", + "integrity": "sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "dev": true + }, + "events": { + "version": "3.3.0" + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + } + } + }, + "exit": { + "version": "0.1.2", + "dev": true + }, + "exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true + }, + "express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "dev": true + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + } + } + }, + "extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "requires": { + "@types/yauzl": "^2.9.1", + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + } + }, + "extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "optional": true + }, + "fast-deep-equal": { + "version": "3.1.3" + }, + "fast-diff": { + "version": "1.2.0", + "dev": true + }, + "fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true + }, + "fastparse": { + "version": "1.1.2", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "requires": { + "reusify": "^1.0.4" + } + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fd-slicer": { + "version": "1.1.0", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-saver": { + "version": "2.0.5", + "dev": true + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "filename-reserved-regex": { + "version": "2.0.0", + "dev": true + }, + "filenamify": { + "version": "4.3.0", + "dev": true, + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + } + }, + "fill-range": { + "version": "7.0.1", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + } + } + }, + "find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "dev": true, + "requires": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "flora-colossus": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flora-colossus/-/flora-colossus-2.0.0.tgz", + "integrity": "sha512-dz4HxH6pOvbUzZpZ/yXhafjbR2I8cenK5xL0KtBFb7U2ADsR+OwXifnxZjij/pZWF775uSCMzWVd+jDik2H2IA==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "fs-extra": "^10.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true + }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + } + } + }, + "forever-agent": { + "version": "0.6.1", + "dev": true + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true + }, + "fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "fs-extra": { + "version": "9.1.0", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "requires": { + "minipass": "^7.0.3" + }, + "dependencies": { + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + } + } + }, + "fs-monkey": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", + "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "dev": true + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "dev": true + }, + "galactus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/galactus/-/galactus-1.0.0.tgz", + "integrity": "sha512-R1fam6D4CyKQGNlvJne4dkNF+PvUUl7TAJInvTGa9fti9qAv95quQz29GXapA4d8Ec266mJJxFVh82M4GIIGDQ==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "flora-colossus": "^2.0.0", + "fs-extra": "^10.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "gensync": { + "version": "1.0.0-beta.2", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.3", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-package-info": { + "version": "1.0.0", + "dev": true, + "requires": { + "bluebird": "^3.1.1", + "debug": "^2.2.0", + "lodash.get": "^4.0.0", + "read-pkg-up": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "dev": true + } + } + }, + "get-package-type": { + "version": "0.1.0", + "dev": true + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "getpass": { + "version": "0.1.7", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.4.1" + }, + "global-agent": { + "version": "3.0.0", + "dev": true, + "optional": true, + "requires": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + } + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "globals": { + "version": "11.12.0", + "dev": true + }, + "globalthis": { + "version": "1.0.3", + "dev": true, + "optional": true, + "requires": { + "define-properties": "^1.1.3" + } + }, + "globby": { + "version": "11.1.0", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, + "golden-layout": { + "version": "2.6.0", + "dev": true + }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", + "optional": true, + "requires": { + "delegate": "^3.1.2" + } + }, + "got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10" + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "guess-parser": { + "version": "0.4.22", + "resolved": "https://registry.npmjs.org/guess-parser/-/guess-parser-0.4.22.tgz", + "integrity": "sha512-KcUWZ5ACGaBM69SbqwVIuWGoSAgD+9iJnchR9j/IarVI1jHVeXv+bUXBIMeqVMSKt3zrn0Dgf9UpcOEpPBLbSg==", + "dev": true, + "requires": { + "@wessberg/ts-evaluator": "0.0.27" + } + }, + "gumshoejs": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/gumshoejs/-/gumshoejs-5.1.2.tgz", + "integrity": "sha512-wIRdZGTNkWMP8dY3po8mtNYmCfiSva41LxXIEek2yEHceETpxRmO7DfW7aUbHsuucC9z2oDPu3alN3+00FUqlw==" + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "dev": true + }, + "har-validator": { + "version": "5.1.5", + "dev": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "dev": true + } + } + }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "dev": true + } + } + }, + "has-flag": { + "version": "3.0.0", + "dev": true + }, + "has-property-descriptors": { + "version": "1.0.0", + "dev": true, + "optional": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, + "hdr-histogram-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", + "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", + "dev": true, + "requires": { + "@assemblyscript/loader": "^0.10.1", + "base64-js": "^1.2.0", + "pako": "^1.0.3" + } + }, + "hdr-histogram-percentiles-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", + "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", + "dev": true + }, + "heap": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", + "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", + "optional": true + }, + "hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "dev": true + }, + "html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true + }, + "htmlhint": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/htmlhint/-/htmlhint-1.1.4.tgz", + "integrity": "sha512-tSKPefhIaaWDk/vKxAOQbN+QwZmDeJCq3bZZGbJMoMQAfTjepudC+MkuT9MOBbuQI3dLLzDWbmU7fLV3JASC7Q==", + "dev": true, + "requires": { + "async": "3.2.3", + "chalk": "^4.1.2", + "commander": "^9.1.0", + "glob": "^7.2.0", + "is-glob": "^4.0.3", + "node-fetch": "^2.6.2", + "strip-json-comments": "3.1.0", + "xml": "1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", + "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "dev": true, + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "dev": true, + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "dependencies": { + "statuses": { + "version": "2.0.1", + "dev": true + } + } + }, + "http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "5.0.0", + "dev": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "requires": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + } + }, + "http-signature": { + "version": "1.2.0", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "humanize-duration-ts": { + "version": "2.1.1" + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "optional": true, + "requires": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + } + }, + "iconv-lite": { + "version": "0.6.3", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "requires": {} + }, + "ieee754": { + "version": "1.2.1", + "dev": true + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==" + }, + "ignore-walk": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.4.tgz", + "integrity": "sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw==", + "dev": true, + "requires": { + "minimatch": "^9.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, + "optional": true + }, + "immediate": { + "version": "3.0.6", + "dev": true + }, + "immutable": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", + "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "dev": true + } + } + }, + "import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "dev": true + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "rxjs": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", + "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "internmap": { + "version": "2.0.3" + }, + "ip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", + "dev": true + }, + "ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "requires": { + "ci-info": "^3.2.0" + } + }, + "is-core-module": { + "version": "2.11.0", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-docker": { + "version": "2.2.1", + "dev": true + }, + "is-extglob": { + "version": "2.1.1" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-interactive": { + "version": "1.0.0", + "dev": true + }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0" + }, + "is-obj": { + "version": "2.0.0" + }, + "is-path-cwd": { + "version": "1.0.0", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + }, + "dependencies": { + "is-path-inside": { + "version": "1.0.1", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + } + } + }, + "is-path-inside": { + "version": "3.0.3", + "dev": true + }, + "is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "dev": true + }, + "is-unicode-supported": { + "version": "0.1.0", + "dev": true + }, + "is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "dev": true + }, + "isbinaryfile": { + "version": "4.0.10", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "5.2.1", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "istanbul-lib-coverage": { + "version": "2.0.5", + "dev": true + }, + "make-dir": { + "version": "2.1.0", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "3.1.5", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dev": true, + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jasmine": { + "version": "2.8.0", + "dev": true, + "requires": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.8.0" + }, + "dependencies": { + "jasmine-core": { + "version": "2.8.0", + "dev": true + } + } + }, + "jasmine-core": { + "version": "3.10.1", + "dev": true + }, + "jasmine-spec-reporter": { + "version": "7.0.0", + "dev": true, + "requires": { + "colors": "1.4.0" + }, + "dependencies": { + "colors": { + "version": "1.4.0", + "dev": true + } + } + }, + "jasminewd2": { + "version": "2.2.0", + "dev": true + }, + "jest-worker": { + "version": "27.5.1", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0" + }, + "supports-color": { + "version": "8.1.1", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true + }, + "joi": { + "version": "17.7.0", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, + "jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==" + }, + "js-tokens": { + "version": "4.0.0", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "dev": true + }, + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + } + }, + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, + "requires": {} + } + } + }, + "jsesc": { + "version": "2.5.2", + "dev": true + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1" + }, + "json-schema": { + "version": "0.4.0", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0" + }, + "json-schema-typed": { + "version": "7.0.3" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true + }, + "jsprim": { + "version": "1.4.2", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "dev": true + }, + "extsprintf": { + "version": "1.3.0", + "dev": true + }, + "verror": { + "version": "1.10.0", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + } + } + }, + "jszip": { + "version": "3.10.1", + "dev": true, + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "junk": { + "version": "3.1.0", + "dev": true + }, + "karma": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.3.tgz", + "integrity": "sha512-LuucC/RE92tJ8mlCwqEoRWXP38UMAqpnq98vktmS9SznSoUPPUJQbc91dHcxcunROvfQjdORVA/YFviH+Xci9Q==", + "dev": true, + "requires": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.7.2", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "dependencies": { + "cliui": { + "version": "7.0.4", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "mkdirp": { + "version": "0.5.6", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "source-map": { + "version": "0.6.1", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "dev": true + } + } + }, + "karma-chrome-launcher": { + "version": "3.1.1", + "dev": true, + "requires": { + "which": "^1.2.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "karma-coverage-istanbul-reporter": { + "version": "3.0.3", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^3.0.2", + "minimatch": "^3.0.4" + } + }, + "karma-jasmine": { + "version": "4.0.2", + "dev": true, + "requires": { + "jasmine-core": "^3.6.0" + } + }, + "karma-jasmine-html-reporter": { + "version": "1.7.0", + "dev": true, + "requires": {} + }, + "karma-source-map-support": { + "version": "1.4.0", + "dev": true, + "requires": { + "source-map-support": "^0.5.5" + } + }, + "katex": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz", + "integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==", + "optional": true, + "requires": { + "commander": "^8.3.0" + }, + "dependencies": { + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "optional": true + } + } + }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==", + "optional": true + }, + "kind-of": { + "version": "6.0.3", + "dev": true + }, + "klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "dev": true + }, + "known-css-properties": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz", + "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==", + "dev": true + }, + "launch-editor": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", + "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", + "dev": true, + "requires": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "optional": true + }, + "lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "dev": true + }, + "lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "peer": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, + "less": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", + "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", + "dev": true, + "requires": { + "copy-anything": "^2.0.1", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "parse-node-version": "^1.0.1", + "source-map": "~0.6.0", + "tslib": "^2.3.0" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "less-loader": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", + "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", + "dev": true, + "requires": { + "klona": "^2.0.4" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "license-webpack-plugin": { + "version": "4.0.2", + "dev": true, + "requires": { + "webpack-sources": "^3.0.0" + } + }, + "lie": { + "version": "3.3.0", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "load-json-file": { + "version": "2.0.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "2.2.0", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "pify": { + "version": "2.3.0", + "dev": true + } + } + }, + "loader-runner": { + "version": "4.3.0" + }, + "loader-utils": { + "version": "3.2.1", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21" + }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "optional": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true, + "peer": true + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "dev": true, + "peer": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true, + "peer": true + }, + "lodash.get": { + "version": "4.4.2", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "peer": true + }, + "lodash.merge": { + "version": "4.6.2", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "dev": true, + "peer": true + }, + "log-symbols": { + "version": "4.1.0", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "log4js": { + "version": "6.7.0", + "dev": true, + "requires": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.3" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "requires": { + "yallist": "^4.0.0" + } + }, + "magic-string": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.1.tgz", + "integrity": "sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "dependencies": { + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + } + } + }, + "make-dir": { + "version": "3.1.0", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "make-error": { + "version": "1.3.6", + "dev": true + }, + "make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "requires": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "dependencies": { + "@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "requires": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, + "requires": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, + "requires": { + "minipass": "^3.1.1" + } + }, + "unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "requires": { + "unique-slug": "^3.0.0" + } + }, + "unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + } + } + }, + "map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true + }, + "marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "peer": true + }, + "matcher": { + "version": "3.0.0", + "dev": true, + "optional": true, + "requires": { + "escape-string-regexp": "^4.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "optional": true + } + } + }, + "mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true + }, + "mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + }, + "media-typer": { + "version": "0.3.0", + "dev": true + }, + "memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "requires": { + "fs-monkey": "^1.0.4" + } + }, + "meow": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", + "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", + "dev": true, + "requires": { + "@types/minimist": "^1.2.2", + "camelcase-keys": "^7.0.0", + "decamelize": "^5.0.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.2", + "read-pkg-up": "^8.0.0", + "redent": "^4.0.0", + "trim-newlines": "^4.0.2", + "type-fest": "^1.2.2", + "yargs-parser": "^20.2.9" + }, + "dependencies": { + "decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "read-pkg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", + "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^1.0.1" + } + }, + "read-pkg-up": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", + "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", + "dev": true, + "requires": { + "find-up": "^5.0.0", + "read-pkg": "^6.0.0", + "type-fest": "^1.0.1" + } + }, + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "merge-stream": { + "version": "2.0.0" + }, + "merge2": { + "version": "1.4.1" + }, + "mermaid": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-9.4.3.tgz", + "integrity": "sha512-TLkQEtqhRSuEHSE34lh5bCa94KATCyluAXmFnNI2PRZwOpXFeqiJWwZl+d2CcemE1RS6QbbueSSq9QIg8Uxcyw==", + "optional": true, + "requires": { + "@braintree/sanitize-url": "^6.0.0", + "cytoscape": "^3.23.0", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.1.0", + "d3": "^7.4.0", + "dagre-d3-es": "7.0.9", + "dayjs": "^1.11.7", + "dompurify": "2.4.3", + "elkjs": "^0.8.2", + "khroma": "^2.0.0", + "lodash-es": "^4.17.21", + "non-layered-tidy-tree-layout": "^2.0.2", + "stylis": "^4.1.2", + "ts-dedent": "^2.2.0", + "uuid": "^9.0.0", + "web-worker": "^1.2.0" + }, + "dependencies": { + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "optional": true + } + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime": { + "version": "2.6.0", + "dev": true + }, + "mime-db": { + "version": "1.52.0" + }, + "mime-types": { + "version": "2.1.35", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-fn": { + "version": "3.1.0" + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, + "mini-css-extract-plugin": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", + "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", + "dev": true, + "requires": { + "schema-utils": "^4.0.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.7" + }, + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "dependencies": { + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true + } + } + }, + "minipass": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.0.tgz", + "integrity": "sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "requires": { + "encoding": "^0.1.13", + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, + "requires": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "monaco-editor": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.34.1.tgz", + "integrity": "sha512-FKc80TyiMaruhJKKPz5SpJPIjL+dflGvz4CpuThaPMc94AyN7SeC9HQ8hrvaxX7EyHdJcUY5i4D0gNyJj1vSZQ==" + }, + "monaco-editor-webpack-plugin": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-7.1.0.tgz", + "integrity": "sha512-ZjnGINHN963JQkFqjjcBtn1XBtUATDZBMgNQhDQwd78w2ukRhFXAPNgWuacaQiDZsUr4h1rWv5Mv6eriKuOSzA==", + "requires": { + "loader-utils": "^2.0.2" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.4", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "mrmime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", + "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", + "dev": true + }, + "ms": { + "version": "2.1.2" + }, + "multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "requires": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + } + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "dev": true + }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "needle": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", + "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", + "dev": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "negotiator": { + "version": "0.6.3", + "dev": true + }, + "neo-async": { + "version": "2.6.2" + }, + "ngx-clipboard": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/ngx-clipboard/-/ngx-clipboard-16.0.0.tgz", + "integrity": "sha512-rZ/Eo1PqiKMiyF8tdjhmUkoUu68f7OzBJ7YH1YFeh2RAaNrerTaW8XfFOzppSckjFQqA1fwGSYuTTJlDhDag5w==", + "requires": { + "ngx-window-token": ">=7.0.0", + "tslib": "^2.0.0" + } + }, + "ngx-color-picker": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/ngx-color-picker/-/ngx-color-picker-16.0.0.tgz", + "integrity": "sha512-Dk2FvcbebD6STZSVzkI5oFHOlTrrNC5bOHh+YVaFgaWuWrVUdVIJm68ocUvTgr/qxTEJjrfcnRnS4wi7BJ2hKg==", + "requires": { + "tslib": "^2.3.0" + } + }, + "ngx-file-drop": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/ngx-file-drop/-/ngx-file-drop-16.0.0.tgz", + "integrity": "sha512-33RPoZBAiMkV110Rzu3iOrzGcG5M20S4sAiwLzNylfJobu9qVw5XR83FhUelSeqJRoaDxXBRKAozYCSnUf2CNw==", + "requires": { + "tslib": "^2.3.0" + } + }, + "ngx-markdown": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/ngx-markdown/-/ngx-markdown-16.0.0.tgz", + "integrity": "sha512-/rlbXi+HBscJCDdwaTWIUrRkvwJicPnuAgeugOCZa0UbZ4VCWV3U0+uB1Zv6krRDF6FXJNXNLTUrMZV7yH8I6A==", + "requires": { + "clipboard": "^2.0.11", + "emoji-toolkit": "^7.0.0", + "katex": "^0.16.0", + "mermaid": "^9.1.2", + "prismjs": "^1.28.0", + "tslib": "^2.3.0" + } + }, + "ngx-slider-v2": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/ngx-slider-v2/-/ngx-slider-v2-16.0.2.tgz", + "integrity": "sha512-Lpl7SlErL+tJJvTRZYdyZoXTThKN8Ro1z3vscJQ1O5azHXwvbv3pnTcsOwY4ltfaP+dpzY27KL1QXyDr6QMaxQ==", + "requires": { + "detect-passive-events": "^2.0.3", + "rxjs": "^7.4.0", + "tslib": "^2.3.0" + }, + "dependencies": { + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "requires": { + "tslib": "^2.1.0" + } + } + } + }, + "ngx-window-token": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ngx-window-token/-/ngx-window-token-7.0.0.tgz", + "integrity": "sha512-5+XfRVSY7Dciu8xyCNMkOlH2UfwR9W2P1Pirz7caaZgOZDjFbL8aEO2stjfJJm2FFf1D6dlVHNzhLWGk9HGkqA==", + "requires": { + "tslib": "^2.0.0" + } + }, + "nice-napi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", + "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", + "dev": true, + "optional": true, + "requires": { + "node-addon-api": "^3.0.0", + "node-gyp-build": "^4.2.2" + }, + "dependencies": { + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true, + "optional": true + } + } + }, + "nice-try": { + "version": "3.0.1", + "dev": true + }, + "node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "optional": true + }, + "node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true + }, + "node-gyp": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", + "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", + "dev": true, + "requires": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + } + }, + "node-gyp-build": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "dev": true + }, + "node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "non-layered-tidy-tree-layout": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==", + "optional": true + }, + "nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "requires": { + "abbrev": "^1.0.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "dev": true + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true + } + } + }, + "normalize-path": { + "version": "3.0.0" + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true + }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true + }, + "npm-bundled": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", + "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", + "dev": true, + "requires": { + "npm-normalize-package-bin": "^3.0.0" + } + }, + "npm-install-checks": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", + "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", + "dev": true, + "requires": { + "semver": "^7.1.1" + } + }, + "npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true + }, + "npm-package-arg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "dev": true, + "requires": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dev": true, + "requires": { + "lru-cache": "^7.5.1" + } + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + } + } + }, + "npm-packlist": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", + "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", + "dev": true, + "requires": { + "ignore-walk": "^6.0.0" + } + }, + "npm-pick-manifest": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz", + "integrity": "sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==", + "dev": true, + "requires": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", + "semver": "^7.3.5" + } + }, + "npm-registry-fetch": { + "version": "14.0.5", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz", + "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==", + "dev": true, + "requires": { + "make-fetch-happen": "^11.0.0", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^10.0.0", + "proc-log": "^3.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "requires": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "requires": { + "encoding": "^0.1.13", + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "dependencies": { + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + } + } + } + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + } + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + }, + "nwsapi": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "dev": true + }, + "nx": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/nx/-/nx-16.5.1.tgz", + "integrity": "sha512-I3hJRE4hG7JWAtncWwDEO3GVeGPpN0TtM8xH5ArZXyDuVeTth/i3TtJzdDzqXO1HHtIoAQN0xeq4n9cLuMil5g==", + "dev": true, + "requires": { + "@nrwl/tao": "16.5.1", + "@nx/nx-darwin-arm64": "16.5.1", + "@nx/nx-darwin-x64": "16.5.1", + "@nx/nx-freebsd-x64": "16.5.1", + "@nx/nx-linux-arm-gnueabihf": "16.5.1", + "@nx/nx-linux-arm64-gnu": "16.5.1", + "@nx/nx-linux-arm64-musl": "16.5.1", + "@nx/nx-linux-x64-gnu": "16.5.1", + "@nx/nx-linux-x64-musl": "16.5.1", + "@nx/nx-win32-arm64-msvc": "16.5.1", + "@nx/nx-win32-x64-msvc": "16.5.1", + "@parcel/watcher": "2.0.4", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.6", + "axios": "^1.0.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^7.0.2", + "dotenv": "~10.0.0", + "enquirer": "~2.3.6", + "fast-glob": "3.2.7", + "figures": "3.2.0", + "flat": "^5.0.2", + "fs-extra": "^11.1.0", + "glob": "7.1.4", + "ignore": "^5.0.4", + "js-yaml": "4.1.0", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "3.0.5", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "semver": "7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "v8-compile-cache": "2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "axios": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", + "dev": true, + "requires": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "lines-and-columns": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", + "dev": true + }, + "minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "oauth-sign": { + "version": "0.9.0", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "dev": true + }, + "object-hash": { + "version": "2.2.0" + }, + "object-inspect": { + "version": "1.12.2", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "dev": true, + "optional": true + }, + "object-path": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.8.tgz", + "integrity": "sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==", + "dev": true + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.4.1", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "requires": { + "mimic-fn": "^2.1.0" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0" + } + } + }, + "open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "ora": { + "version": "5.4.1", + "dev": true, + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "os-tmpdir": { + "version": "1.0.2", + "dev": true + }, + "p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "requires": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "dependencies": { + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true + } + } + }, + "p-try": { + "version": "2.2.0" + }, + "pacote": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz", + "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==", + "dev": true, + "requires": { + "@npmcli/git": "^4.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^6.0.1", + "@npmcli/run-script": "^6.0.0", + "cacache": "^17.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^5.0.0", + "npm-package-arg": "^10.0.0", + "npm-packlist": "^7.0.0", + "npm-pick-manifest": "^8.0.0", + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^6.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^1.3.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "dependencies": { + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + } + } + }, + "pako": { + "version": "1.0.11", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-author": { + "version": "2.0.0", + "dev": true, + "requires": { + "author-regex": "^1.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "devOptional": true, + "requires": { + "entities": "^4.4.0" + } + }, + "parse5-html-rewriting-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", + "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", + "dev": true, + "requires": { + "entities": "^4.3.0", + "parse5": "^7.0.0", + "parse5-sax-parser": "^7.0.0" + } + }, + "parse5-sax-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", + "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", + "dev": true, + "requires": { + "parse5": "^7.0.0" + } + }, + "parseurl": { + "version": "1.3.3", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "dev": true + }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "dev": true + }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + } + } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "path-type": { + "version": "4.0.0" + }, + "pend": { + "version": "1.2.0", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "dev": true + }, + "picocolors": { + "version": "1.0.0" + }, + "picomatch": { + "version": "2.3.1" + }, + "pinkie": { + "version": "2.0.4", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "piscina": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.0.0.tgz", + "integrity": "sha512-641nAmJS4k4iqpNUqfggqUBUMmlw0ZoM5VZKdQkV2e970Inn3Tk9kroCc1wpsYLD07vCwpys5iY0d3xI/9WkTg==", + "dev": true, + "requires": { + "eventemitter-asyncresource": "^1.0.0", + "hdr-histogram-js": "^2.0.1", + "hdr-histogram-percentiles-obj": "^3.0.0", + "nice-napi": "^1.0.2" + } + }, + "pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "dev": true, + "requires": { + "find-up": "^6.3.0" + }, + "dependencies": { + "find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "requires": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + } + }, + "locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "requires": { + "p-locate": "^6.0.0" + } + }, + "p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "requires": { + "yocto-queue": "^1.0.0" + } + }, + "p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "requires": { + "p-limit": "^4.0.0" + } + }, + "path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true + }, + "yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true + } + } + }, + "pkg-up": { + "version": "3.1.0", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0" + } + } + }, + "plist": { + "version": "3.0.6", + "dev": true, + "requires": { + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + } + }, + "portfinder": { + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", + "requires": { + "async": "^2.6.4", + "debug": "^3.2.7", + "mkdirp": "^0.5.6" + }, + "dependencies": { + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + } + } + }, + "postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "dev": true, + "requires": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-loader": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz", + "integrity": "sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==", + "dev": true, + "requires": { + "cosmiconfig": "^8.2.0", + "jiti": "^1.18.2", + "semver": "^7.3.8" + } + }, + "postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.4.tgz", + "integrity": "sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.1.1.tgz", + "integrity": "sha512-uZgqzdTleelWjzJY+Fhti6F3C9iF1JR/dODLs/JDefozYcKTBCdD8BIl6nNPbTbcLnGrk56hzwZC2DaGNvYjzA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "dev": true + }, + "postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "requires": {} + }, + "postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", + "dev": true, + "requires": {} + }, + "postcss-selector-parser": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "2.8.0", + "dev": true, + "peer": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true + }, + "prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "optional": true + }, + "proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "dev": true + }, + "progress": { + "version": "2.0.3", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "protractor": { + "version": "7.0.0", + "dev": true, + "requires": { + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "^3.0.0", + "blocking-proxy": "^1.0.0", + "browserstack": "^1.5.1", + "chalk": "^1.1.3", + "glob": "^7.0.3", + "jasmine": "2.8.0", + "jasminewd2": "^2.1.0", + "q": "1.4.1", + "saucelabs": "^1.5.0", + "selenium-webdriver": "3.6.0", + "source-map-support": "~0.4.0", + "webdriver-js-extender": "2.1.0", + "webdriver-manager": "^12.1.7", + "yargs": "^15.3.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "cliui": { + "version": "6.0.0", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "strip-ansi": { + "version": "3.0.1", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "dev": true + }, + "wrap-ansi": { + "version": "6.2.0", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "y18n": { + "version": "4.0.3", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "dependencies": { + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + } + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true + }, + "psl": { + "version": "1.9.0", + "dev": true + }, + "pump": { + "version": "3.0.0", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1" + }, + "q": { + "version": "1.4.1", + "dev": true + }, + "qjobs": { + "version": "1.2.0", + "dev": true + }, + "qs": { + "version": "6.11.0", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3" + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "dev": true + }, + "raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "rcedit": { + "version": "3.0.1", + "dev": true, + "requires": { + "cross-spawn-windows-exe": "^1.1.0" + } + }, + "read-config-file": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", + "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", + "dev": true, + "requires": { + "config-file-ts": "^0.2.4", + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + } + } + }, + "read-package-json": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", + "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", + "dev": true, + "requires": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dev": true, + "requires": { + "lru-cache": "^7.5.1" + } + }, + "json-parse-even-better-errors": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", + "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", + "dev": true + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + }, + "normalize-package-data": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", + "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", + "dev": true, + "requires": { + "hosted-git-info": "^6.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + } + } + } + }, + "read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "dev": true, + "requires": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "dependencies": { + "json-parse-even-better-errors": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", + "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", + "dev": true + } + } + }, + "read-pkg": { + "version": "2.0.0", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + }, + "dependencies": { + "path-type": { + "version": "2.0.0", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "2.0.0", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "dev": true + } + } + }, + "readable-stream": { + "version": "2.3.7", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "peer": true, + "requires": { + "minimatch": "^5.1.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "peer": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "peer": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "readdirp": { + "version": "3.6.0", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "redent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", + "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", + "dev": true, + "requires": { + "indent-string": "^5.0.0", + "strip-indent": "^4.0.0" + }, + "dependencies": { + "indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true + } + } + }, + "reflect-metadata": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true + }, + "regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-parser": { + "version": "2.2.11", + "dev": true + }, + "regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "requires": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + } + }, + "regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true + } + } + }, + "request": { + "version": "2.88.2", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "form-data": { + "version": "2.3.3", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "qs": { + "version": "6.5.3", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "dev": true + } + } + }, + "require-directory": { + "version": "2.1.1", + "dev": true + }, + "require-from-string": { + "version": "2.0.2" + }, + "require-main-filename": { + "version": "2.0.0", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "dev": true + }, + "resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dev": true, + "requires": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "dev": true + }, + "resolve-url-loader": { + "version": "5.0.0", + "dev": true, + "requires": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.14", + "source-map": "0.6.1" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.4", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "source-map": { + "version": "0.6.1", + "dev": true + } + } + }, + "responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "requires": { + "lowercase-keys": "^2.0.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true + }, + "reusify": { + "version": "1.0.4" + }, + "rfdc": { + "version": "1.3.0", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "roarr": { + "version": "2.15.4", + "dev": true, + "optional": true, + "requires": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + } + }, + "robust-predicates": { + "version": "3.0.1" + }, + "rollup": { + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-parallel": { + "version": "1.2.0", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rw": { + "version": "1.3.3" + }, + "rxjs": { + "version": "6.6.7", + "requires": { + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1" + } + } + }, + "safe-buffer": { + "version": "5.1.2" + }, + "safer-buffer": { + "version": "2.1.2" + }, + "sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "dev": true, + "requires": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "sass": { + "version": "1.64.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.64.1.tgz", + "integrity": "sha512-16rRACSOFEE8VN7SCgBu1MpYCyN7urj9At898tyzdXFhC+a+yOX5dXwAR7L8/IdPJ1NB8OYoXmD55DM30B2kEQ==", + "dev": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } + }, + "sass-loader": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.2.tgz", + "integrity": "sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==", + "dev": true, + "requires": { + "neo-async": "^2.6.2" + } + }, + "saucelabs": { + "version": "1.5.0", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + }, + "dependencies": { + "agent-base": { + "version": "4.3.0", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "debug": { + "version": "3.2.7", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + } + } + }, + "sax": { + "version": "1.2.4", + "dev": true + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + } + }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==", + "optional": true + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "selenium-webdriver": { + "version": "3.6.0", + "dev": true, + "requires": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "tmp": { + "version": "0.0.30", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.1" + } + } + } + }, + "selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "requires": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "semver-compare": { + "version": "1.0.0", + "dev": true, + "optional": true + }, + "semver-dsl": { + "version": "1.0.1", + "dev": true, + "requires": { + "semver": "^5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true + } + } + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } + } + }, + "serialize-error": { + "version": "7.0.1", + "dev": true, + "optional": true, + "requires": { + "type-fest": "^0.13.1" + }, + "dependencies": { + "type-fest": { + "version": "0.13.1", + "dev": true, + "optional": true + } + } + }, + "serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "dev": true + }, + "setimmediate": { + "version": "1.0.5", + "dev": true + }, + "setprototypeof": { + "version": "1.2.0", + "dev": true + }, + "shallow-clone": { + "version": "3.0.1", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "2.0.0", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "dev": true + }, + "shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.7", + "dev": true + }, + "sigstore": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", + "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", + "dev": true, + "requires": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "@sigstore/sign": "^1.0.0", + "@sigstore/tuf": "^1.0.3", + "make-fetch-happen": "^11.0.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "requires": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "requires": { + "encoding": "^0.1.13", + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "dependencies": { + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + } + } + } + } + }, + "simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "requires": { + "semver": "^7.5.3" + } + }, + "slash": { + "version": "3.0.0", + "dev": true + }, + "slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "optional": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "optional": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "optional": true + } + } + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true + }, + "socket.io": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.4.tgz", + "integrity": "sha512-DcotgfP1Zg9iP/dH9zvAQcWrE0TtbMVwXmlV4T4mqsvY+gw+LqUGPfx2AoVyRk0FLME+GQhufDMyacFmw7ksqw==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + } + }, + "socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dev": true, + "requires": { + "ws": "~8.11.0" + } + }, + "socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dev": true, + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + } + }, + "sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dev": true, + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + } + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + }, + "source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==" + }, + "source-map-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.1.tgz", + "integrity": "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==", + "dev": true, + "requires": { + "abab": "^2.0.6", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.2" + } + }, + "source-map-support": { + "version": "0.5.21", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1" + } + } + }, + "spawn-command": { + "version": "0.0.2-1", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.12", + "dev": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "sprintf-js": { + "version": "1.1.2", + "dev": true + }, + "sshpk": { + "version": "1.17.0", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "dev": true, + "requires": { + "minipass": "^7.0.3" + }, + "dependencies": { + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + } + } + }, + "stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true + }, + "state-local": { + "version": "1.0.7" + }, + "statuses": { + "version": "1.5.0", + "dev": true + }, + "streamroller": { + "version": "3.1.3", + "dev": true, + "requires": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "dev": true + } + } + }, + "string_decoder": { + "version": "1.1.1", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "4.2.3", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "requires": { + "min-indent": "^1.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "dev": true + }, + "strip-outer": { + "version": "1.0.1", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "strong-log-transformer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", + "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "minimist": "^1.2.0", + "through": "^2.3.4" + } + }, + "style-loader": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "dev": true, + "requires": {} + }, + "style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true + }, + "stylelint": { + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.11.0.tgz", + "integrity": "sha512-78O4c6IswZ9TzpcIiQJIN49K3qNoXTM8zEJzhaTE/xRTCZswaovSEVIa/uwbOltZrk16X4jAxjaOhzz/hTm1Kw==", + "dev": true, + "requires": { + "@csstools/css-parser-algorithms": "^2.3.1", + "@csstools/css-tokenizer": "^2.2.0", + "@csstools/media-query-list-parser": "^2.1.4", + "@csstools/selector-specificity": "^3.0.0", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^8.2.0", + "css-functions-list": "^3.2.1", + "css-tree": "^2.3.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.1", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^7.0.0", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^5.2.4", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.29.0", + "mathml-tag-names": "^2.1.3", + "meow": "^10.1.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.28", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.13", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^3.0.0", + "svg-tags": "^1.0.0", + "table": "^6.8.1", + "write-file-atomic": "^5.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "file-entry-cache": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-7.0.2.tgz", + "integrity": "sha512-TfW7/1iI4Cy7Y8L6iqNdZQVvdXn0f8B4QcIXmkIbtTIe/Okm/nSlHb4IwGzRVOd3WfSieCgvf5cMzEfySAIl0g==", + "dev": true, + "requires": { + "flat-cache": "^3.2.0" + } + }, + "ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, + "postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "requires": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + } + } + } + }, + "stylelint-config-standard": { + "version": "34.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-34.0.0.tgz", + "integrity": "sha512-u0VSZnVyW9VSryBG2LSO+OQTjN7zF9XJaAJRX/4EwkmU0R2jYwmBSN10acqZisDitS0CLiEiGjX7+Hrq8TAhfQ==", + "dev": true, + "requires": { + "stylelint-config-recommended": "^13.0.0" + }, + "dependencies": { + "stylelint-config-recommended": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-13.0.0.tgz", + "integrity": "sha512-EH+yRj6h3GAe/fRiyaoO2F9l9Tgg50AOFhaszyfov9v6ayXJ1IkSHwTxd7lB48FmOeSGDPLjatjO11fJpmarkQ==", + "dev": true, + "requires": {} + } + } + }, + "stylelint-config-standard-scss": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-10.0.0.tgz", + "integrity": "sha512-bChBEo1p3xUVWh/wenJI+josoMk21f2yuLDGzGjmKYcALfl2u3DFltY+n4UHswYiXghqXaA8mRh+bFy/q1hQlg==", + "dev": true, + "requires": { + "stylelint-config-recommended-scss": "^12.0.0", + "stylelint-config-standard": "^33.0.0" + }, + "dependencies": { + "stylelint-config-recommended": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-12.0.0.tgz", + "integrity": "sha512-x6x8QNARrGO2sG6iURkzqL+Dp+4bJorPMMRNPScdvaUK8PsynriOcMW7AFDKqkWAS5wbue/u8fUT/4ynzcmqdQ==", + "dev": true, + "requires": {} + }, + "stylelint-config-recommended-scss": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-12.0.0.tgz", + "integrity": "sha512-5Bb2mlGy6WLa30oNeKpZvavv2lowJUsUJO25+OA68GFTemlwd1zbFsL7q0bReKipOSU3sG47hKneZ6Nd+ctrFA==", + "dev": true, + "requires": { + "postcss-scss": "^4.0.6", + "stylelint-config-recommended": "^12.0.0", + "stylelint-scss": "^5.0.0" + }, + "dependencies": { + "stylelint-scss": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-5.3.2.tgz", + "integrity": "sha512-4LzLaayFhFyneJwLo0IUa8knuIvj+zF0vBFueQs4e3tEaAMIQX8q5th8ziKkgOavr6y/y9yoBe+RXN/edwLzsQ==", + "dev": true, + "requires": { + "known-css-properties": "^0.29.0", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-selector-parser": "^6.0.13", + "postcss-value-parser": "^4.2.0" + } + } + } + }, + "stylelint-config-standard": { + "version": "33.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-33.0.0.tgz", + "integrity": "sha512-eyxnLWoXImUn77+ODIuW9qXBDNM+ALN68L3wT1lN2oNspZ7D9NVGlNHb2QCUn4xDug6VZLsh0tF8NyoYzkgTzg==", + "dev": true, + "requires": { + "stylelint-config-recommended": "^12.0.0" + } + } + } + }, + "stylis": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", + "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==", + "optional": true + }, + "sumchecker": { + "version": "3.0.1", + "dev": true, + "requires": { + "debug": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-hyperlinks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", + "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", + "dev": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "dev": true + }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "svgo": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.2.0.tgz", + "integrity": "sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==", + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + } + }, + "sweetalert2": { + "version": "11.10.4", + "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.10.4.tgz", + "integrity": "sha512-MOVRuEW/yQsyzgkaiHqAJcYKxW3vhtE5o3Skp6vZdyJejCOWo4FOicbjRfvqHAXTyTMuwDHA+0lYbO6BiHl1Gw==", + "dev": true, + "peer": true + }, + "symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + } + } + }, + "tapable": { + "version": "2.2.1" + }, + "tar": { + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^4.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + } + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "requires": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "terser": { + "version": "5.16.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", + "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "dev": true, + "optional": true, + "peer": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "requires": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "requires": {} + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "json-schema-traverse": { + "version": "0.4.1" + }, + "schema-utils": { + "version": "3.1.1", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "terser": { + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz", + "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } + } + } + }, + "test-exclude": { + "version": "6.0.0", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "text-table": { + "version": "0.2.0", + "dev": true + }, + "through": { + "version": "2.3.8", + "dev": true + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "optional": true + }, + "tmp": { + "version": "0.2.1", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "requires": { + "tmp": "^0.2.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "dev": true + }, + "tough-cookie": { + "version": "2.5.0", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "tree-kill": { + "version": "1.2.2" + }, + "trim-newlines": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", + "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", + "dev": true + }, + "trim-repeated": { + "version": "1.0.0", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "requires": { + "utf8-byte-length": "^1.0.1" + } + }, + "ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "optional": true + }, + "ts-node": { + "version": "8.3.0", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "^3.0.0" + } + }, + "tsconfig-paths": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.1.2.tgz", + "integrity": "sha512-uhxiMgnXQp1IR622dUXI+9Ehnws7i/y6xvpZB9IbUVOPy0muvdvgXeZOn88UcGPiT98Vp3rJPTa8bFoalZ3Qhw==", + "dev": true, + "requires": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "tslint": { + "version": "6.1.3", + "dev": true, + "peer": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "dev": true, + "peer": true + }, + "mkdirp": { + "version": "0.5.6", + "dev": true, + "peer": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "peer": true + }, + "tslib": { + "version": "1.14.1", + "dev": true, + "peer": true + }, + "tsutils": { + "version": "2.29.0", + "dev": true, + "peer": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "tsutils": { + "version": "3.21.0", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "dev": true + } + } + }, + "tuf-js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", + "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", + "dev": true, + "requires": { + "@tufjs/models": "1.0.4", + "debug": "^4.3.4", + "make-fetch-happen": "^11.1.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "requires": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "requires": { + "encoding": "^0.1.13", + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "dependencies": { + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + } + } + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "2.19.0" + }, + "type-is": { + "version": "1.6.18", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typed-assert": { + "version": "1.0.9", + "dev": true + }, + "typescript": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.37", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.37.tgz", + "integrity": "sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==", + "dev": true + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true + }, + "unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dev": true, + "requires": { + "unique-slug": "^4.0.0" + } + }, + "unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "universalify": { + "version": "2.0.0", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "requires": { + "punycode": "^2.1.0" + } + }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "dev": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "dev": true, + "requires": { + "builtins": "^5.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true + }, + "verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "optional": true + } + } + }, + "vite": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", + "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", + "dev": true, + "requires": { + "esbuild": "^0.18.10", + "fsevents": "~2.3.2", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + } + }, + "void-elements": { + "version": "2.0.1", + "dev": true + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "wait-on": { + "version": "5.3.0", + "dev": true, + "requires": { + "axios": "^0.21.1", + "joi": "^17.3.0", + "lodash": "^4.17.21", + "minimist": "^1.2.5", + "rxjs": "^6.6.3" + } + }, + "watchpack": { + "version": "2.4.0", + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "web-worker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.3.0.tgz", + "integrity": "sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==", + "optional": true + }, + "webdriver-js-extender": { + "version": "2.1.0", + "dev": true, + "requires": { + "@types/selenium-webdriver": "^3.0.0", + "selenium-webdriver": "^3.0.1" + } + }, + "webdriver-manager": { + "version": "12.1.9", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.9.tgz", + "integrity": "sha512-Yl113uKm8z4m/KMUVWHq1Sjtla2uxEBtx2Ue3AmIlnlPAKloDn/Lvmy6pqWCUersVISpdMeVpAaGbNnvMuT2LQ==", + "dev": true, + "requires": { + "adm-zip": "^0.5.2", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "dev": true + } + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "webpack": { + "version": "5.76.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", + "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", + "peer": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.10.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "peer": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "peer": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "peer": true + }, + "schema-utils": { + "version": "3.1.1", + "peer": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "webpack-dev-middleware": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.2.tgz", + "integrity": "sha512-Wu+EHmX326YPYUpQLKmKbTyZZJIB8/n6R09pTmB03kJmnMsVPTo9COzHZFr01txwaCAuZvfBJE4ZCHRcKs5JaQ==", + "dev": true, + "requires": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + } + }, + "webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "dev": true, + "requires": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "dependencies": { + "webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "dev": true, + "requires": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + } + }, + "ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "dev": true, + "requires": {} + } + } + }, + "webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "3.2.3" + }, + "webpack-subresource-integrity": { + "version": "5.1.0", + "dev": true, + "requires": { + "typed-assert": "^1.0.8" + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "dev": true + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wildcard": { + "version": "2.0.0", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "dev": true + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "dev": true + }, + "write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + } + } + }, + "ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "requires": {} + }, + "xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", + "dev": true + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xml2js": { + "version": "0.4.23", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "dependencies": { + "xmlbuilder": { + "version": "11.0.1", + "dev": true + } + } + }, + "xmlbuilder": { + "version": "15.1.1", + "dev": true + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "dev": true + }, + "yallist": { + "version": "4.0.0" + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "dev": true + }, + "yauzl": { + "version": "2.10.0", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "yn": { + "version": "3.1.1", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "dev": true + }, + "zip-stream": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", + "dev": true, + "peer": true, + "requires": { + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "archiver-utils": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", + "dev": true, + "peer": true, + "requires": { + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + } + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "zone.js": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.13.3.tgz", + "integrity": "sha512-MKPbmZie6fASC/ps4dkmIhaT5eonHkEt6eAy80K42tAm0G2W+AahLJjbfi6X9NPdciOE9GRFTTM8u2IiF6O3ww==", + "requires": { + "tslib": "^2.3.0" + } + } + } +} diff --git a/src/frontend/package.json b/src/frontend/package.json new file mode 100644 index 0000000000000000000000000000000000000000..c41a49b52a1d2efb053375c6101e039422968492 --- /dev/null +++ b/src/frontend/package.json @@ -0,0 +1,157 @@ +{ + "name": "Cortado", + "version": "1.12.1", + "author": "Daniel Schuster", + "main": "main-electron.js", + "description": "An Interactive Tool for Data-Driven Process Discovery and Modeling", + "build": { + "appId": "Cortado", + "directories": { + "output": "app-dist" + }, + "extraFiles": [ + { + "from": "../backend/dist/cortado-backend/", + "to": "cortado-backend/" + } + ], + "win": { + "target": "nsis", + "icon": "src/assets/icons/win/icon.ico" + }, + "linux": { + "target": "dir", + "icon": "src/assets/icons/png/", + "executableName": "cortado", + "category": "Science" + }, + "mac": { + "target": "dmg", + "icon": "src/assets/icons/png/", + "executableName": "cortado", + "identity": null + }, + "nsis": { + "oneClick": false, + "allowToChangeInstallationDirectory": true + }, + "afterAllArtifactBuild": "build-hooks/afterAllArtifactBuild.js" + }, + "scripts": { + "ng": "ng", + "start": "ng serve --port 4444 --configuration browser", + "start-electron-dev": "ng serve --port 4444", + "start-electron-prod": "ng serve --configuration production --port 4444", + "build": "ng build", + "build-prod": "ng build --configuration production", + "test": "ng test", + "lint": "npm run lint-scripts && npm run lint-html && npm run lint-styles", + "lint-scripts": "npx eslint --format node_modules/eslint-summary/summary.js --ext .js,.ts .", + "lint-scripts-fix": "npx eslint --fix --ext .js,.ts .", + "lint-styles": "npx stylelint --formatter=verbose '**/*.{css,scss}'", + "lint-styles-fix": "npx stylelint --formatter=verbose --fix '**/*.{css,scss}'", + "lint-html": "npx htmlhint . --ignore='app-dist/**,dist/**'", + "e2e": "ng e2e", + "input": "main-electron.js", + "electron": "electron .", + "electron-live-reload": "wait-on http://localhost:4444 && cross-env NODE_ENV=development electron ./main-electron.js", + "build-electron-windows": "electron-builder build -w", + "build-electron-linux": "electron-builder build -l", + "build-electron-macos": "electron-builder build -m" + }, + "private": true, + "dependencies": { + "@monaco-editor/loader": "^1.3.2", + "@perfectmemory/ngx-contextmenu": "^16.0.2", + "class-transformer": "^0.5.1", + "copy-webpack-plugin": "^11.0.0", + "d3": "~7.9.0", + "electron-store": "^8.2.0", + "gumshoejs": "^5.1.2", + "humanize-duration-ts": "^2.1.1", + "jquery": "^3.7.1", + "lodash": "^4.17.21", + "monaco-editor": "^0.34.0", + "monaco-editor-webpack-plugin": "^7.1.0", + "ngx-clipboard": "^16.0.0", + "ngx-color-picker": "^16.0.0", + "ngx-file-drop": "^16.0.0", + "ngx-slider-v2": "^16.0.2", + "ngx-markdown": "^16.0.0", + "object-hash": "^2.2.0", + "portfinder": "^1.0.32", + "reflect-metadata": "^0.1.14", + "svgo": "^3.2.0", + "tree-kill": "^1.2.2" + }, + "devDependencies": { + "@angular-builders/custom-webpack": "^16.0.1", + "@angular-devkit/build-angular": "^16.2.13", + "@angular-eslint/builder": "16.3.1", + "@angular-eslint/eslint-plugin": "16.3.1", + "@angular-eslint/eslint-plugin-template": "16.3.1", + "@angular-eslint/schematics": "16.3.1", + "@angular-eslint/template-parser": "16.3.1", + "@angular/animations": "^16.2.12", + "@angular/cdk": "^16.2.14", + "@angular/cli": "^16.2.13", + "@angular/common": "^16.2.12", + "@angular/compiler": "^16.2.12", + "@angular/compiler-cli": "^16.2.12", + "@angular/core": "^16.2.12", + "@angular/forms": "^16.2.12", + "@angular/platform-browser": "^16.2.12", + "@angular/platform-browser-dynamic": "^16.2.12", + "@angular/router": "^16.2.12", + "@ng-bootstrap/ng-bootstrap": "^15.1.2", + "@sweetalert2/ngx-sweetalert2": "^11.0.0", + "@types/bootstrap": "^5.2.10", + "@types/d3": "^7.4.3", + "@types/electron": "^1.6.10", + "@types/jasmine": "~5.1.4", + "@types/jasminewd2": "~2.0.13", + "@types/jquery": "^3.5.29", + "@types/lodash": "^4.17.0", + "@types/node": "^20.11.30", + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", + "bootstrap": "5.2", + "bootstrap-icons": "^1.11.3", + "codelyzer": "^6.0.2", + "concurrently": "^6.4.0", + "cross-env": "^7.0.3", + "css-loader": "^6.10.0", + "d3-flextree": "^2.1.2", + "electron": "~29.1.5 ", + "electron-builder": "^24.13.3", + "electron-packager": "^17.1.2", + "eslint": "^8.57.0", + "eslint-config-prettier": "^8.3.0", + "eslint-formatter-codeframe": "^7.32.1", + "eslint-plugin-prettier": "^4.0.0", + "eslint-summary": "^1.0.0", + "file-saver": "^2.0.5", + "golden-layout": "^2.4.0", + "htmlhint": "^1.1.4", + "jasmine-core": "~3.10.0", + "jasmine-spec-reporter": "~7.0.0", + "karma": "^6.4.3", + "karma-chrome-launcher": "~3.1.0", + "karma-coverage-istanbul-reporter": "~3.0.2", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", + "nice-try": "^3.0.0", + "protractor": "~7.0.0", + "rxjs": "~6.6.0", + "style-loader": "^3.3.4", + "stylelint": "^15.11.0", + "stylelint-config-standard": "^34.0.0", + "stylelint-config-standard-scss": "^10.0.0", + "ts-node": "~8.3.0", + "tslib": "^2.6.2", + "typescript": "5.1.6", + "wait-on": "^5.3.0", + "yargs-parser": "^21.0.0", + "zone.js": "~0.13.3" + } +} diff --git a/src/frontend/preload.js b/src/frontend/preload.js new file mode 100644 index 0000000000000000000000000000000000000000..e8d9bf082021921cb9c704b54731961ec8d02e92 --- /dev/null +++ b/src/frontend/preload.js @@ -0,0 +1,33 @@ +const { contextBridge, ipcRenderer } = require("electron"); + +console.warn("Running Preload Script..."); + +contextBridge.exposeInMainWorld("electronAPI", { + requestRestart: () => ipcRenderer.send("restartBackend"), + showSaveDialog: (fileName, fileExtension, base64File, buttonLabel, title) => + ipcRenderer.invoke( + "showSaveDialog", + fileName, + fileExtension, + base64File, + buttonLabel, + title + ), + saveToUserFolder: (fileName, fileExtension, base64File) => + ipcRenderer.send("saveToUserFolder", fileName, fileExtension, base64File), + readFromUserFolder: (fileName, fileExtension) => + ipcRenderer.invoke("readFromUserFolder", fileName, fileExtension), + getWSPort: () => ipcRenderer.invoke("getWSPort"), + onSaveProject: (callback) => ipcRenderer.on("save-project", callback), + onCheckUnsavedChanges: (callback) => + ipcRenderer.on("check-unsaved-changes", callback), + unsavedChanges: (unsavedChanges) => + ipcRenderer.send("unsaved-changes", unsavedChanges), + quit: () => ipcRenderer.send("quit", value), +}); + +document.onreadystatechange = function () { + if (document.readyState == "complete") { + const $ = require("jquery"); // Make Jquery Aviable in the Window after load + } +}; diff --git a/src/frontend/renderer.d.ts b/src/frontend/renderer.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..35cb70a346604495ba7186d9936a030ffa2128f9 --- /dev/null +++ b/src/frontend/renderer.d.ts @@ -0,0 +1,9 @@ +export interface IElectronAPI { + requestRestart: () => void; +} + +declare global { + interface Window { + electronAPI: IElectronAPI; + } +} diff --git a/src/frontend/src/@theme/_theme.scss b/src/frontend/src/@theme/_theme.scss new file mode 100644 index 0000000000000000000000000000000000000000..30aa437b0ce6119f34f299f3a6caa5ab9591e990 --- /dev/null +++ b/src/frontend/src/@theme/_theme.scss @@ -0,0 +1,2 @@ +/* Import relevant stylesheets for theming here */ +@import "./bootstrap/bootstrap_theme"; diff --git a/src/frontend/src/@theme/bootstrap/_accordion.scss b/src/frontend/src/@theme/bootstrap/_accordion.scss new file mode 100644 index 0000000000000000000000000000000000000000..d136f6f2eed95fd3d518dd99818b85c5c26b33fb --- /dev/null +++ b/src/frontend/src/@theme/bootstrap/_accordion.scss @@ -0,0 +1,20 @@ + +/* Handle Bootstrap default overwrites here */ + +// Accordion + +$accordion-color: var(--text-secondary); +$accordion-body-padding-y: 0 0; +$accordion-body-padding-x: 0 0; +$accordion-border-width: 0; +$accordion-border-radius: 0; +$accordion-inner-border-radius: 0; +$accordion-icon-width: .65rem; +$accordion-icon-color: #a0a0a0; +$accordion-icon-active-color: #a0a0a0; +$accordion-button-bg: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); +$accordion-transition: border-radius .15s ease, opacity .35s ease-in; +$accordion-icon-transition: transform .2s ease-in-out; +$accordion-button-active-bg: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); +$accordion-button-active-color: var(--text-secondary); +$accordion-icon-transform: rotate(-0deg); diff --git a/src/frontend/src/@theme/bootstrap/_bootstrap_theme.scss b/src/frontend/src/@theme/bootstrap/_bootstrap_theme.scss new file mode 100644 index 0000000000000000000000000000000000000000..b25c12aa774853a85be18a686a216cae551dd694 --- /dev/null +++ b/src/frontend/src/@theme/bootstrap/_bootstrap_theme.scss @@ -0,0 +1,7 @@ +/* add imports here */ +@import "./colors"; +@import "./typography"; +@import "./accordion"; +@import "./buttons"; +@import "./forms"; +@import "./modal"; diff --git a/src/frontend/src/@theme/bootstrap/_buttons.scss b/src/frontend/src/@theme/bootstrap/_buttons.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/@theme/bootstrap/_colors.scss b/src/frontend/src/@theme/bootstrap/_colors.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/@theme/bootstrap/_forms.scss b/src/frontend/src/@theme/bootstrap/_forms.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/@theme/bootstrap/_modal.scss b/src/frontend/src/@theme/bootstrap/_modal.scss new file mode 100644 index 0000000000000000000000000000000000000000..79b1a5a9593f2a5ccfc762d5f76774adad656e29 --- /dev/null +++ b/src/frontend/src/@theme/bootstrap/_modal.scss @@ -0,0 +1,48 @@ +// Modals + +// scss-docs-start modal-variables + + +$modal-content-bg: var(--box-background-color); +$modal-content-color: white !default; + +// $modal-inner-padding: $spacer !default; + +// $modal-footer-margin-between: .5rem !default; + +// $modal-dialog-margin: .5rem !default; +// $modal-dialog-margin-y-sm-up: 1.75rem !default; + +// $modal-title-line-height: $line-height-base !default; + +// $modal-content-color: null !default; + +// $modal-content-border-color: var(--#{$prefix}border-color-translucent) !default; +// $modal-content-border-width: $border-width !default; +// $modal-content-border-radius: $border-radius-lg !default; +// $modal-content-inner-border-radius: subtract($modal-content-border-radius, $modal-content-border-width) !default; +// $modal-content-box-shadow-xs: $box-shadow-sm !default; +// $modal-content-box-shadow-sm-up: $box-shadow !default; + +// $modal-backdrop-bg: $black !default; +// $modal-backdrop-opacity: .5 !default; + +// $modal-header-border-color: var(--#{$prefix}border-color) !default; +// $modal-header-border-width: $modal-content-border-width !default; +// $modal-header-padding-y: $modal-inner-padding !default; +// $modal-header-padding-x: $modal-inner-padding !default; +// $modal-header-padding: $modal-header-padding-y $modal-header-padding-x !default; // Keep this for backwards compatibility + +// $modal-footer-bg: null !default; +// $modal-footer-border-color: $modal-header-border-color !default; +// $modal-footer-border-width: $modal-header-border-width !default; + +// $modal-sm: 300px !default; +// $modal-md: 500px !default; +// $modal-lg: 800px !default; +// $modal-xl: 1140px !default; + +// $modal-fade-transform: translate(0, -50px) !default; +// $modal-show-transform: none !default; +// $modal-transition: transform .3s ease-out !default; +// $modal-scale-transform: scale(1.02) !default; diff --git a/src/frontend/src/@theme/bootstrap/_typography.scss b/src/frontend/src/@theme/bootstrap/_typography.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/animations/component-animations.ts b/src/frontend/src/app/animations/component-animations.ts new file mode 100644 index 0000000000000000000000000000000000000000..f282d96e370c96fd95295a870a2e2765b6fbf120 --- /dev/null +++ b/src/frontend/src/app/animations/component-animations.ts @@ -0,0 +1,67 @@ +import { + animate, + state, + style, + transition, + trigger, +} from '@angular/animations'; + +export const openCloseComponent = trigger('openCloseComponent', [ + // ... + state( + 'openComponent', + style({ + height: '75%', + width: '55%', + overflow: 'hidden', + }) + ), + state( + 'closeComponent', + style({ + height: '25px', + width: '125px', + overflow: 'hidden', + }) + ), + transition('openComponent => closeComponent', [animate('175ms')]), + transition('closeComponent => openComponent', [animate('175ms')]), +]); + +export const fadeInOutComponent = trigger('fadeInOutComponent', [ + // ... + state( + 'fadeInComponent', + style({ + opacity: '1', + width: '100%', + height: '100%', + }) + ), + state( + 'fadeOutComponent', + style({ + opacity: '0', + width: '0%', + height: '0%', + }) + ), + transition('fadeInComponent => fadeOutComponent', [animate('175ms')]), + transition('fadeOutComponent => fadeInComponent', [animate('175ms')]), +]); + +export const flyInComponent = trigger('flyInDiv', [ + transition(':enter', [ + style({ opacity: '0', transform: 'translateX(40px)' }), + animate( + '150ms 50ms ease-in', + style({ opacity: '1', transform: 'translateX(0)' }) + ), + ]), + transition(':leave', [ + animate( + '150ms 50ms ease-in', + style({ opacity: '0', transform: 'translateX(50px)' }) + ), + ]), +]); diff --git a/src/frontend/src/app/animations/text-animations.ts b/src/frontend/src/app/animations/text-animations.ts new file mode 100644 index 0000000000000000000000000000000000000000..6895696011b9c5b67f499077caa079600f732d69 --- /dev/null +++ b/src/frontend/src/app/animations/text-animations.ts @@ -0,0 +1,50 @@ +import { + animate, + state, + style, + transition, + trigger, +} from '@angular/animations'; + +export const collapsingText = trigger('collapseText', [ + transition(':enter', [ + style({ opacity: '0', transform: 'translateX(-40px)' }), + animate( + '100ms 50ms ease-in', + style({ opacity: '1', transform: 'translateX(0)' }) + ), + ]), + transition(':leave', [ + animate( + '100ms 50ms ease-in', + style({ opacity: '0', transform: 'translateX(-50px)' }) + ), + ]), +]); + +export const expandCollapsed = trigger('expandCollapse', [ + state( + 'void', + style({ + height: '0px', + }) + ), + state( + '*', + style({ + height: '*', + }) + ), + transition('void => *', animate('150ms ease-out')), + transition('* => void', animate('150ms ease-in')), +]); + +export const fadeInText = trigger('fadeIn', [ + transition(':enter', [ + style({ opacity: '0' }), + animate('100ms 50ms ease-in', style({ opacity: '1' })), + ]), + transition(':leave', [ + animate('550ms 50ms ease-in', style({ opacity: '0' })), + ]), +]); diff --git a/src/frontend/src/app/app-routing.module.ts b/src/frontend/src/app/app-routing.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..7ab1e574989986bbf43b38d9b3d59258358d3f3a --- /dev/null +++ b/src/frontend/src/app/app-routing.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +const routes: Routes = []; + +@NgModule({ + imports: [RouterModule.forRoot(routes, {})], + exports: [RouterModule], +}) +export class AppRoutingModule {} diff --git a/src/frontend/src/app/app.component.html b/src/frontend/src/app/app.component.html new file mode 100644 index 0000000000000000000000000000000000000000..3411983694b7cc3f6c82bffb126935650d73ed3a --- /dev/null +++ b/src/frontend/src/app/app.component.html @@ -0,0 +1,23 @@ +<app-loading-overlay> </app-loading-overlay> + +<app-drop-zone + [dropzoneConfig]="dropZoneConfig" + (fileOnHover)="toggleBlur($event)" +> +</app-drop-zone> + +<div [class.blur-out-of-focus]="goldenLayoutHostOutOfFocus"> + <app-header-bar #headerComponent></app-header-bar> + + <app-golden-layout-host #goldenLayoutHost></app-golden-layout-host> + + <app-footer #footerComponent></app-footer> + + <app-api-error-dialog></app-api-error-dialog> + + <app-toaster></app-toaster> + + <app-variant-sequentializer></app-variant-sequentializer> + + <app-variant-conformance-dialog></app-variant-conformance-dialog> +</div> diff --git a/src/frontend/src/app/app.component.scss b/src/frontend/src/app/app.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..56e9829a926f5bb0fa496b712f3dd58da1197156 --- /dev/null +++ b/src/frontend/src/app/app.component.scss @@ -0,0 +1,21 @@ +/* Custom page CSS +-------------------------------------------------- */ + +/* Not required for template or sticky footer method. */ + + +:host { + height: calc(100vh - var(--header-bar-height) - var(--footer-bar-height)); + width: 100%; + display: flex; + flex-direction: row; + overflow: hidden; + margin-top: var(--header-bar-height); +} + + +.bootstrap-container { + background-color: #2e3439; + color: #f5f5f5; +} + diff --git a/src/frontend/src/app/app.component.spec.ts b/src/frontend/src/app/app.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..a2a5ce6998ce5589a6b2c0c4396317ff36cc6d3e --- /dev/null +++ b/src/frontend/src/app/app.component.spec.ts @@ -0,0 +1,33 @@ +import { TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { AppComponent } from './app.component'; + +describe('AppComponent', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [RouterTestingModule], + declarations: [AppComponent], + }).compileComponents(); + }); + + it('should create the app', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app).toBeTruthy(); + }); + + it(`should have as title 'interactive-process-mining-angular-app'`, () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app.title).toEqual('interactive-process-mining-angular-app'); + }); + + it('should render title', () => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.nativeElement; + expect(compiled.querySelector('.content span').textContent).toContain( + 'interactive-process-mining-angular-app app is running!' + ); + }); +}); diff --git a/src/frontend/src/app/app.component.ts b/src/frontend/src/app/app.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..951df5ecc4353e1b5cb5f61b9fc3322590cacb36 --- /dev/null +++ b/src/frontend/src/app/app.component.ts @@ -0,0 +1,107 @@ +import { + AfterViewInit, + ApplicationInitStatus, + APP_INITIALIZER, + Component, + HostListener, + Inject, + OnDestroy, + OnInit, + ViewChild, + ElementRef, +} from '@angular/core'; +import { GoldenLayoutHostComponent } from './components/golden-layout-host/golden-layout-host.component'; +import { DropZoneDirective } from './directives/drop-zone/drop-zone.directive'; +import { GoldenLayoutComponentService } from './services/goldenLayoutService/golden-layout-component.service'; +import * as d3 from 'd3'; +import { EditorService } from './services/editorService/editor.service'; +import { DropzoneConfig } from './components/drop-zone/drop-zone.component'; +import { ConformanceCheckingService } from './services/conformanceChecking/conformance-checking.service'; +import { addPatternDefinitions } from './utils/render-utils'; +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'], +}) +export class AppComponent implements AfterViewInit, OnDestroy, OnInit { + title = 'interactive-process-mining-angular-app'; + + @ViewChild('goldenLayoutHost') + private _goldenLayoutHostComponent: GoldenLayoutHostComponent; + private _windowResizeListener = () => this.handleWindowResizeEvent(); + + dropZoneConfig: DropzoneConfig; + goldenLayoutHostOutOfFocus: boolean = false; + elementRef: ElementRef; + + constructor( + elementRef: ElementRef<HTMLElement>, + private goldenLayoutComponentService: GoldenLayoutComponentService, + private monacoEditorService: EditorService, + private conformanceCheckingService: ConformanceCheckingService, + @Inject(APP_INITIALIZER) public appInit: ApplicationInitStatus + ) { + this.elementRef = elementRef; + } + + ngOnInit(): void { + this.monacoEditorService.load(); + + this.dropZoneConfig = new DropzoneConfig( + '.xes .ptml', + 'false', + 'false', + '<large> Import <strong>Event Log</strong> (.xes) or <strong>Process Tree</strong> (.ptml) files</large>' + ); + } + + toggleBlur(event) { + this.goldenLayoutHostOutOfFocus = event; + } + + _sideBarWidth: number = 30; + + ngAfterViewInit() { + globalThis.addEventListener('resize', this._windowResizeListener); + this._goldenLayoutHostComponent.initializeLayout(); + this.goldenLayoutComponentService.goldenLayoutHostComponent = + this._goldenLayoutHostComponent; + setTimeout(() => this.resizeGoldenLayout(), 0); + + this.goldenLayoutComponentService.goldenLayoutHostComponent = + this._goldenLayoutHostComponent; + + const parent = d3.select(this.elementRef.nativeElement); + addPatternDefinitions(parent, this.conformanceCheckingService); + } + + // Put the dropzone in front if a File Drag enters + @HostListener('window:dragenter', ['$event']) + window_dragenter(event) { + if ((event.dataTransfer.types as Array<string>).includes('Files')) { + DropZoneDirective.windowDrag = true; + } + } + + // If the File Drag leaves the window, put the Dropzone back again + @HostListener('window:dragleave', ['$event']) + window_dragleave(event: DragEvent) { + if (event.screenX === 0 && event.screenY === 0) { + DropZoneDirective.windowDrag = false; + } + } + + ngOnDestroy() { + globalThis.removeEventListener('resize', this._windowResizeListener); + } + + private handleWindowResizeEvent() { + this.resizeGoldenLayout(); + } + + private resizeGoldenLayout() { + const bodyWidth = document.body.offsetWidth; + const bodyHeight = document.body.offsetHeight; + this._goldenLayoutHostComponent.setSize(bodyWidth, bodyHeight); + } +} diff --git a/src/frontend/src/app/app.module.ts b/src/frontend/src/app/app.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..d8e5e61c25fcce26dd154a26541a7a94953ceaa3 --- /dev/null +++ b/src/frontend/src/app/app.module.ts @@ -0,0 +1,236 @@ +import { DropZoneComponent } from './components/drop-zone/drop-zone.component'; +import { BrowserModule } from '@angular/platform-browser'; +import { APP_INITIALIZER, NgModule, SecurityContext } from '@angular/core'; +import { + HttpClientModule, + HTTP_INTERCEPTORS, + HttpClient, +} from '@angular/common/http'; + +import { TableSortingPipe } from './pipes/table-sorting/table-sorting.pipe'; +import { AppComponent } from './app.component'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { FooterComponent } from './components/footer/footer.component'; +import { ProcessTreeEditorComponent } from './components/process-tree-editor/process-tree-editor.component'; +import { StrFilterPipe } from './pipes/str-filter/str-filter.pipe'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { NgxFileDropModule } from 'ngx-file-drop'; +import { ColorPickerModule } from 'ngx-color-picker'; +import { ContextMenuModule } from '@perfectmemory/ngx-contextmenu'; + +import { VariantExplorerComponent } from './components/variant-explorer/variant-explorer.component'; +import { ActivityOverviewComponent } from './components/activity-overview/activity-overview.component'; +import { HttpRequestInterceptor } from './interceptors/http-request.interceptor'; +import { VariantInfoComponent } from './components/variant-explorer/variant/subcomponents/variant-info/variant-info.component'; +import { ModelPerformanceComponent } from './components/performance/performance.component'; +import { HumanizeDurationPipe } from './pipes/humanize-duration.pipe'; +import { VariantPerformanceComponent } from './components/variant-performance/variant-performance.component'; +import { InfoBoxComponent } from './components/info-box/info-box.component'; +import { VariantSelectionButtonComponent } from './components/variant-explorer/variant/subcomponents/variant-selection-button/variant-selection-button.component'; +import { GoldenLayoutComponentService } from './services/goldenLayoutService/golden-layout-component.service'; +import { GoldenLayoutHostComponent } from './components/golden-layout-host/golden-layout-host.component'; +import { SubvariantExplorerComponent } from './components/variant-explorer/subvariant-explorer/subvariant-explorer.component'; +import { VariantColorMapComponent } from './components/variant-performance/variant-color-map/variant-color-map.component'; +// tslint:disable-next-line:max-line-length +import { NodeSelectionPerformanceComponent } from './components/performance/node-selection-performance/node-selection-performance.component'; +import { PerformanceTableComponent } from './components/performance/performance-table/performance-table.component'; +import { ColorMapComponent } from './components/performance/color-map/color-map.component'; +import { TreePerformanceColorMapComponent } from './components/performance/tree-performance-color-map/tree-performance-color-map.component'; +import { ExpertModeComponent } from './components/process-tree-editor/expert-mode/expert-mode.component'; +import { SettingsComponent } from './components/settings/settings.component'; +import { DropZoneDirective } from './directives/drop-zone/drop-zone.directive'; +import { TreeStringRendererComponent } from './components/tree-string-renderer/tree-string-renderer.component'; +import { VariantModelerComponent } from './components/variant-modeler/variant-modeler.component'; +import { VariantComponent } from './components/variant-explorer/variant/variant.component'; +import { VariantConformanceDialogComponent } from './components/variant-explorer/conformance-info/variant-conformance-dialog/variant-conformance-dialog.component'; +import { BpmnEditorComponent } from './components/bpmn-editor/bpmn-editor.component'; +import { GoldenLayoutDummyComponent } from './components/golden-layout-host/golden-layout-dummy/golden-layout-dummy.component'; +import { SubVariantComponent } from './components/variant-explorer/subvariant-explorer/subvariants/sub-variant/sub-variant.component'; +import { VariantInfoExplorerComponent } from './components/variant-explorer/variant-info-explorer/variant-info-explorer.component'; +import { ActivityButtonAreaComponent } from './components/variant-modeler/activity-button-area/activity-button-area.component'; +import { HeaderBarComponent } from './components/header-bar/header-bar.component'; +import { SweetAlert2Module } from '@sweetalert2/ngx-sweetalert2'; +import { DialogModule } from './components/dialogs/dialog.module'; +import { VariantMinerComponent } from './components/variant-miner/variant-miner.component'; +import { VariantMinerPatternComponent } from './components/variant-miner/variant-miner-pattern/variant-miner-pattern.component'; +import { NgxSliderModule } from 'ngx-slider-v2'; +import { VariantQueryComponent } from './components/variant-explorer/variant-query/variant-query.component'; +import { ConformanceInfoBarComponent } from './components/variant-explorer/conformance-info/info-bar/conformance-info-bar.component'; +import { initApp, InitService } from './services/init.service'; +import { ToastComponent } from './components/toast/toast/toast.component'; +import { ToasterComponent } from './components/toast/toaster/toaster.component'; +import { PerformanceProgressBarComponent } from './components/performance/performance-progress-bar/performance-progress-bar.component'; +import { VariantQueryInfoComponent } from './components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component'; +import { VariantExplorerContextMenuComponent } from './components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component'; +import { SyntaxHighlightedTextareaDirective } from './directives/syntax-highlighted-textarea/syntax-highlighted-textarea.directive'; +import { VariantDrawerDirective } from './directives/variant-drawer/variant-drawer.directive'; +import { ProcessTreeDrawerDirective } from './directives/process-tree-drawer/process-tree-drawer.directive'; +import { BpmnDrawerDirective } from './directives/bpmn-drawer/bpmn-drawer.directive'; +import { TreePerformanceButtonComponent } from './components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component'; +import { InfixSelectionControllsComponent } from './components/variant-explorer/variant/subcomponents/infix-selection-controlls/infix-selection-controlls.component'; +import { ZoomFieldComponent } from './components/zoom-field/zoom-field.component'; +import { VariantExplorerSidebarComponent } from './components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component'; +import { EditorZoneComponent } from './components/editor-zone/editor-zone.component'; +import { FilterOptionsComponent } from './components/variant-miner/filter-options/filter-options.component'; +import { ResizeableTableHeaderComponent } from './components/resizeable-table-header/resizeable-table-header.component'; +import { ResizeColumnDirective } from './directives/resize-column.directive'; +import { ElectronService } from './services/electronService/electron.service'; +import { UnavailableInfoComponent } from './components/unavailable-info/unavailable-info.component'; +import { ConformanceTabComponent } from './components/conformance-tab/conformance-tab.component'; +import { ConformanceStatusIconComponent } from './components/variant-explorer/variant/subcomponents/variant-info/conformance-status-icon/conformance-status-icon.component'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { VariantSequentializerComponent } from './components/variant-explorer/variant-sequentializer/variant-sequentializer.component'; +import { PatternEditorComponent } from './components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component'; +import { TreeConformanceButtonComponent } from './components/variant-explorer/variant/subcomponents/tree-buttons/tree-conformance-button/tree-conformance-button.component'; +import { DecimalPipe } from '@angular/common'; +import { VariantMinerActivitiesFIlterComponent } from './components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component'; +import { LpmExplorerComponent } from './components/lpm-explorer/lpm-explorer.component'; +import { LpmExplorerRowComponent } from './components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component'; +import { LpmMetricsTabComponent } from './components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component'; +import { ClusteringSettingsDialogComponent } from './components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component'; +import { SearchComponent } from './components/variant-explorer/search/search.component'; +import { GroupByPipe } from './pipes/group-by.pipe'; +import { VariantSortPipe } from './pipes/variant-sort.pipe'; +import { electronServiceFactory } from './dependency-factories'; +import { ProcessTreeToolboxComponent } from './components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component'; +import { InfoBarComponent } from './components/activity-overview/info-bar/info-bar.component'; +import { LoadingOverlayComponent } from './components/loading-overlay/loading-overlay.component'; +import { DocumentationComponent } from './components/documentation/documentation.component'; +import { MarkdownModule } from 'ngx-markdown'; +import { StripHtmlPipe } from './components/documentation/strip-html.pipe'; +import { RouterLink } from '@angular/router'; +import { CaseExplorerComponent } from './components/variant-explorer/case-explorer/case-explorer.component'; +import { ProcessTreeEditorContextMenuComponent } from './components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component'; +import { VariantActionButtonsComponent } from './components/variant-explorer/variant/subcomponents/variant-action-buttons/variant-action-buttons.component'; +import { ArcDiagramDirective } from './directives/arc-diagram/arc-diagram.directive'; +import { ArcDiagramFilterComponent } from './components/variant-explorer/arc-diagram/filter/filter.component'; +import { VariantVisualisationComponent } from './components/variant-explorer/variant/subcomponents/variant-visualisation/variant-visualisation.component'; +import { LogExporterDialogComponent } from './components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component'; +import { EnumToArrayPipe } from './pipes/enum-to-array.pipe'; + +@NgModule({ + declarations: [ + AppComponent, + FooterComponent, + StrFilterPipe, + EditorZoneComponent, + TableSortingPipe, + GoldenLayoutHostComponent, + VariantExplorerComponent, + VariantInfoComponent, + ModelPerformanceComponent, + HumanizeDurationPipe, + VariantPerformanceComponent, + InfoBoxComponent, + ActivityOverviewComponent, + ProcessTreeEditorComponent, + SubvariantExplorerComponent, + VariantInfoExplorerComponent, + VariantInfoComponent, + VariantColorMapComponent, + VariantSelectionButtonComponent, + VariantQueryComponent, + ActivityOverviewComponent, + NodeSelectionPerformanceComponent, + PerformanceTableComponent, + ColorMapComponent, + TreePerformanceColorMapComponent, + VariantInfoComponent, + ExpertModeComponent, + SettingsComponent, + DropZoneComponent, + DropZoneDirective, + VariantConformanceDialogComponent, + TreeStringRendererComponent, + VariantModelerComponent, + VariantDrawerDirective, + SyntaxHighlightedTextareaDirective, + ActivityButtonAreaComponent, + VariantComponent, + BpmnEditorComponent, + SubVariantComponent, + HeaderBarComponent, + GoldenLayoutDummyComponent, + VariantMinerComponent, + VariantMinerPatternComponent, + ConformanceInfoBarComponent, + VariantQueryInfoComponent, + ToastComponent, + ToasterComponent, + PerformanceProgressBarComponent, + VariantExplorerContextMenuComponent, + ProcessTreeDrawerDirective, + BpmnDrawerDirective, + TreePerformanceButtonComponent, + InfixSelectionControllsComponent, + ZoomFieldComponent, + VariantExplorerSidebarComponent, + FilterOptionsComponent, + ResizeableTableHeaderComponent, + ResizeColumnDirective, + VariantActionButtonsComponent, + UnavailableInfoComponent, + ConformanceTabComponent, + ConformanceStatusIconComponent, + VariantSequentializerComponent, + PatternEditorComponent, + TreeConformanceButtonComponent, + VariantMinerActivitiesFIlterComponent, + LpmExplorerComponent, + LpmExplorerRowComponent, + LpmMetricsTabComponent, + ClusteringSettingsDialogComponent, + SearchComponent, + GroupByPipe, + VariantSortPipe, + ProcessTreeToolboxComponent, + InfoBarComponent, + LoadingOverlayComponent, + DocumentationComponent, + StripHtmlPipe, + CaseExplorerComponent, + ProcessTreeEditorContextMenuComponent, + ArcDiagramDirective, + ArcDiagramFilterComponent, + VariantVisualisationComponent, + LogExporterDialogComponent, + EnumToArrayPipe, + ], + imports: [ + BrowserModule, + ReactiveFormsModule, + FormsModule, + HttpClientModule, + NgxFileDropModule, + BrowserAnimationsModule, + ColorPickerModule, + SweetAlert2Module.forRoot(), + DialogModule, + NgxSliderModule, + NgbModule, + MarkdownModule.forRoot({ + loader: HttpClient, + sanitize: SecurityContext.NONE, + }), + RouterLink, + ContextMenuModule, + ], + providers: [ + { + provide: HTTP_INTERCEPTORS, + useClass: HttpRequestInterceptor, + multi: true, + }, + { + provide: APP_INITIALIZER, + useFactory: initApp, + deps: [InitService], + multi: true, + }, + { provide: ElectronService, useFactory: electronServiceFactory }, + GoldenLayoutComponentService, + DecimalPipe, + ], + bootstrap: [AppComponent], +}) +export class AppModule {} diff --git a/src/frontend/src/app/components/activity-overview/activity-overview.component.html b/src/frontend/src/app/components/activity-overview/activity-overview.component.html new file mode 100644 index 0000000000000000000000000000000000000000..a21b133012a2c7e25a04f656b06cdea689ac7fdc --- /dev/null +++ b/src/frontend/src/app/components/activity-overview/activity-overview.component.html @@ -0,0 +1,266 @@ +<div class="d-flex flex-column mh-100 h-100 activity-overview-container"> + <div class="table-container flex-grow-1 table-responsive"> + <table + class="table table-sm table-font table-hover table-striped table-borderless table-dark mb-0" + *ngIf="activityColorMap" + > + <thead class="activity-overview-table-header"> + <tr class="user-select-none"> + <th + resizeable + scope="col" + class="bg-dark th-dropdown-colors resizeable-header-element" + [margin]="-7" + > + <div> + <button + type="button" + class="button" + ngbTooltip="Reset activity colors" + triggers="hover" + (click)="resetActivityColors()" + > + <i class="bi bi-arrow-counterclockwise btn-icon me-1"></i> + </button> + </div> + </th> + <th + resizeable + scope="col" + class="bg-dark border-end border-color toggle-select resizeable-header-element" + (click)="toggleSort('activityName')" + [margin]="-7" + > + <div class="d-flex justify-content-between"> + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + > + <div class="user-select-none mx-1">Activity</div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-alpha-down': !ascending, + 'bi-sort-alpha-down-alt': ascending, + invisible: sortKey !== 'activityName' + }" + ></i> + </div> + + <div class="p-2"> + <button + class="reset-button" + (click)="revertLastChange($event)" + *ngIf="resetAvailable" + ngbTooltip="revert last change to the event log" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-counterclockwise btn-icon"></i> + </button> + </div> + </div> + </th> + <th + resizeable + scope="col" + class="bg-dark text-center border-end border-color toggle-select resizeable-header-element" + (click)="toggleSort('inModel')" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + > + <div class="user-select-none mx-1">in model</div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-up': ascending, + 'bi-sort-down': !ascending, + invisible: sortKey !== 'inModel' + }" + ></i> + </div> + </th> + <th + resizeable + scope="col" + class="bg-dark text-center border-end border-color text-nowrap toggle-select resizeable-header-element" + (click)="toggleSort('isStart')" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + > + <ng-template #startActivityTooltip> + <b class="text-primary">start-activity</b> (in the event log, + there exists a case that starts with the given activity) + </ng-template> + <div + [ngbTooltip]="startActivityTooltip" + triggers="hover" + container="body" + class="mx-1" + > + <i class="bi bi-chevron-right text-white"></i> + <i + class="bi bi-chevron-double-right" + style="margin-left: -9px" + ></i> + <!-- <i class="bi bi-chevron-double-right" style="margin-left: -6px;"></i>--> + </div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-up': ascending, + 'bi-sort-down': !ascending, + invisible: sortKey !== 'isStart' + }" + ></i> + </div> + </th> + <th + resizeable + scope="col" + class="bg-dark text-center border-end border-color text-nowrap toggle-select resizeable-header-element" + (click)="toggleSort('isEnd')" + [margin]="-7" + > + <div class="d-flex flex-row justify-content-center sort-group"> + <ng-template #endActivityTooltip> + <b class="text-primary">end-activity</b> (in the event log, + there exists a case that ends with the given activity) + </ng-template> + <div + [ngbTooltip]="endActivityTooltip" + triggers="hover" + container="body" + > + <!-- <i class="bi bi-chevron-double-right"></i>--> + <i + class="bi bi-chevron-double-right" + style="margin-left: 0px" + ></i> + <i + class="bi bi-chevron-right text-white" + style="margin-left: -7px" + ></i> + </div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-up': ascending, + 'bi-sort-down': !ascending, + invisible: sortKey !== 'isEnd' + }" + ></i> + </div> + </th> + <th + resizeable + scope="col" + class="bg-dark text-center toggle-select resizeable-header-element" + (click)="toggleSort('occurences')" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + > + <div + ngbTooltip="Number of activity occurrences in the loaded event log" + triggers="hover" + > + <i class="bi bi-hash"></i> + </div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-numeric-down': ascending, + 'bi-sort-numeric-down-alt': !ascending, + invisible: sortKey !== 'occurences' + }" + ></i> + </div> + </th> + </tr> + </thead> + + <tbody> + <ng-container *ngIf="activitiesInTree && activityColorMap"> + <tr + *ngFor=" + let activityField of activityFields + | tableSorting : sortKey : ascending + " + > + <!-- <th class="user-select-none" [ngStyle]="{'background-color': activityField.color}"> </th> --> + <td + [ngStyle]="{ 'background-color': activityField.color }" + class="color-picker-cell user-select-none" + > + <div + class="color-picker-div" + [style.color]="activityField.color" + [cpPosition]="'auto'" + [(colorPicker)]="activityField.color" + [cpOutputFormat]="'hex'" + [cpUseRootViewContainer]="true" + [cpCloseClickOutside]="false" + [cpSaveClickOutside]="false" + [cpAlphaChannel]="'disabled'" + [cpCancelButton]="true" + [cpCancelButtonClass]="'button cp-button'" + [cpOKButton]="true" + [cpOKButtonClass]="'button cp-button'" + (colorPickerSelect)=" + changeActivityColor(activityField, activityField.color) + " + > + + </div> + </td> + <td class="border-end border-color activtiy-name-cell"> + <input + class="activity-name-input" + type="text" + value="{{ activityField.activityName }}" + (keyup.enter)=" + applyActivityNameChanges( + activityField.activityName, + $event.target.value + ) + " + (focusout)="$event.target.value = activityField.activityName" + /> + <div + class="cursor-pointer remove-activity-button" + (click)="deleteActivity($event, activityField)" + ngbTooltip="remove activity from event log" + triggers="hover" + container="body" + > + <i class="bi bi-trash"></i> + </div> + </td> + <td class="border-end border-color text-center"> + <i class="bi bi-check2" *ngIf="activityField.inModel"></i> + </td> + <td class="border-end border-color text-center"> + <i class="bi bi-check2" *ngIf="activityField.isStart"></i> + </td> + <td class="border-end border-color text-center"> + <i class="bi bi-check2" *ngIf="activityField.isEnd"></i> + </td> + <td class="text-center user-select-none"> + {{ activityField.occurences | number }} + </td> + </tr> + </ng-container> + </tbody> + </table> + </div> + <div class="bg-dark user-select-none"> + <app-activity-overview-info-bar + [activityFields]="activityFields" + ></app-activity-overview-info-bar> + </div> +</div> diff --git a/src/frontend/src/app/components/activity-overview/activity-overview.component.scss b/src/frontend/src/app/components/activity-overview/activity-overview.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..df6712458281b464da7035d9c3af85a35aa3b36d --- /dev/null +++ b/src/frontend/src/app/components/activity-overview/activity-overview.component.scss @@ -0,0 +1,122 @@ + +:host { + overflow: auto; + position: absolute; +} + + +.activity-overview-container { + background-color: var(--box-background-color); +} + +.table-font{ + font-size: small; +} + +.resizeable-header-element{ + padding : 0.2rem; +} + +.table-header-sort-group{ + display: flex; + flex-direction: column; + align-items: center; +} + +.table-container { + overflow: auto auto; + background-color: var(--box-background-color); +} + +.toggle-select{ + cursor : pointer; +} + +thead th { + vertical-align: top; +} + +thead tr:nth-child(1) th { + position: static; + top: 0; + z-index: 10; +} + +tbody tr { + padding-bottom: .25rem; + padding-top: .25rem; +} + +.border-color { + border-color: var(--line-color)!important; +} + +.reset-button{ + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); + color: var(--text-secondary); + border: none; +} + +.reset-button:hover{ + color: whitesmoke; +} + +/* th { + font-weight: normal; +} */ + + +.dropdown-menu { + border-radius: 0; + background-color: lightgray; +} + +.center { + display: flex; + justify-content: center; + align-items: center; +} + +.th-dropdown-colors { + width: 50px +} + +.activity-name-input { + background: transparent; + height: 20px; + width: 100%; + color: var(--text-secondary); + border: none; +} + +.activtiy-name-cell:hover > div { + visibility: visible; +} + +.remove-activity-button{ + visibility: hidden; +} + +.activtiy-name-cell{ + display: flex; + place-content: center flex-end; + align-items: center; +} + +.color-picker-cell { + height: 1px +} + +.color-picker-div { + height: 100% +} + +.color-picker-div:hover { + cursor: pointer +} + +.activity-overview-table-header { + position: sticky; + top: 0; + z-index: auto; +} diff --git a/src/frontend/src/app/components/activity-overview/activity-overview.component.spec.ts b/src/frontend/src/app/components/activity-overview/activity-overview.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..811aae4b13b16fdfacdffff6f583b8f16af46727 --- /dev/null +++ b/src/frontend/src/app/components/activity-overview/activity-overview.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ActivityOverviewComponent } from './activity-overview.component'; + +describe('ActivityOverviewComponent', () => { + let component: ActivityOverviewComponent; + let fixture: ComponentFixture<ActivityOverviewComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ActivityOverviewComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ActivityOverviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/activity-overview/activity-overview.component.ts b/src/frontend/src/app/components/activity-overview/activity-overview.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..48c4dbec27c3629d2a52ff163e44406b83b1feda --- /dev/null +++ b/src/frontend/src/app/components/activity-overview/activity-overview.component.ts @@ -0,0 +1,244 @@ +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { LogService } from 'src/app/services/logService/log.service'; +import { + Component, + OnInit, + ElementRef, + Inject, + Renderer2, + AfterViewInit, + ChangeDetectorRef, + OnDestroy, +} from '@angular/core'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; +import { ColorMapService } from '../../services/colorMapService/color-map.service'; +import { DropzoneConfig } from '../drop-zone/drop-zone.component'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { VariantPerformanceService } from 'src/app/services/variant-performance.service'; + +@Component({ + selector: 'app-activity-overview', + templateUrl: './activity-overview.component.html', + styleUrls: ['./activity-overview.component.scss'], +}) +export class ActivityOverviewComponent + extends LayoutChangeDirective + implements OnInit, AfterViewInit, OnDestroy +{ + constructor( + private colorMapService: ColorMapService, + private logService: LogService, + private variantService: VariantService, + private processTreeService: ProcessTreeService, + private ref: ChangeDetectorRef, + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef, + renderer: Renderer2, + private variantPerformanceService: VariantPerformanceService + ) { + super(elRef.nativeElement, renderer); + const state = this.container.initialState; + } + + activityColorMap: Map<string, string>; + activitiesInTree: Set<string> = new Set<string>(); + startActivities: Set<string>; + endActivities: Set<string>; + activitiesInLog: any; + activityFields: ActivityField[]; + + sortKey: string = 'activityName'; + ascending: boolean = false; + + resetAvailable: boolean = false; + + private _destroy$ = new Subject(); + + ngOnInit(): void { + this.activityFields = []; + + // Handle change of loaded log + this.logService.loadedEventLog$ + .pipe(takeUntil(this._destroy$)) + .subscribe((eventLogName) => { + console.log( + 'new loadedEventLog$ in activity-overview.component:' + eventLogName + ); + + this.resetActivityFields(); + }); + + this.variantService.cachedChange$ + .pipe(takeUntil(this._destroy$)) + .subscribe((change) => { + this.resetAvailable = change; + }); + } + + ngAfterViewInit(): void { + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + this.activityColorMap = colorMap; + + if (this.activityFields) { + for (let activityField of this.activityFields) { + activityField.color = this.activityColorMap.get( + activityField.activityName + ); + } + } + }); + + // Handle change of current activies in the loaded model + this.processTreeService.activitiesInCurrentTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((activitiesInTree) => { + for (let field of this.activityFields) { + field.inModel = activitiesInTree.has(field.activityName); + } + }); + + this.variantService.variants$ + .pipe(takeUntil(this._destroy$)) + .subscribe(() => { + if (this.activityColorMap) { + this.resetActivityFields(); + } + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + resetActivityFields() { + this.startActivities = this.logService.startActivitiesInEventLog; + this.endActivities = this.logService.endActivitiesInEventLog; + this.activitiesInLog = this.logService.activitiesInEventLog; + this.activitiesInTree = this.processTreeService.activitiesInCurrentTree; + + this.activityFields = []; + for (let activity in this.activitiesInLog) { + this.activityFields.push( + new ActivityField( + activity, + this.activitiesInLog[activity], + this.activityColorMap.get(activity), + this.activitiesInTree.has(activity), + this.startActivities.has(activity), + this.endActivities.has(activity) + ) + ); + } + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + + handleVisibilityChange(visibility: boolean): void {} + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} + + toggleSort(sortKey: string) { + // On the first Click always make descending + if (this.sortKey != sortKey) { + this.sortKey = sortKey; + this.ascending = false; + } else { + // Make it toggle between on subsequent clicks + this.ascending = !this.ascending; + } + } + deleteActivity(e: Event, activity: ActivityField) { + this.variantService.deleteActivity(activity.activityName).subscribe(); + this.variantPerformanceService.resetVariantPerformance(); + this.resetActivityFields(); + } + + changeActivityColor(activityField: ActivityField, color: string) { + if (color) { + activityField.color = color; + this.colorMapService.changeActivityColor( + activityField.activityName, + color + ); + } + } + + resetActivityColors(): void { + this.colorMapService.createColorMap( + Array.from(this.activityColorMap.keys()) + ); + } + + resetActivityNames(): void { + if (this.activityFields) { + for (let activityField of this.activityFields) { + activityField.inputActivityName = activityField.activityName; + } + } + } + + // TODO: refactor this to shared data service + applyActivityNameChanges( + oldActivityName: string, + newActivityName: string + ): void { + if (oldActivityName !== newActivityName) { + this.variantService + .renameActivity(oldActivityName, newActivityName) + .subscribe(); + // Changing activity field table + this.resetActivityFields(); + } + } + + revertLastChange(e: Event) { + e.stopPropagation(); + this.resetAvailable = false; + this.variantService.revertChangeInBackend(); + } +} + +export class ActivityField { + activityName: string; + occurences: number; + inModel: boolean; + isStart: boolean; + isEnd: boolean; + color: string; + inputActivityName: string; // Storing the input name from user + + constructor( + activityName: string, + occurences: number, + color: string, + inModel: boolean, + isStart: boolean, + isEnd: boolean + ) { + this.activityName = activityName; + this.occurences = occurences; + this.inModel = inModel; + this.isStart = isStart; + this.isEnd = isEnd; + this.color = color; + this.inputActivityName = activityName; + } +} + +export namespace ActivityOverviewComponent { + export const componentName = 'ActivityOverviewComponent'; +} diff --git a/src/frontend/src/app/components/activity-overview/info-bar/info-bar.component.spec.ts b/src/frontend/src/app/components/activity-overview/info-bar/info-bar.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..4f5c7ef3eadf6f7bc7c53fe081b9f12e94940165 --- /dev/null +++ b/src/frontend/src/app/components/activity-overview/info-bar/info-bar.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InfoBarComponent } from './info-bar.component'; + +describe('InfoBarComponent', () => { + let component: InfoBarComponent; + let fixture: ComponentFixture<InfoBarComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [InfoBarComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(InfoBarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/activity-overview/info-bar/info-bar.component.ts b/src/frontend/src/app/components/activity-overview/info-bar/info-bar.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..10663f8642198dc9b38da2e6fdef96b68c7f0b6b --- /dev/null +++ b/src/frontend/src/app/components/activity-overview/info-bar/info-bar.component.ts @@ -0,0 +1,53 @@ +import { ActivityField } from 'src/app/components/activity-overview/activity-overview.component'; +import { + Component, + Input, + AfterViewInit, + OnChanges, + OnDestroy, +} from '@angular/core'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { takeUntil } from 'rxjs/operators'; +import { Subject } from 'rxjs'; + +@Component({ + selector: 'app-activity-overview-info-bar', + template: ` <div class="info-bar ps-2 pe-2"> + <span class="float-end" *ngIf="totalActivities" + >Activities in model: {{ numActivitiesInModel }}/{{ totalActivities }} ({{ + ((numActivitiesInModel * 100) / totalActivities).toFixed(1) + }} + %)</span + > + </div>`, +}) +export class InfoBarComponent implements AfterViewInit, OnChanges, OnDestroy { + @Input() + activityFields: ActivityField[]; + + numActivitiesInModel: number; + totalActivities: number; + + private _destroy$ = new Subject(); + + constructor(private processTreeService: ProcessTreeService) {} + + ngOnChanges(): void { + this.totalActivities = this.activityFields.length; + } + + ngAfterViewInit(): void { + // Handle change of current activies in the loaded model + this.processTreeService.activitiesInCurrentTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((activitiesInTree) => { + this.numActivitiesInModel = this.activityFields.filter((act) => + activitiesInTree.has(act.activityName) + ).length; + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } +} diff --git a/src/frontend/src/app/components/bpmn-editor/bpmn-editor.component.css b/src/frontend/src/app/components/bpmn-editor/bpmn-editor.component.css new file mode 100644 index 0000000000000000000000000000000000000000..28497194d4ed8b0f9695aeb74177928348704400 --- /dev/null +++ b/src/frontend/src/app/components/bpmn-editor/bpmn-editor.component.css @@ -0,0 +1,37 @@ +:host { + position: absolute; + width : 100%; + height : 100%; + border-bottom: 1px solid black; + overflow: hidden; +} + + +.bpmn-tree-editor{ + background-color: var(--box-background-color); + max-height: 100%; + position: relative; + border-left: 1px solid var(--thin-border-color); +} + +.crosshair { + cursor: crosshair; +} + +.grid { + background-image: radial-gradient(var(--line-color) 1px, transparent 0); + background-size: 20px 20px; +} + +.editor-zone{ + width : 100%; + height : 100%; +} + +.bi-diagram-2.rotate-270::before { + transform: rotate(270deg); +} + +.button-text{ + display : inline-block; +} diff --git a/src/frontend/src/app/components/bpmn-editor/bpmn-editor.component.html b/src/frontend/src/app/components/bpmn-editor/bpmn-editor.component.html new file mode 100644 index 0000000000000000000000000000000000000000..cea165ebd7fd221a4ee12cff4572476d2541a4a8 --- /dev/null +++ b/src/frontend/src/app/components/bpmn-editor/bpmn-editor.component.html @@ -0,0 +1,125 @@ +<div class="bpmn-tree-editor h-100 d-flex flex-column"> + <div class="bg-dark btn-tool-bar"> + <button + class="button text-warning" + (click)="deleteSelected()" + [disabled]="!this.selectedRootID" + ngbTooltip="remove selected node(s)" + triggers="hover" + container="body" + > + <i class="bi bi-trash btn-icon"></i> + </button> + + <div class="vr"></div> + + <button + class="button btn-fixed-width" + (click)="undo()" + [disabled]="!(treeCacheLength - 1 > 0 && treeCacheIndex !== 0)" + ngbTooltip="undo" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-counterclockwise btn-icon"></i> + <span + class="text-secondary" + *ngIf="treeCacheLength - 1 > 0 && treeCacheIndex !== 0" + > + ({{ treeCacheIndex }}) + </span> + </button> + + <button + class="button btn-fixed-width" + (click)="redo()" + [disabled]="!(treeCacheIndex < treeCacheLength - 1)" + ngbTooltip="redo" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-clockwise btn-icon"></i> + <span class="text-secondary" *ngIf="treeCacheIndex < treeCacheLength - 1"> + ({{ treeCacheLength - 1 - treeCacheIndex }}) + </span> + </button> + + <div class="vr"></div> + + <button + class="button" + (click)="clearSelection()" + [disabled]="!selectedRootID" + ngbTooltip="clear selection" + triggers="hover" + container="body" + > + <i + class="bi bi-x-circle btn-icon" + [ngClass]="selectedRootID ? 'text-danger' : ''" + ></i> + <div class="button-text px-1">clear selection</div> + </button> + + <div class="vr"></div> + + <ng-template #freezeTooltip> + (un)freeze <em>entire</em> subtree to prevent them from being changed when + adding variants + </ng-template> + <button + class="button" + (click)="freezeSubtree()" + [disabled]="buttonFreezeSubtreeDisabled()" + [ngbTooltip]="freezeTooltip" + triggers="hover" + container="body" + > + <i + class="bi bi-snow btn-icon" + [ngClass]="!buttonFreezeSubtreeDisabled() ? 'text-primary' : ''" + ></i> + <div class="button-text px-1">(un)freeze subtrees</div> + </button> + + <div class="vr"></div> + + <button + class="button ms-auto" + ngbTooltip="reset view" + triggers="hover" + container="body" + (click)="reset_zoom(true)" + > + <i class="bi bi-arrows-fullscreen btn-icon text-light"></i> + </button> + + <button + class="button" + ngbTooltip="export the model as an .svg" + triggers="hover" + container="body" + (click)="exportBPMN(bpmn)" + > + <i class="bi bi-save"></i> + </button> + </div> + + <div #BPMNcontainer class="m-1 flex-grow-1 crosshair grid"> + <svg #bpmn class="editor-zone" width="100%" height="100%"> + <g id="bpmn-zoom-group"> + <g + #d3svgDirective + appBpmnDrawer + [computeNodeColor]="computeNodeColor" + [computeTextColor]="computeTextColor" + [tooltipText]="tooltipContent" + [onClickCallBack]="selectNodeCallBack" + id="d3-svg-directive" + width="100%" + height="100%" + ></g> + </g> + </svg> + </div> +</div> diff --git a/src/frontend/src/app/components/bpmn-editor/bpmn-editor.component.spec.ts b/src/frontend/src/app/components/bpmn-editor/bpmn-editor.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..74e294b10273f6db34fe85c7b938e791771d1747 --- /dev/null +++ b/src/frontend/src/app/components/bpmn-editor/bpmn-editor.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BpmnEditorComponent } from './bpmn-editor.component'; + +describe('BpmnEditorComponent', () => { + let component: BpmnEditorComponent; + let fixture: ComponentFixture<BpmnEditorComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [BpmnEditorComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(BpmnEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/bpmn-editor/bpmn-editor.component.ts b/src/frontend/src/app/components/bpmn-editor/bpmn-editor.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3687676bb158c87d3e87cb57f11f06ccadf46d5 --- /dev/null +++ b/src/frontend/src/app/components/bpmn-editor/bpmn-editor.component.ts @@ -0,0 +1,499 @@ +import { ProcessTreeService } from './../../services/processTreeService/process-tree.service'; +import { Subject } from 'rxjs'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; +import { + Component, + ElementRef, + Inject, + OnInit, + Renderer2, + ViewChild, + AfterViewInit, + OnDestroy, +} from '@angular/core'; +import * as d3 from 'd3'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; + +import { + ProcessTree, + ProcessTreeOperator, +} from 'src/app/objects/ProcessTree/ProcessTree'; +import { ModelPerformanceColorScaleService } from 'src/app/services/performance-color-scale.service'; +import { ImageExportService } from 'src/app/services/imageExportService/image-export-service'; +import { PerformanceService } from 'src/app/services/performance.service'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { BPMN_Constant } from 'src/app/constants/bpmn_model_drawer_constants'; +import { BpmnDrawerDirective } from 'src/app/directives/bpmn-drawer/bpmn-drawer.directive'; +import { getPerformanceTable } from '../process-tree-editor/utils'; +import { textColorForBackgroundColor } from 'src/app/utils/render-utils'; +import { takeUntil } from 'rxjs/operators'; +import { ModelViewModeService } from 'src/app/services/viewModeServices/model-view-mode.service'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { ConformanceCheckingService } from 'src/app/services/conformanceChecking/conformance-checking.service'; + +@Component({ + selector: 'app-bpmn-editor', + templateUrl: './bpmn-editor.component.html', + styleUrls: ['./bpmn-editor.component.css'], +}) +export class BpmnEditorComponent + extends LayoutChangeDirective + implements OnInit, AfterViewInit, OnDestroy +{ + selectedNode: any; + currentTree: ProcessTree; + + activityColorMap: Map<string, string>; + performanceColorMap: Map<number, any>; + + nodeWidthCache = new Map<string, number>(); + selectedRootID: number; + + @ViewChild('bpmn') svgElem: ElementRef; + @ViewChild('BPMNcontainer') bpmnContainerElem: ElementRef; + @ViewChild(BpmnDrawerDirective) bpmnDrawer: BpmnDrawerDirective; + + mainGroup: d3.Selection<SVGGElement, any, any, any>; + selectedStatistic: string; + selectedPerformanceIndicator: string; + zoom: d3.ZoomBehavior<Element, unknown>; + + treeCacheLength: number = 0; + treeCacheIndex: number = 0; + + private _destroy$ = new Subject(); + + constructor( + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef, + private renderer: Renderer2, + private colorMapService: ColorMapService, + private performanceColorScaleService: ModelPerformanceColorScaleService, + private performanceService: PerformanceService, + private processTreeService: ProcessTreeService, + private imageExportService: ImageExportService, + private modelViewModeService: ModelViewModeService, + private conformanceCheckingService: ConformanceCheckingService + ) { + super(elRef.nativeElement, renderer); + const state = this.container.initialState; + } + + ngOnInit(): void { + this.processTreeService.nodeWidthCache$ + .pipe(takeUntil(this._destroy$)) + .subscribe((cache) => { + this.nodeWidthCache = cache; + }); + + this.processTreeService.treeCacheIndex$ + .pipe(takeUntil(this._destroy$)) + .subscribe((idx) => { + this.treeCacheIndex = idx; + }); + + this.processTreeService.treeCacheLength$ + .pipe(takeUntil(this._destroy$)) + .subscribe((len) => { + this.treeCacheLength = len; + }); + } + + ngAfterViewInit(): void { + this.nodeWidthCache = this.processTreeService.nodeWidthCache; + + this.modelViewModeService.viewMode$ + .pipe(takeUntil(this._destroy$)) + .subscribe((viewMode) => { + if (this.currentTree) { + this.redraw(this.currentTree); + } + }); + + this.conformanceCheckingService.isConformanceWeighted$ + .pipe(takeUntil(this._destroy$)) + .subscribe((_) => { + if (this.currentTree) { + this.redraw(this.currentTree); + } + }); + + this.mainGroup = d3.select('#bpmn-zoom-group'); + + this.createArrowHeadMarker(); + + this.addZoomFunctionality(); + + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + this.activityColorMap = colorMap; + + if (this.currentTree) { + this.redraw(this.currentTree); + } + }); + + this.performanceColorScaleService.currentColorScale + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + if (colorMap && colorMap != this.performanceColorMap) { + this.performanceColorMap = colorMap; + + if (this.currentTree) { + this.redraw(this.currentTree); + } + } + }); + + this.processTreeService.currentDisplayedProcessTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((tree) => { + this.currentTree = tree; + this.redraw(tree); + this.reset_zoom(false); + }); + + this.processTreeService.selectedRootNodeID$ + .pipe(takeUntil(this._destroy$)) + .subscribe((id) => { + if (id) { + this.selectBPMNNode(id); + } else { + this.unselectAll(); + } + + this.selectedRootID = id; + }); + } + + selectNodeCallBack = (self, event: PointerEvent, d) => { + // hide the tooltip + if (self.variantService.activityTooltipReference) { + self.variantService.activityTooltipReference.tooltip('hide'); + } + + event.stopPropagation(); + event.preventDefault(); + + if (d.id === this.selectedRootID) { + this.processTreeService.selectedRootNodeID = null; + this.processTreeService.selectedTree = undefined; + } else { + this.processTreeService.selectedRootNodeID = d.id; + this.processTreeService.selectedTree = ProcessTree.fromObj(d); + } + }; + + createArrowHeadMarker() { + const marker_colors = { + 'arrow-grey': BPMN_Constant.STROKE_COLOR, + 'arrow-red': 'red', + 'arrow-frozen': '#425bbf', + }; + + for (const [marker_id, fill_color] of Object.entries(marker_colors)) { + d3.select(this.svgElem.nativeElement) + .append('svg:defs') + .append('svg:marker') + .attr('id', marker_id) + .attr('viewBox', '-1 -2 4 4') + .attr('refX', 0) + .attr('refY', 0) + .attr('markerWidth', BPMN_Constant.ARROW_LENGTH) + .attr('markerHeight', '100%') + .attr('orient', 'auto') + .attr('markerUnits', 'userSpaceOnUse') + .append('polygon') + .attr('points', '-1,-2 3,0 -1,2 0,0') + .attr('fill', fill_color); + } + } + + redraw(tree: ProcessTree) { + this.selectedStatistic = + this.performanceColorScaleService.selectedColorScale.statistic; + this.selectedPerformanceIndicator = + this.performanceColorScaleService.selectedColorScale.performanceIndicator; + + this.bpmnDrawer.redraw(tree); + this.selectBPMNNode(this.selectedRootID); + } + + tooltipContent = (d: ProcessTree) => { + let returnTempValue = d.label || d.operator; + + const tableHead = + `<div style="display: flex; justify-content: space-between; border-radius: 5px 5px 0px 0px;" class="bg-dark"> + <h6 style="flex: 1; margin-top: 8px;">` + + (d.label || d.operator) + + `</h6> + </div>`; + + if ( + this.modelViewModeService.viewMode === ViewMode.PERFORMANCE && + d.hasPerformance() && + d.label !== ProcessTreeOperator.tau + ) { + returnTempValue = + tableHead + + getPerformanceTable( + d.performance, + this.selectedPerformanceIndicator, + this.selectedStatistic + ); + } else if ( + this.modelViewModeService.viewMode === ViewMode.CONFORMANCE && + d.conformance !== null + ) { + returnTempValue = + tableHead + + `<table class="table table-dark table-striped table-bordered"> + <tr> + <td>Weighted</td> + <td>Conformance</td> + <td>Weight</td> + </tr>` + + `<tr> + <td>Equally</td> + <td>${(d.conformance?.weighted_equally.value * 100).toFixed( + 2 + )}%</td> + <td>${d.conformance?.weighted_equally.weight}</td> + </tr>` + + (d.conformance?.weighted_by_counts !== null + ? `<tr> + <td>By Log Frequency</td> + <td>${(d.conformance?.weighted_by_counts?.value * 100).toFixed( + 2 + )}%</td> + <td>${d.conformance?.weighted_by_counts?.weight}</td> + </tr>` + : '') + + '</table>'; + } + + return returnTempValue; + }; + + computeNodeColor = (pt: ProcessTree) => { + let color; + + switch (this.modelViewModeService.viewMode) { + case ViewMode.CONFORMANCE: + if (pt.conformance === null) return '#404041'; + const conformanceValue = + this.conformanceCheckingService.isConformanceWeighted && + pt.conformance?.weighted_by_counts != undefined + ? pt.conformance?.weighted_by_counts.value + : pt.conformance?.weighted_equally.value; + if (conformanceValue === 0) return 'url(#modelConformanceStriped)'; + return this.conformanceCheckingService.modelConformanceColorMap.getColor( + conformanceValue + ); + case ViewMode.PERFORMANCE: + if ( + this.performanceColorMap.has(pt.id) && + pt.performance?.[this.selectedPerformanceIndicator]?.[ + this.selectedStatistic + ] !== undefined + ) { + if ( + pt.performance[this.selectedPerformanceIndicator][ + this.selectedStatistic + ] === 0 + ) + return 'url(#whiteStriped)'; + else + return this.performanceColorMap + .get(pt.id) + .getColor( + pt.performance[this.selectedPerformanceIndicator][ + this.selectedStatistic + ] + ); + } else { + color = '#404040'; + } + + break; + default: + color = + pt.label !== '\u03C4' + ? this.activityColorMap.get(pt.label) + : BPMN_Constant.INVISIBLE_ACTIVITIY_DEFAULT_COLOR; + break; + } + + return color; + }; + + computeTextColor = (pt: ProcessTree) => { + return pt.label === ProcessTreeOperator.tau || pt.frozen + ? 'White' + : textColorForBackgroundColor(this.computeNodeColor(pt)); + }; + + ngOnDestroy() { + this._destroy$.next(); + } + + unselectAll() { + this.mainGroup.classed('selected-bpmn-operator', false); + + this.mainGroup + .selectAll('.selected-bpmn-event') + .classed('selected-bpmn-event', false); + this.mainGroup + .selectAll('.selected-bpmn-operator') + .classed('selected-bpmn-operator', false); + } + + freezeSubtree() { + this.processTreeService.freezeSubtree(this.selectedNode.datum()); + } + + buttonFreezeSubtreeDisabled() { + return ( + this.selectedRootID == null || + (this.selectedNode && this.selectedNode.datum().children.length === 0) + ); + } + + selectBPMNNode(id: number) { + this.unselectAll(); + + const selected_node = this.mainGroup.select('[id="' + id + '"]'); + if (!selected_node.empty()) { + this.selectedNode = selected_node; + if ((selected_node.datum() as ProcessTree).operator) { + if (this.currentTree === selected_node.datum()) { + this.mainGroup.classed('selected-bpmn-operator', true); + } else { + selected_node.classed('selected-bpmn-operator', true); + } + } else { + selected_node.classed('selected-bpmn-event', true); + } + } + } + + undo(): void { + this.processTreeService.undo(); + } + + redo(): void { + this.processTreeService.redo(); + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + + handleVisibilityChange(visibile: boolean): void { + if (this.currentTree && visibile) { + this.reset_zoom(false); + this.redraw(this.currentTree); + } + } + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} + + clearSelection() { + this.processTreeService.selectedRootNodeID = null; + } + + deleteSelected() { + this.processTreeService.deleteSelected(this.selectedNode.datum()); + } + + addZoomFunctionality(): void { + const zooming = function (event) { + this.mainGroup.attr('transform', event.transform.translate(0, 0)); + }.bind(this); + + this.zoom = d3 + .zoom() + .scaleExtent([BPMN_Constant.MIN_ZOOM, BPMN_Constant.MAX_ZOOM]) + .on('zoom', zooming); + d3.select(this.svgElem.nativeElement) + .call(this.zoom) + .on('dblclick.zoom', null); + } + + reset_zoom(animation: boolean = true): void { + const rTime = animation ? 250 : 0; + + const bounds = this.mainGroup.node().getBBox(); + const editorZone = <any>this.mainGroup.node().parentElement; + const svgWidth = editorZone.width.baseVal.value - 2 * BPMN_Constant.PADDING; + const svgHeight = + editorZone.height.baseVal.value - 2 * BPMN_Constant.PADDING; + + // Calculate the scale to fit the content within the SVG + let scale = Math.min(svgWidth / bounds.width, svgHeight / bounds.height); + scale = Math.min(scale, BPMN_Constant.DEFAULT_ZOOM); + scale = Math.max(scale, BPMN_Constant.MIN_ZOOM); + + // Center SVG + const translateX = (svgWidth - bounds.width * scale) / 2; + const translateY = (svgHeight - bounds.height * scale) / 2; + + d3.select(this.svgElem.nativeElement) + .transition() + .duration(rTime) + .ease(d3.easeExpInOut) + .call( + this.zoom.transform, + d3.zoomIdentity.translate(translateX, translateY).scale(scale) + ); + } + + exportBPMN(svg: SVGGraphicsElement): void { + // Copy the current tree + const bpmn_copy = svg.cloneNode(true) as SVGGraphicsElement; + const svgBBox = (this.mainGroup.node() as SVGGraphicsElement).getBBox(); + + // Strip all the classed information + const bpmn = d3.select(bpmn_copy); + + bpmn + .selectAll('g') + .attr('data-bs-toggle', 'none') + .attr('data-bs-placement', 'none') + .attr('data-bs-title', 'none') + .attr('data-bs-html', 'none') + .attr('data-bs-template', 'none'); + + // Reset origin and add padding + bpmn + .select('#bpmn-zoom-group') + .attr( + 'transform', + `translate(${BPMN_Constant.PADDING}, ${BPMN_Constant.PADDING})` + ); + + // Change Cortado colors of BPMN Nodes to black and white + bpmn.selectAll('.BPMNOperatorNode').attr('fill', 'white'); + bpmn.selectAll('.BPMNOperatorText').attr('fill', 'black'); + + // Export the BPMN + this.imageExportService.export( + 'bpmn_diagram', + svgBBox.width + 2 * BPMN_Constant.PADDING, + svgBBox.height + 2 * BPMN_Constant.PADDING, + bpmn_copy + ); + } +} + +export namespace BpmnEditorComponent { + export const componentName = 'BpmnEditorComponent'; +} diff --git a/src/frontend/src/app/components/conformance-tab/conformance-tab.component.css b/src/frontend/src/app/components/conformance-tab/conformance-tab.component.css new file mode 100644 index 0000000000000000000000000000000000000000..3ffd61787b5990a7be9732ca89a38fcbf86e2baf --- /dev/null +++ b/src/frontend/src/app/components/conformance-tab/conformance-tab.component.css @@ -0,0 +1,35 @@ +:host { + display: flex; + flex-direction: column; + overflow: auto; + position: absolute; +} + +.nav-tabs { + padding-bottom: 5px; +} + +.color-map { + padding: 10px; + display: flex; +} + +.card { + background-color: transparent; + border: 0; +} + +.card-body{ + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.card-deck { + display: flex; + flex-direction: row; +} + +.card-description { + padding-bottom: 20px; +} diff --git a/src/frontend/src/app/components/conformance-tab/conformance-tab.component.html b/src/frontend/src/app/components/conformance-tab/conformance-tab.component.html new file mode 100644 index 0000000000000000000000000000000000000000..6c63c874a0712b614f30a51463bb99611853f7d7 --- /dev/null +++ b/src/frontend/src/app/components/conformance-tab/conformance-tab.component.html @@ -0,0 +1,233 @@ +<ul class="nav nav-tabs bg-dark" role="tablist"> + <li class="nav-item" role="presentation"> + <button + class="nav-link active button" + id="model-selection-tab" + data-bs-toggle="tab" + data-bs-target="#model-selection" + role="tab" + aria-controls="model-selection" + aria-selected="true" + > + Model Selection + </button> + </li> + <li class="nav-item" role="presentation"> + <button + class="nav-link button" + id="color-map-tab" + data-bs-toggle="tab" + data-bs-target="#color-map" + role="tab" + aria-controls="color-map" + aria-selected="true" + #colorMapTab + > + Color Maps + </button> + </li> +</ul> + +<div class="tab-content"> + <div + class="tab-pane fade show active" + id="model-selection" + role="tabpanel" + aria-labelledby="model-selection-tab" + > + <div + *ngIf=" + modelViewModeService.viewMode === VM.CONFORMANCE && + processTreeService.selectedTree?.conformance !== null; + else unavailableInfoNodeSelection + " + style="overflow: auto; display: flex; flex-direction: column" + > + <app-tree-string-renderer + [styled_tree_string]="processTreeService.selectedTree?.toString()" + ></app-tree-string-renderer> + <table + class="table table-sm table-striped table-dark table-hover table-bordered mb-0" + style="font-size: small; margin-top: 5px" + > + <tbody> + <tr> + <td> + Conformance weighted equally + + <i + class="bi bi-info-circle" + ngbTooltip="The conformance is the mean value of all sub-trees. Leaf nodes have the conformance value based on the fraction of alignments where the model and log move was aligned." + triggers="hover" + container="body" + ></i> + </td> + <td style="width: 20%"> + {{ + ( + processTreeService.selectedTree.conformance?.weighted_equally + .value * 100 + ).toFixed(2) + }}% + </td> + </tr> + <ng-container + *ngIf=" + processTreeService.selectedTree.conformance?.weighted_by_counts + " + > + <tr> + <td> + Conformance weighted by frequencies + <i + class="bi bi-info-circle" + ngbTooltip="The conformance is the mean value of all sub-trees, where each sub-tree is weighted by the activity frequency within that tree. Leaf nodes have the conformance value based on the fraction of alignments where the model and log move was aligned." + triggers="hover" + container="body" + ></i> + </td> + <td> + {{ + ( + processTreeService.selectedTree.conformance + ?.weighted_by_counts.value * 100 + ).toFixed(2) + }}% + </td> + </tr> + <tr> + <td> + Activity Frequency + <i + class="bi bi-info-circle" + ngbTooltip="The activity frequency is the number of times a model move occured within the alignments. Concurrency within the traces is treated by evaluating all sequential traces that can be created with the given concurrency. The values of sub-trees are the sum of its childs." + triggers="hover" + container="body" + ></i> + </td> + <td> + {{ + processTreeService.selectedTree.conformance + ?.weighted_by_counts.weight + }} + </td> + </tr> + </ng-container> + </tbody> + </table> + </div> + <ng-template #unavailableInfoNodeSelection> + <app-unavailable-info> + <div *ngIf="!processTreeService.currentDisplayedProcessTree"> + No tree discovered. + <br /> + You first need to discover a tree model. + </div> + <div + *ngIf=" + processTreeService.currentDisplayedProcessTree && + modelViewModeService.viewMode !== VM.CONFORMANCE + " + > + Project the conformance of a variant onto the process tree by + switching to the Variant Explorers <strong>Conformance Mode</strong> + and clicking on the + <i class="bi bi-toggle2-off" style="color: white"></i> symbol. + <br /> + Then you can select a tree node to see its conformance values. + </div> + <div + *ngIf=" + modelViewModeService.viewMode === VM.CONFORMANCE && + processTreeService.selectedTree?.conformance !== undefined + " + > + The variant and selected process tree have no alignment because non of + the variants activities do show up in this tree. + </div> + </app-unavailable-info> + </ng-template> + </div> + <div + class="tab-pane fade color-map-tab" + id="color-map" + role="tabpanel" + aria-labelledby="color-map-tab" + > + <div class="card-deck"> + <div class="card text-white mb-3 w-50"> + <div class="card-body"> + <h5 class="card-title"> + Model Conformance + <i + class="bi bi-question-circle-fill" + ngbTooltip="The Model Conformance describes how many nodes + contained in a sub-tree are properly aligned for a set of + variants. The method of aggregation for multiple selected variants + can be selected from equal weights and weighted by the their log + frequency." + triggers="hover" + container="body" + ></i> + </h5> + <div class="mb-3"> + <select + class="form-select form-select-sm" + aria-label="variant conformance aggregation" + name="weightMethod" + (change)="conformanceWeightMethodChange($event)" + > + <option value="weighted_equally">Weighted Equally</option> + <option value="weighted_by_counts">Weighted By Frequency</option> + </select> + </div> + <app-color-map + [colorMapValues]="modelConformanceColorMapValues" + [timeBasedLabel]="false" + [prefixes]="modelConformancePrefixes" + suffix="%" + [firstColorDetached]="true" + [lastColorDetached]="true" + [firstColorStriped]="true" + [stripeColor]=" + conformanceCheckingService.modelConformanceStripeColors[1] + " + [stripeBackgroundColor]=" + conformanceCheckingService.modelConformanceStripeColors[0] + " + ></app-color-map> + </div> + </div> + <div class="card text-white mb-3 w-50"> + <div class="card-body"> + <h5 class="card-title"> + Variant Conformance + <i + class="bi bi-question-circle-fill" + ngbTooltip="The Variant Conformance describes how often an + activity is properly aligned with the process model. Concurrent + activties are sequentialized to get aggregate values." + triggers="hover" + container="body" + ></i> + </h5> + <app-color-map + [colorMapValues]="variantConformanceColorMapValues" + [timeBasedLabel]="false" + [prefixes]="variantConformancePrefixes" + suffix="%" + [firstColorDetached]="true" + [lastColorDetached]="true" + [firstColorStriped]="true" + [stripeColor]=" + conformanceCheckingService.variantConformanceStripeColors[1] + " + [stripeBackgroundColor]=" + conformanceCheckingService.variantConformanceStripeColors[0] + " + ></app-color-map> + </div> + </div> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/conformance-tab/conformance-tab.component.spec.ts b/src/frontend/src/app/components/conformance-tab/conformance-tab.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..3c3977227af433743f0b21c6c9f6e33d3f343e76 --- /dev/null +++ b/src/frontend/src/app/components/conformance-tab/conformance-tab.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConformanceTabComponent } from './conformance-tab.component'; + +describe('ConformanceTabComponent', () => { + let component: ConformanceTabComponent; + let fixture: ComponentFixture<ConformanceTabComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ConformanceTabComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConformanceTabComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/conformance-tab/conformance-tab.component.ts b/src/frontend/src/app/components/conformance-tab/conformance-tab.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..3946c21ba9a05fdf34c4eb76be375f212a5b4f76 --- /dev/null +++ b/src/frontend/src/app/components/conformance-tab/conformance-tab.component.ts @@ -0,0 +1,144 @@ +import { + AfterViewInit, + Component, + ElementRef, + Inject, + OnDestroy, + Renderer2, + ViewChild, +} from '@angular/core'; +import { Tab } from 'bootstrap'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { ColorMap } from 'src/app/objects/ColorMap'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { ConformanceCheckingService } from 'src/app/services/conformanceChecking/conformance-checking.service'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { ModelViewModeService } from 'src/app/services/viewModeServices/model-view-mode.service'; +import { VariantViewModeService } from 'src/app/services/viewModeServices/variant-view-mode.service'; +import { ColorMapValue } from '../performance/color-map/color-map.component'; + +@Component({ + selector: 'app-conformance-tab', + templateUrl: './conformance-tab.component.html', + styleUrls: ['./conformance-tab.component.css'], +}) +export class ConformanceTabComponent + extends LayoutChangeDirective + implements AfterViewInit, OnDestroy +{ + @ViewChild('colorMapTab') colorMapTab: ElementRef; + + private _destroy$ = new Subject(); + public modelConformanceColorMapValues: ColorMapValue[]; + public modelConformancePrefixes: string[]; + public variantConformanceColorMapValues: ColorMapValue[]; + public variantConformancePrefixes: string[]; + + public VM = ViewMode; + + constructor( + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef, + renderer: Renderer2, + public conformanceCheckingService: ConformanceCheckingService, + private variantViewModeService: VariantViewModeService, + public modelViewModeService: ModelViewModeService, + public processTreeService: ProcessTreeService + ) { + super(elRef.nativeElement, renderer); + + this.modelConformanceColorMapValues = this.calculateColorMapValues( + this.conformanceCheckingService.modelConformanceColorMap + ); + this.variantConformanceColorMapValues = this.calculateColorMapValues( + this.conformanceCheckingService.variantConformanceColorMap + ); + + this.variantConformancePrefixes = new Array( + this.variantConformanceColorMapValues.length + ); + this.variantConformancePrefixes[1] = '>'; + this.variantConformancePrefixes[ + this.variantConformancePrefixes.length - 2 + ] = '<'; + this.modelConformancePrefixes = new Array( + this.modelConformanceColorMapValues.length + ); + this.modelConformancePrefixes[1] = '>'; + this.modelConformancePrefixes[this.modelConformancePrefixes.length - 2] = + '<'; + } + + private calculateColorMapValues(colorMap: ColorMap) { + const min = colorMap.domain()[0]; + const max = colorMap.domain()[colorMap.domain().length - 1]; + const increment = (max - min) / (colorMap.range().length - 3); + + const minColor = { + lowerBound: min * 100, + color: colorMap.range()[1], + }; + const maxColor = { + lowerBound: max * 100, + color: null, + }; + const otherColors = colorMap + .range() + .slice(2) + .map((v, i) => { + const t = min + i * increment; + + return { + lowerBound: Math.round(t * 100), + color: v, + }; + }); + return [minColor].concat(otherColors, [maxColor]); + } + + ngAfterViewInit(): void { + this.variantViewModeService.viewMode$ + .pipe(takeUntil(this._destroy$)) + .subscribe((viewMode) => { + if (viewMode === ViewMode.CONFORMANCE) + this.colorMapTab.nativeElement.click(); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + + handleVisibilityChange(visibility: boolean): void {} + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} + + public performanceStats: any; + public colorScale; + public title; + + public conformanceWeightMethodChange(event): void { + const value = event.target.value; + if (value == 'weighted_equally') + this.conformanceCheckingService.isConformanceWeighted = false; + else this.conformanceCheckingService.isConformanceWeighted = true; + } +} + +export namespace ConformanceTabComponent { + export const componentName = 'VariantConformanceComponent'; +} diff --git a/src/frontend/src/app/components/dialogs/api-error-dialog/api-error-dialog.component.html b/src/frontend/src/app/components/dialogs/api-error-dialog/api-error-dialog.component.html new file mode 100644 index 0000000000000000000000000000000000000000..4fe6b1e9cbdbcd1330f2ddeee8e5caca40a0c453 --- /dev/null +++ b/src/frontend/src/app/components/dialogs/api-error-dialog/api-error-dialog.component.html @@ -0,0 +1,56 @@ +<swal + swalOptions="" + #apiErrorDialog + [swalVisible]="isVisible" + title="Error occurred" + icon="error" + [showConfirmButton]="false" + [focusCancel]="true" + showCancelButton="true" + cancelButtonText="Close" + (didClose)="onClose()" +> + <div #content *swalPortal> + <div class="section"> + <b>Error message: </b><br /> + <code style="white-space: pre-line"> + {{ message }} + </code> + </div> + + <div + *ngIf="apiError.stack_trace" + (click)="toggleStackTrace()" + class="d-flex flex-column p-2 section stackTrace" + > + <div class="d-flex flex-row justify-content-between"> + <b>Stack trace </b> + <div class="d-flex flex-row iconContainer"> + <i + appStopClickEventPropagation + ngxClipboard + *ngxClipboardIfSupported + (cbOnSuccess)="onCopySuccess()" + [cbContent]="apiError?.stack_trace" + class="copyToClipboard bi bi-clipboard pr-2" + ></i> + + <i + [ngClass]=" + isStackTraceExpanded ? 'bi-chevron-up' : 'bi-chevron-down' + " + class="bi toggleTraceIcon" + ></i> + </div> + </div> + + <div + *ngIf="isStackTraceExpanded" + @expandCollapse + class="stackTraceContainer pt-2" + > + <code>{{ apiError?.stack_trace }}</code> + </div> + </div> + </div> +</swal> diff --git a/src/frontend/src/app/components/dialogs/api-error-dialog/api-error-dialog.component.scss b/src/frontend/src/app/components/dialogs/api-error-dialog/api-error-dialog.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..d96985c11af1c63421c2719d52983ca548541702 --- /dev/null +++ b/src/frontend/src/app/components/dialogs/api-error-dialog/api-error-dialog.component.scss @@ -0,0 +1,30 @@ +.section { + padding-bottom: 10px; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.section.stackTrace { + border: 1px solid gray; + border-radius: 5px; + cursor: pointer; + + /* stylelint-disable-next-line selector-class-pattern */ + .stackTraceContainer { + height: 200px; + overflow: auto; + + code { + color: red; + } + } + + /* stylelint-disable-next-line selector-class-pattern */ + .iconContainer { + gap: 6px; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .iconContainer .toggleTraceIcon, .copyToClipboard { + cursor: pointer; + } +} diff --git a/src/frontend/src/app/components/dialogs/api-error-dialog/api-error-dialog.component.spec.ts b/src/frontend/src/app/components/dialogs/api-error-dialog/api-error-dialog.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..07951d684ce9599416c79ce5a93c4ddf14ea69eb --- /dev/null +++ b/src/frontend/src/app/components/dialogs/api-error-dialog/api-error-dialog.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApiErrorDialogComponent } from './api-error-dialog.component'; + +describe('ApiErrorDialogComponent', () => { + let component: ApiErrorDialogComponent; + let fixture: ComponentFixture<ApiErrorDialogComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ApiErrorDialogComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApiErrorDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/dialogs/api-error-dialog/api-error-dialog.component.ts b/src/frontend/src/app/components/dialogs/api-error-dialog/api-error-dialog.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..d9725e040a71df3e38248ab3ec869daf9e8047d1 --- /dev/null +++ b/src/frontend/src/app/components/dialogs/api-error-dialog/api-error-dialog.component.ts @@ -0,0 +1,72 @@ +import { HttpErrorResponse } from '@angular/common/http'; +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { SwalPortalTargets } from '@sweetalert2/ngx-sweetalert2'; +import { NextObserver, Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { expandCollapsed } from 'src/app/animations/text-animations'; +import { ApiError } from 'src/app/objects/ApiError'; +import { ErrorService } from 'src/app/services/errorService/error.service'; +import { LoadingOverlayService } from 'src/app/services/loadingOverlayService/loading-overlay.service'; + +@Component({ + selector: 'app-api-error-dialog', + templateUrl: './api-error-dialog.component.html', + styleUrls: ['./api-error-dialog.component.scss'], + animations: [expandCollapsed], +}) +export class ApiErrorDialogComponent implements OnInit, OnDestroy { + public isVisible: boolean; + public apiError: ApiError; + public message: string; + public isStackTraceExpanded: boolean = false; + + private _destroy$ = new Subject(); + + constructor( + private errorService: ErrorService, + private loadingOverlayService: LoadingOverlayService, + public readonly swalTargets: SwalPortalTargets + ) {} + + ngOnInit(): void { + this.errorService + .getErrors() + .pipe(takeUntil(this._destroy$)) + .subscribe(this.updatePropsObserver()); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + toggleStackTrace() { + this.isStackTraceExpanded = !this.isStackTraceExpanded; + } + + updatePropsObserver(): NextObserver<HttpErrorResponse> { + return { + next: (errorRes: HttpErrorResponse) => { + // initial value if errorRes is {} + this.isVisible = Object.keys(errorRes).length != 0; + this.apiError = errorRes.error; + this.message = errorRes.message; + + if (errorRes.error && errorRes.error.detail) { + this.message += '\n' + errorRes.error.detail; + this.loadingOverlayService.hideLoader(); + } + + if (errorRes.status === 0) { + this.message = + 'The backend is unavailable. Wait for the backend to start or start it manually.'; + } + }, + }; + } + + onCopySuccess() {} + + onClose() { + this.isVisible = false; + } +} diff --git a/src/frontend/src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component.css b/src/frontend/src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component.css new file mode 100644 index 0000000000000000000000000000000000000000..cfc4e779419cc2125f6c604e484da0b3e1daada9 --- /dev/null +++ b/src/frontend/src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component.css @@ -0,0 +1,3 @@ +.modal-body { + overflow: auto; +} diff --git a/src/frontend/src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component.html b/src/frontend/src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component.html new file mode 100644 index 0000000000000000000000000000000000000000..073f8ef3d3956ee3902dd18282ba772dd6303d6f --- /dev/null +++ b/src/frontend/src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component.html @@ -0,0 +1,34 @@ +<div class="modal-header h-line-modal-bottom"> + <h4 class="modal-title text-light" id="modal-basic-title"> + Continue on last project? + </h4> + <button + type="button" + class="btn-close btn-close-white" + aria-label="Close" + (click)="modal.dismiss()" + ></button> +</div> +<div class="modal-body text-light"> + You have previously worked on the event-log <code>{{ projectName }}</code + >. + <br /> + Do you want to continue where you left off? +</div> +<div class="modal-footer h-line-modal-top"> + <button + type="button" + class="btn btn-outline-secondary" + (click)="modal.dismiss()" + > + No + </button> + <button + type="button" + class="btn btn-success" + ngbAutofocus + (click)="modal.close()" + > + Yes + </button> +</div> diff --git a/src/frontend/src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component.spec.ts b/src/frontend/src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..8a1c82afac77052923b153b405da2297c7256a7f --- /dev/null +++ b/src/frontend/src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ContinueLastProjectDialogComponent } from './continue-last-project-dialog.component'; + +describe('ContinueLastProjectDialogComponent', () => { + let component: ContinueLastProjectDialogComponent; + let fixture: ComponentFixture<ContinueLastProjectDialogComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ContinueLastProjectDialogComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(ContinueLastProjectDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component.ts b/src/frontend/src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..027423d2b55daebbac8cee4289380056541b34ec --- /dev/null +++ b/src/frontend/src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component.ts @@ -0,0 +1,12 @@ +import { Component, Input } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; + +@Component({ + selector: 'app-continue-last-project-dialog', + templateUrl: './continue-last-project-dialog.component.html', + styleUrls: ['./continue-last-project-dialog.component.css'], +}) +export class ContinueLastProjectDialogComponent { + @Input() projectName: string; + constructor(public modal: NgbActiveModal) {} +} diff --git a/src/frontend/src/app/components/dialogs/dialog.module.ts b/src/frontend/src/app/components/dialogs/dialog.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..30a380c2b36b02436e7e4620b4b82a555c539d49 --- /dev/null +++ b/src/frontend/src/app/components/dialogs/dialog.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ApiErrorDialogComponent } from './api-error-dialog/api-error-dialog.component'; +import { SweetAlert2Module } from '@sweetalert2/ngx-sweetalert2'; +import { ClipboardModule } from 'ngx-clipboard'; +import { SharedDirectivesModule } from 'src/app/directives/shared-directives/shared-directives.module'; +import { ContinueLastProjectDialogComponent } from './continue-last-project-dialog/continue-last-project-dialog.component'; + +@NgModule({ + declarations: [ApiErrorDialogComponent, ContinueLastProjectDialogComponent], + imports: [ + CommonModule, + SweetAlert2Module.forChild(), + ClipboardModule, + SharedDirectivesModule, + ], + exports: [ApiErrorDialogComponent], +}) +export class DialogModule {} diff --git a/src/frontend/src/app/components/documentation/documentation.component.html b/src/frontend/src/app/components/documentation/documentation.component.html new file mode 100644 index 0000000000000000000000000000000000000000..3c2eb3aea78a0c68649a9013a27f320ef4e6fc6d --- /dev/null +++ b/src/frontend/src/app/components/documentation/documentation.component.html @@ -0,0 +1,73 @@ +<div + class="modal fade" + id="documentation-modal-dialog" + tabindex="-1" + role="dialog" + aria-labelledby="doc-modal-header" + aria-hidden="true" + (scroll)="onScroll()" +> + <div class="modal-dialog" role="document"> + <div class="modal-content light-style"> + <div class="modal-header h-line-modal-bottom light-style"> + <h4 + class="modal-title text-light modal-title-dark" + id="doc-modal-header" + > + Documentation + </h4> + <button + type="button" + class="btn-close" + data-bs-dismiss="modal" + aria-label="Close" + ></button> + </div> + + <div class="modal-body"> + <div class="flex-container" style="padding-left: 15px"> + <main + markdown + ngPreserveWhitespaces + [src]="'./assets/doc/user_manual.md'" + [srcRelativeLink]="true" + (load)="onLoad()" + ></main> + <nav *ngIf="headings"> + <ul class="scrollspy-nav" id="table-of-contents"> + <li + *ngFor="let heading of headings" + [ngClass]="{ + first: heading.nodeName === 'H1', + second: heading.nodeName === 'H2', + third: heading.nodeName === 'H3', + fourth: heading.nodeName === 'H4', + fifth: heading.nodeName === 'H5' + }" + (click)="navToSection(heading)" + > + <a + style="cursor: pointer" + fragment="{{ heading.id }}" + [attr.href]="'#' + heading.id" + >{{ heading.innerHTML | stripHtml }}</a + > + </li> + </ul> + </nav> + </div> + </div> + <div class="modal-footer h-line-modal-top"> + <button + id="close-modal" + type="button" + class="button btn-light doc-modal-close-btn" + data-bs-dismiss="modal" + > + <i class="bi bi-x-lg btn-icon text-danger"></i> + Close + </button> + </div> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/documentation/documentation.component.scss b/src/frontend/src/app/components/documentation/documentation.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e2c8c8a18d8b34e18a953acbdae9bd8f9f672872 --- /dev/null +++ b/src/frontend/src/app/components/documentation/documentation.component.scss @@ -0,0 +1,246 @@ +#documentation-modal-dialog { + --bs-modal-width: calc(100vw - 80px); +} + +.flex-container { + display: flex; +} + +.modal-header { + top: 0; + position: sticky; + z-index: 1; +} + +nav { + align-self: flex-start; + position: sticky; + top: 85px; + min-width: 220px; + border-left: 1px #a0a0a0 solid; + margin-left: 22px; +} + + +nav > ul { + list-style-type: none; + padding: 0 16px; +} + +li { + margin-left: -4px; +} + +li.active { + border-left: 5px solid rgb(84 103 239); +} + + +ul.scrollspy-nav { + padding: 0; + + li { + border-radius: 2px; + font-size: 15px; + font-weight: 500; + list-style: none; + padding: 4px 0 4px 16px; + color: black !important; + + > a { + color: black; + } + + > a, + > a:active, + > a:focus, + > a:hover { + text-decoration: none; + } + + &:not(.active) { + border-color: transparent; + opacity: 0.6; + } + } + + .first { + color: var(--bs-modal-color); + padding-left: 12px; + font-weight: 700; + } + + .first.active { + padding-left: 8px; + } + + .second { + color: var(--bs-modal-color); + padding-left: 18px; + font-weight: 600; + } + + .second.active { + padding-left: 14px; + } + + .third { + color: var(--bs-modal-color); + padding-left: 24px; + font-weight: 400; + } + + .third.active { + padding-left: 20px; + } + + .fourth { + color: var(--bs-modal-color); + padding-left: 30px; + font-weight: 200; + } + + .fourth.active { + padding-left: 26px; + } + + .fifth { + color: var(--bs-modal-color); + padding-left: 36px; + font-weight: 100; + } + + .fifth.active { + padding-left: 32px; + } + + counter-reset: first + +} + +main > h3 { + margin: 38px 0 17px; + color: black; +} + +main > h4 { + margin: 32px 0 14px; + color: black; + font-size: calc(1.2rem + 0.3vw); +} + +main > h5 { + margin: 26px 0 11px; + color: black; + font-size: 1.1rem; +} + + +// White background theme: + +.modal-title-dark { + color: black !important; +} + +.light-style { + background-color: #eee; + color: black; +} + +.markdown-table { + border: 1px solid black; +} + +.doc-modal-close-btn { + color: black !important; +} + + +main { + counter-reset: h1; + margin-top: -30px; +} + +main > h1 { + counter-reset: h2; + margin: 50px 0 23px; + scroll-margin-top: 85px; + color: black; +} + +main > h2 { + counter-reset: h3; + margin: 44px 0 20px; + scroll-margin-top: 85px; + color: black; +} + +// main > h3 { +// counter-reset: h4 +// } + +// main > h4 { +// counter-reset: h5 +// } + +main > h1::before { + counter-increment: h1; + content: counter(h1) ". " +} + +main > h2::before { + counter-increment: h2; + content: counter(h1) "." counter(h2) ". " +} + +main > h3::before { + counter-increment: h3; + content: counter(h1) "." counter(h2) "." counter(h3) ". " +} + +// main > h4:before { +// counter-increment: h4; +// content: counter(h1) "." counter(h2) "." counter(h3) "." counter(h4) ". " +// } + +// main > h5:before { +// counter-increment: h5; +// content: counter(h1) "." counter(h2) "." counter(h3) "." counter(h4) "." counter(h5) ". " +// } + + +ul.scrollspy-nav > .first { + counter-reset: second +} + +ul.scrollspy-nav > .first::before { + counter-increment: first; + content: counter(first) ". " +} + +ul.scrollspy-nav > .second::before { + counter-increment: second; + content: counter(first) "." counter(second) ". " +} + +img[alt="xxxsmall"] { width: calc(8vw); } +img[alt="xxsmall"] { width: calc(13vw); } +img[alt="xsmall"] { width: calc(20vw); } +img[alt="small"] { width: calc(30vw); } +img[alt="medium"] { width: calc(40vw); } +img[alt="large"] { width: calc(50vw); } +img[alt="xlarge"] { width: calc(60vw); } +img[alt="xxlarge"] { width: calc(70vw); } + +.xxxsmall { width: calc(8vw); } +.xxsmall { width: calc(13vw); } +.xsmall { width: calc(20vw); } +.small { width: calc(30vw); } +.medium { width: calc(40vw); } +.large { width: calc(50vw); } +.xlarge { width: calc(60vw); } +.xxlarge { width: calc(70vw); } + +.xxxsmall-img { width: calc(8vw); } +.xxsmall-img { width: calc(13vw); } +.xsmall-img { width: calc(18vw); } diff --git a/src/frontend/src/app/components/documentation/documentation.component.ts b/src/frontend/src/app/components/documentation/documentation.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..a64fd161b78b128f1422639bc6b1977e6125d3e1 --- /dev/null +++ b/src/frontend/src/app/components/documentation/documentation.component.ts @@ -0,0 +1,132 @@ +import { + Component, + Inject, + Input, + NgZone, + OnDestroy, + OnInit, + ViewEncapsulation, +} from '@angular/core'; +import { DOCUMENT } from '@angular/common'; +import { Observable, Subject } from 'rxjs'; +import { first, takeUntil } from 'rxjs/operators'; + +declare let Gumshoe: any; + +declare var $: any; + +@Component({ + selector: 'app-documentation', + templateUrl: './documentation.component.html', + styleUrls: ['./documentation.component.scss'], + encapsulation: ViewEncapsulation.None, +}) +export class DocumentationComponent implements OnInit, OnDestroy { + @Input() + showDocumentation: Observable<string>; + headings: NodeListOf<Element>; + // tslint:disable-next-line:variable-name + private _destroy$ = new Subject(); + private scrollSpy: typeof Gumshoe; + + constructor( + @Inject(DOCUMENT) private document: Document, + private zone: NgZone + ) {} + + ngOnInit() { + this.showDocumentation + .pipe(takeUntil(this._destroy$)) + .subscribe((heading) => { + this.showModal(heading); + }); + } + + showModal(heading): void { + $('#documentation-modal-dialog').modal('show'); + setTimeout(() => { + if (heading) { + this.navToSectionByHeading(heading); + } + if (this.scrollSpy) { + this.scrollSpy.detect(); + } + }, 180); + } + + onLoad() { + setTimeout(() => { + this.headings = this.document + .querySelector('main') + .querySelectorAll('h1, h2'); + this.setScrollSpy(); + }); + const tables = this.document + .querySelector('main') + .querySelectorAll('table, th, td'); + + // add class for styling the tables + for (let i = 0; i < tables.length; i++) { + tables[i].classList.add('markdown-table'); + } + } + + onScroll(): void { + if (this.scrollSpy) { + this.scrollSpy.detect(); + } + } + + blink(element) { + let f = document.getElementById(element); + setTimeout(function () { + f.style.background = f.style.background == 'lightgray' ? '' : 'lightgray'; + }, 200); + setTimeout(function () { + f.style.background = f.style.background == 'lightgray' ? '' : 'lightgray'; + }, 1200); + } + + navToSection(element) { + element.scrollIntoView(); + return false; + } + + navToSectionByHeading(heading: string) { + let elementId; + // tslint:disable-next-line:prefer-for-of + for (let i = 0; i < this.headings.length; i++) { + if (this.headings[i].innerHTML === heading) { + elementId = this.headings[i].id; + break; + } + } + if (elementId) { + document.querySelector('#' + elementId).scrollIntoView(); + // this.blink(elementId); + } + } + + setScrollSpy(): void { + if (this.scrollSpy) { + this.scrollSpy.setup(); + return; + } + this.zone.onStable.pipe(first()).subscribe(() => { + this.scrollSpy = new Gumshoe('#table-of-contents a', { + offset: 90, + }); + this.scrollSpy.setup(); + }); + } + + ngOnDestroy(): void { + this.destroyScrollSpy(); + } + + destroyScrollSpy(): void { + if (this.scrollSpy) { + this.scrollSpy.destroy(); + } + } +} diff --git a/src/frontend/src/app/components/documentation/documentation.service.ts b/src/frontend/src/app/components/documentation/documentation.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..fd926e165249a4c6fec647f35ec69207ba3e9837 --- /dev/null +++ b/src/frontend/src/app/components/documentation/documentation.service.ts @@ -0,0 +1,12 @@ +import { Injectable } from '@angular/core'; +import { Subject } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class DocumentationService { + showDocumentationEvent: Subject<string> = new Subject<string>(); + showDocumentationDialog(heading: string = null) { + this.showDocumentationEvent.next(heading); + } +} diff --git a/src/frontend/src/app/components/documentation/strip-html.pipe.ts b/src/frontend/src/app/components/documentation/strip-html.pipe.ts new file mode 100644 index 0000000000000000000000000000000000000000..e0fa7313719641d2ebc67414a559d715d5052a7a --- /dev/null +++ b/src/frontend/src/app/components/documentation/strip-html.pipe.ts @@ -0,0 +1,10 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'stripHtml', +}) +export class StripHtmlPipe implements PipeTransform { + transform(value: string): string { + return value.replace(/<[^>]*>?/gm, ''); + } +} diff --git a/src/frontend/src/app/components/drop-zone/drop-zone.component.css b/src/frontend/src/app/components/drop-zone/drop-zone.component.css new file mode 100644 index 0000000000000000000000000000000000000000..1bc09759468df19a3d1fe269187f8415b761cda3 --- /dev/null +++ b/src/frontend/src/app/components/drop-zone/drop-zone.component.css @@ -0,0 +1,34 @@ +.drop-zone-container{ + position: absolute; + height: 100%; + width: 100%; + z-index : -1; +} + +.pull-in-front{ + z-index : 3; +} + +.drop-zone-text{ + z-index : -1; +} + +.drop-zone{ + width : 100%; + height: 100%; +} + +.drop-zone-content{ + height: 100%; + width : 100%; + align-items: center; + color: var(--text-secondary); + display: flex; + justify-content: center; +} + +.blur-out-of-focus{ + opacity: 0.8; + filter: blur(3px) brightness(0.5); +} + diff --git a/src/frontend/src/app/components/drop-zone/drop-zone.component.html b/src/frontend/src/app/components/drop-zone/drop-zone.component.html new file mode 100644 index 0000000000000000000000000000000000000000..e627d2018b17c9c5c8f45d5affece1ecf96499ff --- /dev/null +++ b/src/frontend/src/app/components/drop-zone/drop-zone.component.html @@ -0,0 +1,21 @@ +<ngx-file-drop + *ngIf="dropZoneDirective.windowDrag" + (onFileDrop)="importDroppedFile($event)" + class="drop-zone-container" + [class.pull-in-front]="dropZoneDirective.windowDrag" + (onFileOver)="fileOver($event)" + (onFileLeave)="fileLeave($event)" + dropZoneClassName="drop-zone" + contentClassName="drop-zone-content" + [accept]="dropzoneConfig.acceptedFormats" + directory="false" + [multiple]="dropzoneConfig.dropZoneHoverMessage" +> + <ng-template ngx-file-drop-content-tmp> + <div + *ngIf="showText" + [innerHTML]="dropZoneText" + class="drop-zone-text" + ></div> + </ng-template> +</ngx-file-drop> diff --git a/src/frontend/src/app/components/drop-zone/drop-zone.component.spec.ts b/src/frontend/src/app/components/drop-zone/drop-zone.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..1fc9bae2c19ad49cf91486133de0cf490366bf38 --- /dev/null +++ b/src/frontend/src/app/components/drop-zone/drop-zone.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DropZoneComponent } from './drop-zone.component'; + +describe('DropZoneComponent', () => { + let component: DropZoneComponent; + let fixture: ComponentFixture<DropZoneComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [DropZoneComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DropZoneComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/drop-zone/drop-zone.component.ts b/src/frontend/src/app/components/drop-zone/drop-zone.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..d2a64d75953c1f7e85befa6d69cd2153171b75bf --- /dev/null +++ b/src/frontend/src/app/components/drop-zone/drop-zone.component.ts @@ -0,0 +1,185 @@ +import { environment } from '../../../environments/environment'; +import { + Component, + Input, + ViewEncapsulation, + OnInit, + Output, + EventEmitter, + NgZone, +} from '@angular/core'; +import { DomSanitizer, SafeStyle } from '@angular/platform-browser'; +import { NgxFileDropEntry, FileSystemFileEntry } from 'ngx-file-drop'; +import { BackendService } from 'src/app/services/backendService/backend.service'; +import { DropZoneDirective } from 'src/app/directives/drop-zone/drop-zone.directive'; +import Swal from 'sweetalert2'; +import { LoadingOverlayService } from 'src/app/services/loadingOverlayService/loading-overlay.service'; + +@Component({ + selector: 'app-drop-zone', + templateUrl: './drop-zone.component.html', + styleUrls: ['./drop-zone.component.css'], + encapsulation: ViewEncapsulation.None, +}) +export class DropZoneComponent extends DropZoneDirective implements OnInit { + file: NgxFileDropEntry = null; + showText: boolean; + dropZoneText: SafeStyle; + @Input() dropzoneConfig: DropzoneConfig; + @Output() fileOnHover: EventEmitter<boolean> = new EventEmitter<boolean>( + false + ); + + dropZoneDirective = DropZoneDirective; + + constructor( + private sanitizer: DomSanitizer, + private backendService: BackendService, + private loadingOverlayService: LoadingOverlayService, + private ngZone: NgZone + ) { + super(); + } + + ngOnInit() { + this.dropZoneText = this.sanitizer.bypassSecurityTrustHtml( + this.dropzoneConfig.dropZoneHoverMessage + ); + } + + fileOver(event) { + this.fileOnHover.emit(true); + this.showText = true; + } + + fileLeave(event) { + this.fileOnHover.emit(false); + this.showText = false; + } + + importDroppedFile(files: NgxFileDropEntry[]) { + if (files.length > 1) { + Swal.fire({ + title: + '<tspan class = "text-warning">Multiple Files not supported </tspan>', + html: + '<b>Error Message: </b><br>' + + '<code> The dropzone does not support directories or multiple files at once.\ + Select a single file of the supported format and try again\ + </code> <br> <br> Supported Formats: ' + + '<tspan class = "text-danger">' + + this.dropzoneConfig.acceptedFormats + + '</tspan>', + icon: 'warning', + showCloseButton: false, + showConfirmButton: false, + showCancelButton: true, + cancelButtonText: 'close', + }); + } else { + // Send a general User Warning, that this Action is not supported + this.file = files[0]; + + if (this.file.fileEntry.isFile) { + const fileName: string = this.file.fileEntry.name; + const fileEnding: string = fileName.slice( + fileName.lastIndexOf('.'), + fileName.length + ); + const fileEntry = this.file.fileEntry as FileSystemFileEntry; + + if (this.dropzoneConfig.acceptedFormats.includes(fileEnding)) { + fileEntry.file((file: File) => { + switch (fileEnding) { + case '.xes': + this.ngZone.run(() => { + this.loadingOverlayService.showLoader( + 'Importing event log (for large logs this can take up to several minutes)' + ); + + const backendCall = !environment.electron + ? this.backendService.uploadEventLog(file) + : this.backendService.loadEventLogFromFilePath( + file['path'] + ); + + backendCall.subscribe((_) => { + this.loadingOverlayService.hideLoader(); + }); + }); + break; + + case '.ptml': + !environment.electron + ? this.backendService.loadProcessTreeFromFile(file) + : this.backendService.loadProcessTreeFromFilePath( + file['path'] + ); + break; + default: + break; + } + }); + } else { + Swal.fire({ + title: '<tspan class = "text-warning">Wrong File Format</tspan>', + html: + '<b>Error Message: </b><br>' + + '<code> The dropped files format is not supported.\ + File not uploaded. Check the format and try again\ + </code> <br> <br> Supported Formats: ' + + '<tspan class = "text-danger">' + + this.dropzoneConfig.acceptedFormats + + '</tspan>', + icon: 'warning', + showCloseButton: false, + showConfirmButton: false, + showCancelButton: true, + cancelButtonText: 'close', + }); + } + } else { + Swal.fire({ + title: + '<tspan class = "text-warning">Directory not supported</tspan>', + html: + '<b>Error Message: </b><br>' + + '<code> The dropzone does not support directories.\ + Select a single file of the supported format and try again\ + </code> <br> <br> Supported Formats: ' + + '<tspan class = "text-danger">' + + this.dropzoneConfig.acceptedFormats + + '</tspan>', + icon: 'warning', + showCloseButton: false, + showConfirmButton: false, + showCancelButton: true, + cancelButtonText: 'close', + }); + } + } + + DropZoneDirective.windowDrag = false; + this.fileOnHover.emit(false); + this.showText = false; + } +} + +export class DropzoneConfig { + acceptedFormats: string; + directory: string; + multiple: string; + dropZoneHoverMessage: string; + + constructor( + acceptedFormats: string, + directory: string, + multiple: string, + dropZoneHoverMessage: string + ) { + this.acceptedFormats = acceptedFormats; + this.directory = directory; + this.multiple = multiple; + this.dropZoneHoverMessage = dropZoneHoverMessage; + } +} diff --git a/src/frontend/src/app/components/editor-zone/editor-languages/vql-constants.ts b/src/frontend/src/app/components/editor-zone/editor-languages/vql-constants.ts new file mode 100644 index 0000000000000000000000000000000000000000..eeaf0e646128bf2e7500329f82779e82a6534b48 --- /dev/null +++ b/src/frontend/src/app/components/editor-zone/editor-languages/vql-constants.ts @@ -0,0 +1,23 @@ +export const binarylogicalOperator = ['AND', 'OR', '->']; + +export const unarylogicalOperator = ['NOT']; + +export const groupOperator = ['ALL', 'ANY']; + +export const binaryOperator = [ + 'isEF', + 'isEventuallyFollowed', + 'isDF', + 'isDirectlyFollowed', + 'isP', + 'isParallel', +]; + +export const unaryOperator = [ + 'isS', + 'isStart', + 'isE', + 'isEnd', + 'isC', + 'isContained', +]; diff --git a/src/frontend/src/app/components/editor-zone/editor-languages/vql-editor-options.ts b/src/frontend/src/app/components/editor-zone/editor-languages/vql-editor-options.ts new file mode 100644 index 0000000000000000000000000000000000000000..214628d59022fa78a9ee32d267893d9d3ef431cd --- /dev/null +++ b/src/frontend/src/app/components/editor-zone/editor-languages/vql-editor-options.ts @@ -0,0 +1,43 @@ +import * as Monaco from 'monaco-editor'; + +export const vqlEditorOptions: Monaco.editor.IStandaloneEditorConstructionOptions = + { + language: 'VQL', + lineNumbers: 'off', + roundedSelection: false, + scrollBeyondLastLine: false, + readOnly: false, + automaticLayout: true, + theme: 'VQLTheme', + wordWrap: 'on', + matchBrackets: 'always', + glyphMargin: false, + folding: false, + lineDecorationsWidth: 0, + lineNumbersMinChars: 0, + fontSize: 12, + fontFamily: getComputedStyle(document.documentElement) + .getPropertyValue('--bs-font-monospace') + .trim(), + lineHeight: 16, + fixedOverflowWidgets: true, + overflowWidgetsDomNode: document.getElementById( + 'monaco-editor-overflow-widgets-root' + )!, + minimap: { enabled: false }, + bracketPairColorization: { + enabled: true, + independentColorPoolPerBracketType: true, + }, + scrollbar: { + useShadows: true, + verticalHasArrows: false, + horizontalHasArrows: false, + horizontal: 'auto', + vertical: 'auto', + verticalScrollbarSize: 5, + horizontalScrollbarSize: 5, + }, + dragAndDrop: true, + contextmenu: false, + }; diff --git a/src/frontend/src/app/components/editor-zone/editor-languages/vql-language-completion-provider.ts b/src/frontend/src/app/components/editor-zone/editor-languages/vql-language-completion-provider.ts new file mode 100644 index 0000000000000000000000000000000000000000..7ab27297ad2bbfdb0f339f30b0ba173a9da85c5c --- /dev/null +++ b/src/frontend/src/app/components/editor-zone/editor-languages/vql-language-completion-provider.ts @@ -0,0 +1,91 @@ +import { + groupOperator, + unarylogicalOperator, + unaryOperator, + binaryOperator, + binarylogicalOperator, +} from './vql-constants'; +import * as Monaco from 'monaco-editor'; + +export function getVQLCompletionProvider(activityNames) { + activityNames = Array.from(activityNames); + + return function createProposals(range) { + // returning a static list of proposals, not even looking at the prefix (filtering is done by the Monaco editor), + // here you could do a server side lookup + + const suggetions = []; + + activityNames.forEach((element) => { + suggetions.push({ + label: element, + kind: Monaco.languages.CompletionItemKind.Text, + documentation: 'Activity Name', + insertText: element, + range: range, + }); + }); + + unarylogicalOperator.forEach((element) => { + suggetions.push({ + label: element, + kind: Monaco.languages.CompletionItemKind.Snippet, + documentation: 'Logical Operator', + insertText: element + '(${1:Expression})', + range: range, + insertTextRules: + Monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, + }); + }); + + binarylogicalOperator.forEach((element) => { + suggetions.push({ + label: element, + kind: Monaco.languages.CompletionItemKind.Snippet, + documentation: 'Logical Operator', + insertText: element + ' ${1:Expression}', + range: range, + insertTextRules: + Monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, + }); + }); + + groupOperator.forEach((element) => { + suggetions.push({ + label: element, + kind: Monaco.languages.CompletionItemKind.Snippet, + documentation: 'Group Operator', + insertText: element + " {${1:'Activity'}, ${2:'Activity'}}", + range: range, + insertTextRules: + Monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, + }); + }); + + binaryOperator.forEach((element) => { + suggetions.push({ + label: element, + kind: Monaco.languages.CompletionItemKind.Snippet, + documentation: 'Binary Operator', + insertText: element + ' $0', + range: range, + insertTextRules: + Monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, + }); + }); + + unaryOperator.forEach((element) => { + suggetions.push({ + label: element, + kind: Monaco.languages.CompletionItemKind.Snippet, + documentation: 'Unary Operator', + insertText: element + ' $0', + range: range, + insertTextRules: + Monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, + }); + }); + + return suggetions; + }; +} diff --git a/src/frontend/src/app/components/editor-zone/editor-languages/vql-language-theme.ts b/src/frontend/src/app/components/editor-zone/editor-languages/vql-language-theme.ts new file mode 100644 index 0000000000000000000000000000000000000000..3c218d2f95cf32c4a159e4d05e839b5188511e52 --- /dev/null +++ b/src/frontend/src/app/components/editor-zone/editor-languages/vql-language-theme.ts @@ -0,0 +1,43 @@ +import * as Monaco from 'monaco-editor'; +import { EditorOptions } from '../../variant-explorer/variant-query/variant-query.component'; + +export function generateVQLTheme( + colorMap: Map<string, string>, + options: EditorOptions +): Monaco.editor.IStandaloneThemeData { + const activityTokens = []; + if (options.highlightActivityNames) { + activityTokens.push({ + token: 'activites', + foreground: 'ffc107', + fontStyle: 'bold', + }); + + colorMap.forEach((v, k) => { + // The replace is used, due to the tokenizer converting certain char into -, if there is a bug during Tokenizing start checking here + activityTokens.push({ + token: 'activites.' + k.replace(/(<|_|>)/g, '-'), + foreground: v, + }); + }); + } + + return { + base: 'vs-dark', + inherit: true, + rules: [ + { token: 'quantifier', foreground: '008800', fontStyle: 'bold' }, + { token: 'string', foreground: 'FFFFFF' }, + { token: 'text', foreground: 'a0a0a0' }, + { token: 'identifier', foreground: 'a0a0a0' }, + { token: 'logicalOperator', foreground: '569cd6', fontStyle: 'bold' }, + { token: 'operator', foreground: '569cd6', fontStyle: 'underline' }, + { token: 'string.invalid', foreground: 'dc3545' }, + ...activityTokens, + ], + colors: { + 'editorBracketMatch.background': '00FF00', + 'editorBracketMatch.border': 'FF0000', + }, + }; +} diff --git a/src/frontend/src/app/components/editor-zone/editor-languages/vql-language.ts b/src/frontend/src/app/components/editor-zone/editor-languages/vql-language.ts new file mode 100644 index 0000000000000000000000000000000000000000..e79f8056ddd1d9ecb998825f1bafad3c4380c654 --- /dev/null +++ b/src/frontend/src/app/components/editor-zone/editor-languages/vql-language.ts @@ -0,0 +1,109 @@ +import { + unaryOperator, + binaryOperator, + binarylogicalOperator, + groupOperator, + unarylogicalOperator, +} from './vql-constants'; +import * as Monaco from 'monaco-editor'; + +export function getVQLTokenizer(): Monaco.languages.IMonarchLanguage { + return { + defaultToken: 'text', + + wordPattern: + /(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\{\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, + + logicalOperator: groupOperator.concat( + unarylogicalOperator, + binarylogicalOperator + ), + + operator: unaryOperator.concat(binaryOperator), + + symbols: /[=><!~?:&|+\-*\/\^%]+/, + + quantifier: ['=', '>', '<', '~'], + + // we include these common regular expressions + brackets: [ + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '[', close: ']', token: 'delimiter.bracket' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + ], + + tokenizer: { + root: [ + { include: '@whitespace' }, + { include: '@numbers' }, + + [/[,;]/, 'delimiter'], + [/[{}\[\]()]/, '@brackets'], + + [ + /@symbols/, + { + cases: { + '@logicalOperator': 'logicalOperator', + '@quantifier': 'quantifier', + '@default': 'text', + }, + }, + ], + + [ + /[a-zA-Z]\w*/, + { + cases: { + '@logicalOperator': 'logicalOperator', + '@operator': 'operator', + '@default': 'identifier', + }, + }, + ], + [ + /'/, + { token: 'string.quote', bracket: '@open', next: '@activityName' }, + ], + ], + + numbers: [ + [/-?0x([abcdef]|[ABCDEF]|\d)+[lL]?/, 'number.hex'], + [/-?(\d*\.)?\d+([eE][+\-]?\d+)?[jJ]?[lL]?/, 'number'], + ], + whitespace: [[/\s+/, 'white']], + + activityName: [ + [/([^'\\]|\\.)*(?!')$/, 'string.invalid'], + [/([^\\']+)/, { token: 'activites.$1' }], + [/'/, { token: 'string.quote', bracket: '@close', next: '@pop' }], + ], + }, + }; +} + +export const vqlConfig: Monaco.languages.LanguageConfiguration = { + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '<', close: '>' }, + { open: "'", close: "'" }, + { open: '"', close: '"' }, + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: "'", close: "'", notIn: ['string', 'comment'] }, + { open: '"', close: '"', notIn: ['string', 'comment'] }, + ], + brackets: [ + ['(', ')'], + ['{', '}'], + ], + colorizedBracketPairs: [ + ['(', ')'], + ['{', '}'], + ], +}; diff --git a/src/frontend/src/app/components/editor-zone/editor-zone.component.css b/src/frontend/src/app/components/editor-zone/editor-zone.component.css new file mode 100644 index 0000000000000000000000000000000000000000..889ef279f812cbab55553e2f19928f86aa85c7d6 --- /dev/null +++ b/src/frontend/src/app/components/editor-zone/editor-zone.component.css @@ -0,0 +1,12 @@ +.editor-container { + width: 100%; + height: 100%; + overflow: auto; +} + +.editor-top-container { + width: 100%; + min-height: 100px; + height: 100%; +} + diff --git a/src/frontend/src/app/components/editor-zone/editor-zone.component.html b/src/frontend/src/app/components/editor-zone/editor-zone.component.html new file mode 100644 index 0000000000000000000000000000000000000000..6d86dda9c6879260bbf565b7e6a3ff95dce80058 --- /dev/null +++ b/src/frontend/src/app/components/editor-zone/editor-zone.component.html @@ -0,0 +1,3 @@ +<div class="editor-top-container"> + <div id="editorContainer" class="editor-container" #editorContainer></div> +</div> diff --git a/src/frontend/src/app/components/editor-zone/editor-zone.component.spec.ts b/src/frontend/src/app/components/editor-zone/editor-zone.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..6d4949bf46d77f17923d2c7bb47477a9b971bdf3 --- /dev/null +++ b/src/frontend/src/app/components/editor-zone/editor-zone.component.spec.ts @@ -0,0 +1,27 @@ +/* tslint:disable:no-unused-variable */ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { DebugElement } from '@angular/core'; + +import { EditorZoneComponent } from './editor-zone.component'; + +describe('EditorZoneComponent', () => { + let component: EditorZoneComponent; + let fixture: ComponentFixture<EditorZoneComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [EditorZoneComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(EditorZoneComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/editor-zone/editor-zone.component.ts b/src/frontend/src/app/components/editor-zone/editor-zone.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..b9262509965941d729dd0346f21006dc4606dcf2 --- /dev/null +++ b/src/frontend/src/app/components/editor-zone/editor-zone.component.ts @@ -0,0 +1,217 @@ +import { EditorService } from './../../services/editorService/editor.service'; +import { + Component, + ElementRef, + OnInit, + ViewChild, + AfterViewInit, + Output, + EventEmitter, + OnDestroy, + forwardRef, + Input, + ChangeDetectionStrategy, +} from '@angular/core'; +import { take } from 'rxjs/operators'; +import { vqlEditorOptions } from './editor-languages/vql-editor-options'; +import { + ControlValueAccessor, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + ValidationErrors, + Validator, +} from '@angular/forms'; + +import * as Monaco from 'monaco-editor'; +declare var monaco: typeof Monaco; + +@Component({ + selector: 'app-editor-zone', + templateUrl: './editor-zone.component.html', + styleUrls: ['./editor-zone.component.css'], + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => EditorZoneComponent), + multi: true, + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => EditorZoneComponent), + multi: true, + }, + ], +}) +export class EditorZoneComponent + implements AfterViewInit, OnDestroy, ControlValueAccessor, Validator +{ + constructor(private monacoEditorService: EditorService) {} + + validate(): ValidationErrors { + return !this.parsedError + ? null + : { + monaco: { + value: this.parsedError.split('|'), + }, + }; + } + + get model() { + return this._editor && this._editor.getModel(); + } + + get modelMarkers() { + return ( + this.model && + monaco.editor.getModelMarkers({ + resource: this.model.uri, + }) + ); + } + + writeValue(value: string): void { + this._editorContent = value; + if (this._editor && value) { + this._editor.setValue(value); + } else if (this._editor) { + this._editor.setValue(''); + } + } + + registerOnChange(fn: any): void { + this._propagateChange = fn; + } + + registerOnErrorStatusChange(fn: any): void { + this._onErrorStatusChange = fn; + } + + registerOnTouched(fn: any): void { + this._onTouched = fn; + } + + protected _options; + protected _editorContent: string = ''; + + parsedError: string; + + private _onTouched: () => void = () => {}; + private _onErrorStatusChange: () => void = () => {}; + private _propagateChange: (_: any) => any = () => {}; + + private _editor: Monaco.editor.IStandaloneCodeEditor; + + @Output() editor: EventEmitter<any> = new EventEmitter(); + + @ViewChild('editorContainer', { static: true }) _editorContainer: ElementRef; + + private initMonaco(): void { + if (!this.monacoEditorService.loaded) { + this.monacoEditorService.loadingFinished.pipe(take(1)).subscribe(() => { + this.initMonaco(); + }); + return; + } + + console.log('Creating Editor...'); + + this._editor = monaco.editor.create( + this._editorContainer.nativeElement, + vqlEditorOptions + ); + + const model: Monaco.editor.ITextModel = this._editor.getModel(); + + this.registerEditorListeners(); + this.editor.emit(this._editor); + } + + ngAfterViewInit(): void { + this.initMonaco(); + } + + registerOnChangeCallback(fn: (val: string) => void) { + // Prevent the default context menu from appearing + this._editor.onContextMenu((e) => { + e.event.preventDefault(); + }); + + this._editor.onDidChangeModelContent((event) => { + fn(this._editor.getValue()); + }); + } + + registerValidatorFunction(fn) { + this._editor.onDidChangeModelContent((event) => { + fn(this._editor.getModel()); + }); + } + + registerEditorListeners() { + this._editor.onDidChangeModelContent(() => { + this._propagateChange(this._editor.getValue()); + }); + + this._editor.onDidChangeModelDecorations(() => { + const currentParsedError = this.modelMarkers + .map(({ message }) => message) + .join('|'); + + this.parsedError = currentParsedError; + this._onErrorStatusChange(); + }); + + this._editor.onDidBlurEditorText(() => { + this._onTouched(); + }); + + // Add event listener for ending query with semicolon + this._editor.onDidChangeModelContent((event) => { + const model = this._editor.getModel(); + if (!model) return; + + // if query already has a semicolon do nothing + if (model.getLinesContent().join().includes(';')) return; + + const lineCount = model.getLineCount(); + + // Traverse the lines in reverse order until we find the last non-empty line + let lastNonEmptyLineIndex: number; + for ( + lastNonEmptyLineIndex = lineCount; + lastNonEmptyLineIndex >= 0; + lastNonEmptyLineIndex-- + ) { + // do nothing if not a single line has content + if (lastNonEmptyLineIndex == 0) return; + if (model.getLineContent(lastNonEmptyLineIndex).trim().length > 0) + break; + } + + const appendSemicolonEdit = { + range: new monaco.Range( + lastNonEmptyLineIndex, + model.getLineContent(lastNonEmptyLineIndex).length + 1, + lastNonEmptyLineIndex, + model.getLineContent(lastNonEmptyLineIndex).length + 1 + ), + text: ';', + }; + + // Insert a semicolon at the end of the last line + this._editor.executeEdits( + '', + [appendSemicolonEdit], + [this._editor.getSelection()] + ); + }); + } + + ngOnDestroy() { + if (this._editor) { + this._editor.dispose(); + } + } +} diff --git a/src/frontend/src/app/components/footer/footer.component.css b/src/frontend/src/app/components/footer/footer.component.css new file mode 100644 index 0000000000000000000000000000000000000000..ea9d8cdf121ccf9098c148c69c8891104bd8eb5b --- /dev/null +++ b/src/frontend/src/app/components/footer/footer.component.css @@ -0,0 +1,18 @@ +.footer { + /* background-color: var(--box-background-color); */ + left: 0; + bottom: 0; + position: fixed; + width: 100%; + color:whitesmoke; + font-size: small; + max-height: 20px; + z-index: 6; + border-top: 1px solid #101010; +} + +.footer > .container { + padding-right: 1px; + padding-left: 1px; +} + diff --git a/src/frontend/src/app/components/footer/footer.component.html b/src/frontend/src/app/components/footer/footer.component.html new file mode 100644 index 0000000000000000000000000000000000000000..b77e05448df902ff673b74be551d57c60f947754 --- /dev/null +++ b/src/frontend/src/app/components/footer/footer.component.html @@ -0,0 +1,71 @@ +<footer class="footer bg-dark"> + <div class="d-flex justify-content-between pe-1 ps-1 user-select-none"> + <div> + <ng-container *ngIf="currentTask"> + <div + class="spinner-border spinner-border-sm text-primary" + role="status" + ></div> + <span class="sr-only ps-1">Loading...</span> + + <span class="fw-light"> + ( {{ currentTask.Description | lowercase }} ) + </span> + <span class="fw-light" *ngIf="numberTasks > 1"> + (remaining tasks: {{ numberTasks | number }}) + </span> + <span style="cursor: pointer" *ngIf="isCancelableTask()"> + <i class="bi bi-x text-danger" (click)="cancelCurrentRequest()"></i> + </span> + </ng-container> + </div> + + <span class="d-flex justify-content-end text-secondary"> + <ng-template #backendRunningTooltip> + indicates whether the backend is running: + <br /><i class="text-success bi bi-circle-fill"> + backend is available</i + > + <br /><i class="text-danger bi bi-circle-fill"> + backend is unavailable</i + > + </ng-template> + <a [ngbTooltip]="backendRunningTooltip" triggers="hover" container="body"> + <i *ngIf="isRunning" class="text-success bi bi-circle-fill"></i> + <i *ngIf="!isRunning" class="text-danger bi bi-circle-fill"></i> + </a> + + <div class="vr ms-2 me-2 text-success"></div> + + <a + class="cursor-pointer text-decoration-none" + (click)="restartBackend()" + ngbTooltip="restart backend" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-clockwise"></i> restart backend + </a> + <div class="vr ms-2 me-2"></div> + + <a href="mailto:cortado@fit.fraunhofer.de" class="text-decoration-none" + ><i class="bi bi-question-circle"></i> contact</a + > + + <div class="vr ms-2 me-2"></div> + <a + href="https://cortado.fit.fraunhofer.de/#download" + class="text-decoration-none" + target="_blank" + ngbTooltip="Check for updates" + triggers="hover" + container="body" + >version {{ version }}</a + > + + <div class="vr ms-2 me-2"></div> + powered by + <img src="assets/pm4py-logo.svg" height="20" /> + </span> + </div> +</footer> diff --git a/src/frontend/src/app/components/footer/footer.component.spec.ts b/src/frontend/src/app/components/footer/footer.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..36c31ab3d099f38349ee5218056bca9dc5b3913c --- /dev/null +++ b/src/frontend/src/app/components/footer/footer.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FooterComponent } from './footer.component'; + +describe('FooterComponent', () => { + let component: FooterComponent; + let fixture: ComponentFixture<FooterComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [FooterComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FooterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/footer/footer.component.ts b/src/frontend/src/app/components/footer/footer.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..d99e75a937c1c809936c7de5f46a0fdd5228ca80 --- /dev/null +++ b/src/frontend/src/app/components/footer/footer.component.ts @@ -0,0 +1,87 @@ +import { + Component, + OnInit, + ElementRef, + Inject, + OnDestroy, +} from '@angular/core'; +import { BackgroundTaskInfoService } from '../../services/backgroundTaskInfoService/background-task-info.service'; +import { DOCUMENT } from '@angular/common'; +import { BackendInfoService } from 'src/app/services/backendInfoService/backend-info.service'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { environment } from 'src/environments/environment'; +declare var electron: any; + +@Component({ + selector: 'app-footer', + templateUrl: './footer.component.html', + styleUrls: ['./footer.component.css'], +}) +export class FooterComponent implements OnInit, OnDestroy { + constructor( + private backgroundTaskInfoService: BackgroundTaskInfoService, + private backendInfoService: BackendInfoService, + private _elRef: ElementRef<HTMLElement>, + @Inject(DOCUMENT) private document: Document + ) {} + + currentTask = undefined; + numberTasks = 0; + version = environment.VERSION; + public isRunning: boolean = false; + + private _destroy$ = new Subject(); + + ngOnInit(): void { + this.backgroundTaskInfoService + .currentBackgroundTask$() + .pipe(takeUntil(this._destroy$)) + .subscribe((backgroundTask) => { + this.currentTask = backgroundTask; + }); + + this.backgroundTaskInfoService + .numberBackgroundTasks$() + .pipe(takeUntil(this._destroy$)) + .subscribe((res) => { + this.numberTasks = res; + if (res > 0) { + this.document.getElementById('body').style.cursor = 'progress'; + } else if (res == 0) { + this.document.getElementById('body').style.cursor = ''; + } + }); + + this.backendInfoService + .getIsRunningSubscription() + .pipe(takeUntil(this._destroy$)) + .subscribe((isRunning) => (this.isRunning = isRunning)); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + isCancelableTask(): boolean { + return ( + this.currentTask !== undefined && + this.currentTask.CancellationFunc !== null + ); + } + + cancelCurrentRequest(): void { + if (this.isCancelableTask()) { + this.currentTask.CancellationFunc(); + } + } + + restartBackend(): void { + this.backendInfoService.setRunning(false); + (<any>window).electronAPI.requestRestart(); + } + + get element() { + return this._elRef.nativeElement; + } +} diff --git a/src/frontend/src/app/components/golden-layout-host/LayoutTemplates/golden-layout-cortado-base.ts b/src/frontend/src/app/components/golden-layout-host/LayoutTemplates/golden-layout-cortado-base.ts new file mode 100644 index 0000000000000000000000000000000000000000..da178dcc7168ee05ce30ec1fcf3852d5459f5529 --- /dev/null +++ b/src/frontend/src/app/components/golden-layout-host/LayoutTemplates/golden-layout-cortado-base.ts @@ -0,0 +1,168 @@ +import { + LayoutConfig, + ItemType, + ComponentItemConfig, + StackItemConfig, + RowOrColumnItemConfig, + Side, +} from 'golden-layout'; + +import { ProcessTreeEditorComponent } from '../../process-tree-editor/process-tree-editor.component'; +import { VariantExplorerComponent } from '../../variant-explorer/variant-explorer.component'; +import { ActivityOverviewComponent } from '../../activity-overview/activity-overview.component'; +import { ModelPerformanceComponent } from '../../performance/performance.component'; +import { VariantPerformanceComponent } from '../../variant-performance/variant-performance.component'; +import { ConformanceTabComponent } from '../../conformance-tab/conformance-tab.component'; +import { LpmMetricsTabComponent } from '../../lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component'; +import { environment } from '../../../../environments/environment'; + +let addLpmFeatures = environment.showLpms; + +export const baseLayout: LayoutConfig = { + dimensions: { + borderWidth: 0.75, + borderGrabWidth: 10, + minItemHeight: 10, + minItemWidth: 10, + }, + settings: { + showPopoutIcon: false, + constrainDragToContainer: true, + }, + root: { + type: ItemType.column, + content: [ + { + type: ItemType.row, + height: 61.803, + isClosable: false, + reorderEnabled: false, + id: ProcessTreeEditorComponent.componentName + '_Container_Row', + content: [ + { + type: ItemType.stack, + header: { + show: Side.left, + }, + isClosable: true, + content: [ + { + type: 'component', + title: 'Process Tree Editor', + isClosable: false, + reorderEnabled: false, + id: ProcessTreeEditorComponent.componentName, + componentType: ProcessTreeEditorComponent.componentName, + componentState: { cssParentClass: 'process-tree-editor-stack' }, + } as ComponentItemConfig, + ], + }, + ], + } as RowOrColumnItemConfig, + { + type: ItemType.row, + height: 38.197, + isClosable: true, + content: [ + { + type: ItemType.stack, + height: 38.197, + isClosable: false, + width: 61.803, + id: VariantExplorerComponent.componentName + '_Container_Stack', + content: [ + { + id: VariantExplorerComponent.componentName, + type: 'component', + title: 'Variant Explorer', + isClosable: false, + cssClass: 'highlight', + reorderEnabled: false, + componentType: VariantExplorerComponent.componentName, + componentState: { cssParentClass: 'variant-explorer-stack' }, + } as ComponentItemConfig, + ], + } as StackItemConfig, + { + type: ItemType.stack, + height: 38.197, + isClosable: false, + width: 61.803, + id: ActivityOverviewComponent.componentName + '_Container_Stack', + content: [ + { + type: 'component', + header: { + show: false, + }, + width: 38.197, + isClosable: false, + reorderEnabled: false, + title: 'Activity Overview', + id: ActivityOverviewComponent.componentName, + componentType: ActivityOverviewComponent.componentName, + componentState: { cssParentClass: 'info-box-stack' }, + } as ComponentItemConfig, + { + type: 'component', + header: { + show: false, + }, + width: 38.197, + isClosable: false, + reorderEnabled: true, + title: 'Model Performance', + id: ModelPerformanceComponent.componentName, + componentType: ModelPerformanceComponent.componentName, + componentState: { cssParentClass: 'info-box-stack' }, + } as ComponentItemConfig, + { + type: 'component', + header: { + show: false, + }, + width: 38.197, + isClosable: false, + reorderEnabled: true, + title: 'Variant Performance', + id: VariantPerformanceComponent.componentName, + componentType: VariantPerformanceComponent.componentName, + componentState: { cssParentClass: 'info-box-stack' }, + } as ComponentItemConfig, + { + type: 'component', + header: { + show: false, + }, + width: 38.197, + isClosable: false, + reorderEnabled: true, + title: 'Conformance', + id: ConformanceTabComponent.componentName, + componentType: ConformanceTabComponent.componentName, + componentState: { cssParentClass: 'info-box-stack' }, + } as ComponentItemConfig, + ...(addLpmFeatures + ? [ + { + type: 'component', + header: { + show: false, + }, + width: 38.197, + isClosable: false, + reorderEnabled: true, + title: 'LPM Metrics', + id: LpmMetricsTabComponent.componentName, + componentType: LpmMetricsTabComponent.componentName, + componentState: { cssParentClass: 'info-box-stack' }, + } as ComponentItemConfig, + ] + : []), + ], + } as StackItemConfig, + ], + } as RowOrColumnItemConfig, + ], + } as RowOrColumnItemConfig, +}; diff --git a/src/frontend/src/app/components/golden-layout-host/golden-layout-dummy/golden-layout-dummy.component.css b/src/frontend/src/app/components/golden-layout-host/golden-layout-dummy/golden-layout-dummy.component.css new file mode 100644 index 0000000000000000000000000000000000000000..eeb43aeddaada195dbfa441295158fa8e7285d12 --- /dev/null +++ b/src/frontend/src/app/components/golden-layout-host/golden-layout-dummy/golden-layout-dummy.component.css @@ -0,0 +1,6 @@ +:host { + position: absolute; + width : 100%; + height : 100%; + border-bottom: 1px solid black; +} diff --git a/src/frontend/src/app/components/golden-layout-host/golden-layout-dummy/golden-layout-dummy.component.html b/src/frontend/src/app/components/golden-layout-host/golden-layout-dummy/golden-layout-dummy.component.html new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/golden-layout-host/golden-layout-dummy/golden-layout-dummy.component.spec.ts b/src/frontend/src/app/components/golden-layout-host/golden-layout-dummy/golden-layout-dummy.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..4a1ac7fa6a42820ea976a2a5a63bd868aa1ebe84 --- /dev/null +++ b/src/frontend/src/app/components/golden-layout-host/golden-layout-dummy/golden-layout-dummy.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GoldenLayoutDummyComponent } from './golden-layout-dummy.component'; + +describe('GoldenLayoutDummyComponent', () => { + let component: GoldenLayoutDummyComponent; + let fixture: ComponentFixture<GoldenLayoutDummyComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [GoldenLayoutDummyComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GoldenLayoutDummyComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/golden-layout-host/golden-layout-dummy/golden-layout-dummy.component.ts b/src/frontend/src/app/components/golden-layout-host/golden-layout-dummy/golden-layout-dummy.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..43cf21a9f57951c786058fa6a1a55bfee0d642a1 --- /dev/null +++ b/src/frontend/src/app/components/golden-layout-host/golden-layout-dummy/golden-layout-dummy.component.ts @@ -0,0 +1,44 @@ +import { + Component, + ChangeDetectionStrategy, + Renderer2, + Inject, + ElementRef, +} from '@angular/core'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; + +@Component({ + selector: 'app-golden-layout-dummy', + templateUrl: './golden-layout-dummy.component.html', + styleUrls: ['./golden-layout-dummy.component.css'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class GoldenLayoutDummyComponent extends LayoutChangeDirective { + constructor( + private renderer: Renderer2, + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef + ) { + super(elRef.nativeElement, renderer); + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + + handleVisibilityChange(visibility: boolean): void {} + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} +} + +export namespace GoldenLayoutDummyComponent { + export const componentName = 'GoldenLayoutDummyComponent'; +} diff --git a/src/frontend/src/app/components/golden-layout-host/golden-layout-host.component.css b/src/frontend/src/app/components/golden-layout-host/golden-layout-host.component.css new file mode 100644 index 0000000000000000000000000000000000000000..f3d5caa652842a978de253c8a496b356b522b199 --- /dev/null +++ b/src/frontend/src/app/components/golden-layout-host/golden-layout-host.component.css @@ -0,0 +1,5 @@ +:host { + height: 100%; + width: 100%; + position: relative; +} diff --git a/src/frontend/src/app/components/golden-layout-host/golden-layout-host.component.html b/src/frontend/src/app/components/golden-layout-host/golden-layout-host.component.html new file mode 100644 index 0000000000000000000000000000000000000000..219653d325c2b1e95b7737ade5ac9791d752e218 --- /dev/null +++ b/src/frontend/src/app/components/golden-layout-host/golden-layout-host.component.html @@ -0,0 +1 @@ +<ng-template #componentViewContainer></ng-template> diff --git a/src/frontend/src/app/components/golden-layout-host/golden-layout-host.component.spec.ts b/src/frontend/src/app/components/golden-layout-host/golden-layout-host.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..456fbaaa08e8eedea799889da3065a0c6ffd31f4 --- /dev/null +++ b/src/frontend/src/app/components/golden-layout-host/golden-layout-host.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GoldenLayoutHostComponent } from './golden-layout-host.component'; + +describe('GoldenLayoutHostComponent', () => { + let component: GoldenLayoutHostComponent; + let fixture: ComponentFixture<GoldenLayoutHostComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [GoldenLayoutHostComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GoldenLayoutHostComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/golden-layout-host/golden-layout-host.component.ts b/src/frontend/src/app/components/golden-layout-host/golden-layout-host.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..6bf9769c6d6c0f6aa3c33ea22070a6dbc3da08db --- /dev/null +++ b/src/frontend/src/app/components/golden-layout-host/golden-layout-host.component.ts @@ -0,0 +1,430 @@ +import { VariantMinerComponent } from './../variant-miner/variant-miner.component'; +import { GoldenLayoutDummyComponent } from './golden-layout-dummy/golden-layout-dummy.component'; +import { + Component, + ComponentRef, + ElementRef, + OnDestroy, + Renderer2, + ViewChild, + ViewContainerRef, +} from '@angular/core'; +import { + ComponentContainer, + GoldenLayout, + LogicalZIndex, + ResolvedComponentItemConfig, + Stack, +} from 'golden-layout'; + +import { baseLayout } from './LayoutTemplates/golden-layout-cortado-base'; +import { ProcessTreeEditorComponent } from '../process-tree-editor/process-tree-editor.component'; +import { VariantExplorerComponent } from '../variant-explorer/variant-explorer.component'; +import { ActivityOverviewComponent } from '../activity-overview/activity-overview.component'; +import { SubvariantExplorerComponent } from '../variant-explorer/subvariant-explorer/subvariant-explorer.component'; +import { VariantInfoExplorerComponent } from '../variant-explorer/variant-info-explorer/variant-info-explorer.component'; +import { CaseExplorerComponent } from '../variant-explorer/case-explorer/case-explorer.component'; +import { + findContentItemByUniqueID, + GoldenLayoutComponentService, +} from '../../services/goldenLayoutService/golden-layout-component.service'; +import { BpmnEditorComponent } from '../bpmn-editor/bpmn-editor.component'; +import { VariantModelerComponent } from '../variant-modeler/variant-modeler.component'; +import { InfoBoxComponent } from '../info-box/info-box.component'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; + +import { ModelPerformanceComponent } from '../performance/performance.component'; +import { VariantPerformanceComponent } from '../variant-performance/variant-performance.component'; +import { ConformanceTabComponent } from '../conformance-tab/conformance-tab.component'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { VariantViewModeService } from 'src/app/services/viewModeServices/variant-view-mode.service'; +import { LpmExplorerComponent } from '../lpm-explorer/lpm-explorer.component'; +import { LpmMetricsTabComponent } from '../lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component'; +@Component({ + selector: 'app-golden-layout-host', + templateUrl: './golden-layout-host.component.html', + styleUrls: ['./golden-layout-host.component.css'], +}) +export class GoldenLayoutHostComponent implements OnDestroy { + private _goldenLayout: GoldenLayout; + private _goldenLayoutElement: HTMLElement; + private _componentRefMap = new Map< + ComponentContainer, + ComponentRef<LayoutChangeDirective> + >(); + + private _collapsedComponentContainers: Set<ComponentContainer> = + new Set<ComponentContainer>(); + private _goldenLayoutBoundingClientRect: DOMRect = new DOMRect(); + + private _goldenLayoutBindComponentEventListener = ( + container: ComponentContainer, + itemConfig: ResolvedComponentItemConfig + ) => this.handleBindComponentEvent(container, itemConfig); + + private _goldenLayoutUnbindComponentEventListener = ( + container: ComponentContainer + ) => this.handleUnbindComponentEvent(container); + + @ViewChild('componentViewContainer', { read: ViewContainerRef, static: true }) + private _componentViewContainerRef: ViewContainerRef; + + get goldenLayout() { + return this._goldenLayout; + } + + constructor( + private _elRef: ElementRef<HTMLElement>, + private renderer: Renderer2, + private goldenLayoutComponentService: GoldenLayoutComponentService, + private variantViewModeService: VariantViewModeService + ) { + // Get the Layout Host Component + this._goldenLayoutElement = this._elRef.nativeElement; + + // Register Components to the Layout Template Host + this.goldenLayoutComponentService.registerComponentType( + ProcessTreeEditorComponent.componentName, + ProcessTreeEditorComponent + ); + this.goldenLayoutComponentService.registerComponentType( + ActivityOverviewComponent.componentName, + ActivityOverviewComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + VariantPerformanceComponent.componentName, + VariantPerformanceComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + ModelPerformanceComponent.componentName, + ModelPerformanceComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + ConformanceTabComponent.componentName, + ConformanceTabComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + InfoBoxComponent.componentName, + InfoBoxComponent + ); + this.goldenLayoutComponentService.registerComponentType( + SubvariantExplorerComponent.componentName, + SubvariantExplorerComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + VariantInfoExplorerComponent.componentName, + VariantInfoExplorerComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + CaseExplorerComponent.componentName, + CaseExplorerComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + VariantMinerComponent.componentName, + VariantMinerComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + VariantExplorerComponent.componentName, + VariantExplorerComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + BpmnEditorComponent.componentName, + BpmnEditorComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + GoldenLayoutDummyComponent.componentName, + GoldenLayoutDummyComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + VariantModelerComponent.componentName, + VariantModelerComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + LpmExplorerComponent.componentName, + LpmExplorerComponent + ); + + this.goldenLayoutComponentService.registerComponentType( + LpmMetricsTabComponent.componentName, + LpmMetricsTabComponent + ); + + this._goldenLayout = new GoldenLayout( + this._goldenLayoutElement, + this._goldenLayoutBindComponentEventListener, + this._goldenLayoutUnbindComponentEventListener + ); + + this._goldenLayout.beforeVirtualRectingEvent = () => + this.handleBeforeVirtualRectingEvent(); + + this.goldenLayoutComponentService.goldenLayout = this.goldenLayout; + this.goldenLayoutComponentService.goldenLayoutHostComponent = this; + + this.variantViewModeService.viewMode$.subscribe((viewMode) => { + this.reactOnViewModeChange(viewMode); + }); + } + + initializeLayout() { + // Start rendering the Template + this.goldenLayout.loadLayout(baseLayout); + } + + ngOnDestroy() { + this._goldenLayout.destroy(); + } + + setSize(width: number, height: number) { + this._goldenLayout.setSize(width, height); + } + + getComponentRef(container: ComponentContainer) { + return this._componentRefMap.get(container); + } + + private handleBindComponentEvent( + container: ComponentContainer, + itemConfig: ResolvedComponentItemConfig + ): ComponentContainer.BindableComponent { + const componentType = itemConfig.componentType; + const componentRef = this.goldenLayoutComponentService.createComponent( + componentType, + container + ); + + const component = componentRef.instance; + this._componentRefMap.set(container, componentRef); + + container.virtualRectingRequiredEvent = (container, width, height) => + this.handleContainerVirtualRectingRequiredEvent(container, width, height); + container.virtualVisibilityChangeRequiredEvent = (container, visible) => + this.handleContainerVisibilityChangeRequiredEvent(container, visible); + container.virtualZIndexChangeRequiredEvent = ( + container, + logicalZIndex, + defaultZIndex + ) => + this.handleContainerVirtualZIndexChangeRequiredEvent( + container, + logicalZIndex, + defaultZIndex + ); + + if (itemConfig.componentState['cssParentClass']) { + this.renderer.addClass( + container.parent.parentItem.element, + itemConfig.componentState['cssParentClass'] + ); + } + + if (itemConfig.componentState['cssContainerClass']) { + this.renderer.addClass( + container.element, + itemConfig.componentState['cssContainerClass'] + ); + } + + this._componentViewContainerRef.insert(componentRef.hostView); + + return { + component, + virtual: true, + }; + } + + private handleUnbindComponentEvent(container: ComponentContainer) { + const componentRef = this._componentRefMap.get(container); + if (componentRef === undefined) { + throw new Error('Could not unbind component. Container not found'); + } + this._componentRefMap.delete(container); + + const hostView = componentRef.hostView; + const viewRefIndex = this._componentViewContainerRef.indexOf(hostView); + if (viewRefIndex < 0) { + throw new Error('Could not unbind component. ViewRef not found'); + } + + this._componentViewContainerRef.remove(viewRefIndex); + componentRef.destroy(); + } + + private handleBeforeVirtualRectingEvent() { + this._goldenLayoutBoundingClientRect = + this._goldenLayoutElement.getBoundingClientRect(); + } + + private handleContainerVirtualRectingRequiredEvent( + container: ComponentContainer, + width: number, + height: number + ) { + const containerBoundingClientRect = + container.element.getBoundingClientRect(); + const left = + containerBoundingClientRect.left - + this._goldenLayoutBoundingClientRect.left; + const top = + containerBoundingClientRect.top - + this._goldenLayoutBoundingClientRect.top; + + const componentRef = this._componentRefMap.get(container); + if (componentRef === undefined) { + throw new Error( + 'handleContainerVirtualRectingRequiredEvent: ComponentRef not found' + ); + } + + const parent = container.parent; + const grand_parent = parent.parent; + const grand_parent_children_elements = grand_parent.element.children; + const component = componentRef.instance; + + if (width < 250 || height < 150) { + for (let i = 0; i < grand_parent_children_elements.length; i++) { + this.renderer.setStyle( + grand_parent_children_elements[i], + 'visibility', + 'hidden' + ); + } + + component.setVisibility(false); + component.handleVisibilityChange(false); + + this.renderer.addClass( + grand_parent.element, + 'collapsed-golden-layout-container' + ); + + if (width < 150) { + this.renderer.addClass(grand_parent.element, 'vertical-dots'); + } else { + this.renderer.addClass(grand_parent.element, 'horizontal-dots'); + } + + this._collapsedComponentContainers.add(container); + } else if (this._collapsedComponentContainers.has(container)) { + this._collapsedComponentContainers.delete(container); + + component.setVisibility(true); + component.handleVisibilityChange(true); + + for (let i = 0; i < grand_parent_children_elements.length; i++) { + this.renderer.removeStyle( + grand_parent_children_elements[i], + 'visibility' + ); + } + + this._componentRefMap.get(container).instance.setVisibility(true); + this.renderer.removeClass( + grand_parent.element, + 'collapsed-golden-layout-container' + ); + + this.renderer.removeClass(grand_parent.element, 'vertical-dots'); + this.renderer.removeClass(grand_parent.element, 'horizontal-dots'); + } + + component.setPositionAndSize(left, top, width, height); + component.handleResponsiveChange(left, top, width, height); + } + + private handleContainerVisibilityChangeRequiredEvent( + container: ComponentContainer, + visible: boolean + ) { + const componentRef = this._componentRefMap.get(container); + if (componentRef === undefined) { + throw new Error( + 'handleContainerVisibilityChangeRequiredEvent: ComponentRef not found' + ); + } + + const component = componentRef.instance; + + component.setVisibility(visible); + component.handleVisibilityChange(visible); + } + + private handleContainerVirtualZIndexChangeRequiredEvent( + container: ComponentContainer, + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ) { + const componentRef = this._componentRefMap.get(container); + if (componentRef === undefined) { + throw new Error( + 'handleContainerVirtualZIndexChangeRequiredEvent: ComponentRef not found' + ); + } + + const component = componentRef.instance; + component.setZIndex(defaultZIndex); + component.handleZIndexChange(logicalZIndex, defaultZIndex); + + if (logicalZIndex === 'base') { + // Triggers a Redraw, to prevent faulty rendering after minimization + this.goldenLayout.setSize( + this.goldenLayout.width + 4, + this.goldenLayout.height + 4 + ); + this.goldenLayout.setSize( + this.goldenLayout.width - 4, + this.goldenLayout.height - 4 + ); + } + } + + reactOnViewModeChange(viewMode: ViewMode) { + if (this.goldenLayout.rootItem) { + const stackItem = findContentItemByUniqueID( + ActivityOverviewComponent.componentName + '_Container_Stack', + this.goldenLayout.rootItem + ) as Stack; + + switch (viewMode) { + case ViewMode.PERFORMANCE: + stackItem.setActiveComponentItem( + this.goldenLayout.findFirstComponentItemById( + VariantPerformanceComponent.componentName + ), + true + ); + break; + + case ViewMode.CONFORMANCE: + stackItem.setActiveComponentItem( + this.goldenLayout.findFirstComponentItemById( + ConformanceTabComponent.componentName + ), + true + ); + break; + + default: + stackItem.setActiveComponentItem( + this.goldenLayout.findFirstComponentItemById( + ActivityOverviewComponent.componentName + ), + true + ); + break; + } + } + } +} diff --git a/src/frontend/src/app/components/header-bar/header-bar.component.css b/src/frontend/src/app/components/header-bar/header-bar.component.css new file mode 100644 index 0000000000000000000000000000000000000000..044b0fbf0c07f399b6b564ce83fb6c888fa6942e --- /dev/null +++ b/src/frontend/src/app/components/header-bar/header-bar.component.css @@ -0,0 +1,76 @@ +.header-bar { + /* background-color: var(--box-background-color) !important; */ + color: whitesmoke; + font-size: small; + position: fixed; + width: 100%; + height: var(--header-bar-height); + border-bottom: 1px solid var(--thin-border-color); + -webkit-app-region: drag; + user-select: none; + z-index: 50; + top: 0; + left: 0; + display: flex; + align-items: center; +} + +.ps { + margin-left: 20px; +} + +.cortado-icon { + height: var(--header-bar-height); + width: 20px; + padding: calc(4px + (var(--header-bar-height) - 20px) / 2) 4px; +} + +.button { + -webkit-app-region: no-drag; + width: 100%; + text-align: left; +} + +.header-button { + height: var(--header-bar-height); + -webkit-app-region: no-drag; + color: whitesmoke; + padding: 2px 12px; + font-size: small; +} + +.dropright-header { + display: inline-block; + margin-right: 65px; +} + +.button:hover:enabled { + background-color: #4d4e50; +} + +.drop-down-button:hover:enabled { + background-color: #c7c9cc; +} + +.btn-icon { + margin-left: 6px; + margin-right: 6px; +} + +.tool-bar-drop { + background-color: var(--box-background-color); + z-index: 100; + border-radius: 0; +} + +.tool-bar-dropdown { + transform: translate(0, 22px) !important; +} + +.icon { + font-size: 12px; +} + +.bi-diagram-2.rotate-270::before { + transform: rotate(270deg); +} diff --git a/src/frontend/src/app/components/header-bar/header-bar.component.html b/src/frontend/src/app/components/header-bar/header-bar.component.html new file mode 100644 index 0000000000000000000000000000000000000000..f06c6307b3804935b05be633248fe90369504a0f --- /dev/null +++ b/src/frontend/src/app/components/header-bar/header-bar.component.html @@ -0,0 +1,252 @@ +<div class="bg-dark header-bar"> + <span class="ps"></span> + <div class="dropdown"> + <button + class="button header-button" + data-bs-auto-close="outside" + type="button" + id="Files" + data-bs-toggle="dropdown" + aria-expanded="false" + > + Files + </button> + <ul + class="dropdown-menu tool-bar-drop tool-bar-dropdown" + aria-labelledby="Files" + > + <li> + <button class="button align-bottom" (click)="importEventLog()"> + <div> + <i class="bi bi-upload btn-icon"></i> + <span><b>Import</b> event log</span> + </div> + </button> + </li> + <li> + <button class="button align-bottom" (click)="importTreeFromPTML()"> + <div> + <i class="bi bi-file-earmark-arrow-up btn-icon"></i> + <span + ><b>Import</b> process tree (<samp class="text-primary fw-bold" + >.ptml</samp + >)</span + > + </div> + </button> + </li> + <li><hr class="dropdown-divider" /></li> + <li> + <button class="button align-bottom" (click)="exportTreeAsPTML()"> + <div> + <i class="bi bi-file-earmark-arrow-down-fill btn-icon"></i> + <span + ><b>Export</b> model as Process tree (<samp + class="text-primary fw-bold" + >.ptml</samp + >)</span + > + </div> + </button> + </li> + + <li> + <button class="button align-bottom" (click)="exportTreeAsPNML()"> + <div> + <i class="bi bi-file-earmark-arrow-down-fill btn-icon"></i> + <span + ><b>Export</b> model as Petri net (<samp + class="text-primary fw-bold" + >.pnml</samp + >)</span + > + </div> + </button> + </li> + + <li> + <button class="button align-bottom" (click)="exportTreeAsBPMN()"> + <div> + <i class="bi bi-file-earmark-arrow-down-fill btn-icon"></i> + <span + ><b>Export</b> model as BPMN (<samp class="text-primary fw-bold" + >.bpmn</samp + >)</span + > + </div> + </button> + </li> + <li> + <button class="button align-bottom" (click)="showLogExporter()"> + <div> + <i class="bi bi-file-earmark-arrow-down-fill btn-icon"></i> + <span + ><b>Export</b> Log as XES (<samp class="text-primary fw-bold" + >.xes</samp + >)</span + > + </div> + </button> + </li> + <li><hr class="dropdown-divider" /></li> + <li> + <button class="button align-bottom" (click)="loadProject()"> + <div> + <i class="bi bi-upload btn-icon"></i> + <span + ><b>Load</b> project (<samp class="text-primary fw-bold" + >.json</samp + >)</span + > + </div> + </button> + </li> + <li> + <button class="button align-bottom" (click)="saveProject()"> + <div> + <i class="bi bi-download btn-icon"></i> + <span + ><b>Save</b> project (<samp class="text-primary fw-bold" + >.json</samp + >)</span + > + </div> + </button> + </li> + </ul> + </div> + <div class="dropdown"> + <button class="button header-button" (click)="showSettingsDialog()"> + Settings + </button> + </div> + + <div class="dropdown"> + <button + class="button header-button" + type="button" + id="Editors" + data-bs-toggle="dropdown" + aria-expanded="false" + > + Editors + </button> + <ul + class="dropdown-menu tool-bar-drop tool-bar-dropdown" + aria-labelledby="Files" + > + <li> + <button class="button align-bottom" (click)="openProcessTreeEditor()"> + <div> + <i class="bi bi-diagram-2 btn-icon"></i> + <span><b>Open</b> Process Tree Editor</span> + </div> + </button> + </li> + <li> + <button class="button align-bottom" (click)="openBPMNViewer()"> + <div> + <i class="bi bi-diagram-2 btn-icon rotate-270"></i> + <span><b>Open</b> BPMN Viewer</span> + </div> + </button> + </li> + <li> + <button class="button align-bottom" (click)="openVariantModeler()"> + <div> + <i class="bi bi-tools btn-icon"></i> + <span> <b>Open</b> Variant Modeler </span> + </div> + </button> + </li> + <li> + <button class="button align-bottom" (click)="openVariantMiner()"> + <div> + <i class="bi bi-minecart btn-icon"></i> + <span> <b>Open</b> Variant Miner </span> + </div> + </button> + </li> + </ul> + </div> + + <div class="dropdown"> + <button class="button header-button" (click)="showDocumentationDialog()"> + Documentation + </button> + </div> + + <input + #fileUploadEventLog + type="file" + class="d-none" + (change)="handleSelectedEventLogFile($event, false)" + accept=".xes" + /> + + <input + #fileUploadProcessTree + type="file" + class="d-none" + (change)="handleSelectedProcessTreeFile($event)" + accept=".ptml" + /> + + <input + #fileUploadProject + type="file" + class="d-none" + (change)="handleSelectedProjectFile($event)" + accept=".json" + /> + <input + #fileUploadEventLogRetry + type="file" + class="d-none" + (change)="handleSelectedEventLogFile($event, true)" + accept=".xes" + /> +</div> + +<app-settings [showSettings]="showSettingsEvent.asObservable()"></app-settings> +<app-documentation + [showDocumentation]=" + documentationService.showDocumentationEvent.asObservable() + " +></app-documentation> + +<ng-template let-modal #eventLogSelectionRetryModal> + <div class="modal-header h-line-modal-bottom"> + <h4 class="modal-title text-light" id="modal-basic-title"> + Select new event log path + </h4> + <button + type="button" + class="btn-close btn-close-white" + aria-label="Close" + (click)="modal.dismiss('Cross click')" + ></button> + </div> + <div class="modal-body text-light"> + The path of the event log + <code>{{ oldEventLogPath.split("/").pop() }}</code> has changed. You need to + select a new path to this event log. + </div> + <div class="modal-footer h-line-modal-top"> + <button + type="button" + class="btn btn-outline-secondary" + (click)="modal.close()" + > + Cancel + </button> + <button + type="button" + class="btn btn-success" + ngbAutofocus + (click)="importEventLog(); modal.close()" + > + Select new path + </button> + </div> +</ng-template> diff --git a/src/frontend/src/app/components/header-bar/header-bar.component.spec.ts b/src/frontend/src/app/components/header-bar/header-bar.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..4021897fee46bde2680e696fca53be9952472975 --- /dev/null +++ b/src/frontend/src/app/components/header-bar/header-bar.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HeaderBarComponent } from './header-bar.component'; + +describe('HeaderBarComponent', () => { + let component: HeaderBarComponent; + let fixture: ComponentFixture<HeaderBarComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HeaderBarComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(HeaderBarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/header-bar/header-bar.component.ts b/src/frontend/src/app/components/header-bar/header-bar.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..28a6282eecbec6f872a320292682391184a13d36 --- /dev/null +++ b/src/frontend/src/app/components/header-bar/header-bar.component.ts @@ -0,0 +1,347 @@ +import { VariantMinerComponent } from './../variant-miner/variant-miner.component'; +import { VariantModelerComponent } from './../variant-modeler/variant-modeler.component'; +import { ProcessTreeEditorComponent } from './../process-tree-editor/process-tree-editor.component'; +import { BpmnEditorComponent } from './../bpmn-editor/bpmn-editor.component'; +import { GoldenLayoutComponentService } from 'src/app/services/goldenLayoutService/golden-layout-component.service'; +import { Component, ElementRef, OnDestroy, ViewChild } from '@angular/core'; +import { Subject } from 'rxjs'; +import { environment } from '../../../environments/environment'; +import { BackendService } from '../../services/backendService/backend.service'; +import { ComponentItemConfig, LayoutManager, Side } from 'golden-layout'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { ProjectService } from 'src/app/services/projectService/project.service'; +import { takeUntil } from 'rxjs/operators'; +import { Modal } from 'bootstrap'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { LoadingOverlayService } from 'src/app/services/loadingOverlayService/loading-overlay.service'; +import { DocumentationService } from '../documentation/documentation.service'; +import { VariantViewModeService } from 'src/app/services/viewModeServices/variant-view-mode.service'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { LogExportService } from 'src/app/services/logExportService/log-export.service'; + +@Component({ + selector: 'app-header-bar', + templateUrl: './header-bar.component.html', + styleUrls: ['./header-bar.component.css'], +}) +export class HeaderBarComponent implements OnDestroy { + @ViewChild('fileUploadEventLog') fileUploadEventLog: ElementRef; + @ViewChild('fileUploadProcessTree') fileUploadProcessTree: ElementRef; + @ViewChild('fileUploadProject') fileUploadProject: ElementRef; + @ViewChild('fileUploadEventLogRetry') fileUploadEventLogRetry: ElementRef; + @ViewChild('eventLogSelectionRetryModal') + eventLogSelectionRetryModal: ElementRef; + + public exportVariant = ExportVariant; + showSettingsEvent: Subject<void> = new Subject<void>(); + + public oldEventLogPath: string; + + private _destroy$ = new Subject(); + + constructor( + public variantService: VariantService, + private backendService: BackendService, + private projectService: ProjectService, + public variantViewModeService: VariantViewModeService, + private modalService: NgbModal, + private loadingOverlayService: LoadingOverlayService, + private _elRef: ElementRef<HTMLElement>, + private goldenLayoutComponentService: GoldenLayoutComponentService, + public documentationService: DocumentationService, + private logExportService: LogExportService + ) { + this.backendService.retryEventLogSelection + .pipe(takeUntil(this._destroy$)) + .subscribe((oldPath: string) => { + this.oldEventLogPath = oldPath; + this.modalService.open(this.eventLogSelectionRetryModal); + }); + } + + public VM = ViewMode; + + ngOnDestroy(): void { + this._destroy$.next(); + } + + get element() { + return this._elRef.nativeElement; + } + + importEventLog(): void { + this.fileUploadEventLog.nativeElement.click(); + } + + handleSelectedEventLogFile(e, isRetry = false): void { + const fileList: FileList = e.target.files; + if (fileList.length > 0) { + const backendCall = !environment.electron + ? this.backendService.uploadEventLog(fileList[0]) + : this.backendService.loadEventLogFromFilePath(fileList[0]['path']); + this.loadingOverlayService.showLoader( + 'Importing event log (for large logs this can take up to several minutes)' + ); + backendCall.subscribe(() => { + this.loadingOverlayService.hideLoader(); + }); + } + + // reset form + if (isRetry) this.fileUploadEventLogRetry.nativeElement.value = ''; + else this.fileUploadEventLog.nativeElement.value = ''; + } + + handleSelectedProcessTreeFile(e): void { + const fileList: FileList = e.target.files; + if (fileList.length > 0) { + if (environment.electron) { + this.backendService.loadProcessTreeFromFilePath(fileList[0]['path']); + } else { + this.backendService.loadProcessTreeFromFile(fileList[0]); + } + } + this.fileUploadProcessTree.nativeElement.value = ''; + } + + exportTreeAsPTML(): void { + this.backendService.downloadCurrentTreeAsPTML(); + } + + exportTreeAsPNML(): void { + this.backendService.downloadCurrentTreeAsPNML(); + } + + exportTreeAsBPMN(): void { + this.backendService.downloadCurrentTreeAsBPMN(); + } + + importTreeFromPTML(): void { + this.fileUploadProcessTree.nativeElement.click(); + } + + showSettingsDialog(): void { + this.showSettingsEvent.next(); + } + + showDocumentationDialog(): void { + this.documentationService.showDocumentationDialog(); + } + + showLogExporter(): void { + this.logExportService.showLogExportDialog(); + } + + /* Handle Electron Window Behavior via IPC messages + toggleHide(): void{ + this.ipc.send('maximize-window') + } + + toggleMaximization(): void { + this.ipc.send('maximize-window') + } + + closeApp(): void { + this.ipc.send('maximize-window') + } + */ + + openBPMNViewer() { + const componentID = BpmnEditorComponent.componentName; + const parentComponentID = ProcessTreeEditorComponent.componentName; + + const LocationSelectors: LayoutManager.LocationSelector[] = [ + { + typeId: LayoutManager.LocationSelector.TypeId.FocusedStack, + index: undefined, + }, + ]; + + const itemConfig: ComponentItemConfig = { + id: componentID, + type: 'component', + title: 'BPMN Editor', + isClosable: true, + reorderEnabled: true, + header: { + show: Side.left, + }, + componentType: componentID, + componentState: { cssParentClass: 'bpmn-viewer-stack' }, + }; + + this.goldenLayoutComponentService.openWindow( + componentID, + parentComponentID, + LocationSelectors, + itemConfig + ); + } + + openProcessTreeEditor() { + const componentID = ProcessTreeEditorComponent.componentName; + + const LocationSelectors: LayoutManager.LocationSelector[] = [ + { + typeId: LayoutManager.LocationSelector.TypeId.FirstRow, + index: undefined, + }, + ]; + + const itemConfig: ComponentItemConfig = { + id: componentID, + type: 'component', + title: 'BPMN Editor', + isClosable: false, + reorderEnabled: false, + header: { + show: Side.left, + }, + componentType: componentID, + componentState: { cssParentClass: 'process-tree-editor-stack' }, + }; + + this.goldenLayoutComponentService.openWindow( + componentID, + null, + LocationSelectors, + itemConfig + ); + } + + openVariantMiner() { + const componentID = VariantMinerComponent.componentName; + const parentComponentID = ProcessTreeEditorComponent.componentName; + + const LocationSelectors: LayoutManager.LocationSelector[] = [ + { + typeId: LayoutManager.LocationSelector.TypeId.FocusedStack, + index: undefined, + }, + ]; + + const itemConfig: ComponentItemConfig = { + id: componentID, + type: 'component', + title: 'Variant Miner', + isClosable: true, + reorderEnabled: true, + header: { + show: Side.left, + }, + componentType: componentID, + }; + + this.goldenLayoutComponentService.openWindow( + componentID, + parentComponentID, + LocationSelectors, + itemConfig + ); + } + + openVariantModeler() { + const componentID = VariantModelerComponent.componentName; + + const LocationSelectors: LayoutManager.LocationSelector[] = [ + { + typeId: LayoutManager.LocationSelector.TypeId.FocusedStack, + index: undefined, + }, + ]; + + const itemConfig: ComponentItemConfig = { + id: componentID, + type: 'component', + title: 'Variant Modeler', + isClosable: true, + reorderEnabled: true, + header: { + show: Side.left, + }, + componentType: componentID, + componentState: { cssParentClass: 'variant-modeler-stack' }, + }; + + this.goldenLayoutComponentService.openWindow( + componentID, + ProcessTreeEditorComponent.componentName, + LocationSelectors, + itemConfig + ); + } + + exportVariantsAsLog(type: ExportVariant) { + const variant = this.variantService.variants; + switch (type) { + case ExportVariant.ALL: + this.backendService.exportEventLogFromLog(variant.map((v) => v.bid)); + break; + + case ExportVariant.FITTING: + this.backendService.exportEventLogFromLog( + variant + .filter((v) => { + return v.deviations == 0; + }) + .map((v) => v.bid) + ); + break; + + case ExportVariant.NONFITTING: + this.backendService.exportEventLogFromLog( + variant + .filter((v) => { + return v.deviations > 0; + }) + .map((v) => v.bid) + ); + break; + + case ExportVariant.SELECTED: + this.backendService.exportEventLogFromLog( + variant + .filter((v) => { + return v.isSelected; + }) + .map((v) => v.bid) + ); + break; + + case ExportVariant.DISPLAYED: + this.backendService.exportEventLogFromLog( + variant + .filter((v) => { + return v.isDisplayed; + }) + .map((v) => v.bid) + ); + break; + } + } + + public loadProject() { + this.fileUploadProject.nativeElement.click(); + } + + public saveProject() { + this.projectService.saveProject(); + } + + handleSelectedProjectFile(e): void { + const fileList: FileList = e.target.files; + if (fileList.length > 0) { + this.projectService.loadProjectFromFile(fileList[0]); + } + // reset form + this.fileUploadProject.nativeElement.value = ''; + } +} + +export enum ExportVariant { + ALL = 1, + FITTING = 2, + NONFITTING = 3, + SELECTED = 4, + DISPLAYED = 5, +} diff --git a/src/frontend/src/app/components/info-box/info-box.component.html b/src/frontend/src/app/components/info-box/info-box.component.html new file mode 100644 index 0000000000000000000000000000000000000000..d89c56f2c2d883e5359126257121306c0b795045 --- /dev/null +++ b/src/frontend/src/app/components/info-box/info-box.component.html @@ -0,0 +1,102 @@ +<div class="info-box"> + <ul class="nav nav-tabs bg-dark btn-tool-bar" id="myTab" role="tablist"> + <li class="nav-item" role="presentation"> + <button + class="nav-link active button" + id="activities-tab" + data-bs-toggle="tab" + data-bs-target="#activities" + type="button" + role="tab" + aria-controls="activities" + aria-selected="true" + > + Activities + </button> + </li> + <li class="nav-item" role="presentation"> + <button + class="nav-link button" + id="tree-performance-tab" + data-bs-toggle="tab" + data-bs-target="#tree-performance" + type="button" + role="tab" + aria-controls="tree-performance" + aria-selected="false" + > + Model Performance + </button> + </li> + <li class="nav-item" role="presentation"> + <button + class="nav-link button" + id="variant-performance-tab" + data-bs-toggle="tab" + data-bs-target="#variant-performance" + type="button" + role="tab" + aria-controls="variant-performance" + aria-selected="false" + > + Variant Performance + </button> + </li> + <li class="nav-item" role="presentation"> + <button + class="nav-link button" + id="lpm-metrics-tab" + data-bs-toggle="tab" + data-bs-target="#lpm-metrics" + type="button" + role="tab" + aria-controls="lpm-metrics" + aria-selected="false" + > + LPM Metrics + </button> + </li> + </ul> + <div class="tab-content" id="myTabContent"> + <div + class="tab-pane fade show active" + id="activities" + role="tabpanel" + aria-labelledby="activities-tab" + > + <app-activity-overview + style="width: 100%; max-height: 100%" + ></app-activity-overview> + </div> + <div + class="tab-pane fade" + id="tree-performance" + role="tabpanel" + aria-labelledby="tree-performance-tab" + > + <app-performance class="mh-100" style="width: 100%"></app-performance> + </div> + <div + class="tab-pane fade" + id="variant-performance" + role="tabpanel" + aria-labelledby="variant-performance-tab" + > + <app-variant-performance + class="mh-100" + style="width: 100%" + ></app-variant-performance> + </div> + <div + class="tab-pane fade" + id="lpm-metrics" + role="tabpanel" + aria-labelledby="lpm-metrics-tab" + > + <app-lpm-metrics-tab + class="mh-100" + style="width: 100%" + ></app-lpm-metrics-tab> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/info-box/info-box.component.scss b/src/frontend/src/app/components/info-box/info-box.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..c2ba965122849904143be355cc8e49861344c303 --- /dev/null +++ b/src/frontend/src/app/components/info-box/info-box.component.scss @@ -0,0 +1,48 @@ +:host { + position: absolute; + overflow: hidden; + color: whitesmoke; + border-left:1px solid black; +} + +.btn-tool-bar{ + border-top : 0; +} + +.nav-tabs { + border-bottom: none; + padding-left: 5px; + padding-right: 5px; + height: 28px; +} + +.tab-content { + overflow: auto; + display: flex; + flex-direction: column; +} + +.tab-pane { + max-height: 100%; +} + +.nav-link { + border: none; + background-color: transparent !important; + color: #495057; + + &.active { + background-color: none; + border-bottom: 1px solid whitesmoke; + color: whitesmoke + } +} + +.info-box { + display: flex; + flex-direction: column; + height: 100%; + background-color: var(--box-background-color); + + // border-left: 1px solid var(--thin-border-color); +} diff --git a/src/frontend/src/app/components/info-box/info-box.component.spec.ts b/src/frontend/src/app/components/info-box/info-box.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..1d4986f5f16b5fe4f9394c3d2251fe12862c0f6c --- /dev/null +++ b/src/frontend/src/app/components/info-box/info-box.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InfoBoxComponent } from './info-box.component'; + +describe('InfoBoxComponent', () => { + let component: InfoBoxComponent; + let fixture: ComponentFixture<InfoBoxComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [InfoBoxComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(InfoBoxComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/info-box/info-box.component.ts b/src/frontend/src/app/components/info-box/info-box.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..b6699ebe7a227c853169e74a810a9a5aefe3cc21 --- /dev/null +++ b/src/frontend/src/app/components/info-box/info-box.component.ts @@ -0,0 +1,38 @@ +import { + ChangeDetectionStrategy, + Component, + ElementRef, + Renderer2, +} from '@angular/core'; +import { LogicalZIndex } from 'golden-layout'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; + +@Component({ + selector: 'app-info-box', + templateUrl: './info-box.component.html', + styleUrls: ['./info-box.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class InfoBoxComponent extends LayoutChangeDirective { + constructor(renderer: Renderer2, elRef: ElementRef) { + super(elRef.nativeElement, renderer); + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + + handleVisibilityChange(visibility: boolean): void {} + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} +} + +export namespace InfoBoxComponent { + export const componentName = 'InfoBoxComponent'; +} diff --git a/src/frontend/src/app/components/loading-overlay/loading-overlay.component.css b/src/frontend/src/app/components/loading-overlay/loading-overlay.component.css new file mode 100644 index 0000000000000000000000000000000000000000..60234cda86882e4a44e412ba015eb2dca80fdcd2 --- /dev/null +++ b/src/frontend/src/app/components/loading-overlay/loading-overlay.component.css @@ -0,0 +1,13 @@ +.loader-overlay { + position: absolute; + width: 100%; + height: 100%; + background-color: rgb(0 0 0 / 50%); + top: 0; + z-index: 1000; + align-items: center; + display: flex; + justify-content: center; + backdrop-filter: blur(5px); + color: var(--text-primary) +} \ No newline at end of file diff --git a/src/frontend/src/app/components/loading-overlay/loading-overlay.component.html b/src/frontend/src/app/components/loading-overlay/loading-overlay.component.html new file mode 100644 index 0000000000000000000000000000000000000000..cbed704a6dde3696ff9ac11149fce5cb07ddf60f --- /dev/null +++ b/src/frontend/src/app/components/loading-overlay/loading-overlay.component.html @@ -0,0 +1,7 @@ +<div + *ngIf="loadingInProgress" + class="loader-overlay d-flex flex-column justify-content-center align-items-center" +> + <img class="cortado-logo" src="./assets/icons/win/icon.ico" /> + {{ loadingOverlayService.loadingText }} +</div> diff --git a/src/frontend/src/app/components/loading-overlay/loading-overlay.component.spec.ts b/src/frontend/src/app/components/loading-overlay/loading-overlay.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..9df4f929cf3557c0a55d5b5594a825da93e3b720 --- /dev/null +++ b/src/frontend/src/app/components/loading-overlay/loading-overlay.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LoadingOverlayComponent } from './loading-overlay.component'; + +describe('LoadingOverlayComponent', () => { + let component: LoadingOverlayComponent; + let fixture: ComponentFixture<LoadingOverlayComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [LoadingOverlayComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(LoadingOverlayComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/loading-overlay/loading-overlay.component.ts b/src/frontend/src/app/components/loading-overlay/loading-overlay.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..5e1e49b5c6a7e1625ab87e9fb9bb533e2299ceeb --- /dev/null +++ b/src/frontend/src/app/components/loading-overlay/loading-overlay.component.ts @@ -0,0 +1,25 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { LoadingOverlayService } from 'src/app/services/loadingOverlayService/loading-overlay.service'; + +@Component({ + selector: 'app-loading-overlay', + templateUrl: './loading-overlay.component.html', + styleUrls: ['./loading-overlay.component.css'], +}) +export class LoadingOverlayComponent implements OnInit, OnDestroy { + loadingInProgressEvent: any; + loadingInProgress: boolean = false; + + constructor(public loadingOverlayService: LoadingOverlayService) {} + + ngOnInit() { + this.loadingInProgressEvent = + this.loadingOverlayService.loadingInProgressEvent.subscribe((event) => { + this.loadingInProgress = event; + }); + } + + ngOnDestroy() { + this.loadingInProgressEvent.unsubscribe(); + } +} diff --git a/src/frontend/src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component.css b/src/frontend/src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component.css new file mode 100644 index 0000000000000000000000000000000000000000..e681b2ba30ea00103d07867f3f7a7a32abeff1fb --- /dev/null +++ b/src/frontend/src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component.css @@ -0,0 +1,19 @@ +/* .nav-link > */ +button { + color: whitesmoke !important; + + &.disabled { + color: #757575 !important; + } +} + +.nav-link { + border: none !important; + border-radius: 0 !important; + border-color: rgb(84 103 239) !important; + + &.active { + border-left-style: solid !important; + border-width: 5px !important; + } +} diff --git a/src/frontend/src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component.html b/src/frontend/src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component.html new file mode 100644 index 0000000000000000000000000000000000000000..ce745155e5037eb18c798a7bb47856872ed332a9 --- /dev/null +++ b/src/frontend/src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component.html @@ -0,0 +1,333 @@ +<div class="modal-header h-line-modal-bottom"> + <h5 class="modal-title text-light">Event-Log Export</h5> + + <span class="ml-3"> + <i + class="bi bi-question-circle-fill font-large ms-1 align-middle secondary-text cursor-help question-icon" + container="body" + (click)="openDocumentation()" + ></i> + </span> + + <button + type="button" + class="btn-close btn-close-white" + (click)="modal.dismiss('Cross click')" + aria-label="Close" + ></button> +</div> + +<div class="modal-body d-flex"> + <ul + ngbNav + #nav="ngbNav" + orientation="vertical" + [(activeId)]="activeIndex" + class="col-4 nav-tabs" + > + <li [ngbNavItem]="0"> + <button ngbNavLink>Variants</button> + <ng-template ngbNavContent> + <div> + Select which variations are taken into account for export: + <br /> + <ul> + <li>All: includes all variants</li> + <li> + Display: includes only visible variants in the Variant Explorer, + i.e. excluding those hidden by filters. + </li> + <li> + Fitting and Non-Fitting: + <ul> + <li>ignores variants without calculated conformance values</li> + <li> + outdated conformance results are considered like up-to-date + values + </li> + </ul> + </li> + <li>Selected: consider only variants selected in the explorer</li> + </ul> + </div> + <div class="d-flex align-self-center mt-3"> + <div class="form-select-element"> + <label class="col-form-label text-light dialog-label"> + Considered Variants: + </label> + <select + class="form-select" + style="width: 200px" + [(ngModel)]="logExportConfig.variantSelectionMethod" + > + <option + *ngFor="let item of VariantSelectionMethod | enumToArray" + [value]="item.value" + > + {{ item.value }} + </option> + </select> + </div> + </div> + </ng-template> + </li> + + <li [ngbNavItem]="1" [disabled]="skipUserCreatedVariants"> + <button ngbNavLink>User-created Variants</button> + <ng-template ngbNavContent> + <div> + Should user-created variants be included in the final event log?<br /> + Since there is no real data available for them they will: + <ul> + <li>Have artificially generated timestamps for their events</li> + <li> + For non-concurrent variants, be represented by a single trace in + the exported event-log + </li> + <li> + For concurrent variants, each possible sequentilization has a + corresponding trace in the log + </li> + </ul> + </div> + <div class="form-check form-switch mt-3"> + <label class="form-check-label"> + Include user-created variants + </label> + <input + class="form-check-input" + type="checkbox" + [(ngModel)]="logExportConfig.includeUserCreatedVariants" + [disabled]="logExportConfig.includeTraceFragments" + /> + </div> + </ng-template> + </li> + + <li [ngbNavItem]="2" [disabled]="skipTraceFragments"> + <button ngbNavLink>Trace Fragments</button> + <ng-template ngbNavContent> + <div> + Should trace fragments such as pre-, in-, and suffixes be included in + the event log?<br /> + <ul> + <li>They count towards the user-created variants</li> + <ul> + <li> + Therefore, other user-created variants will also be included, + unless they are not within the set of variants selected in the + first step + </li> + </ul> + <li> + Be treated as they were a normal trace, i.e. their fragment type + will be ignored + </li> + </ul> + </div> + <div class="form-check form-switch mt-3"> + <label class="form-check-label"> Include trace fragments </label> + <input + class="form-check-input" + type="checkbox" + [(ngModel)]="logExportConfig.includeTraceFragments" + (change)="onIncludeFragementsToggle()" + /> + </div> + </ng-template> + </li> + + <li [ngbNavItem]="3"> + <button ngbNavLink>Sequentialization</button> + <ng-template ngbNavContent> + <div> + Should all variants be sequentialized?<br /> + This leads to: + <ul> + <li>Original traces are no longer contained in the log</li> + <li>Traces are synthesised with fake timestamps</li> + <li>Each trace will only occur once</li> + <li> + Each sequentialisation of a concurrent variant will include a + unique trace + </li> + </ul> + </div> + <div class="form-check form-switch mt-3"> + <label class="form-check-label"> Sequentialize Variants </label> + <input + class="form-check-input" + type="checkbox" + [(ngModel)]="logExportConfig.sequentializeVariants" + /> + </div> + </ng-template> + </li> + + <li [ngbNavItem]="4"> + <button ngbNavLink>Log Info</button> + <ng-template ngbNavContent> + <div> + This allows you to decide whether or not the exported log should have + the same global log level data as the original log. + </div> + <div class="form-check form-switch mt-3"> + <label class="form-check-label"> Include Original Log Info</label> + <input + class="form-check-input" + type="checkbox" + [(ngModel)]="logExportConfig.includeOriginalLogInfo" + /> + </div> + </ng-template> + </li> + + <li [ngbNavItem]="5"> + <button ngbNavLink>Log Type</button> + <ng-template ngbNavContent> + <div> + Should the exported be exported an interval log? + <ul> + <li>No:</li> + <ul> + <li>Log will be in lifecycle format</li> + <li> + Each activity will have two events with the attribute + <code>lifecycle:transition</code>: + <ul> + <li>start</li> + <li>complete</li> + </ul> + </li> + </ul> + <li>Yes:</li> + <ul> + <li>Log will be in interval format</li> + <li> + Each activity will be a single event having the attributes: + <ul> + <li><code>start_timestamp</code> for the starting time</li> + <li><code>time:timestamp</code> for the completion time</li> + </ul> + </li> + </ul> + </ul> + </div> + <div class="form-check form-switch mt-3"> + <label class="form-check-label"> Convert log to interval </label> + <input + class="form-check-input" + type="checkbox" + [(ngModel)]="logExportConfig.exportAsIntervalLog" + /> + </div> + </ng-template> + </li> + + <li [ngbNavItem]="6"> + <button ngbNavLink> + <b>Summary</b> + </button> + <ng-template ngbNavContent> + <div class="form-select-element"> + <label class="col-form-label text-light dialog-label"> + Considered Variants: + </label> + <select + class="form-select" + style="width: 200px" + [(ngModel)]="logExportConfig.variantSelectionMethod" + > + <option + *ngFor="let item of VariantSelectionMethod | enumToArray" + [value]="item.value" + > + {{ item.value }} + </option> + </select> + </div> + <div class="form-check form-switch mt-3"> + <input + id="userCreatedVariantsSwitch" + class="form-check-input" + type="checkbox" + [(ngModel)]="logExportConfig.includeUserCreatedVariants" + [disabled]=" + logExportConfig.includeTraceFragments || skipUserCreatedVariants + " + /> + <label class="form-check-label" for="userCreatedVariantsSwitch"> + Include user-created variants + </label> + </div> + <div class="form-check form-switch mt-3"> + <input + id="traceFragmentSwitch" + class="form-check-input" + type="checkbox" + [(ngModel)]="logExportConfig.includeTraceFragments" + (change)="onIncludeFragementsToggle()" + [disabled]="skipTraceFragments" + /> + <label class="form-check-label" for="traceFragmentSwitch"> + Include trace fragments + </label> + </div> + <div class="form-check form-switch mt-3"> + <label class="form-check-label"> Sequentialize variants </label> + <input + class="form-check-input" + type="checkbox" + [(ngModel)]="logExportConfig.sequentializeVariants" + /> + </div> + <div class="form-check form-switch mt-3"> + <label class="form-check-label"> Include original log info </label> + <input + class="form-check-input" + type="checkbox" + [(ngModel)]="logExportConfig.includeOriginalLogInfo" + /> + </div> + <div class="form-check form-switch mt-3"> + <label class="form-check-label"> Export as interval log </label> + <input + class="form-check-input" + type="checkbox" + [(ngModel)]="logExportConfig.exportAsIntervalLog" + /> + </div> + </ng-template> + </li> + </ul> + + <div [ngbNavOutlet]="nav" class="col-8 p-2" style="min-height: 250px"></div> +</div> + +<div class="modal-footer h-line-modal-top d-flex justify-content-between"> + <button + type="button" + class="button" + [disabled]="activeIndex === 0" + (click)="onBack(nav)" + > + Back + </button> + <button + type="button" + class="button" + *ngIf="activeIndex < lastPageIndex" + (click)="onNext(nav)" + > + Next + </button> + <button + type="button" + class="button" + *ngIf="activeIndex === lastPageIndex" + (click)="onExport()" + > + <i class="bi bi-save btn-icon text-success"></i> + Export + </button> +</div> diff --git a/src/frontend/src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component.spec.ts b/src/frontend/src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..f2c03e6496420f9e5b4dda333061bdabf8719d99 --- /dev/null +++ b/src/frontend/src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LogExporterDialogComponent } from './log-exporter-dialog.component'; + +describe('LogExporterDialogComponent', () => { + let component: LogExporterDialogComponent; + let fixture: ComponentFixture<LogExporterDialogComponent>; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [LogExporterDialogComponent], + }); + fixture = TestBed.createComponent(LogExporterDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component.ts b/src/frontend/src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..86485325333fbb20a3ba6e1300c6c797eb2f40a3 --- /dev/null +++ b/src/frontend/src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component.ts @@ -0,0 +1,88 @@ +import { Component } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { VariantSelectionMethod } from 'src/app/objects/VariantSelectionMethod'; +import { DocumentationService } from '../../documentation/documentation.service'; +import { LogExportConfig } from 'src/app/objects/LogExportConfig/LogExportConfig'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { InfixType } from 'src/app/objects/Variants/infix_selection'; + +@Component({ + selector: 'app-log-exporter-dialog', + templateUrl: './log-exporter-dialog.component.html', + styleUrls: ['./log-exporter-dialog.component.css'], +}) +export class LogExporterDialogComponent { + activeIndex = 0; + lastPageIndex = 6; + + skipUserCreatedVariants = false; + skipTraceFragments = false; + + includeUserCreatedVariantsForced = false; + + VariantSelectionMethod = VariantSelectionMethod; + + logExportConfig: LogExportConfig; + + constructor( + public modal: NgbActiveModal, + private documentationService: DocumentationService, + private variantService: VariantService + ) { + this.logExportConfig = { + variantSelectionMethod: VariantSelectionMethod.ALL, + includeTraceFragments: false, + includeUserCreatedVariants: false, + sequentializeVariants: false, + exportAsIntervalLog: true, + includeOriginalLogInfo: true, + }; + + this.skipUserCreatedVariants = !variantService.variants.some( + (v) => v.userDefined + ); + this.skipTraceFragments = !variantService.variants.some( + (v) => v.infixType != InfixType.NOT_AN_INFIX + ); + } + + openDocumentation() { + this.documentationService.showDocumentationDialog('Log Export'); + this.modal.dismiss('Documentation opened'); + } + + onExport() { + this.modal.close(this.logExportConfig); + } + + onIncludeFragementsToggle() { + if ( + this.logExportConfig.includeTraceFragments && + !this.logExportConfig.includeUserCreatedVariants + ) { + this.logExportConfig.includeUserCreatedVariants = true; + this.includeUserCreatedVariantsForced = true; + } + if ( + !this.logExportConfig.includeTraceFragments && + this.includeUserCreatedVariantsForced + ) { + this.logExportConfig.includeUserCreatedVariants = false; + this.includeUserCreatedVariantsForced = false; + } + } + + onNext(nav) { + let newIndex = this.activeIndex + 1; + if (newIndex == 1 && this.skipUserCreatedVariants) newIndex += 1; + if (newIndex == 2 && this.skipTraceFragments) newIndex += 1; + nav.select(newIndex); + } + + onBack(nav) { + let newIndex = this.activeIndex - 1; + if (newIndex == 2 && this.skipTraceFragments) newIndex -= 1; + if (newIndex == 1 && this.skipUserCreatedVariants) newIndex -= 1; + nav.select(newIndex); + } +} diff --git a/src/frontend/src/app/components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component.html b/src/frontend/src/app/components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component.html new file mode 100644 index 0000000000000000000000000000000000000000..39fbc1d6d12bee85573e813548d11131ddff12fe --- /dev/null +++ b/src/frontend/src/app/components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component.html @@ -0,0 +1,76 @@ +<td style="width: 100px"> + <div class="row"> + <div class="col text-center"> + <button + class="button text-center" + ngbTooltip="calculate statistics" + triggers="hover" + container="body" + (click)="showMetrics()" + > + <i class="bi bi-graph-up"></i> + </button> + <button + class="button text-center" + ngbTooltip="show in process tree editor" + triggers="hover" + container="body" + (click)="showInProcessTreeEditor()" + > + <i class="bi bi-diagram-2-fill"></i> + </button> + </div> + </div> +</td> +<td #row class="border-start border-lightgrey"> + <svg + #d3svg + id="d3-svg" + width="100%" + [attr.height]="treeSvgHeight" + class="pt-2 pb-2 d-flex" + > + <g + #d3svgDirective + appProcessTreeDrawer + [onClickCallBack]="selectNodeCallBack" + [computeNodeColor]="computeNodeColor" + [computeTextColor]="computeTextColor" + [tooltipText]="tooltipContent" + id="d3-svg-directive" + width="100%" + height="100%" + class="text-center" + [style.transform]="'translateX(' + lpmColumnSize / 2 + 'px) scale(0.8)'" + ></g> + </svg> +</td> + +<td class="border-start border-lightgrey ps-2 overflow-cell" *ngIf="isVisible"> + <div class="p-2" *ngFor="let pattern of lpm.patterns; let j = index"> + <svg + appVariantDrawer + #fragment + [variant]="pattern" + [computeActivityColor]="computeActivityColor" + [onRightMouseClickCbFc]="openContextCallback" + [infixType]="InfixType.PROPER_INFIX" + [keepStandardView]="true" + [addCursorPointer]="false" + class="zoom-group-variant" + ></svg> + </div> +</td> + +<td *ngIf="!isVisible" class="border-start border-lightgrey ps-2 overflow-cell"> + <div + *ngFor="let pattern of lpm.patterns; let j = index" + class="variant-spacer" + [ngStyle]="{ + height: pattern.variant.getHeight() + 'px', + width: pattern.variant.getWidth() + 'px' + }" + > + Loading... + </div> +</td> diff --git a/src/frontend/src/app/components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component.scss b/src/frontend/src/app/components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..407aa1c10ef009d2b2150e3f968418d22bd36416 --- /dev/null +++ b/src/frontend/src/app/components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component.scss @@ -0,0 +1,20 @@ +.border-lightgrey { + border-color: rgb(106 106 106 / 60%) !important; +} + + +.variant-spacer { + display: flex; + flex-direction: row; + align-items: center; +} + +.text-size { + font-size: 0.9rem; +} + +.overflow-cell { + overflow: visible; + text-overflow: ellipsis; + white-space: nowrap; +} \ No newline at end of file diff --git a/src/frontend/src/app/components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component.spec.ts b/src/frontend/src/app/components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..543e86de348d384d174c9ad9d4ed0d51609f6e65 --- /dev/null +++ b/src/frontend/src/app/components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LpmExplorerRowComponent } from './lpm-explorer-row.component'; + +describe('LpmExplorerRowComponent', () => { + let component: LpmExplorerRowComponent; + let fixture: ComponentFixture<LpmExplorerRowComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [LpmExplorerRowComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(LpmExplorerRowComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component.ts b/src/frontend/src/app/components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..7ff1a24ee3888d2b8ea6f6c6f491dcb1fac5ca67 --- /dev/null +++ b/src/frontend/src/app/components/lpm-explorer/lpm-explorer-row/lpm-explorer-row.component.ts @@ -0,0 +1,190 @@ +import { + AfterViewInit, + Component, + ElementRef, + Input, + OnDestroy, + OnInit, + ViewChild, +} from '@angular/core'; +import * as d3 from 'd3'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { PT_Constant } from 'src/app/constants/process_tree_drawer_constants'; +import { ProcessTreeDrawerDirective } from 'src/app/directives/process-tree-drawer/process-tree-drawer.directive'; +import { VariantDrawerDirective } from 'src/app/directives/variant-drawer/variant-drawer.directive'; +import { LocalProcessModelWithPatterns } from 'src/app/objects/LocalProcessModelWithPatterns'; +import { LpmMetrics } from 'src/app/objects/LpmMetrics'; +import { + ProcessTree, + ProcessTreeOperator, +} from 'src/app/objects/ProcessTree/ProcessTree'; +import { InfixType } from 'src/app/objects/Variants/infix_selection'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { + VariantElement, + LeafNode, +} from 'src/app/objects/Variants/variant_element'; +import { BackendService } from 'src/app/services/backendService/backend.service'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; +import { LazyLoadingServiceService } from 'src/app/services/lazyLoadingService/lazy-loading.service'; +import { LpmService } from 'src/app/services/lpmService/lpm.service'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { textColorForBackgroundColor } from 'src/app/utils/render-utils'; +import { contextMenuCallback } from '../../variant-explorer/functions/variant-drawer-callbacks'; + +@Component({ + // eslint-disable-next-line @angular-eslint/component-selector + selector: '[app-lpm-explorer-row]', + templateUrl: './lpm-explorer-row.component.html', + styleUrls: ['./lpm-explorer-row.component.scss'], +}) +export class LpmExplorerRowComponent + implements AfterViewInit, OnDestroy, OnInit +{ + @Input() + lpm: LocalProcessModelWithPatterns; + + @ViewChild('row') + lpmRowElement: ElementRef; + + _rootElement: ElementRef; + + @ViewChild(VariantDrawerDirective) + variantDrawer: VariantDrawerDirective; + + @ViewChild(ProcessTreeDrawerDirective) + processTreeDrawer: ProcessTreeDrawerDirective; + + processTreeInSvg; + openContextCallback = contextMenuCallback.bind(this); + InfixType = InfixType; + isVisible: boolean = false; + activityColorMap: Map<string, string>; + private _destroy$ = new Subject(); + lpmColumnSize = 0; + treeSvgHeight = '0px'; + + constructor( + private lazyLoadingService: LazyLoadingServiceService, + private colorMapService: ColorMapService, + private processTreeService: ProcessTreeService, + private backendService: BackendService, + private lpmService: LpmService + ) {} + ngOnInit(): void { + let height = this.getHeightOfLpm(this.lpm.lpm); + let treeSvgHeightN = + height * (PT_Constant.BASE_HEIGHT_WIDTH + 2 * 3) + + (height - 1) * PT_Constant.NODE_SPACING; + this.treeSvgHeight = treeSvgHeightN + 'px'; + } + + ngAfterViewInit(): void { + this.processTreeInSvg = d3.select('d3-svg-directive'); + + let obs = new ResizeObserver((entries) => { + for (let entry of entries) { + this.lpmColumnSize = entry.contentRect.width; + } + }); + obs.observe(this.lpmRowElement.nativeElement); + + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + this.activityColorMap = colorMap; + }); + + const self = this; + this.lazyLoadingService.addLpm( + this.lpmRowElement.nativeElement, + (isIntersecting) => { + self.isVisible = isIntersecting; + if (self.isVisible) { + this.processTreeDrawer.redraw(this.lpm.lpm); + } + } + ); + } + + showInProcessTreeEditor() { + this.processTreeService.set_currentDisplayedProcessTree_with_Cache( + this.lpm.lpm + ); + } + + showMetrics() { + this.backendService + .getLpmMetrics(this.lpm.lpm) + .subscribe( + (metrics: LpmMetrics) => (this.lpmService.lpmMetrics = metrics) + ); + } + + computeTextColor = (d: d3.HierarchyNode<ProcessTree>) => { + if (d.data.label === ProcessTreeOperator.tau) { + return 'white'; + } + const nodeColor = this.computeNodeColor(d); + + const isVisibleActivity = + d.data.label !== null && d.data.label !== ProcessTreeOperator.tau; + return isVisibleActivity ? textColorForBackgroundColor(nodeColor) : 'white'; + }; + + computeNodeColor = (d: d3.HierarchyNode<ProcessTree>) => { + if (d.data.operator !== null) return PT_Constant.OPERATOR_COLOR; + if (d.data.label === '...') return 'gray'; + if (d.data.label !== null && d.data.label === ProcessTreeOperator.tau) + return PT_Constant.INVISIBLE_ACTIVTIY_COLOR; + const isVisibleActivity = + d.data.label !== null && d.data.label !== ProcessTreeOperator.tau; + + return isVisibleActivity ? this.activityColorMap.get(d.data.label) : null; + }; + + computeActivityColor = ( + self: VariantDrawerDirective, + element: VariantElement, + variant: Variant + ) => { + let color; + + if (element instanceof LeafNode) { + color = this.activityColorMap.get(element.asLeafNode().activity[0]); + + if (element.activity.length > 1) { + color = '#d3d3d3'; // lightgray + } + } else { + color = '#d3d3d3'; + } + + return color; + }; + + selectNodeCallBack = (self, event, d) => { + console.log(this.treeSvgHeight); + }; + + tooltipContent = (d: d3.HierarchyNode<ProcessTree>) => { + return ''; + }; + + getHeightOfLpm(processTree: ProcessTree) { + if (processTree.children.length == 0) { + return 1; + } + let childHeights = []; + for (let child of processTree.children) { + childHeights.push(this.getHeightOfLpm(child)); + } + + return 1 + Math.max(...childHeights); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } +} diff --git a/src/frontend/src/app/components/lpm-explorer/lpm-explorer.component.html b/src/frontend/src/app/components/lpm-explorer/lpm-explorer.component.html new file mode 100644 index 0000000000000000000000000000000000000000..7b7b6fd056ab3660caed2c6c3d77db0a29ddc003 --- /dev/null +++ b/src/frontend/src/app/components/lpm-explorer/lpm-explorer.component.html @@ -0,0 +1,45 @@ +<div class="lpm-explorer h-100 d-flex flex-column" #lpmExplorer> + <div class="lpm-explorer-container"> + <div class="lpm-table-container" style="width: 100%"> + <div class="lpm-table-container-secondary"> + <table class="lpm-table"> + <thead class="user-select-none sticky-header-row"> + <tr> + <th class="text-center" style="width: 100px"> + <div class="header-text-container"> + <div class="header-text">Actions</div> + </div> + </th> + <th + resizeable + class="text-center border-start border-lightgrey" + [margin]="-4" + > + <div class="header-text-container"> + <div class="header-text">Local Process Model</div> + </div> + </th> + <th + resizeable + class="text-center border-start border-lightgrey" + [margin]="-4" + > + <div class="header-text-container"> + <div class="header-text">Patterns</div> + </div> + </th> + </tr> + </thead> + <tbody> + <tr + *ngFor="let lpm of lpms; let i = index" + app-lpm-explorer-row + [lpm]="lpm" + class="lpm-tr-divider" + ></tr> + </tbody> + </table> + </div> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/lpm-explorer/lpm-explorer.component.scss b/src/frontend/src/app/components/lpm-explorer/lpm-explorer.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..b9c0144af09936cc393e0f7222c3ae176515cc7e --- /dev/null +++ b/src/frontend/src/app/components/lpm-explorer/lpm-explorer.component.scss @@ -0,0 +1,82 @@ +.lpm-explorer { + background-color: var(--box-background-color); + max-height: 100%; + position: relative; + border-left: 1px solid var(--thin-border-color); +} + + +:host { + position: absolute; + overflow: hidden; +} + +.lpm-tr-divider { + border-bottom: 1px solid black; +} + +.lpm-table-container { + color: var(--text-secondary); + width: 100%; + height: 100%; + overflow: auto; +} + +.lpm-table-container-secondary { + overflow: auto; + height: 100%; + width: 100%; +} + +.lpm-table { + color: var(--text-secondary); + width: 100%; + table-layout: fixed; +} + +.button-text { + display: inline-block; +} + +.header-text-container { + display: flex; + flex-flow: row nowrap; + justify-content: space-evenly; + font-size: 0.9rem; +} + +.header-text { + padding-left: 5px; + padding-right: 5px; + cursor: pointer; + user-select: none; +} + +.header-text:hover { + color: whitesmoke; +} + + +.sticky-header-row { + position: sticky; + top: 0; + z-index: 10; + background-color: var(--box-background-color); +} + +.border-lightgrey { + border-color: rgb(106 106 106 / 60%) !important; +} + +.center-element { + border-color: rgb(106 106 106 / 20%) !important; + border-right-width: 1px; + border-left-width: 1px; +} + +.lpm-explorer-container { + width: 100%; + height: 100%; + display: flex; + border-bottom: black 0.5px solid; +} diff --git a/src/frontend/src/app/components/lpm-explorer/lpm-explorer.component.spec.ts b/src/frontend/src/app/components/lpm-explorer/lpm-explorer.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..c478396a6843cf4acf89aceaef87aedb77cf4238 --- /dev/null +++ b/src/frontend/src/app/components/lpm-explorer/lpm-explorer.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LpmExplorerComponent } from './lpm-explorer.component'; + +describe('LpmExplorerComponent', () => { + let component: LpmExplorerComponent; + let fixture: ComponentFixture<LpmExplorerComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [LpmExplorerComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(LpmExplorerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/lpm-explorer/lpm-explorer.component.ts b/src/frontend/src/app/components/lpm-explorer/lpm-explorer.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..0213a12a3b304e23aa39373fec768e2aec873958 --- /dev/null +++ b/src/frontend/src/app/components/lpm-explorer/lpm-explorer.component.ts @@ -0,0 +1,83 @@ +import { + AfterViewInit, + Component, + ElementRef, + Inject, + OnDestroy, + OnInit, + Renderer2, + ViewChild, +} from '@angular/core'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; +import { Subject } from 'rxjs'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { LocalProcessModelWithPatterns } from 'src/app/objects/LocalProcessModelWithPatterns'; +import { InfixType } from 'src/app/objects/Variants/infix_selection'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; +import { LazyLoadingServiceService } from 'src/app/services/lazyLoadingService/lazy-loading.service'; +import { LpmService } from 'src/app/services/lpmService/lpm.service'; + +@Component({ + selector: 'app-lpm-explorer', + templateUrl: './lpm-explorer.component.html', + styleUrls: ['./lpm-explorer.component.scss'], +}) +export class LpmExplorerComponent + extends LayoutChangeDirective + implements OnInit, OnDestroy, AfterViewInit +{ + lpms: LocalProcessModelWithPatterns[] = []; + + @ViewChild('lpmExplorer') + lpmExplorerDiv: ElementRef<HTMLDivElement>; + + InfixType = InfixType; + + private _destroy$ = new Subject(); + + constructor( + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef, + renderer: Renderer2, + public lpmService: LpmService, + public colorMapService: ColorMapService, + public lazyLoadingService: LazyLoadingServiceService + ) { + super(elRef.nativeElement, renderer); + } + ngAfterViewInit(): void { + this.lazyLoadingService.initializeLpmExplorer(this.lpmExplorerDiv); + } + + ngOnInit(): void { + this.lpmService.localProcessModels$.subscribe((models) => { + this.lpms = models; + }); + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + handleVisibilityChange(visibility: boolean): void {} + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} + + exportLocalProcessModels() { + console.log('implement lpm export here'); + } + + ngOnDestroy(): void { + this._destroy$.next(); + this.lazyLoadingService.destoryLpmExplorerObserver(); + } +} + +export namespace LpmExplorerComponent { + export const componentName = 'LpmExplorerComponent'; +} diff --git a/src/frontend/src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component.css b/src/frontend/src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component.css new file mode 100644 index 0000000000000000000000000000000000000000..93f332d1c489b8b3306f7c97f86f5ca923703a3e --- /dev/null +++ b/src/frontend/src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component.css @@ -0,0 +1,7 @@ +:host { + display: flex; + flex-direction: column; + overflow: auto; + position: absolute; + background-color: var(--box-background-color); +} \ No newline at end of file diff --git a/src/frontend/src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component.html b/src/frontend/src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component.html new file mode 100644 index 0000000000000000000000000000000000000000..b65bf847ce0e363273b2b4e92954823ff6da38f2 --- /dev/null +++ b/src/frontend/src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component.html @@ -0,0 +1,86 @@ +<div *ngIf="metrics === null"> + <app-unavailable-info> + Mine an eventually follows patterns using the Variant Miner and click + <i class="bi bi-graph-up text-white"></i> to calculate statistics. + </app-unavailable-info> +</div> +<div *ngIf="metrics !== null"> + <table + class="table table-sm table-striped table-dark table-hover table-bordered mb-0" + style="font-size: small; table-layout: fixed" + > + <thead> + <tr> + <th colspan="2">Metrics</th> + </tr> + </thead> + <tbody class="no-top-border"> + <tr> + <td>Support (Tax et al.):</td> + <td> + {{ metrics.support | number : "1.2" }} + </td> + </tr> + <tr> + <td>Transaction Support:</td> + <td> + {{ metrics.supportTrans | number : "1.2" }} + </td> + </tr> + <tr> + <td>Occurrence Support:</td> + <td> + {{ metrics.supportOcc | number : "1.2" }} + </td> + </tr> + <tr> + <td>Confidence:</td> + <td> + {{ metrics.confidence | number : "1.2" }} + </td> + </tr> + <tr> + <td>Precision:</td> + <td> + {{ metrics.precision | number : "1.2" }} + </td> + </tr> + <tr> + <td>Coverage:</td> + <td> + {{ metrics.coverage | number : "1.2" }} + </td> + </tr> + <tr> + <td>Simplicity:</td> + <td> + {{ metrics.simplicity | number : "1.2" }} + </td> + </tr> + <tr> + <td>Skip Precision:</td> + <td> + {{ metrics.skipPrecision | number : "1.2" }} + </td> + </tr> + <tr> + <td>Mean Range:</td> + <td> + {{ metrics.meanRange | number : "1.2" }} + </td> + </tr> + <tr> + <td>Min Range:</td> + <td> + {{ metrics.minRange | number : "1.2" }} + </td> + </tr> + <tr> + <td>Max Range:</td> + <td> + {{ metrics.maxRange | number : "1.2" }} + </td> + </tr> + </tbody> + </table> +</div> diff --git a/src/frontend/src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component.spec.ts b/src/frontend/src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..5b36f7e3151459e69b7cd595b818f86eec8dc9d2 --- /dev/null +++ b/src/frontend/src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LpmMetricsTabComponent } from './lpm-metrics-tab.component'; + +describe('LpmMetricsTabComponent', () => { + let component: LpmMetricsTabComponent; + let fixture: ComponentFixture<LpmMetricsTabComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [LpmMetricsTabComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(LpmMetricsTabComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component.ts b/src/frontend/src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..b584a5a20879c22c2972129b1d0e6d142c56db72 --- /dev/null +++ b/src/frontend/src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component.ts @@ -0,0 +1,63 @@ +import { + ChangeDetectorRef, + Component, + ElementRef, + Inject, + OnInit, + Renderer2, +} from '@angular/core'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { LpmMetrics } from 'src/app/objects/LpmMetrics'; +import { GoldenLayoutComponentService } from 'src/app/services/goldenLayoutService/golden-layout-component.service'; +import { LpmService } from 'src/app/services/lpmService/lpm.service'; +import { VariantPerformanceService } from 'src/app/services/variant-performance.service'; +import { VariantViewModeService } from 'src/app/services/viewModeServices/variant-view-mode.service'; + +@Component({ + selector: 'app-lpm-metrics-tab', + templateUrl: './lpm-metrics-tab.component.html', + styleUrls: ['./lpm-metrics-tab.component.css'], +}) +export class LpmMetricsTabComponent + extends LayoutChangeDirective + implements OnInit +{ + metrics: LpmMetrics = null; + + constructor( + renderer: Renderer2, + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef, + private lpmService: LpmService, + private goldenLayoutService: GoldenLayoutComponentService + ) { + super(elRef.nativeElement, renderer); + } + ngOnInit(): void { + this.lpmService.lpmMetrics$.subscribe((m) => { + this.metrics = m; + if (this.metrics !== null) + this.goldenLayoutService.activateLpmMetricsView(); + }); + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + + handleVisibilityChange(visibility: boolean): void {} + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} +} + +export namespace LpmMetricsTabComponent { + export const componentName = 'LpmMetricsTabComponent'; +} diff --git a/src/frontend/src/app/components/performance/color-map/color-map.component.html b/src/frontend/src/app/components/performance/color-map/color-map.component.html new file mode 100644 index 0000000000000000000000000000000000000000..75bf3af452ed96c0075e5270da95486e227d78fd --- /dev/null +++ b/src/frontend/src/app/components/performance/color-map/color-map.component.html @@ -0,0 +1,84 @@ +<div class="color-map" *ngIf="colorMapValues"> + <ng-container + *ngFor=" + let e of colorMapValues; + index as i; + last as isLast; + first as isFirst + " + > + <span + class="list-group-item" + style="height: 40px" + *ngIf="e.color !== null" + [ngStyle]="{ + 'margin-bottom': isFirst && firstColorDetached ? '30px' : '0', + 'margin-top': + i === colorMapValues.length - 2 && lastColorDetached ? '30px' : '0', + background: + isFirst && firstColorStriped ? getCssStripes(e.color) : e.color + }" + > + <!-- lower bound --> + <div + class="color-map-label" + *ngIf=" + !(i === colorMapValues.length - 2 && lastColorDetached); + else lastDetachedLowerBound + " + > + {{ prefixes[i] }} + {{ + timeBasedLabel + ? (e.lowerBound | humanizeDuration : false : true : 3 : true) + : e.lowerBound + }}{{ suffix }} + </div> + + <ng-template #lastDetachedLowerBound> + <div class="color-map-label"> + {{ prefixes[i + 1] }} + {{ + timeBasedLabel + ? (colorMapValues[i + 1].lowerBound + | humanizeDuration : false : true : 3 : true) + : colorMapValues[i + 1].lowerBound + }}{{ suffix }} + </div> + </ng-template> + </span> + + <!-- upper bound --> + <span + class="list-group-item" + *ngIf="isLast && !excludeUpperLabel && !lastColorDetached" + style="background: unset" + > + <div class="color-map-label"> + {{ prefixes[i] }} + {{ + timeBasedLabel + ? (e.lowerBound | humanizeDuration : false : true : 3 : true) + : e.lowerBound + }}{{ suffix }} + </div> + </span> + + <!-- upper bound if lastColorDetached --> + <span + class="list-group-item" + *ngIf="i === colorMapValues.length - 3 && lastColorDetached" + style="background: unset" + > + <div class="color-map-label"> + {{ prefixes[i + 1] }} + {{ + timeBasedLabel + ? (colorMapValues[i + 1].lowerBound + | humanizeDuration : false : true : 3 : true) + : colorMapValues[i + 1].lowerBound + }}{{ suffix }} + </div> + </span> + </ng-container> +</div> diff --git a/src/frontend/src/app/components/performance/color-map/color-map.component.scss b/src/frontend/src/app/components/performance/color-map/color-map.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..6b252f9e938f1cedb5fed9915e6a08696a33ce81 --- /dev/null +++ b/src/frontend/src/app/components/performance/color-map/color-map.component.scss @@ -0,0 +1,15 @@ +.color-map-label { + position: absolute; + top: -11px; + font-size: 12px; + background: lightgrey; + padding-right: 4px; + padding-left: 4px; + color: black; + margin-left: 15px; +} + +.color-map { + padding-top: 10px; + padding-bottom: 10px; +} diff --git a/src/frontend/src/app/components/performance/color-map/color-map.component.spec.ts b/src/frontend/src/app/components/performance/color-map/color-map.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..982a4b9b1a15293af9744982e2a4dd3d0d5298cd --- /dev/null +++ b/src/frontend/src/app/components/performance/color-map/color-map.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ColorMapComponent } from './color-map.component'; + +describe('ColorMapComponent', () => { + let component: ColorMapComponent; + let fixture: ComponentFixture<ColorMapComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ColorMapComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ColorMapComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/performance/color-map/color-map.component.ts b/src/frontend/src/app/components/performance/color-map/color-map.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..2bbe987eadd06976c027e3a3a6d89d1978ed932b --- /dev/null +++ b/src/frontend/src/app/components/performance/color-map/color-map.component.ts @@ -0,0 +1,93 @@ +import { Component, Input } from '@angular/core'; +import { ColorMap, ZERO_VALUE_COLOR } from 'src/app/objects/ColorMap'; + +@Component({ + selector: 'app-color-map', + templateUrl: './color-map.component.html', + styleUrls: ['./color-map.component.scss'], +}) +export class ColorMapComponent { + @Input() + colorMapValues: ColorMapValue[]; + @Input() + timeBasedLabel: Boolean = true; + @Input() + prefixes: string[] = []; + @Input() + suffix: string = ''; + @Input() + excludeUpperLabel: Boolean = false; + @Input() + firstColorStriped: Boolean = false; + @Input() + stripeColor: string = '#EEEEEE'; + @Input() + stripeBackgroundColor: string = 'white'; + @Input() + firstColorDetached: Boolean = false; + @Input() + lastColorDetached: Boolean = false; + + getCssStripes( + backgroundColor = this.stripeBackgroundColor, + stripeColor = this.stripeColor, + stripeSpacing = 3, + stripeThickness = 2 + ) { + return getCssStripes( + backgroundColor, + stripeColor, + stripeSpacing, + stripeThickness + ); + } + + constructor() {} +} + +export interface ColorMapValue { + lowerBound: number; + color: string; +} + +export function buildColorValues( + colorScale, + values?: number[] +): ColorMapValue[] { + let thresholds = colorScale.domain(); + if (values) { + let min = Math.min(...values); + let max = Math.max(...values); + + if (min != max) { + thresholds = [min, ...thresholds, max]; + if (min !== 0) thresholds.unshift(0); // Add artifical zero + } else thresholds = [min]; + } + let colors = colorScale.range(); + colors = [...colors, null]; + return thresholds.map((t, i) => { + let color = t == 0 ? ZERO_VALUE_COLOR : colors[i - 1]; + + return { + lowerBound: t, + color: color, + }; + }); +} + +export function getCssStripes( + backgroundColor = 'white', + stripeColor = '#EEEEEE', + stripeSpacing = 3, + stripeThickness = 2 +) { + return `repeating-linear-gradient( + -45deg, + ${backgroundColor} 0px, + ${backgroundColor} ${stripeSpacing}px, + ${stripeColor} ${stripeSpacing + 1}px, + ${stripeColor} ${stripeSpacing + stripeThickness + 1}px, + ${backgroundColor} ${stripeSpacing + stripeThickness + 2}px + )`; +} diff --git a/src/frontend/src/app/components/performance/node-selection-performance/node-selection-performance.component.html b/src/frontend/src/app/components/performance/node-selection-performance/node-selection-performance.component.html new file mode 100644 index 0000000000000000000000000000000000000000..ceb21fc0cda7a8fc4859960e4c90c42ea1472b6b --- /dev/null +++ b/src/frontend/src/app/components/performance/node-selection-performance/node-selection-performance.component.html @@ -0,0 +1,88 @@ +<div class="accordion" *ngIf="meanValues"> + <div class="accordion-item"> + <h2 class="accordion-header"> + <button + class="accordion-button" + type="button" + data-bs-toggle="collapse" + data-bs-target="#collapseMean" + aria-expanded="true" + > + Overall Performance + </button> + </h2> + <div + id="collapseMean" + class="accordion-collapse collapse" + [class.show]="performanceService.activeVariant === undefined" + > + <app-performance-table + [performanceValues]="meanValues.service_time" + heading="Service Time" + [isBodyExpanded]="false" + > + </app-performance-table> + <app-performance-table + [performanceValues]="meanValues.waiting_time" + heading="Waiting Time" + [isBodyExpanded]="false" + > + </app-performance-table> + <app-performance-table + [performanceValues]="meanValues.cycle_time" + heading="Cycle Time" + [isBodyExpanded]="false" + > + </app-performance-table> + <app-performance-table + [performanceValues]="meanValues.idle_time" + heading="Idle Time" + [isBodyExpanded]="false" + > + </app-performance-table> + </div> + </div> + <div class="accordion-item" *ngFor="let variant of variants; let i = index"> + <h2 class="accordion-header"> + <button + class="accordion-button" + type="button" + data-bs-toggle="collapse" + [attr.data-bs-target]="'#collapse' + i" + aria-expanded="true" + > + Variant No. {{ variantIndices.get(variant) }} + </button> + </h2> + <div + [id]="'collapse' + i" + class="accordion-collapse collapse" + [class.show]="performanceService.activeVariant === variant" + > + <app-performance-table + [performanceValues]="serviceTimeValues.get(variant)" + heading="Service Time" + [isBodyExpanded]="false" + > + </app-performance-table> + <app-performance-table + [performanceValues]="waitingTimeValues.get(variant)" + heading="Waiting Time" + [isBodyExpanded]="false" + > + </app-performance-table> + <app-performance-table + [performanceValues]="cycleTimeValues.get(variant)" + heading="Cycle Time" + [isBodyExpanded]="false" + > + </app-performance-table> + <app-performance-table + [performanceValues]="idleTimeValues.get(variant)" + heading="Idle Time" + [isBodyExpanded]="false" + > + </app-performance-table> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/performance/node-selection-performance/node-selection-performance.component.scss b/src/frontend/src/app/components/performance/node-selection-performance/node-selection-performance.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..4167eb2e2865251a33aa744085a9e3ed34a1e06a --- /dev/null +++ b/src/frontend/src/app/components/performance/node-selection-performance/node-selection-performance.component.scss @@ -0,0 +1,15 @@ +.accordion-body { + padding: 0; +} + +.accordion-button { + height: 30px; +} + +hr { + border-top: solid black; +} + +.accordion-item { + padding-top: 5px; +} diff --git a/src/frontend/src/app/components/performance/node-selection-performance/node-selection-performance.component.spec.ts b/src/frontend/src/app/components/performance/node-selection-performance/node-selection-performance.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..3c1e2749137663578e12c52f6f0e51b20463b07d --- /dev/null +++ b/src/frontend/src/app/components/performance/node-selection-performance/node-selection-performance.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NodeSelectionPerformanceComponent } from './node-selection-performance.component'; + +describe('NodeSelectionPerformanceComponent', () => { + let component: NodeSelectionPerformanceComponent; + let fixture: ComponentFixture<NodeSelectionPerformanceComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [NodeSelectionPerformanceComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NodeSelectionPerformanceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/performance/node-selection-performance/node-selection-performance.component.ts b/src/frontend/src/app/components/performance/node-selection-performance/node-selection-performance.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..7ff0afdfb5107974da9d887092e8076cba34df3c --- /dev/null +++ b/src/frontend/src/app/components/performance/node-selection-performance/node-selection-performance.component.ts @@ -0,0 +1,123 @@ +import { VariantService } from './../../../services/variantService/variant.service'; +import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { + HumanizeDuration, + HumanizeDurationLanguage, +} from 'humanize-duration-ts'; +import { ModelPerformanceColorScaleService } from 'src/app/services/performance-color-scale.service'; +import { PerformanceService } from 'src/app/services/performance.service'; +import { SharedDataService } from 'src/app/services/sharedDataService/shared-data.service'; +import { TreePerformance } from '../../../objects/ProcessTree/ProcessTree'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { PerformanceStats } from 'src/app/objects/Variants/variant_element'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; + +@Component({ + selector: 'app-node-selection-performance', + templateUrl: './node-selection-performance.component.html', + styleUrls: ['./node-selection-performance.component.scss'], +}) +export class NodeSelectionPerformanceComponent implements OnInit, OnDestroy { + treeSelection: string = undefined; + humanizeDuration: HumanizeDuration; + + meanValues: TreePerformance; + serviceTimeValues: Map<Variant, PerformanceStats> = new Map(); + waitingTimeValues: Map<Variant, PerformanceStats> = new Map(); + idleTimeValues: Map<Variant, PerformanceStats> = new Map(); + cycleTimeValues: Map<Variant, PerformanceStats> = new Map(); + + public variants: Variant[]; + + public variantIndices = new Map<Variant, number>(); + + private _destroy$ = new Subject(); + + constructor( + private processTreeService: ProcessTreeService, + public performanceService: PerformanceService, + public performanceColorScaleService: ModelPerformanceColorScaleService, + public sharedDataService: SharedDataService, + private variantService: VariantService, + private changeDetectorRef: ChangeDetectorRef + ) { + const durationLang = new HumanizeDurationLanguage(); + this.humanizeDuration = new HumanizeDuration(durationLang); + } + + ngOnInit(): void { + this.processTreeService.selectedTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((tree) => { + if ( + tree === undefined || + !this.performanceService.anyTreePerformanceActive() + ) { + this.treeSelection = undefined; + this.meanValues = undefined; + return; + } + this.treeSelection = tree?.toString(); + const meanValues = this.performanceService.allValuesMean.get(tree?.id); + if (tree && meanValues) { + this.meanValues = this.performanceService.allValuesMean.get(tree.id); + + const availableVariants = Array.from( + this.performanceService.allValues.get(tree.id).entries() + ).filter( + ([v, perf]) => + perf.service_time || + perf.waiting_time || + perf.idle_time || + perf.cycle_time + ); + + availableVariants.sort((a, b) => a[0].bid - b[0].bid); + this.variants = availableVariants.map((v) => v[0]); + availableVariants + .map( + ([v, p]) => + <[number, TreePerformance]>[ + this.variantService.variants.indexOf(v), + p, + ] + ) + .forEach(([vIdx, p]) => { + const v = this.variantService.variants[vIdx]; + this.variantIndices.set(v, vIdx + 1); + this.serviceTimeValues.set( + v, + this.performanceService.allValues.get(tree.id).get(v) + .service_time + ); + this.waitingTimeValues.set( + v, + this.performanceService.allValues.get(tree.id).get(v) + .waiting_time + ); + this.cycleTimeValues.set( + v, + this.performanceService.allValues.get(tree.id).get(v).cycle_time + ); + this.idleTimeValues.set( + v, + this.performanceService.allValues.get(tree.id).get(v).idle_time + ); + }); + } + + this.changeDetectorRef.markForCheck(); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } +} + +export class PerformanceValues { + variantName: string | undefined; + performance: PerformanceStats; +} diff --git a/src/frontend/src/app/components/performance/performance-progress-bar/performance-progress-bar.component.css b/src/frontend/src/app/components/performance/performance-progress-bar/performance-progress-bar.component.css new file mode 100644 index 0000000000000000000000000000000000000000..76f93f935fc43fb7bf1a5253e6f282f578b3b4fb --- /dev/null +++ b/src/frontend/src/app/components/performance/performance-progress-bar/performance-progress-bar.component.css @@ -0,0 +1,15 @@ +.loader-overlay { + position: absolute; + width: 100%; + height: 100%; + background-color: rgb(0 0 0 / 50%); + top: 0; + z-index: 1000; + align-items: center; + display: flex; + justify-content: center; +} + +.progress-color { + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); +} diff --git a/src/frontend/src/app/components/performance/performance-progress-bar/performance-progress-bar.component.html b/src/frontend/src/app/components/performance/performance-progress-bar/performance-progress-bar.component.html new file mode 100644 index 0000000000000000000000000000000000000000..7b9c8457e3507ed6b6799f7f103298d84be5b6f4 --- /dev/null +++ b/src/frontend/src/app/components/performance/performance-progress-bar/performance-progress-bar.component.html @@ -0,0 +1,38 @@ +<div + class="progress loader-overlay" + *ngIf="variantPerformanceService.performanceUpdateIsInProgress" +> + <div class="container"> + <div class="row"> + <div class="col"></div> + <div class="col-6 text-center"> + <p style="color: whitesmoke; font-size: 14px"> + Loading performance statistics ... + </p> + </div> + <div class="col"></div> + </div> + <div class="row"> + <div class="col"></div> + <div class="col-6"> + <div class="progress"> + <div + class="progress-bar progress-bar-striped progress-bar-animated progress-color" + role="progressbar" + [attr.aria-valuenow]=" + variantPerformanceService.performanceUpdateProgress + " + aria-valuemin="0" + aria-valuemax="1" + [style.width]=" + ( + variantPerformanceService.performanceUpdateProgress * 100 + ).toString() + '%' + " + ></div> + </div> + </div> + <div class="col"></div> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/performance/performance-progress-bar/performance-progress-bar.component.spec.ts b/src/frontend/src/app/components/performance/performance-progress-bar/performance-progress-bar.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..eeecf0bd1c06f9c7554c0b1006431e28f8f09026 --- /dev/null +++ b/src/frontend/src/app/components/performance/performance-progress-bar/performance-progress-bar.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PerformanceProgressBarComponent } from './performance-progress-bar.component'; + +describe('PerformanceProgressBarComponent', () => { + let component: PerformanceProgressBarComponent; + let fixture: ComponentFixture<PerformanceProgressBarComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PerformanceProgressBarComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PerformanceProgressBarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/performance/performance-progress-bar/performance-progress-bar.component.ts b/src/frontend/src/app/components/performance/performance-progress-bar/performance-progress-bar.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..dc657cca8bd39b1dd7f8b6c5d831b83a702cb57c --- /dev/null +++ b/src/frontend/src/app/components/performance/performance-progress-bar/performance-progress-bar.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; +import { VariantPerformanceService } from 'src/app/services/variant-performance.service'; + +@Component({ + selector: 'app-performance-progress-bar', + templateUrl: './performance-progress-bar.component.html', + styleUrls: ['./performance-progress-bar.component.css'], +}) +export class PerformanceProgressBarComponent { + constructor(public variantPerformanceService: VariantPerformanceService) {} +} diff --git a/src/frontend/src/app/components/performance/performance-table/performance-table.component.html b/src/frontend/src/app/components/performance/performance-table/performance-table.component.html new file mode 100644 index 0000000000000000000000000000000000000000..84ed120369129d4a220f6ac234f6cfd9aeff9b64 --- /dev/null +++ b/src/frontend/src/app/components/performance/performance-table/performance-table.component.html @@ -0,0 +1,78 @@ +<table + class="table table-sm table-striped table-dark table-hover table-bordered mb-0" + style="font-size: small" + *ngIf="performanceValues" +> + <tbody + *ngIf="!isBodyExpanded" + (click)="isBodyExpanded = !isBodyExpanded" + style="cursor: pointer" + > + <tr> + <td + style=" + border-right: none; + white-space: nowrap; + vertical-align: middle; + width: 35%; + " + > + {{ heading }} (mean) + </td> + <td style="width: 60%" *ngIf="!isBodyExpanded"> + {{ performanceValues.mean | humanizeDuration : false : true : 3 }} + </td> + <td colspan="2" style="width: 5%; border-left: none"> + <i class="bi bi-caret-left-fill" *ngIf="!isBodyExpanded"></i> + <i class="bi bi-caret-down-fill" *ngIf="isBodyExpanded"></i> + </td> + </tr> + </tbody> + <tbody + *ngIf="isBodyExpanded" + (click)="isBodyExpanded = !isBodyExpanded" + style="cursor: pointer" + > + <tr> + <td style="width: 35%" rowspan="6">{{ heading }}</td> + <td class="performance-table-metric">Mean:</td> + <td class="performance-table-value"> + {{ performanceValues.mean | humanizeDuration }} + </td> + <td rowspan="6" style="width: 5%; border-left: none"> + <i class="bi bi-caret-left-fill" *ngIf="!isBodyExpanded"></i> + <i class="bi bi-caret-down-fill" *ngIf="isBodyExpanded"></i> + </td> + </tr> + <tr> + <td class="performance-table-metric">Min:</td> + <td class="performance-table-value"> + {{ performanceValues.min | humanizeDuration }} + </td> + </tr> + <tr> + <td class="performance-table-metric">Max:</td> + <td class="performance-table-value"> + {{ performanceValues.max | humanizeDuration }} + </td> + </tr> + <tr> + <td class="performance-table-metric">Stdev:</td> + <td class="performance-table-value"> + {{ performanceValues.stdev | humanizeDuration }} + </td> + </tr> + <tr> + <td class="performance-table-metric">95th Percentile:</td> + <td class="performance-table-value"> + {{ performanceValues["95th"] | humanizeDuration }} + </td> + </tr> + <tr> + <td class="performance-table-metric">50th Percentile:</td> + <td class="performance-table-value"> + {{ performanceValues["50th"] | humanizeDuration }} + </td> + </tr> + </tbody> +</table> diff --git a/src/frontend/src/app/components/performance/performance-table/performance-table.component.scss b/src/frontend/src/app/components/performance/performance-table/performance-table.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..dd86ce17fad8b791ee0024e24f38beeb792ced8c --- /dev/null +++ b/src/frontend/src/app/components/performance/performance-table/performance-table.component.scss @@ -0,0 +1,25 @@ +table { + td:nth-child(2) { + width: 100%; + } + + td:first-child { + white-space: nowrap; + } +} + +thead { + cursor: pointer; +} + +.performance-table-value { + width: 40% !important; +} + +.performance-table-metric { + width: 20% !important; +} + +.performance-table-heading { + width: 35% !important; +} \ No newline at end of file diff --git a/src/frontend/src/app/components/performance/performance-table/performance-table.component.spec.ts b/src/frontend/src/app/components/performance/performance-table/performance-table.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..64a2a08ce45a68d2200fac667406b58b6b91b81d --- /dev/null +++ b/src/frontend/src/app/components/performance/performance-table/performance-table.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PerformanceTableComponent } from './performance-table.component'; + +describe('PerformanceTableComponent', () => { + let component: PerformanceTableComponent; + let fixture: ComponentFixture<PerformanceTableComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PerformanceTableComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PerformanceTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/performance/performance-table/performance-table.component.ts b/src/frontend/src/app/components/performance/performance-table/performance-table.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..4390ddbafb3eea29dd66cb52ed995d855602399f --- /dev/null +++ b/src/frontend/src/app/components/performance/performance-table/performance-table.component.ts @@ -0,0 +1,18 @@ +import { Component, Input } from '@angular/core'; +import { PerformanceStats } from 'src/app/objects/Variants/variant_element'; + +@Component({ + selector: 'app-performance-table', + templateUrl: './performance-table.component.html', + styleUrls: ['./performance-table.component.scss'], +}) +export class PerformanceTableComponent { + @Input() + performanceValues: PerformanceStats; + + @Input() + heading: string; + + @Input() + isBodyExpanded = false; +} diff --git a/src/frontend/src/app/components/performance/performance.component.html b/src/frontend/src/app/components/performance/performance.component.html new file mode 100644 index 0000000000000000000000000000000000000000..98f9c536a110ba574c45b22c070fdc36a136907e --- /dev/null +++ b/src/frontend/src/app/components/performance/performance.component.html @@ -0,0 +1,89 @@ +<ul class="nav nav-tabs bg-dark" id="myTab" role="tablist"> + <li class="nav-item" role="presentation"> + <button + class="nav-link active button" + id="selection-tab" + data-bs-toggle="tab" + data-bs-target="#selection" + role="tab" + aria-controls="selection" + aria-selected="true" + > + Selection + </button> + </li> + <li class="nav-item" role="presentation"> + <button + class="nav-link button" + id="colormap-tab" + data-bs-toggle="tab" + data-bs-target="#colormap" + type="button" + role="tab" + aria-controls="colormap" + aria-selected="false" + > + Color Map + </button> + </li> +</ul> +<div class="tab-content" id="myTabContent"> + <div + class="tab-pane fade show active" + id="selection" + role="tabpanel" + aria-labelledby="selection-tab" + > + <div + *ngIf=" + modelViewModeService.viewMode === VM.PERFORMANCE && + processTreeService.selectedTree && + performanceValues.length > 0; + else unavailableInfoNodeSelection + " + style="overflow: auto; display: flex; flex-direction: column" + > + <app-tree-string-renderer + [styled_tree_string]="treeSelection" + ></app-tree-string-renderer> + <div class="tree-selection-body"> + <app-node-selection-performance></app-node-selection-performance> + </div> + </div> + <ng-template #unavailableInfoNodeSelection> + <app-unavailable-info> + No performance values available. + <br /> + Discover a tree model and compute the performance for a variant in the + variant explorer by clicking on the + <i class="bi bi-toggle2-off" style="color: white"></i> symbol. + <br /> + Then you can select a tree node for detailed performance values. + </app-unavailable-info> + </ng-template> + </div> + <div + class="tab-pane fade color-map-tab" + id="colormap" + role="tabpanel" + aria-labelledby="colormap-tab" + > + <app-tree-performance-color-map + *ngIf=" + modelViewModeService.viewMode === VM.PERFORMANCE && + processTreeService.selectedTree && + performanceValues.length > 0; + else unavailableInfoColorMap + " + ></app-tree-performance-color-map> + <ng-template #unavailableInfoColorMap> + <app-unavailable-info> + No performance values available. + <br /> + Discover a tree model and compute the performance for a variant in the + variant explorer by clicking on the + <i class="bi bi-toggle2-off" style="color: white"></i> symbol. + </app-unavailable-info> + </ng-template> + </div> +</div> diff --git a/src/frontend/src/app/components/performance/performance.component.scss b/src/frontend/src/app/components/performance/performance.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..b6c4f2813789ef7fe4493a0db910ca26c27e37c8 --- /dev/null +++ b/src/frontend/src/app/components/performance/performance.component.scss @@ -0,0 +1,36 @@ +:host { + background-color: var(--box-background-color); + display: flex; + flex-direction: column; + overflow: auto; + position: absolute; +} + +.color-span { + height: 5%; + width: 100%; + display: inline-block; +} + +.tree-selection-title { + background-color: rgba(var(--bs-dark-rgb)); + padding: 5px; + filter: drop-shadow(0 2px 3px black); +} + +.tree-selection-body { + overflow: auto; + + table { + margin: 0; + margin-top: 5px; + } +} + +.accordion-body { + padding: 0; +} + +.color-map-tab { + padding: 0 10px; +} diff --git a/src/frontend/src/app/components/performance/performance.component.spec.ts b/src/frontend/src/app/components/performance/performance.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..04bd6ff771d86668845cc3b7d2bb9a1f8c6eba8e --- /dev/null +++ b/src/frontend/src/app/components/performance/performance.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ModelPerformanceComponent } from './performance.component'; + +describe('PerformanceComponent', () => { + let component: ModelPerformanceComponent; + let fixture: ComponentFixture<ModelPerformanceComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ModelPerformanceComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ModelPerformanceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/performance/performance.component.ts b/src/frontend/src/app/components/performance/performance.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..9f78806eb39d1ef442427efd33aa8d0e27dbcfbc --- /dev/null +++ b/src/frontend/src/app/components/performance/performance.component.ts @@ -0,0 +1,151 @@ +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { + ChangeDetectorRef, + Component, + OnInit, + ElementRef, + Inject, + Renderer2, + OnDestroy, +} from '@angular/core'; + +import { + HumanizeDuration, + HumanizeDurationLanguage, +} from 'humanize-duration-ts'; +import { + ProcessTree, + TreePerformance, +} from 'src/app/objects/ProcessTree/ProcessTree'; +import { ModelPerformanceColorScaleService } from 'src/app/services/performance-color-scale.service'; +import { PerformanceService } from 'src/app/services/performance.service'; +import { PerformanceStats } from 'src/app/objects/Variants/variant_element'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { ModelViewModeService } from 'src/app/services/viewModeServices/model-view-mode.service'; +import { ViewMode } from 'src/app/objects/ViewMode'; +@Component({ + selector: 'app-performance', + templateUrl: './performance.component.html', + styleUrls: ['./performance.component.scss'], +}) +export class ModelPerformanceComponent + extends LayoutChangeDirective + implements OnInit, OnDestroy +{ + duration: HumanizeDuration; + + colorValues = []; + + performanceValues = []; + + treeSelection: string = undefined; + selectionPerformances: [string, PerformanceStats][] = undefined; + + private _destroy$ = new Subject(); + + public VM = ViewMode; + + constructor( + public performanceService: PerformanceService, + public processTreeService: ProcessTreeService, + public performanceColorScaleService: ModelPerformanceColorScaleService, + public modelViewModeService: ModelViewModeService, + private changeDetectionRef: ChangeDetectorRef, + renderer: Renderer2, + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef + ) { + super(elRef.nativeElement, renderer); + const durationLang = new HumanizeDurationLanguage(); + this.duration = new HumanizeDuration(durationLang); + } + + ngOnInit(): void { + this.processTreeService.currentDisplayedProcessTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((tree) => { + this.performanceValues = []; + if (tree && tree.performance) { + this.nodePerformance(tree); + this.changeDetectionRef.markForCheck(); + } else if (tree === undefined) { + this.selectionPerformances = []; + this.treeSelection = undefined; + this.changeDetectionRef.markForCheck(); + return; + } + }); + + this.processTreeService.selectedTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((tree) => { + if ( + tree === undefined || + !this.performanceService.anyTreePerformanceActive() + ) { + this.selectionPerformances = []; + this.treeSelection = undefined; + this.changeDetectionRef.markForCheck(); + return; + } + + this.selectionPerformances = []; + this.treeSelection = tree?.toString(); + + if (tree && this.performanceService.allValuesMean.has(tree.id)) { + if (this.performanceService.allValuesMean.get(tree.id).service_time) { + this.selectionPerformances.push([ + 'Mean', + this.performanceService.allValuesMean.get(tree.id).service_time, + ]); + } + Array.from(this.performanceService.allValues.get(tree.id).entries()) + .map(([v, p]) => <[number, TreePerformance]>[v.bid, p]) + .filter(([v, p]) => p.service_time) + .sort((a, b) => (a[0] = b[0])) + .forEach(([v, p]) => { + if (p.service_time) { + this.selectionPerformances.push([ + `Variant No. ${v}`, + p.service_time, + ]); + } + }); + } + this.changeDetectionRef.markForCheck(); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + private nodePerformance(treeNode: ProcessTree): void { + if (treeNode.performance) { + this.performanceValues.push([treeNode.toString(), treeNode.performance]); + treeNode.children.forEach((n) => this.nodePerformance(n)); + } + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + + handleVisibilityChange(visibility: boolean): void {} + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} +} + +export namespace ModelPerformanceComponent { + export const componentName = 'ModelPerformanceComponent'; +} diff --git a/src/frontend/src/app/components/performance/tree-performance-color-map/tree-performance-color-map.component.html b/src/frontend/src/app/components/performance/tree-performance-color-map/tree-performance-color-map.component.html new file mode 100644 index 0000000000000000000000000000000000000000..c53e26968e2a52277d5fe657071ab32ac5f31380 --- /dev/null +++ b/src/frontend/src/app/components/performance/tree-performance-color-map/tree-performance-color-map.component.html @@ -0,0 +1,115 @@ +<form> + <div class="mb-3"> + <label for="compareModeSelect" class="form-label text-white">Mode</label> + <select + id="compareModeSelect" + class="form-select form-select-sm" + aria-label="performance color scale selection" + aria-describedby="compareModeHelp" + [(ngModel)]="performanceColorScaleService.selectedColorScale.mode" + (change)="colorScaleChange($event)" + name="compareMode" + > + <option + *ngFor="let colorScale of availableColorMaps" + [value]="colorScale.key" + > + {{ colorScale.name }} + </option> + </select> + <div + style=" + display: flex; + justify-content: space-between; + padding-left: 5px; + padding-right: 10px; + " + > + <div class="form-text">{{ modeLongHelpText }}</div> + <div class="form-text"> + <i + class="bi bi-info-circle" + [ngbTooltip]="modeLongHelpText" + triggers="hover" + container="body" + ></i> + </div> + </div> + </div> + <div class="mb-3"> + <label class="form-label text-white">Performance Indicator</label> + <select + class="form-select form-select-sm" + aria-label="performance indicator for color scale selection" + [(ngModel)]=" + performanceColorScaleService.selectedColorScale.performanceIndicator + " + (change)="colorScaleChange($event)" + name="performanceIndicator" + > + <option + *ngFor="let pMeasure of availablePerformanceIndicators" + [value]="pMeasure" + > + {{ pMeasure }} + </option> + </select> + <div class="form-text"> + Choose which performance indicator to use for the color map. + </div> + </div> + <div class="mb-3"> + <label class="form-label text-white">Statistical Measure</label> + <select + class="form-select form-select-sm" + aria-label="statistic aggregation for color scale seleciton" + [(ngModel)]="performanceColorScaleService.selectedColorScale.statistic" + (change)="colorScaleChange($event)" + name="performanceValue" + > + <option + *ngFor="let pValue of availablePerformanceValues" + [value]="pValue" + > + {{ pValue }} + </option> + </select> + <div class="form-text"> + Choose which statistical measure to use for the color map. + </div> + </div> +</form> + +<div + class="card" + style="width: 100%; background: transparent" + *ngIf="colorMapValues" +> + <div class="card-body"> + <h5 + *ngIf=" + performanceColorScaleService.selectedColorScale.mode === + 'compareVariants' && selectedTree !== undefined + " + class="card-title text-white" + > + Color Map - {{ selectedTree }} + </h5> + <h5 + *ngIf=" + performanceColorScaleService.selectedColorScale.mode !== + 'compareVariants' || selectedTree === undefined + " + class="card-title text-white" + > + Color Map + </h5> + <p class="card-text"> + <app-color-map + [colorMapValues]="colorMapValues" + [firstColorStriped]="true" + [firstColorDetached]="true" + ></app-color-map> + </p> + </div> +</div> diff --git a/src/frontend/src/app/components/performance/tree-performance-color-map/tree-performance-color-map.component.scss b/src/frontend/src/app/components/performance/tree-performance-color-map/tree-performance-color-map.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/performance/tree-performance-color-map/tree-performance-color-map.component.spec.ts b/src/frontend/src/app/components/performance/tree-performance-color-map/tree-performance-color-map.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..86c24442397d330b8d41d22fb1aeb0fc35a7deaf --- /dev/null +++ b/src/frontend/src/app/components/performance/tree-performance-color-map/tree-performance-color-map.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TreePerformanceColorMapComponent } from './tree-performance-color-map.component'; + +describe('TreePerformanceColorMapComponent', () => { + let component: TreePerformanceColorMapComponent; + let fixture: ComponentFixture<TreePerformanceColorMapComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [TreePerformanceColorMapComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TreePerformanceColorMapComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/performance/tree-performance-color-map/tree-performance-color-map.component.ts b/src/frontend/src/app/components/performance/tree-performance-color-map/tree-performance-color-map.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..cd8b36762e6958dd5b801fa92623c96756de51e5 --- /dev/null +++ b/src/frontend/src/app/components/performance/tree-performance-color-map/tree-performance-color-map.component.ts @@ -0,0 +1,114 @@ +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { ModelPerformanceColorScaleService } from '../../../services/performance-color-scale.service'; +import { SharedDataService } from '../../../services/sharedDataService/shared-data.service'; +import { PerformanceService } from '../../../services/performance.service'; +import { + buildColorValues, + ColorMapValue, +} from '../color-map/color-map.component'; +import { ProcessTree } from '../../../objects/ProcessTree/ProcessTree'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + selector: 'app-tree-performance-color-map', + templateUrl: './tree-performance-color-map.component.html', + styleUrls: ['./tree-performance-color-map.component.scss'], +}) +export class TreePerformanceColorMapComponent implements OnInit, OnDestroy { + availableColorMaps = ModelPerformanceColorScaleService.COLOR_MAPS; + availablePerformanceValues = ['mean', 'min', 'max', 'stdev']; + availablePerformanceIndicators = [ + 'service_time', + 'waiting_time', + 'cycle_time', + 'idle_time', + ]; + modeHelpText = ''; + modeLongHelpText = ''; + + selectedTree: ProcessTree; + + colorMapValues: ColorMapValue[]; + + private _destroy$ = new Subject(); + + constructor( + public performanceColorScaleService: ModelPerformanceColorScaleService, + private sharedDataService: SharedDataService, + private processTreeService: ProcessTreeService, + private performanceService: PerformanceService + ) {} + + ngOnInit(): void { + this.modeHelpText = ModelPerformanceColorScaleService.COLOR_MAPS.filter( + (x) => x.key === this.performanceColorScaleService.selectedColorScale.mode + )[0]?.description; + this.modeLongHelpText = ModelPerformanceColorScaleService.COLOR_MAPS.filter( + (x) => x.key === this.performanceColorScaleService.selectedColorScale.mode + )[0]?.longDescription; + this.performanceColorScaleService.currentColorScale + .pipe(takeUntil(this._destroy$)) + .subscribe((colorScale) => { + if (colorScale && this.performanceService.anyTreePerformanceActive()) { + this.updateColorMapValues(); + } + }); + this.processTreeService.selectedTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((t) => { + if ( + t && + this.performanceColorScaleService.selectedColorScale.mode === + 'compareVariants' + ) { + this.selectedTree = t; + this.updateColorMapValues(); + } + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + colorScaleChange(e): void { + const selected = this.availableColorMaps.find( + (m) => m.key === this.performanceColorScaleService.selectedColorScale.mode + ); + this.modeHelpText = selected.description; + this.modeLongHelpText = selected.longDescription; + this.performanceColorScaleService.updateCurrentColorScale(); + + if (this.processTreeService.currentDisplayedProcessTree?.performance) { + this.updateColorMapValues(); + } + } + + updateColorMapValues(): ColorMapValue[] { + if (this.performanceColorScaleService.getColorScale() === undefined) { + return; + } + let colorScale; + if ( + this.performanceColorScaleService.selectedColorScale.mode === + 'compareNodes' + ) { + colorScale = this.performanceColorScaleService + .getColorScale() + .values() + .next().value; + } else { + colorScale = this.performanceColorScaleService + .getColorScale() + .get(this.selectedTree.id); + } + let values = this.performanceColorScaleService.getAllAllValues(); + if (colorScale !== undefined) { + this.colorMapValues = buildColorValues(colorScale, values); + } else { + this.colorMapValues = undefined; + } + } +} diff --git a/src/frontend/src/app/components/process-tree-editor/expert-mode/expert-mode.component.html b/src/frontend/src/app/components/process-tree-editor/expert-mode/expert-mode.component.html new file mode 100644 index 0000000000000000000000000000000000000000..483d39712ef61282cac19af901ca038ebeb1707b --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/expert-mode/expert-mode.component.html @@ -0,0 +1,140 @@ +<div + class="expert-mode-open-button" + [@openCloseComponent]="editorActive ? 'openComponent' : 'closeComponent'" +> + <div + class="expert-mode-header expert-mode-button d-flex" + (click)="toggleExpertMode()" + > + <i class="bi bi-search"></i> + <span class="ms-2">Expert Mode</span> + </div> + + <div + class="expert-mode-app-container" + [@fadeInOutComponent]=" + editorActive ? 'fadeInComponent' : 'fadeOutComponent' + " + > + <form class="form" [formGroup]="syntaxTreeInput" (ngSubmit)="onSubmit()"> + <div class="form-container"> + <div [hidden]="!edit"> + <ng-template #treeStringTooltip> + A valid process tree string uses a parent operator followed by its + child leafs and or subtrees listed in left to right order surronded + by normal parenthesis<br /> + <br /> + <table class="tooltip-table"> + <tr> + <th>Operator</th> + <th>String Encoding</th> + </tr> + <tr> + <td>✕</td> + <td>X</td> + </tr> + <tr> + <td>➔</td> + <td>-></td> + </tr> + <tr> + <td>↺</td> + <td>*</td> + </tr> + <tr> + <td>∧</td> + <td>+</td> + </tr> + <tr> + <td>τ</td> + <td>*tau*</td> + </tr> + </table> + </ng-template> + <span class="secondary-text fw-bold mb-1 tree-string-heading" + >Editing Tree String + <i + class="bi bi-question-circle-fill font-large ms-1 secondary-text fs-6 cursor-help" + [ngbTooltip]="treeStringTooltip" + triggers="hover" + container="body" + > + </i> + </span> + + <textarea + class="expert-mode-editor" + #textEditor + [formControl]="syntax_tree" + spellcheck="false" + > + </textarea> + </div> + + <div + [hidden]="edit || !currentlyDisplayedTreeInExpertMode" + (click)="toggleEditor(true)" + > + <span class="secondary-text fw-bold mb-1 tree-string-heading" + >Tree String</span + > + <app-tree-string-renderer + [styled_tree_string]="styled_tree_string" + [custom_class]="'styled-input-field cursor-pointer'" + ></app-tree-string-renderer> + </div> + </div> + + <ul + *ngIf=" + (syntax_tree.invalid && (syntax_tree.dirty || syntax_tree.touched)) || + backendErrorMessage + " + class="syntax-error" + > + <div *ngIf="syntax_tree.errors?.['unknowActivities']"> + <li + *ngFor="let unknownActivity of syntax_tree.errors?.['unknowActivities']" + > + Unknown activity name {{ unknownActivity.name }} at position + {{ unknownActivity.index }} + </li> + </div> + <div *ngIf="syntax_tree.errors?.['imbalanced']"> + <li *ngFor="let imbalancedItem of syntax_tree.errors?.['imbalanced']"> + Imbalanced {{ imbalancedItem.symbol }} at position + {{ imbalancedItem.index + 1 }} + </li> + </div> + <li *ngIf="syntax_tree.errors?.['apostrophe']"> + Imbalanced Apostrophes + </li> + + <li + *ngIf="backendErrorMessage && syntax_tree.pristine" + class="backend-error" + > + <span> {{ backendErrorMessage }} </span> + </li> + </ul> + + <div class="expert-mode-tool-bar mt-3"> + <button + type="submit" + class="button expert-mode-button" + [disabled]="!allowRender || syntax_tree.errors?.['imbalanced'] || syntax_tree.errors?.['apostrophe']" + > + Render Tree + </button> + + <button + type="button" + class="button expert-mode-button" + (click)="toggleEditor(!edit)" + > + {{ edit ? "Close Editor" : "Open Editor" }} + </button> + </div> + </form> + </div> +</div> diff --git a/src/frontend/src/app/components/process-tree-editor/expert-mode/expert-mode.component.scss b/src/frontend/src/app/components/process-tree-editor/expert-mode/expert-mode.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..bc6dc4bb1780c1e374356f1a87b6168fc0db228f --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/expert-mode/expert-mode.component.scss @@ -0,0 +1,100 @@ + +.tree-syntax-string{ + color : var(--text-secondary); +} + +.expert-mode-body{ + background-color: var(--box-background-color); +} + +.form-container{ + width: 90%; + height: 45%; + display: block; + transform: translateZ(0); + text-size-adjust: none; + margin: 0.5rem auto 0; +} + +.tree-string-heading{ + vertical-align: super; +} + +.expert-mode-tool-bar{ + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); +} + +.expert-mode-open-button { + right: 0; + bottom: 0; + position: absolute; + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); + border-top-left-radius: 5px; + display: flex; + place-content: flex-end flex-start; + align-items: stretch; + flex-direction: column; +} + +.expert-mode-app-container{ + width: 100%; + height: 100%; + background-color: var(--box-background-color); +} + +.expert-mode-button{ + color: var(--text-secondary); + font-size: var(--standard-font-size); + cursor : pointer; +} + +.expert-mode-header{ + color: var(--text-secondary); + font-size: var(--standard-font-size); + padding : 2px 0 2px 6px; +} + +.form{ + width: 100%; + height: 100%; + display: flex; + flex-flow: column nowrap; + place-content: center space-between; + align-items: stretch; +} + +.backend-error{ + color : var(--bs-danger); +} + +.syntax-error{ + color : var(--bs-warning); + font-size : smaller; + overflow: scroll; + max-height: 8em; + margin-top: 0.5rem; + margin-bottom: 0.25rem; +} + +.expert-mode-editor{ + display: block; + position: absolute; + z-index: 2; + margin: 0; + border-radius: 3px; + color : var(--text-secondary); + overflow: auto; + resize: none; + width: 100%; + height : 100%; + cursor:text; + padding: 10px; + font-size: var(--standard-font-size); + letter-spacing: 0.25px; + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); +} + +.expert-mode-editor:focus{ + outline: none; + box-shadow: none; +} diff --git a/src/frontend/src/app/components/process-tree-editor/expert-mode/expert-mode.component.spec.ts b/src/frontend/src/app/components/process-tree-editor/expert-mode/expert-mode.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..79fbd95e54600cbd1ac10f619ab66a5a639c11e8 --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/expert-mode/expert-mode.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExpertModeComponent } from './expert-mode.component'; + +describe('ExpertModeComponent', () => { + let component: ExpertModeComponent; + let fixture: ComponentFixture<ExpertModeComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ExpertModeComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ExpertModeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/process-tree-editor/expert-mode/expert-mode.component.ts b/src/frontend/src/app/components/process-tree-editor/expert-mode/expert-mode.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..21f5e447ebccf7d31174fbee51320515e490e70e --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/expert-mode/expert-mode.component.ts @@ -0,0 +1,301 @@ +import { LogService } from 'src/app/services/logService/log.service'; +import { ProcessTreeService } from './../../../services/processTreeService/process-tree.service'; +import { BackendService } from 'src/app/services/backendService/backend.service'; +import { + Component, + OnInit, + ViewChild, + ElementRef, + OnDestroy, +} from '@angular/core'; +import { + AbstractControl, + UntypedFormControl, + ValidationErrors, + ValidatorFn, + UntypedFormGroup, +} from '@angular/forms'; +import { + fadeInOutComponent, + openCloseComponent, +} from 'src/app/animations/component-animations'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + selector: 'app-expert-mode', + templateUrl: './expert-mode.component.html', + styleUrls: ['./expert-mode.component.scss'], + animations: [fadeInOutComponent, openCloseComponent], +}) +export class ExpertModeComponent implements OnInit, OnDestroy { + syntax_tree_string: string = ''; + syntaxTreeInput: any; + edit: boolean = true; + allowRender: boolean = true; + activityNameRegEx = new RegExp("'([^']*)'", 'g'); + backendErrorMessage: string; + styled_tree_string: string = null; + editorActive: boolean = false; + + imbalancedItems: Array<imbalancedItem>; + + @ViewChild('expertModeButton') expertModeButton: ElementRef; + @ViewChild('textEditor') textEditor: ElementRef<HTMLDivElement>; + + currentlyDisplayedTreeInExpertMode; + + private _destroy$ = new Subject(); + + constructor( + private logService: LogService, + private backendService: BackendService, + private processTreeService: ProcessTreeService + ) {} + + ngOnInit() { + this.syntaxTreeInput = new UntypedFormGroup({ + syntax_tree: new UntypedFormControl('', { + validators: [ + this.balancedParenthesisValidator(), + this.unknownActivityNameValidator(), + this.balancedApostropheValidator(), + ], + updateOn: 'change', + }), + }); + + /* Handling the styling as the input changes, currently problematic due to issues with input cursor tracking + + this.syntax_tree.valueChanges.pipe( + debounceTime(500), + distinctUntilChanged(), + takeUntil(this._destroy$) + ).subscribe(res => { + res = this.strip_html(res); + this.syntax_tree.setValue(res, {emitEvent : false}); + }) + */ + + // If the tree changes and expert mode is open, compute the syntax tree string + this.processTreeService.currentDisplayedProcessTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((tree) => { + this.collectCurrentTreeString(tree); + this.backendErrorMessage = null; + }); + + this.processTreeService.currentTreeString$ + .pipe(takeUntil(this._destroy$)) + .subscribe((treeString) => { + this.syntax_tree.setValue(treeString); + this.highlightText(); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + // Preconducts expert mode specific highlighting and passes the tree-string down to the tree-string-renderer-component + highlightText() { + this.styled_tree_string = this.highlightImbalancedParenthesis( + this.syntax_tree.value + ); + } + + toggleEditor(edit: boolean) { + this.edit = edit; + if (!edit) this.highlightText(); + } + + highlightImbalancedParenthesis(value: any) { + let runningOffset = 0; + + if (this.imbalancedItems && this.imbalancedItems.length > 0) { + this.imbalancedItems.sort((a, b) => a.index - b.index); + + for (let imbalancedItem of this.imbalancedItems) { + const highlightedPara = + '<span class="imbalanced-parenthesis">' + + imbalancedItem.symbol + + '</span>'; + value = + value.slice(0, imbalancedItem.index + runningOffset) + + highlightedPara + + value.slice(imbalancedItem.index + runningOffset + 1, value.length); + runningOffset += highlightedPara.length - 1; + } + } + + return value; + } + + strip_html(value: any): string { + const regex = new RegExp('<[^>]*>', 'g'); + value = value.replaceAll(regex, ''); + return value; + } + + onSubmit() { + this.allowRender = false; + let treeString = this.syntax_tree.value; + treeString = this.strip_html(treeString); + + const $pendingTreeParse = this.backendService.renderStringToPT(treeString); + + $pendingTreeParse + .pipe(takeUntil(this._destroy$)) + .subscribe((result: any) => { + if (!result.errors) { + console.warn('Expert Mode Tree Update'); + this.processTreeService.set_currentDisplayedProcessTree_with_Cache( + result.tree + ); + this.backendErrorMessage = null; + } else { + this.backendErrorMessage = result.errors; + this.syntax_tree.markAsPristine(); + } + this.allowRender = true; + }); + } + + replaceRichTextPlaceholderChars(treeString: string): string { + const richTextChar = new RegExp('&[\\w]+;', 'g'); + + // Replace the > with > + treeString = treeString.replace('>', '>'); + + // Remove all the unknown richTextChars + treeString = treeString.replace(richTextChar, ''); + return treeString; + } + + get syntax_tree(): UntypedFormControl { + return this.syntaxTreeInput.get('syntax_tree')!; + } + + toggleExpertMode() { + this.editorActive = !this.editorActive; + if (this.editorActive) { + this.collectCurrentTreeString( + this.processTreeService.currentDisplayedProcessTree + ); + } + } + + // If expert mode is open, compute the syntax tree string + private collectCurrentTreeString(tree) { + // Check if tree exists, if the expert mode is active and if it did change + if (tree && tree !== this.currentlyDisplayedTreeInExpertMode) { + this.backendService.computeTreeString(tree); + this.currentlyDisplayedTreeInExpertMode = tree; + this.edit = false; + } + } + + balancedParenthesisValidator(): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + let stack = new Array<imbalancedItem>(); + let imbalanced = false; + + let imbalancedItems = new Array<imbalancedItem>(); + + const popStack = function ( + checkSymbol: string, + index: number, + expected: string + ) { + let item = stack.pop(); + + // If we have a mismatch, add it to the imbalanced Items + if (item && item.symbol !== checkSymbol) { + imbalancedItems.push(item); + imbalanced = true; + + // If the stack is already empty we get a mismatch + } else if (!item) { + imbalancedItems.push(new imbalancedItem(expected, index)); + imbalanced = true; + } + }; + + for (let i = 0; i < control.value.length; i++) { + switch (control.value[i]) { + case '(': + stack.push(new imbalancedItem('(', i)); + break; + case ')': + popStack('(', i, ')'); + break; + case '{': + stack.push(new imbalancedItem('{', i)); + break; + case '}': + popStack('{', i, '}'); + break; + case '[': + stack.push(new imbalancedItem('[', i)); + break; + case ']': + popStack('[', i, ']'); + break; + default: + continue; + } + } + + if (stack.length > 0) { + imbalancedItems.push(...stack); + imbalanced = true; + } + + this.imbalancedItems = imbalancedItems; + + return imbalanced ? { imbalanced: imbalancedItems } : null; + }; + } + + unknownActivityNameValidator(): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + let unknowActivities = new Set(); + + const res = control.value.matchAll(this.activityNameRegEx); + for (let match of res) { + if (!this.logService.activitiesInEventLog[match[1]]) { + unknowActivities.add({ index: match.index, name: match[1] }); + } + } + return unknowActivities.size > 0 + ? { unknowActivities: unknowActivities } + : null; + }; + } + + balancedApostropheValidator(): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + let occurences = 0; + + if (control.value) { + let matches = control.value.match(/'/g || []); + + if (matches) { + occurences = matches.length; + } + } + + return occurences % 2 === 1 ? { apostrophe: true } : null; + }; + } +} + +class imbalancedItem { + symbol: string; + index: number; + + constructor(symbol: string, index: number) { + this.symbol = symbol; + this.index = index; + } +} diff --git a/src/frontend/src/app/components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component.css b/src/frontend/src/app/components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component.html b/src/frontend/src/app/components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component.html new file mode 100644 index 0000000000000000000000000000000000000000..7e9b2f385d3b205285b31c30c0ff2a4cc0c0204e --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component.html @@ -0,0 +1,138 @@ +<context-menu #contextMenu menuClass="custom-style"> + <ng-template contextMenuItem [subMenu]="quickActionMenu"> + <div> + <i class="bi bi-magic"></i> + Quick actions + </div> + </ng-template> + + <ng-template contextMenuItem [subMenu]="shiftSubMenu"> + <div> + <i class="bi bi-arrows-move"></i> + Shift + </div> + </ng-template> + + <ng-template contextMenuItem [divider]="true"></ng-template> + + <ng-template + contextMenuItem + (execute)="onCopy($event)" + [disabled]="copyDisabled" + > + <div> + <i class="bi bi-copy"></i> + Copy + </div> + </ng-template> + <ng-template + contextMenuItem + (execute)="onCut($event)" + [disabled]="cutDisabled" + > + <div> + <i class="bi bi-scissors"></i> + Cut + </div> + </ng-template> + <ng-template + contextMenuItem + (execute)="onPaste($event)" + [disabled]="pasteDisabled" + > + <div> + <i class="bi bi-clipboard2-fill"></i> + Paste + </div> + </ng-template> + + <ng-template contextMenuItem [divider]="true"></ng-template> + + <ng-template + contextMenuItem + (execute)="onDelete($event)" + [disabled]="deleteDisabled" + let-value + > + <div> + <i + class="bi bi-trash" + [ngClass]="!deleteDisabled(value) ? 'text-warning' : ''" + ></i> + Delete + </div> + </ng-template> + + <ng-template contextMenuItem [divider]="true"></ng-template> + + <ng-template + contextMenuItem + (execute)="onFreeze($event)" + [disabled]="freezeDisabled" + let-value + > + <div> + <i + class="bi bi-snow" + [ngClass]="!freezeDisabled(value) ? 'text-primary' : ''" + ></i> + Freeze + </div> + </ng-template> +</context-menu> + +<context-menu #shiftSubMenu> + <ng-template + contextMenuItem + (execute)="onShiftLeft($event)" + [disabled]="shiftLeftDisabled" + > + <div> + <i class="bi bi-chevron-double-left"></i> + Left + </div> + </ng-template> + <ng-template + contextMenuItem + (execute)="onShiftUp($event)" + [disabled]="shiftUpDisabled" + > + <div> + <i class="bi bi-chevron-double-up"></i> + Up + </div> + </ng-template> + <ng-template + contextMenuItem + (execute)="onShiftRight($event)" + [disabled]="shiftRightDisabled" + > + <div> + <i class="bi bi-chevron-double-right"></i> + Right + </div> + </ng-template> +</context-menu> + +<context-menu #quickActionMenu> + <ng-template + contextMenuItem + (execute)="onMakeOptional($event)" + [disabled]="makeOptionalDisabled" + > + <div> + <i class="bi bi-alt"></i> + Make subtree optional + </div> + </ng-template> + <ng-template + contextMenuItem + (execute)="onMakeRepeatable($event)" + [disabled]="makeRepeatableDisabled" + > + <div> + <i class="bi bi-repeat"></i> + Make subtree repeatable + </div> + </ng-template> +</context-menu> diff --git a/src/frontend/src/app/components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component.spec.ts b/src/frontend/src/app/components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..20a357f19198aeb250387f92349d1ef48c6e2ee2 --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProcessTreeEditorContextMenuComponent } from './process-tree-editor-context-menu.component'; + +describe('ProcessTreeEditorContextMenuComponent', () => { + let component: ProcessTreeEditorContextMenuComponent; + let fixture: ComponentFixture<ProcessTreeEditorContextMenuComponent>; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ProcessTreeEditorContextMenuComponent], + }); + fixture = TestBed.createComponent(ProcessTreeEditorContextMenuComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component.ts b/src/frontend/src/app/components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..351efb445e5ad9af068eb8d91ef7e13f023e05a7 --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component.ts @@ -0,0 +1,118 @@ +import { Component, ViewChild } from '@angular/core'; +import { ContextMenuComponent } from '@perfectmemory/ngx-contextmenu'; +import { ContextMenuAction } from 'src/app/objects/ContextMenuAction'; +import { ProcessTree } from 'src/app/objects/ProcessTree/ProcessTree'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; + +@Component({ + selector: 'app-process-tree-editor-context-menu', + templateUrl: './process-tree-editor-context-menu.component.html', + styleUrls: ['./process-tree-editor-context-menu.component.css'], +}) +export class ProcessTreeEditorContextMenuComponent { + @ViewChild('contextMenu', { static: true }) + public contextMenu?: ContextMenuComponent<any>; + + constructor(private processTreeService: ProcessTreeService) { + this.pasteDisabled = this.pasteDisabled.bind(this); + } + + copyDisabled(pt: ProcessTree) { + return !pt; + } + + onCopy(action: ContextMenuAction<ProcessTree>) { + if (!action.value) return; + this.processTreeService.copySubtreeToBuffer(action.value); + } + + cutDisabled(pt: ProcessTree) { + return !pt; + } + + onCut(action: ContextMenuAction<ProcessTree>) { + if (!action.value) return; + this.processTreeService.copySubtreeToBuffer(action.value); + this.processTreeService.deleteSelected(action.value); + } + + pasteDisabled(pt: ProcessTree) { + return !this.processTreeService.bufferedProcessTree || !pt || !!pt?.label; + } + + onPaste(action: ContextMenuAction<ProcessTree>) { + this.processTreeService.pasteSubtreeFromBuffer(action.value); + } + + deleteDisabled(pt: ProcessTree) { + return !pt; + } + + onDelete(action: ContextMenuAction<ProcessTree>) { + if (!action.value) return; + this.processTreeService.deleteSelected(action.value); + } + + freezeDisabled(pt: ProcessTree) { + return !pt; + } + + onFreeze(action: ContextMenuAction<ProcessTree>) { + if (!action.value) return; + this.processTreeService.freezeSubtree(action.value); + } + + shiftLeftDisabled(pt: ProcessTree) { + if (!pt) return true; + if (!pt.parent) return true; + if (pt.parent.children.indexOf(pt) == 0) return true; + return false; + } + + onShiftLeft(action: ContextMenuAction<ProcessTree>) { + if (!action.value) return; + this.processTreeService.shiftSubtreeToLeft(action.value); + } + + shiftUpDisabled(pt: ProcessTree) { + if (!pt) return true; + if (!pt.parent || !pt.parent.parent) return true; + return false; + } + + onShiftUp(action: ContextMenuAction<ProcessTree>) { + if (!action.value) return; + this.processTreeService.shiftSubtreeUp(action.value); + } + + shiftRightDisabled(pt: ProcessTree) { + if (!pt) return true; + if (!pt.parent) return true; + if (pt.parent.children.indexOf(pt) == pt.parent.children.length - 1) + return true; + return false; + } + + onShiftRight(action: ContextMenuAction<ProcessTree>) { + if (!action.value) return; + this.processTreeService.shiftSubtreeToRight(action.value); + } + + onMakeOptional(action: ContextMenuAction<ProcessTree>) { + if (!action.value) return; + this.processTreeService.makeSubtreeOptional(action.value); + } + + makeOptionalDisabled(pt: ProcessTree) { + return !pt; + } + + onMakeRepeatable(action: ContextMenuAction<ProcessTree>) { + if (!action.value) return; + this.processTreeService.makeSubtreeRepeatable(action.value); + } + + makeRepeatableDisabled(pt: ProcessTree) { + return !pt; + } +} diff --git a/src/frontend/src/app/components/process-tree-editor/process-tree-editor.component.html b/src/frontend/src/app/components/process-tree-editor/process-tree-editor.component.html new file mode 100644 index 0000000000000000000000000000000000000000..ab119513027523d41854b11cfdda1674860d6406 --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/process-tree-editor.component.html @@ -0,0 +1,387 @@ +<div class="main-process-tree-editor h-100 d-flex flex-column"> + <div class="bg-dark btn-tool-bar"> + <div class="btn-group round-corners" role="group"> + <button + type="button" + class="button" + [disabled]="disabledInsertPositions.above" + (click)="nodeInsertionStrategy = NodeInsertionStrategy.ABOVE" + [ngClass]=" + nodeInsertionStrategy === NodeInsertionStrategy.ABOVE + ? 'strategy-selected' + : '' + " + ngbTooltip="insert new node above the selected one" + triggers="hover" + container="body" + > + <i class="bi bi-chevron-up"></i> + </button> + + <button + type="button" + class="button" + [disabled]="disabledInsertPositions.below" + (click)="nodeInsertionStrategy = NodeInsertionStrategy.BELOW" + [ngClass]=" + nodeInsertionStrategy === NodeInsertionStrategy.BELOW + ? 'strategy-selected' + : '' + " + ngbTooltip="insert new node below the selected one" + triggers="hover" + container="body" + > + <i class="bi bi-chevron-down"></i> + </button> + + <button + type="button" + class="button" + [disabled]="disabledInsertPositions.leftRight" + (click)="nodeInsertionStrategy = NodeInsertionStrategy.LEFT" + [ngClass]=" + nodeInsertionStrategy === NodeInsertionStrategy.LEFT + ? 'strategy-selected' + : '' + " + ngbTooltip="insert new node left to the selected one" + triggers="hover" + container="body" + > + <i class="bi bi-chevron-left"></i> + </button> + + <button + type="button" + class="button" + [disabled]="disabledInsertPositions.leftRight" + (click)="nodeInsertionStrategy = NodeInsertionStrategy.RIGHT" + [ngClass]=" + nodeInsertionStrategy === NodeInsertionStrategy.RIGHT + ? 'strategy-selected' + : '' + " + ngbTooltip="insert new node right to the selected one" + triggers="hover" + container="body" + > + <i class="bi bi-chevron-right"></i> + </button> + + <button + type="button" + class="button" + (click)="nodeInsertionStrategy = NodeInsertionStrategy.CHANGE" + [ngClass]=" + nodeInsertionStrategy === NodeInsertionStrategy.CHANGE + ? 'strategy-selected' + : '' + " + ngbTooltip="replace the currently selected node" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-repeat"></i> + </button> + </div> + + <div class="vr"></div> + + <button + class="button btn-fixed-width" + (click)="undo()" + [disabled]="!(treeCacheLength - 1 > 0 && treeCacheIndex !== 0)" + ngbTooltip="undo" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-counterclockwise btn-icon"></i> + <span + class="text-secondary" + *ngIf="treeCacheLength - 1 > 0 && treeCacheIndex !== 0" + > + ({{ treeCacheIndex }}) + </span> + </button> + + <button + class="button btn-fixed-width" + (click)="redo()" + [disabled]="!(treeCacheIndex < treeCacheLength - 1)" + ngbTooltip="redo" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-clockwise btn-icon"></i> + <span class="text-secondary" *ngIf="treeCacheIndex < treeCacheLength - 1"> + ({{ treeCacheLength - 1 - treeCacheIndex }}) + </span> + </button> + + <div class="vr"></div> + + <button + class="button" + (click)="shiftSubtreeUp()" + [disabled]="shiftSubtreeUpDisabled" + ngbTooltip="shift selected node(s) up" + triggers="hover" + container="body" + > + <i class="bi bi-chevron-double-up btn-icon"></i> + </button> + + <button + class="button" + (click)="shiftSubtreeToLeft()" + [disabled]="shiftSubtreeLeftDisabled" + ngbTooltip="shift selected node(s) to left" + triggers="hover" + container="body" + > + <i class="bi bi-chevron-double-left btn-icon"></i> + </button> + + <button + class="button" + (click)="shiftSubtreeToRight()" + [disabled]="shiftSubtreeRightDisabled" + ngbTooltip="shift selected node(s) to right" + triggers="hover" + container="body" + > + <i class="bi bi-chevron-double-right btn-icon"></i> + </button> + + <button + class="button" + (click)="applyReductionRules()" + [disabled]="!currentlyDisplayedTreeInEditor" + ngbTooltip="Applies reduction rules to remove redundant and unnecessary nodes" + triggers="hover" + container="body" + > + <i class="bi bi-diagram-2"></i> + </button> + + <div + class="dropdown" + ngbTooltip="Quick Actions" + triggers="hover" + container="body" + > + <button + class="button dropdown-toggle" + type="button" + id="quickActionDropdown" + [disabled]="allQuickActionsDisabled" + data-bs-toggle="dropdown" + aria-expanded="false" + > + <i class="bi bi-magic btn-icon"></i> + </button> + <div + class="dropdown-menu custom-dropdown" + aria-labelledby="quickActionDropdown" + id="quickActionDropdownMenu" + > + <div + class="dropdown-item" + (click)="onMakeOptional()" + [ngClass]="makeOptionalDisabled ? 'disabled' : ''" + > + <i class="bi bi-alt"></i> + <span class="ms-3">Make subtree optional</span> + </div> + <div + class="dropdown-item" + (click)="onMakeRepeatable()" + [ngClass]="makeRepeatableDisabled ? 'disabled' : ''" + > + <i class="bi bi-repeat"></i> + <span class="ms-3">Make subtree repeatable</span> + </div> + </div> + </div> + + + <div class="vr"></div> + + <button + class="button" + (click)="copySubtree()" + [disabled]="copyDisabled" + ngbTooltip="copy selected subtree" + triggers="hover" + container="body" + > + <i class="bi bi-copy btn-icon"></i> + </button> + + <button + class="button" + (click)="cutSubtree()" + [disabled]="copyDisabled" + ngbTooltip="cut selected subtree" + triggers="hover" + container="body" + > + <i class="bi bi-scissors btn-icon"></i> + </button> + + <button + class="button" + (click)="pasteSubtree()" + [disabled]="pasteDisabled" + ngbTooltip="paste subtree below selected node" + triggers="hover" + container="body" + > + <i class="bi bi-clipboard2-fill btn-icon"></i> + </button> + + <button + class="button text-warning" + (click)="deleteSubtree()" + [disabled]="!selectedRootNode" + ngbTooltip="remove selected node(s)" + triggers="hover" + container="body" + > + <i class="bi bi-trash btn-icon"></i> + </button> + + <div class="vr"></div> + + <button + class="button" + (click)="clearSelection()" + [disabled]="!selectedRootNode" + ngbTooltip="clear selection" + triggers="hover" + container="body" + > + <i + class="bi bi-x-circle btn-icon" + [ngClass]="selectedRootNode ? 'text-danger' : ''" + ></i> + <div class="button-text px-1" @collapseText *ngIf="!collapse"> + clear selection + </div> + </button> + + <div class="vr"></div> + + <ng-template #unfreezeTooltip> + (un)freeze <em>entire</em> subtree to prevent them from being changed when + adding variants + </ng-template> + <button + class="button" + (click)="freezeSubtree()" + [disabled]="buttonFreezeSubtreeDisabled()" + [ngbTooltip]="unfreezeTooltip" + triggers="hover" + container="body" + > + <i + class="bi bi-snow btn-icon" + [ngClass]="!buttonFreezeSubtreeDisabled() ? 'text-primary' : ''" + ></i> + <div class="button-text px-1" @collapseText *ngIf="!collapse"> + (un)freeze subtrees + </div> + </button> + + <div class="vr"></div> + + <button + class="button ms-auto" + ngbTooltip="Toggle BPMN editor in Splitview" + triggers="hover" + container="body" + (click)="toggleBPMNEditor()" + > + <i class="bi bi-window-split"></i> + </button> + + <button + id="btn-reset-zoom" + class="button" + ngbTooltip="reset view" + triggers="hover" + container="body" + > + <i class="bi bi-arrows-fullscreen btn-icon text-light"></i> + </button> + + <button + class="button" + ngbTooltip="export the tree as an .svg" + triggers="hover" + container="body" + (click)="exportCurrentTree(d3svg)" + > + <i class="bi bi-save"></i> + </button> + </div> + <app-process-tree-toolbox + (operatorInsertion)="insertNewNode($event, null)" + [operatorInsertionDisabled]="disabledOperatorInsertion" + (activityInsertion)="insertNewNode(null, $event)" + [activityInsertionDisabled]="disabledActivityInsertion" + ></app-process-tree-toolbox> + + <div #d3container id="d3-container" class="m-1 flex-grow-1 crosshair grid"> + <div class="floating-infobox" *ngIf="processTreeSyntaxInfo"> + <div class="text-success" *ngIf="processTreeSyntaxInfo.correctSyntax"> + syntax correct + </div> + <div class="text-danger" *ngIf="!processTreeSyntaxInfo.correctSyntax"> + <b> + <i class="bi bi-exclamation-triangle"></i> + syntax incorrect + </b> + </div> + + <div class="text-danger" *ngIf="processTreeSyntaxInfo.errors.length > 0"> + syntax errors: + <ul> + <li *ngFor="let err of processTreeSyntaxInfo.errors">{{ err }}</li> + </ul> + </div> + + <div + class="text-warning" + *ngIf="processTreeSyntaxInfo.warnings.length > 0" + > + syntax warnings: + <ul> + <li *ngFor="let war of processTreeSyntaxInfo.warnings">{{ war }}</li> + </ul> + </div> + </div> + + <app-expert-mode> </app-expert-mode> + <app-process-tree-editor-context-menu + #contextMenuComponent + ></app-process-tree-editor-context-menu> + <svg #d3svg id="d3-svg" width="100%" height="100%"> + <g id="zoomGroup"> + <g + #d3svgDirective + appProcessTreeDrawer + [contextMenuComponent]="contextMenuComponent" + [onClickCallBack]="selectNodeCallBack" + [computeNodeColor]="computeNodeColor" + [computeTextColor]="computeTextColor" + [tooltipText]="tooltipContent" + id="d3-svg-directive" + width="100%" + height="100%" + ></g> + </g> + </svg> + </div> +</div> diff --git a/src/frontend/src/app/components/process-tree-editor/process-tree-editor.component.scss b/src/frontend/src/app/components/process-tree-editor/process-tree-editor.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..f430c3032febb33020f351c1ea7048782cc3b05d --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/process-tree-editor.component.scss @@ -0,0 +1,79 @@ + + +:host { + position: absolute; + overflow:hidden; + width : 100%; + height : 100%; + border-bottom: 1px solid black; +} + +.main-process-tree-editor { + background-color: var(--box-background-color); + max-height: 100%; + position: relative; + border-left: 1px solid var(--thin-border-color); +} + +.floating-infobox { + background-color: rgb(0 0 0 / 60%); + position: absolute; + font-size: small; + bottom: 0; + left: 0; + text-align: left; + cursor: auto; + padding: .25rem; +} + +.syntax-info { + background-color: rgb(0 0 0 / 40%); + position: absolute; + font-size: small; + bottom: 0; + left: 0; + text-align: left; + cursor: auto; +} + +.syntax-info ul { + margin-bottom: 0; +} + +.crosshair { + cursor: crosshair; +} + +.button-text{ + display : inline-block; +} + +.dropdown-node-insert { + font-size: small; + overflow: auto scroll; + user-select: none; + +} + +.insertion-position-active{ + background-color: var(--bs-primary); + color: white; +} + +.grid { + background-image: radial-gradient(var(--line-color) 1px, transparent 0); + background-size: 20px 20px; +} + +.dropdown-menu { + border-radius: 0; + background-color: lightgray; +} + +input:disabled::placeholder { + color: var(--bs-dropdown-link-disabled-color) +} + +.strategy-selected{ + background-color: #515a64; +} diff --git a/src/frontend/src/app/components/process-tree-editor/process-tree-editor.component.spec.ts b/src/frontend/src/app/components/process-tree-editor/process-tree-editor.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..06815e248f577e2b1ee825da06a706662644f45a --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/process-tree-editor.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProcessTreeEditorComponent } from './process-tree-editor.component'; + +describe('ProcessTreeEditorComponent', () => { + let component: ProcessTreeEditorComponent; + let fixture: ComponentFixture<ProcessTreeEditorComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ProcessTreeEditorComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ProcessTreeEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/process-tree-editor/process-tree-editor.component.ts b/src/frontend/src/app/components/process-tree-editor/process-tree-editor.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..958b702d7c40e66c2536e3f255464e29458b9bc8 --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/process-tree-editor.component.ts @@ -0,0 +1,868 @@ +import { PT_Constant } from './../../constants/process_tree_drawer_constants'; + +import { GoldenLayoutHostComponent } from 'src/app/components/golden-layout-host/golden-layout-host.component'; +import { GoldenLayoutComponentService } from 'src/app/services/goldenLayoutService/golden-layout-component.service'; +import { BpmnEditorComponent } from './../bpmn-editor/bpmn-editor.component'; +import { BackendService } from './../../services/backendService/backend.service'; +import { + Component, + OnInit, + ViewChild, + AfterViewInit, + ElementRef, + Inject, + Renderer2, + OnDestroy, +} from '@angular/core'; + +import { ComponentContainer, GoldenLayout, LogicalZIndex } from 'golden-layout'; +import * as d3 from 'd3'; +import { ColorMapService } from '../../services/colorMapService/color-map.service'; + +import { ImageExportService } from '../../services/imageExportService/image-export-service'; + +declare var $; +import { PerformanceService } from 'src/app/services/performance.service'; +import { ModelPerformanceColorScaleService } from 'src/app/services/performance-color-scale.service'; + +import { + ProcessTree, + ProcessTreeSyntaxInfo, + checkSyntax, + ProcessTreeOperator, +} from '../../objects/ProcessTree/ProcessTree'; + +import { DropzoneConfig } from '../drop-zone/drop-zone.component'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; + +import { LogService } from 'src/app/services/logService/log.service'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { ProcessTreeDrawerDirective } from 'src/app/directives/process-tree-drawer/process-tree-drawer.directive'; +import { getPerformanceTable } from './utils'; +import { collapsingText } from 'src/app/animations/text-animations'; +import { textColorForBackgroundColor } from 'src/app/utils/render-utils'; +import { NodeInsertionStrategy } from 'src/app/objects/ProcessTree/utility-functions/process-tree-edit-tree'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { ModelViewModeService } from 'src/app/services/viewModeServices/model-view-mode.service'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { ConformanceCheckingService } from 'src/app/services/conformanceChecking/conformance-checking.service'; + +@Component({ + selector: 'app-process-tree-editor', + templateUrl: './process-tree-editor.component.html', + styleUrls: ['./process-tree-editor.component.scss'], + animations: [collapsingText], +}) +export class ProcessTreeEditorComponent + extends LayoutChangeDirective + implements OnInit, AfterViewInit, OnDestroy +{ + selectedPerformanceIndicator: string; + selectedStatistic: string; + constructor( + private colorMapService: ColorMapService, + private imageExportService: ImageExportService, + private backendService: BackendService, + private logService: LogService, + private goldenLayoutComponentService: GoldenLayoutComponentService, + private performanceService: PerformanceService, + private performanceColorScaleService: ModelPerformanceColorScaleService, + private processTreeService: ProcessTreeService, + private modelViewModeService: ModelViewModeService, + private conformanceCheckingService: ConformanceCheckingService, + private renderer: Renderer2, + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef + ) { + super(elRef.nativeElement, renderer); + } + + @ViewChild('d3svg') svgElem: ElementRef; + @ViewChild('d3container') d3ContainerElem: ElementRef; + + @ViewChild(ProcessTreeDrawerDirective) + processTreeDrawer: ProcessTreeDrawerDirective; + + currentlyDisplayedTreeInEditor; + + // used in dropdown search form + searchText: string; + + processTreeSyntaxInfo: ProcessTreeSyntaxInfo = undefined; + + currentEditorHeight; + + svg; + mainSvgGroup; + nodeEnter; + + collapse: boolean = false; + + readonly NodeInsertionStrategy = NodeInsertionStrategy; + nodeInsertionStrategy: NodeInsertionStrategy = NodeInsertionStrategy.ABOVE; + lastNodeInsertionStrategy: NodeInsertionStrategy; + + selectedRootNodeId: number; + selectedRootNode: d3.HierarchyNode<ProcessTree>; + + readonly disabledInsertPositions = { + above: false, + leftRight: false, + below: false, + }; + + get disabledActivityInsertion() { + if ( + this.nodeInsertionStrategy === NodeInsertionStrategy.ABOVE && + this.selectedRootNode?.data + ) + return true; + // Disable insertion when no node is selected but pt is present + if (!this.selectedRootNode && this.currentlyDisplayedTreeInEditor) + return true; + return false; + } + + get disabledOperatorInsertion() { + // Disable insertion when no node is selected but pt is present + if (!this.selectedRootNode && this.currentlyDisplayedTreeInEditor) + return true; + return false; + } + + root: d3.HierarchyNode<any>; + + nodeWidthCache = new Map<string, number>(); + + activityColorMap: Map<string, string>; + performanceColorMap: Map<number, any>; + editorOpen: boolean = false; + _goldenLayoutHostComponent: GoldenLayoutHostComponent; + _goldenLayout: GoldenLayout; + + tree_syntax_string: string; + tree_syntax_result: any; + + treeCacheLength: number = 0; + treeCacheIndex: number = 0; + + activitiesOccurringInLog: string[]; + + private _destroy$ = new Subject(); + + get processTreeOriginX() { + return this.d3ContainerElem.nativeElement.offsetWidth / 2; + } + + readonly processTreeOriginY = 30; + + ngOnInit(): void { + this.processTreeService.treeCacheIndex$ + .pipe(takeUntil(this._destroy$)) + .subscribe((idx) => { + this.treeCacheIndex = idx; + }); + + this.processTreeService.treeCacheLength$ + .pipe(takeUntil(this._destroy$)) + .subscribe((len) => { + this.treeCacheLength = len; + }); + + this.modelViewModeService.viewMode$ + .pipe(takeUntil(this._destroy$)) + .subscribe((viewMode) => { + if (this.currentlyDisplayedTreeInEditor) { + this.redraw(this.currentlyDisplayedTreeInEditor); + } + }); + + this.conformanceCheckingService.isConformanceWeighted$ + .pipe(takeUntil(this._destroy$)) + .subscribe((_) => { + if (this.currentlyDisplayedTreeInEditor) { + this.redraw(this.currentlyDisplayedTreeInEditor); + } + }); + + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + this.activityColorMap = colorMap; + + if (this.currentlyDisplayedTreeInEditor) { + this.redraw(this.currentlyDisplayedTreeInEditor); + } + }); + + this.performanceColorScaleService.currentColorScale + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + if (colorMap && colorMap != this.performanceColorMap) { + this.performanceColorMap = colorMap; + this.redraw(this.currentlyDisplayedTreeInEditor); + } + }); + + this.logService.activitiesInEventLog$ + .pipe(takeUntil(this._destroy$)) + .subscribe((activties) => { + this.activitiesOccurringInLog = Object.keys(activties); + }); + + this.processTreeService.currentDisplayedProcessTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((res) => { + const centerTree = !this.currentlyDisplayedTreeInEditor && !!res; + // If the tree was loaded via the process tree import or Drag&Drop that does not contain the current activities + this.currentlyDisplayedTreeInEditor = res; + + if (res) { + console.warn('update tree triggered by service'); + + this.processTreeSyntaxInfo = checkSyntax(res); + this.processTreeService.correctTreeSyntax = + this.processTreeSyntaxInfo.correctSyntax; + this.redraw(res); + if (centerTree) this.centerTree(); + } else if (res === null && this.mainSvgGroup) { + this.processTreeDrawer.redraw(null); + this.selectedRootNode = null; + } + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + redraw(tree) { + this.selectedStatistic = + this.performanceColorScaleService.selectedColorScale.statistic; + this.selectedPerformanceIndicator = + this.performanceColorScaleService.selectedColorScale.performanceIndicator; + this.performanceColorMap = + this.performanceColorScaleService.getColorScale(); + + this.processTreeDrawer.redraw(tree); + setTimeout(() => this.selectRootNodeFromID(this.selectedRootNodeId), 0); + } + + ngAfterViewInit(): void { + this._goldenLayoutHostComponent = + this.goldenLayoutComponentService.goldenLayoutHostComponent; + this._goldenLayout = this.goldenLayoutComponentService.goldenLayout; + + this.initializeSvg(); + + this._goldenLayoutHostComponent = + this.goldenLayoutComponentService.goldenLayoutHostComponent; + this._goldenLayout = this.goldenLayoutComponentService.goldenLayout; + + this.processTreeService.selectedRootNodeID$ + .pipe(takeUntil(this._destroy$)) + .subscribe((id) => { + // Change the Selection + if (id) { + this.selectRootNodeFromID(id); //the last one failed + // Unselect all + } else { + this.clearDisplayedSelection(); + } + + this.selectedRootNodeId = id; + }); + } + + private selectRootNodeFromID(id) { + const selectedRoot = this.mainSvgGroup.select(`[id="${id}"]`); + const node = selectedRoot.data()[0]; + if (id && node) { + this.setSelectedRootNode(node); + this.selectSubtreeFromRoot(selectedRoot.node(), node); + + this.checkNodeInsertionStrategy(this.selectedRootNode.data); + } + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void { + this.collapse = width < 970; + + this.currentEditorHeight = height; + } + + handleVisibilityChange(visibile: boolean): void { + if (visibile) { + if (this.currentlyDisplayedTreeInEditor) { + this.redraw(this.currentlyDisplayedTreeInEditor); + } + } + } + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} + + insertNewNodeButtonDisabled(): boolean { + return ( + !this.selectedRootNode && + this.currentlyDisplayedTreeInEditor !== null && + this.currentlyDisplayedTreeInEditor !== undefined + ); + } + + leafNodeSelected(): boolean { + return this.selectedRootNode && !this.selectedRootNode.children; + } + + rootNodeSelected(): boolean { + return this.selectedRootNode && this.selectedRootNode.depth === 0; + } + + get shiftSubtreeUpDisabled(): boolean { + if (this.buttonManipulatingMultipleNodesDisabled()) return true; + // Disabled if there is no granparent of the selected node + if (!this.selectedRootNode.data.parent.parent) return true; + return false; + } + + get shiftSubtreeLeftDisabled(): boolean { + if (this.buttonManipulatingMultipleNodesDisabled()) return true; + const selectedNode = this.selectedRootNode.data; + // Disabled when selected subtree already at leftmost position + if (selectedNode.parent.children.indexOf(selectedNode) == 0) return true; + return false; + } + + get shiftSubtreeRightDisabled(): boolean { + if (this.buttonManipulatingMultipleNodesDisabled()) return true; + const selectedNode = this.selectedRootNode.data; + // Disabled when selected subtree already at rightmost position + if ( + selectedNode.parent.children.indexOf(selectedNode) == + selectedNode.parent.children.length - 1 + ) + return true; + return false; + } + + buttonManipulatingMultipleNodesDisabled(): boolean { + return !this.selectedRootNode || this.rootNodeSelected(); + } + + buttonFreezeSubtreeDisabled(): boolean { + return !this.selectedRootNode || this.leafNodeSelected(); + } + + shiftSubtreeUp(): void { + this.processTreeService.shiftSubtreeUp(this.selectedRootNode.data); + } + + shiftSubtreeToLeft(): void { + this.processTreeService.shiftSubtreeToLeft(this.selectedRootNode.data); + } + + shiftSubtreeToRight(): void { + this.processTreeService.shiftSubtreeToRight(this.selectedRootNode.data); + } + + get copyDisabled() { + return !this.selectedRootNode; + } + + copySubtree(): void { + this.processTreeService.copySubtreeToBuffer(this.selectedRootNode.data); + } + + cutSubtree(): void { + this.processTreeService.copySubtreeToBuffer(this.selectedRootNode.data); + this.processTreeService.deleteSelected(this.selectedRootNode.data); + } + + get pasteDisabled() { + return ( + !this.processTreeService.bufferedProcessTree || + (!this.selectedRootNode && this.currentlyDisplayedTreeInEditor) || + this.selectedRootNode?.data.label + ); + } + + pasteSubtree(): void { + this.processTreeService.pasteSubtreeFromBuffer(this.selectedRootNode?.data); + } + + undo(): void { + this.processTreeService.undo(); + } + + redo(): void { + this.processTreeService.redo(); + } + + centerTree(): void { + this.mainSvgGroup.attr( + 'transform', + `translate(${this.processTreeOriginX}, ${this.processTreeOriginY})` + ); + } + + deleteSubtree(): void { + this.processTreeService.deleteSelected(this.selectedRootNode.data); + } + + insertNewNode(operator, label) { + this.processTreeService.insertNewNode( + this.selectedRootNode?.data, + this.nodeInsertionStrategy, + operator, + label + ); + this.afterInsertNode(); + } + + afterInsertNode(): void { + this.searchText = undefined; + } + + // @REFRACTOR INTO PROCESSTREE SERVICE + createNode(operator, label): d3.HierarchyNode<any> { + // TODO make sure that IDs are unique!!! + const nodeData = { + operator, + label, + id: Math.floor(1000000000 + Math.random() * 900000000), + children: [], + }; + return d3.hierarchy(nodeData); + } + + computeNodeColor = (d: d3.HierarchyNode<ProcessTree>) => { + switch (this.modelViewModeService.viewMode) { + case ViewMode.CONFORMANCE: + if (d.data.conformance === null) return '#404041'; + const conformanceValue = + this.conformanceCheckingService.isConformanceWeighted && + d.data.conformance?.weighted_by_counts != undefined + ? d.data.conformance?.weighted_by_counts.value + : d.data.conformance?.weighted_equally.value; + if (conformanceValue === 0) return 'url(#modelConformanceStriped)'; + return this.conformanceCheckingService.modelConformanceColorMap.getColor( + conformanceValue + ); + case ViewMode.PERFORMANCE: + if (d.data.label !== ProcessTreeOperator.tau) { + if ( + this.performanceColorMap.has(d.data.id) && + d.data.performance?.[this.selectedPerformanceIndicator]?.[ + this.selectedStatistic + ] !== undefined + ) { + if ( + d.data.performance[this.selectedPerformanceIndicator][ + this.selectedStatistic + ] === 0 + ) + return 'url(#whiteStriped)'; + else + return this.performanceColorMap + .get(d.data.id) + .getColor( + d.data.performance[this.selectedPerformanceIndicator][ + this.selectedStatistic + ] + ); + } else { + return '#404040'; + } + } + default: + if (d.data.operator !== null) return PT_Constant.OPERATOR_COLOR; + if (d.data.label !== null && d.data.label === ProcessTreeOperator.tau) + return PT_Constant.INVISIBLE_ACTIVTIY_COLOR; + const isVisibleActivity = + d.data.label !== null && d.data.label !== ProcessTreeOperator.tau; + return isVisibleActivity + ? this.activityColorMap.get(d.data.label) + : null; + } + }; + + tooltipContent = (d: d3.HierarchyNode<ProcessTree>) => { + let returnTempValue = d.data.label || d.data.operator; + + const tableHead = + `<div style="display: flex; justify-content: space-between; border-radius: 5px 5px 0px 0px;" class="bg-dark"> + <h6 style="flex: 1; margin-top: 8px;">` + + (d.data.label || d.data.operator) + + `</h6> + </div>`; + + if ( + this.modelViewModeService.viewMode === ViewMode.PERFORMANCE && + d.data.hasPerformance() && + d.data.label !== ProcessTreeOperator.tau + ) { + returnTempValue = + tableHead + + getPerformanceTable( + d.data.performance, + this.selectedPerformanceIndicator, + this.selectedStatistic + ); + } else if ( + this.modelViewModeService.viewMode === ViewMode.CONFORMANCE && + d.data.conformance !== null + ) { + returnTempValue = + tableHead + + `<table class="table table-dark table-striped table-bordered"> + <tr> + <td>Weighted</td> + <td>Conformance</td> + <td>Weight</td> + </tr>` + + `<tr> + <td>Equally</td> + <td>${(d.data.conformance?.weighted_equally.value * 100).toFixed( + 2 + )}%</td> + <td>${d.data.conformance?.weighted_equally.weight}</td> + </tr>` + + (d.data.conformance?.weighted_by_counts !== null + ? `<tr> + <td>By Log Frequency</td> + <td>${(d.data.conformance?.weighted_by_counts?.value * 100).toFixed( + 2 + )}%</td> + <td>${d.data.conformance?.weighted_by_counts?.weight}</td> + </tr>` + : '') + + '</table>'; + } + + return returnTempValue; + }; + + computeFillColor = (d: d3.HierarchyNode<ProcessTree>) => { + if (d.data.operator !== null) return PT_Constant.OPERATOR_COLOR; + if (d.data.label !== null && d.data.label === ProcessTreeOperator.tau) + return PT_Constant.INVISIBLE_ACTIVTIY_COLOR; + const isVisibleActivity = + d.data.label !== null && d.data.label !== ProcessTreeOperator.tau; + return isVisibleActivity + ? this.activityColorMap.get(d.data.label) || + PT_Constant.VISIBILE_ACTIVITY_DEFAULT_COLOR + : null; + }; + + computeTextColor = (d: d3.HierarchyNode<ProcessTree>) => { + if (d.data.frozen || d.data.label === ProcessTreeOperator.tau) { + return 'white'; + } + const nodeColor = this.computeNodeColor(d); + + const isVisibleActivity = + (d.data.label !== null && d.data.label !== ProcessTreeOperator.tau) || + (this.modelViewModeService.viewMode === ViewMode.PERFORMANCE && + nodeColor !== undefined) || + this.modelViewModeService.viewMode === ViewMode.CONFORMANCE; + return isVisibleActivity ? textColorForBackgroundColor(nodeColor) : 'white'; + }; + + // END - Inserting node functionality + + // Refactor to Directive with Variant Modeler / BPMN Viewer + addZoomFunctionality(): void { + const zooming = function (event) { + this.mainSvgGroup.attr( + 'transform', + event.transform.translate( + this.processTreeOriginX, + this.processTreeOriginY + ) + ); + }.bind(this); + + const zoom: any = d3.zoom().scaleExtent([0.1, 3]).on('zoom', zooming); + this.svg.call(zoom).on('dblclick.zoom', null); + + // reset zoom + d3.select('#btn-reset-zoom').on( + 'click', + function () { + this.svg + .transition() + .duration(250) + .ease(d3.easeExpInOut) + .call(zoom.transform, d3.zoomIdentity.translate(0, 0)); + }.bind(this) + ); + } + + selectNodeCallBack = (self, event, d: d3.HierarchyNode<ProcessTree>) => { + // hide the tooltip + if (self.variantService.activityTooltipReference) { + self.variantService.activityTooltipReference.tooltip('hide'); + } + // correct the selected node after undo + if (d && d.data && d.parent) { + d.data.parent = d.parent.data; + } + this.pushIDtoService(self, d); + this.processTreeService.selectedTree = ProcessTree.fromObj(d.data); + }; + + private pushIDtoService = (svg, d) => { + // Activate Toogle by pushing Null to service + if (d.data.id !== this.selectedRootNodeId) { + this.processTreeService.selectedRootNodeID = d.data.id; + } else { + this.processTreeService.selectedRootNodeID = null; + } + }; + + private setSelectedRootNode(d) { + this.selectedRootNode = d; + } + + private selectSubtreeFromRoot = function (svgGroup, d) { + // Unselect All Edges and Rect + this.mainSvgGroup.selectAll('rect').each((d) => { + d.data.selected = false; + }); + + this.mainSvgGroup.selectAll('rect').classed('selected-node', false); + this.mainSvgGroup.selectAll('line').classed('selected-edge', false); + + // Select the node, if it isn't selected yet + d.data.selected = true; + + d3.select(svgGroup).select('.node').classed('selected-node', true); + }; + + private selectAllChildren = function (svgGroup, d) { + d.data.selected = true; + d3.select(svgGroup).select('.node').classed('selected-node', true); + + if (!d.children) return; + + // add red stroke around sub-nodes if select subtree is selected + d.children.forEach((c) => { + this.selectAllChildren( + this.mainSvgGroup.select('[id="' + c.data.id + '"]').node(), + c + ); + }); + }; + + private selectEdges = function () { + this.mainSvgGroup + .selectAll('line') + .classed('frozen-edge', (e) => { + return e.source.data.frozen; + }) + .classed('selected-edge', (e) => { + return e.source.data.selected; + }); + }; + + freezeSubtree(): void { + this.processTreeService.freezeSubtree(this.selectedRootNode.data); + } + + clearSelection(): void { + this.processTreeService.selectedRootNodeID = null; + } + + clearDisplayedSelection(): void { + this.selectedRootNode = null; + this.processTreeService.selectedTree = undefined; + + this.mainSvgGroup.selectAll('rect').each((d) => { + d.data.selected = false; + }); + + this.mainSvgGroup.selectAll('rect').classed('selected-node', false); + this.mainSvgGroup.selectAll('line').classed('selected-edge', false); + } + + applyReductionRules(): void { + this.backendService.applyTreeReductionRules(); + } + + initializeSvg(): void { + this.svg = d3.select('#d3-svg'); + // add svg group for zooming + this.mainSvgGroup = this.svg.select('#zoomGroup'); + + this.centerTree(); + this.addZoomFunctionality(); + } + + toggleBPMNEditor() { + this.goldenLayoutComponentService.createBPMNSplitViewWindow( + ProcessTreeEditorComponent.componentName, + BpmnEditorComponent.componentName + ); + } + + exportCurrentTree(svg: SVGGraphicsElement): void { + // Copy the current tree + const tree_copy = svg.cloneNode(true) as SVGGraphicsElement; + const svgBBox = ( + d3.select('#zoomGroup').node() as SVGGraphicsElement + ).getBBox(); + + // Strip all the classed information + const tree = d3.select(tree_copy); + tree + .selectAll('rect') + .classed('.selected-node', false) + .classed('.frozen-node', false); + tree + .selectAll('line') + .classed('.selected-edge', false) + .classed('.frozen-edge', false); + + tree + .selectAll('g') + .attr('data-bs-toggle', 'none') + .attr('data-bs-placement', 'none') + .attr('data-bs-title', 'none') + .attr('data-bs-html', 'none') + .attr('data-bs-template', 'none'); + + const shiftbyXOffset = (node, offset, attrKey) => { + return parseFloat(node.getAttribute(attrKey)) + offset; + }; + + // Recenter the tree and reset scaling + let xCords: number[] = []; + tree.selectAll('rect').each(function (this: SVGGraphicsElement) { + xCords.push(parseFloat(this.getAttribute('x'))); + }); + + const xLower = Math.min(...xCords); + const xOffset = Math.abs(xLower) + PT_Constant.EXPORT_OFFSET; + + tree.selectAll('rect').attr('x', function (this: SVGGraphicsElement) { + return shiftbyXOffset(this, xOffset, 'x'); + }); + tree.selectAll('text').attr('x', function (this: SVGGraphicsElement) { + return shiftbyXOffset(this, xOffset, 'x'); + }); + tree + .selectAll('line') + .attr('x1', function (this: SVGGraphicsElement) { + return shiftbyXOffset(this, xOffset, 'x1'); + }) + .attr('x2', function (this: SVGGraphicsElement) { + return shiftbyXOffset(this, xOffset, 'x2'); + }); + + tree + .selectChild() + .attr('transform', `translate(0, ${PT_Constant.EXPORT_OFFSET})`); + + // Export the tree + this.imageExportService.export( + 'process_tree', + svgBBox.width + 2 * PT_Constant.EXPORT_OFFSET, + svgBBox.height + 2 * PT_Constant.EXPORT_OFFSET, + tree_copy + ); + } + + checkNodeInsertionStrategy(rootNode: ProcessTree) { + this.disabledInsertPositions.leftRight = false; + + // Disable insertions above on non-root nodes + this.disabledInsertPositions.above = rootNode.parent != null; + // Disable insertions below non-operator nodes, i.e. activities + this.disabledInsertPositions.below = rootNode.operator == null; + // Disable insertions left/right of root node + if (rootNode.parent == null) this.disabledInsertPositions.leftRight = true; + // Disable insertions left/right of child from loop node that already has 2 childs + if ( + rootNode.parent?.operator === ProcessTreeOperator.loop && + rootNode.parent?.children.length === 2 + ) + this.disabledInsertPositions.leftRight = true; + // Disable insertions below redo node that has 2 childs + if ( + rootNode.operator === ProcessTreeOperator.loop && + rootNode.children.length === 2 + ) + this.disabledInsertPositions.below = true; + + switch (this.nodeInsertionStrategy) { + case NodeInsertionStrategy.ABOVE: + if (this.disabledInsertPositions.above) + this.nodeInsertionStrategy = + this.getFirstAvailableNodeInsertionStrategy(); + break; + case NodeInsertionStrategy.BELOW: + if (this.disabledInsertPositions.below) + this.nodeInsertionStrategy = + this.getFirstAvailableNodeInsertionStrategy(); + break; + case NodeInsertionStrategy.LEFT: + case NodeInsertionStrategy.RIGHT: + if (this.disabledInsertPositions.leftRight) + this.nodeInsertionStrategy = + this.getFirstAvailableNodeInsertionStrategy(); + break; + case NodeInsertionStrategy.CHANGE: + break; + default: + this.nodeInsertionStrategy = + this.getFirstAvailableNodeInsertionStrategy(); + } + } + + getFirstAvailableNodeInsertionStrategy(): NodeInsertionStrategy { + if (!this.disabledInsertPositions.above) return NodeInsertionStrategy.ABOVE; + if (!this.disabledInsertPositions.leftRight) + return NodeInsertionStrategy.LEFT; + if (!this.disabledInsertPositions.below) return NodeInsertionStrategy.BELOW; + return NodeInsertionStrategy.CHANGE; + } + + hideAllTooltips() {} + + get allQuickActionsDisabled() { + return this.makeOptionalDisabled && this.makeRepeatableDisabled; + } + + onMakeOptional() { + if (!this.selectedRootNode) return; + this.processTreeService.makeSubtreeOptional(this.selectedRootNode.data); + } + + get makeOptionalDisabled() { + return !this.selectedRootNode; + } + + onMakeRepeatable() { + if (!this.selectedRootNode) return; + this.processTreeService.makeSubtreeRepeatable(this.selectedRootNode.data); + } + + get makeRepeatableDisabled() { + return !this.selectedRootNode; + } +} + +// TODO should be solved differently +// tslint:disable-next-line:no-namespace +export namespace ProcessTreeEditorComponent { + export const componentName = 'ProcessTreeEditorComponent'; +} diff --git a/src/frontend/src/app/components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component.css b/src/frontend/src/app/components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component.css new file mode 100644 index 0000000000000000000000000000000000000000..69650751f33ca68674c3448ed58134f2e1fcdf74 --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component.css @@ -0,0 +1,45 @@ +.node-btn { + height: 33px; + min-width: 33px; + max-width: 150px; + margin: 5px 3px; + border: 2px solid grey; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.node-btn:hover { + border: 2px solid #515a64; +} + +.node-btn:focus { + border: 2px solid darkgray; +} + +.vr { + border-color: var(--line-color); +} + +.toolbox-area { + border-top: 1px solid; + border-color: var(--thin-border-color); +} + +.activity-buttons { + max-height: 172px; + overflow-y: auto; +} + +#collapse-button { + height: fit-content; + width: fit-content; + text-align: center; + position: absolute; + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); + border-radius: 0 0 5px 5px; +} + +button:disabled { + opacity: 0.5; +} diff --git a/src/frontend/src/app/components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component.html b/src/frontend/src/app/components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component.html new file mode 100644 index 0000000000000000000000000000000000000000..4d1c23b08408fd0c74bd19539113dab52f9cfa2c --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component.html @@ -0,0 +1,88 @@ +<div class="toolbox-area bg-dark" *ngIf="showToolbox"> + <div class="d-flex"> + <div + class="d-flex flex-wrap justify-content-end align-self-start operator-buttons" + > + <button + *ngFor="let op of processTreeOperators | slice : 0 : 2" + type="button" + [disabled]="operatorInsertionDisabled" + [style.background]="operatorNodeColor" + [style.color]="operatorTextColor" + (click)="insertOperatorNode(op)" + [ngbTooltip]="op" + triggers="hover" + container="body" + placement="bottom" + class="btn btn-sm node-btn" + > + {{ op }} + </button> + <div class="w-100 d-block d-xl-none"></div> + <button + *ngFor="let op of processTreeOperators | slice : 2" + type="button" + [disabled]="operatorInsertionDisabled" + [style.background]="operatorNodeColor" + [style.color]="operatorTextColor" + (click)="insertOperatorNode(op)" + [ngbTooltip]="op" + triggers="hover" + container="body" + placement="bottom" + class="btn btn-sm node-btn" + > + {{ op }} + </button> + </div> + <div class="vr"></div> + <div + class="flew-grow-1 d-flex flex-wrap justify-content-start align-self-start activity-buttons" + > + <button + type="button" + [disabled]="activityInsertionDisabled" + [style.background]="computeActivityColor(ProcessTreeOperator.tau)" + [style.color]="computeTextColor(ProcessTreeOperator.tau)" + (click)="insertActivityNode(ProcessTreeOperator.tau)" + [ngbTooltip]="ProcessTreeOperator.tau" + triggers="hover" + container="body" + placement="bottom" + class="btn btn-sm node-btn" + > + {{ ProcessTreeOperator.tau }} + </button> + <button + *ngFor="let act of processTreeActivities.sort()" + type="button" + [disabled]="activityInsertionDisabled" + [style.background]="computeActivityColor(act)" + [style.color]="computeTextColor(act)" + (click)="insertActivityNode(act)" + [ngbTooltip]="act" + triggers="hover" + container="body" + placement="bottom" + class="btn btn-sm node-btn" + > + {{ act }} + </button> + </div> + </div> +</div> +<div class="d-flex justify-content-center"> + <button + class="button" + id="collapse-button" + (click)="showToolbox = !showToolbox" + > + <i + class="btn-icon bi" + [ngClass]="{ + 'bi-chevron-bar-up': showToolbox, + 'bi-chevron-bar-down': !showToolbox + }" + ></i> + </button> +</div> diff --git a/src/frontend/src/app/components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component.spec.ts b/src/frontend/src/app/components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..e38da00ac19f82db4634b2b214134ea6ee4dc5de --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProcessTreeToolboxComponent } from './process-tree-toolbox.component'; + +describe('ProcessTreeToolboxComponent', () => { + let component: ProcessTreeToolboxComponent; + let fixture: ComponentFixture<ProcessTreeToolboxComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ProcessTreeToolboxComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(ProcessTreeToolboxComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component.ts b/src/frontend/src/app/components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..25683cfe803a5f5cba549e5def33a1e8f156841c --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/process-tree-toolbox/process-tree-toolbox.component.ts @@ -0,0 +1,85 @@ +import { + Component, + EventEmitter, + Input, + OnDestroy, + Output, +} from '@angular/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { PT_Constant } from 'src/app/constants/process_tree_drawer_constants'; +import { ProcessTreeOperator } from 'src/app/objects/ProcessTree/ProcessTree'; +import { ProcessTree } from 'src/app/objects/ProcessTree/ProcessTree'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; +import { LogService } from 'src/app/services/logService/log.service'; +import { textColorForBackgroundColor } from 'src/app/utils/render-utils'; + +@Component({ + selector: 'app-process-tree-toolbox', + templateUrl: './process-tree-toolbox.component.html', + styleUrls: ['./process-tree-toolbox.component.css'], +}) +export class ProcessTreeToolboxComponent implements OnDestroy { + readonly operatorNodeColor = PT_Constant.OPERATOR_COLOR; + readonly operatorTextColor = textColorForBackgroundColor( + PT_Constant.OPERATOR_COLOR + ); + readonly ProcessTreeOperator = ProcessTreeOperator; + + processTreeOperators: ProcessTreeOperator[]; + processTreeActivities: string[]; + + showToolbox: boolean = false; + + @Input() operatorInsertionDisabled = false; + @Output() operatorInsertion = new EventEmitter<string>(); + + @Input() activityInsertionDisabled = false; + @Output() activityInsertion = new EventEmitter<string>(); + + private _destroy$ = new Subject(); + + constructor( + private colorMapService: ColorMapService, + private logService: LogService + ) { + this.processTreeOperators = [ + ProcessTreeOperator.sequence, + ProcessTreeOperator.parallelism, + ProcessTreeOperator.choice, + ProcessTreeOperator.loop, + ]; + + this.logService.activitiesInEventLog$ + .pipe(takeUntil(this._destroy$)) + .subscribe((activities) => { + this.processTreeActivities = Object.keys(activities); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + insertOperatorNode(operator: string) { + this.operatorInsertion.emit(operator); + } + + insertActivityNode(activity: string) { + this.activityInsertion.emit(activity); + } + + computeActivityColor(activity: string) { + if (activity === ProcessTreeOperator.tau) + return PT_Constant.INVISIBLE_ACTIVTIY_COLOR; + return this.colorMapService.colorMap?.get(activity); + } + + computeTextColor(activity: string) { + return textColorForBackgroundColor(this.computeActivityColor(activity)); + } + + tooltipContent = (d: d3.HierarchyNode<ProcessTree>) => { + return d.data.label || d.data.operator; + }; +} diff --git a/src/frontend/src/app/components/process-tree-editor/utils.ts b/src/frontend/src/app/components/process-tree-editor/utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..3de7bfdfd5863b64baba6b671293de3eaec5c9eb --- /dev/null +++ b/src/frontend/src/app/components/process-tree-editor/utils.ts @@ -0,0 +1,81 @@ +import { HumanizeDurationOptions } from 'humanize-duration-ts'; +import { HumanizeDurationPipe } from 'src/app/pipes/humanize-duration.pipe'; +import { TreePerformance } from '../../objects/ProcessTree/ProcessTree'; + +export function getPerformanceTable( + performance: TreePerformance, + selectedPerformanceIndicator, + selectedStatistic +): string { + let table = '<table class="table table-dark table-striped table-bordered">'; + + if (!performance) { + return undefined; + } + + let performanceAvailable = false; + const options: HumanizeDurationOptions = { largest: 2, round: true }; + + if (performance.service_time?.[selectedStatistic] !== undefined) { + const serviceTime = HumanizeDurationPipe.apply( + performance?.service_time?.[selectedStatistic] * 1000, + options + ); + table += `<tr> + <td>Service Time (${selectedStatistic}):</td> + <td>${serviceTime}</td> + </tr>`; + performanceAvailable = true; + } + if (performance.waiting_time?.[selectedStatistic] !== undefined) { + const waitingTime = HumanizeDurationPipe.apply( + performance.waiting_time?.[selectedStatistic] * 1000, + options + ); + table += `<tr> + <td>Waiting Time (${selectedStatistic}):</td> + <td>${waitingTime}</td> + </tr>`; + performanceAvailable = true; + } + if (performance.idle_time?.[selectedStatistic] !== undefined) { + const idleTime = HumanizeDurationPipe.apply( + performance.idle_time?.[selectedStatistic] * 1000, + options + ); + table += `<tr> + <td>Idle Time (${selectedStatistic}):</td> + <td>${idleTime}</td> + </tr>`; + performanceAvailable = true; + } + if (performance.cycle_time?.[selectedStatistic] !== undefined) { + const cycleTime = HumanizeDurationPipe.apply( + performance.cycle_time?.[selectedStatistic] * 1000, + options + ); + table += `<tr> + <td>Cycle Time (${selectedStatistic}):</td> + <td>${cycleTime}</td> + </tr>`; + performanceAvailable = true; + } + table += '</table>'; + if (performanceAvailable) { + return table; + } + return undefined; +} + +export function getBootstrapTooltipsAllowList() { + // @ts-ignore + const myDefaultAllowList = $.fn.tooltip.Constructor.Default.allowList; + myDefaultAllowList.div = ['class', 'style', 'role']; + myDefaultAllowList.h6 = ['style']; + myDefaultAllowList.table = ['class']; + myDefaultAllowList.tbody = []; + myDefaultAllowList.tr = []; + myDefaultAllowList.td = []; + + return myDefaultAllowList; +} diff --git a/src/frontend/src/app/components/resizeable-table-header/resizeable-table-header.component.html b/src/frontend/src/app/components/resizeable-table-header/resizeable-table-header.component.html new file mode 100644 index 0000000000000000000000000000000000000000..5b7e7d8a14949f5236fab964cf31349a39f0e9d7 --- /dev/null +++ b/src/frontend/src/app/components/resizeable-table-header/resizeable-table-header.component.html @@ -0,0 +1,10 @@ +<div class="wrapper"> + <div class="content"> + <ng-content></ng-content> + </div> + <div + class="bar" + (resizeable)="onResize($event)" + [style.marginRight.px]="margin" + ></div> +</div> diff --git a/src/frontend/src/app/components/resizeable-table-header/resizeable-table-header.component.scss b/src/frontend/src/app/components/resizeable-table-header/resizeable-table-header.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..87e3aee80bfcdea4e765c045a24f7b766300ee3f --- /dev/null +++ b/src/frontend/src/app/components/resizeable-table-header/resizeable-table-header.component.scss @@ -0,0 +1,35 @@ +.wrapper { + display: flex; + justify-content: flex-end; +} + +.content { + flex: 1; +} + +.bar { + position: absolute; + top: 0; + bottom: 0; + width: 5px; + margin: 0 -7px 0 0; + justify-self: flex-end; + border-left: 2px solid transparent; + border-right: 2px solid transparent; + background: #b9b9b9; + background-clip: content-box; + cursor: col-resize; + opacity: 0; + transition: opacity 0.3s; + + &:hover, + &:active { + opacity: 1; + } +} + +:host { + &:last-child .bar { + display: none; + } +} diff --git a/src/frontend/src/app/components/resizeable-table-header/resizeable-table-header.component.spec.ts b/src/frontend/src/app/components/resizeable-table-header/resizeable-table-header.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..9a276f4e286aef2435260c38865208d49a76162a --- /dev/null +++ b/src/frontend/src/app/components/resizeable-table-header/resizeable-table-header.component.spec.ts @@ -0,0 +1,25 @@ +/* tslint:disable:no-unused-variable */ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ResizeableTableHeaderComponent } from './resizeable-table-header.component'; + +describe('ResizeableTableHeaderComponent', () => { + let component: ResizeableTableHeaderComponent; + let fixture: ComponentFixture<ResizeableTableHeaderComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ResizeableTableHeaderComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ResizeableTableHeaderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/resizeable-table-header/resizeable-table-header.component.ts b/src/frontend/src/app/components/resizeable-table-header/resizeable-table-header.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..bd37fe6a0a72a7cf6b81433e13efddb45c74636e --- /dev/null +++ b/src/frontend/src/app/components/resizeable-table-header/resizeable-table-header.component.ts @@ -0,0 +1,21 @@ +import { Component, HostBinding, Input } from '@angular/core'; + +@Component({ + selector: 'th[resizeable]', // eslint-disable-line @angular-eslint/component-selector + templateUrl: './resizeable-table-header.component.html', + styleUrls: ['./resizeable-table-header.component.scss'], +}) + +// https://stackblitz.com/edit/angular-resizable-columns +export class ResizeableTableHeaderComponent { + constructor() {} + @HostBinding('style.width.px') + width: number | null = null; + + @Input() + margin: number; + + onResize(width: any) { + this.width = width; + } +} diff --git a/src/frontend/src/app/components/settings/model.ts b/src/frontend/src/app/components/settings/model.ts new file mode 100644 index 0000000000000000000000000000000000000000..e5a909ea9cc82de0021630be0156bca85827018f --- /dev/null +++ b/src/frontend/src/app/components/settings/model.ts @@ -0,0 +1,9 @@ +import { TimeUnit } from 'src/app/objects/TimeUnit'; + +export class Configuration { + timeoutCVariantAlignmentComputation: number; + timeGranularity: TimeUnit; + minTracesVariantDetectionMultiprocessing: number; + isNSequentializationReductionEnabled: boolean; + numberOfSequentializationsPerVariant: number; +} diff --git a/src/frontend/src/app/components/settings/settings.component.html b/src/frontend/src/app/components/settings/settings.component.html new file mode 100644 index 0000000000000000000000000000000000000000..61dc0ef31c87d6617ef6d7e6ac83b23aa4a76205 --- /dev/null +++ b/src/frontend/src/app/components/settings/settings.component.html @@ -0,0 +1,159 @@ +<div + class="modal fade" + id="settingsModalDialog" + tabindex="-1" + role="dialog" + aria-labelledby="settingsModalLabel" + aria-hidden="true" +> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header h-line-modal-bottom"> + <h5 class="modal-title text-light" id="settingsModalLabel">Settings</h5> + <button + type="button" + class="btn-close btn-close-white" + data-bs-dismiss="modal" + aria-label="Close" + ></button> + </div> + <div class="modal-body"> + <form class="was-validated" [formGroup]="configForm"> + <div class="form-group row mx-0"> + <label + for="timeout" + class="col-7 col-form-label text-light dialog-label" + >Conformance checking timeout + <i + class="bi bi-question-circle-fill font-large ms-1 align-middle secondary-text" + ngbTooltip="The calculation of conformance statistics stops after the configured timeout (in seconds). The timeout is applied per variant." + triggers="hover" + container="body" + > + </i> + </label> + <div class="col-5"> + <input + type="number" + class="form-control styled-input-field" + id="timeout" + aria-describedby="timeoutHelp" + placeholder="Enter timeout" + formControlName="timeoutCVariantAlignmentComputation" + required + /> + <div class="invalid-feedback"> + Please provide a valid timeout. + </div> + </div> + </div> + <div class="form-group row mx-0 d-flex flex-row align-items-center"> + <label + for="timeout" + class="col-7 col-form-label text-light dialog-label" + > + Minimum number of traces for multiprocessing in variant detection. + <i + class="bi bi-question-circle-fill font-large ms-1 align-middle secondary-text" + ngbTooltip="For variant detection multiprocessing is enabled if the number of traces in the log is greater or equal to this number." + triggers="hover" + container="body" + > + </i> + </label> + <div class="col-5"> + <input + type="number" + class="form-control styled-input-field" + id="mintraces" + aria-describedby="minTracesHelp" + placeholder="" + formControlName="minTracesVariantDetectionMultiprocessing" + required + /> + <div class="invalid-feedback">Please provide a valid input.</div> + </div> + </div> + <div class="form-group row mx-0 d-flex flex-row align-items-center"> + <label + for="timeout" + class="col-7 col-form-label text-light dialog-label" + > + Enable Randomized Sequentializations + <i + class="bi bi-question-circle-fill font-large ms-1 align-middle secondary-text" + ngbTooltip="Before applying standard process mining algorithms in the backend, concurrent variants are sequentialized. For variants with much concurrent behavior, this step can result in many sequentializations. If this configuration is enabled, the backend uses a subset of sequentializations." + triggers="hover" + container="body" + > + </i> + </label> + <div class="col-5"> + <div class="form-check form-switch"> + <input + class="form-check-input" + id="enableNSeq" + type="checkbox" + formControlName="isNSequentializationReductionEnabled" + /> + </div> + </div> + </div> + <div class="form-group row mx-0 d-flex flex-row align-items-center"> + <label + for="timeout" + class="col-7 col-form-label text-light dialog-label" + > + <ng-template #numSequentializationsTooltip> + Before applying standard process mining algorithms in the + backend, concurrent variants are sequentialized. This parameter + changes the number of sequentializations. Only applied if + <b>Enable Randomized Sequentializations</b> is enabled. + </ng-template> + Number of sequentializations + <i + class="bi bi-question-circle-fill font-large ms-1 align-middle secondary-text" + [ngbTooltip]="numSequentializationsTooltip" + triggers="hover" + container="body" + > + </i> + </label> + <div class="col-5"> + <input + type="number" + class="form-control styled-input-field" + id="nseq" + aria-describedby="nSeqHelp" + placeholder="" + formControlName="numberOfSequentializationsPerVariant" + required + /> + <div class="invalid-feedback">Please provide a valid input.</div> + </div> + </div> + </form> + </div> + <div class="modal-footer h-line-modal-top"> + <button + id="close-modal" + type="button" + class="button" + data-bs-dismiss="modal" + > + <i class="bi bi-x-lg btn-icon text-danger"></i> + close without save + </button> + <button + [disabled]="configForm.invalid || configForm.pristine" + type="button" + class="button" + (click)="saveChanges()" + > + <i class="bi bi-save btn-icon text-success"></i> + save + </button> + </div> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/settings/settings.component.scss b/src/frontend/src/app/components/settings/settings.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/settings/settings.component.spec.ts b/src/frontend/src/app/components/settings/settings.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..e659651dba977ab25445d0cb247fad26653d730b --- /dev/null +++ b/src/frontend/src/app/components/settings/settings.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SettingsComponent } from './settings.component'; + +describe('SettingsComponent', () => { + let component: SettingsComponent; + let fixture: ComponentFixture<SettingsComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SettingsComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/settings/settings.component.ts b/src/frontend/src/app/components/settings/settings.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..04475032f63fad271319ac52755d0ed340ecaf37 --- /dev/null +++ b/src/frontend/src/app/components/settings/settings.component.ts @@ -0,0 +1,90 @@ +import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { + UntypedFormBuilder, + UntypedFormGroup, + Validators, +} from '@angular/forms'; +import { Observable, Subject } from 'rxjs'; +import { takeUntil, tap } from 'rxjs/operators'; +import { TimeUnit } from 'src/app/objects/TimeUnit'; +import { BackendService } from 'src/app/services/backendService/backend.service'; +import { LogService } from 'src/app/services/logService/log.service'; +import { SettingsService } from 'src/app/services/settingsService/settings.service'; +import { SharedDataService } from 'src/app/services/sharedDataService/shared-data.service'; +import { Configuration } from './model'; + +declare var $: any; + +@Component({ + selector: 'app-settings', + templateUrl: './settings.component.html', + styleUrls: ['./settings.component.scss'], +}) +export class SettingsComponent implements OnInit, OnDestroy { + @Input() + showSettings: Observable<void>; + configForm: UntypedFormGroup; + + configuration: Configuration = new Configuration(); + + private _destroy$ = new Subject(); + + constructor( + private backendService: BackendService, + private settingsService: SettingsService, + private logService: LogService, + private fb: UntypedFormBuilder + ) {} + + ngOnInit(): void { + this.showSettings + .pipe(takeUntil(this._destroy$)) + .subscribe(() => this.showModal()); + this.configForm = this.fb.group({ + timeoutCVariantAlignmentComputation: [null, Validators.required], + minTracesVariantDetectionMultiprocessing: [null, Validators.required], + isNSequentializationReductionEnabled: [null, Validators.required], + numberOfSequentializationsPerVariant: [null, Validators.required], + // timeGranularity: [null, Validators.required], + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + onGranularityChange(event) { + this.logService.timeGranularity = event; + } + + showModal(): void { + this.backendService + .getConfiguration() + .pipe( + tap((config) => { + this.settingsService.notify(config); + }) + ) + .pipe(takeUntil(this._destroy$)) + .subscribe((config) => { + this.configForm.patchValue(config); + $('#settingsModalDialog').modal('show'); + }); + } + + hideModal(): void { + document.getElementById('close-modal').click(); + } + + saveChanges(): void { + this.backendService + .saveConfiguration(this.configForm.getRawValue()) + .pipe( + tap(() => this.settingsService.notify(this.configForm.getRawValue())) + ) + .pipe(takeUntil(this._destroy$)) + .subscribe((_) => { + this.hideModal(); + }); + } +} diff --git a/src/frontend/src/app/components/toast/toast/toast.component.css b/src/frontend/src/app/components/toast/toast/toast.component.css new file mode 100644 index 0000000000000000000000000000000000000000..3b9cbb22e273aa21f65ebb3e5ee8f49a1c2c1b2b --- /dev/null +++ b/src/frontend/src/app/components/toast/toast/toast.component.css @@ -0,0 +1,3 @@ +.toast-header-bg { + background-color: #3e444a; +} \ No newline at end of file diff --git a/src/frontend/src/app/components/toast/toast/toast.component.html b/src/frontend/src/app/components/toast/toast/toast.component.html new file mode 100644 index 0000000000000000000000000000000000000000..c84f17cfb816b67bb29035f9e9ee28b7ff9d3870 --- /dev/null +++ b/src/frontend/src/app/components/toast/toast/toast.component.html @@ -0,0 +1,35 @@ +<div + class="toast bg-dark secondary-text-color" + role="alert" + aria-live="assertive" + aria-atomic="true" + #toastElement +> + <div class="toast-header toast-header-bg"> + <i + class="bi {{ toastEvent.icon }}" + [ngClass]="{ + 'secondary-text-color': toastEvent.type === ToastType.SUCCESS, + 'text-warning': toastEvent.type === ToastType.WARNING, + 'text-danger': toastEvent.type === ToastType.ERROR + }" + ></i> + <strong + class="me-auto ms-2" + [ngClass]="{ + 'secondary-text-color': toastEvent.type === ToastType.SUCCESS, + 'text-warning': toastEvent.type === ToastType.WARNING, + 'text-danger': toastEvent.type === ToastType.ERROR + }" + >{{ toastEvent.title }} - {{ type }}</strong + > + + <button + type="button" + class="btn-close btn-close-white" + data-bs-dismiss="toast" + aria-label="Close" + ></button> + </div> + <div class="toast-body bg-dark">{{ toastEvent.body }}</div> +</div> diff --git a/src/frontend/src/app/components/toast/toast/toast.component.spec.ts b/src/frontend/src/app/components/toast/toast/toast.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..7cacf6a279729fe97cceb304d1ba5f0b66bc1c36 --- /dev/null +++ b/src/frontend/src/app/components/toast/toast/toast.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ToastComponent } from './toast.component'; + +describe('ToastComponent', () => { + let component: ToastComponent; + let fixture: ComponentFixture<ToastComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ToastComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ToastComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/toast/toast/toast.component.ts b/src/frontend/src/app/components/toast/toast/toast.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..a6431dbe0434cb44c49d5c0f02ce8077853aa3d5 --- /dev/null +++ b/src/frontend/src/app/components/toast/toast/toast.component.ts @@ -0,0 +1,79 @@ +import { + Component, + ElementRef, + EventEmitter, + Input, + OnDestroy, + OnInit, + Output, + ViewChild, +} from '@angular/core'; +import { fromEvent, Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { ToastEvent, ToastType } from 'src/app/objects/toast-event'; +declare var bootstrap: any; + +@Component({ + selector: 'app-toast', + templateUrl: './toast.component.html', + styleUrls: ['./toast.component.css'], +}) +export class ToastComponent implements OnInit, OnDestroy { + @Output() disposeEvent = new EventEmitter(); + + @ViewChild('toastElement', { static: true }) + toastEl!: ElementRef; + + @Input() + toastEvent: ToastEvent; + + toast: any; + + type: string; + + ToastType = ToastType; + + private _destroy$ = new Subject(); + + ngOnInit() { + this.setTypeString(); + this.show(); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + setTypeString(): void { + switch (this.toastEvent.type) { + case ToastType.SUCCESS: + this.type = 'Info'; + break; + case ToastType.WARNING: + this.type = 'Warning'; + break; + case ToastType.ERROR: + this.type = 'Error'; + break; + default: + this.type = ''; + break; + } + } + + show() { + this.toast = new bootstrap.Toast(this.toastEl.nativeElement, { + autohide: this.toastEvent.autoclose, + delay: this.toastEvent.delay, + }); + fromEvent(this.toastEl.nativeElement, 'hidden.bs.toast') + .pipe(takeUntil(this._destroy$)) + .subscribe(() => this.hide()); + this.toast.show(); + } + + hide() { + this.toast.dispose(); + this.disposeEvent.emit(); + } +} diff --git a/src/frontend/src/app/components/toast/toaster/toaster.component.css b/src/frontend/src/app/components/toast/toaster/toaster.component.css new file mode 100644 index 0000000000000000000000000000000000000000..a59b12c67a2e463beb233c5a1b29a29c76d752f0 --- /dev/null +++ b/src/frontend/src/app/components/toast/toaster/toaster.component.css @@ -0,0 +1,3 @@ +.toast-container { + z-index: 20; +} \ No newline at end of file diff --git a/src/frontend/src/app/components/toast/toaster/toaster.component.html b/src/frontend/src/app/components/toast/toaster/toaster.component.html new file mode 100644 index 0000000000000000000000000000000000000000..85b595e2b8afad67757b92c3105b4fc8a62810f7 --- /dev/null +++ b/src/frontend/src/app/components/toast/toaster/toaster.component.html @@ -0,0 +1,7 @@ +<div + class="position-fixed bottom-0 mb-4 start-50 translate-middle-x toast-container" +> + <div *ngFor="let toast of currentToasts; index as i"> + <app-toast [toastEvent]="toast" (disposeEvent)="dispose(i)"></app-toast> + </div> +</div> diff --git a/src/frontend/src/app/components/toast/toaster/toaster.component.spec.ts b/src/frontend/src/app/components/toast/toaster/toaster.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..247289fd08a6b23b29438c89176e30fc1244b452 --- /dev/null +++ b/src/frontend/src/app/components/toast/toaster/toaster.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ToasterComponent } from './toaster.component'; + +describe('ToasterComponent', () => { + let component: ToasterComponent; + let fixture: ComponentFixture<ToasterComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ToasterComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ToasterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/toast/toaster/toaster.component.ts b/src/frontend/src/app/components/toast/toaster/toaster.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..c2674199d57f095140c79effcda408c8e4303358 --- /dev/null +++ b/src/frontend/src/app/components/toast/toaster/toaster.component.ts @@ -0,0 +1,38 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { ToastEvent } from 'src/app/objects/toast-event'; +import { ToastService } from 'src/app/services/toast/toast.service'; + +@Component({ + selector: 'app-toaster', + templateUrl: './toaster.component.html', + styleUrls: ['./toaster.component.css'], +}) +export class ToasterComponent implements OnInit, OnDestroy { + currentToasts: ToastEvent[] = []; + + private _destroy$ = new Subject(); + + constructor(private toastService: ToastService) {} + + ngOnInit() { + this.subscribeToToasts(); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + subscribeToToasts() { + this.toastService.toastEvents + .pipe(takeUntil(this._destroy$)) + .subscribe((toast) => { + this.currentToasts.push(toast); + }); + } + + dispose(index: number) { + this.currentToasts.splice(index, 1); + } +} diff --git a/src/frontend/src/app/components/tree-string-renderer/tree-string-renderer.component.css b/src/frontend/src/app/components/tree-string-renderer/tree-string-renderer.component.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/tree-string-renderer/tree-string-renderer.component.html b/src/frontend/src/app/components/tree-string-renderer/tree-string-renderer.component.html new file mode 100644 index 0000000000000000000000000000000000000000..2e0aebb78e245264c67729edff8cc2741a2feb53 --- /dev/null +++ b/src/frontend/src/app/components/tree-string-renderer/tree-string-renderer.component.html @@ -0,0 +1,6 @@ +<div + #styledText + [ngClass]=" + custom_class ? custom_class : 'styled-input-field user-select-none' + " +></div> diff --git a/src/frontend/src/app/components/tree-string-renderer/tree-string-renderer.component.spec.ts b/src/frontend/src/app/components/tree-string-renderer/tree-string-renderer.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..64423bf2a33d504e8393a7f9cc94122dcf71e4ad --- /dev/null +++ b/src/frontend/src/app/components/tree-string-renderer/tree-string-renderer.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TreeStringRendererComponent } from './tree-string-renderer.component'; + +describe('TreeStringRendererComponent', () => { + let component: TreeStringRendererComponent; + let fixture: ComponentFixture<TreeStringRendererComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [TreeStringRendererComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TreeStringRendererComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/tree-string-renderer/tree-string-renderer.component.ts b/src/frontend/src/app/components/tree-string-renderer/tree-string-renderer.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..8fa1661b143e781d6032514749361f24ceb291d7 --- /dev/null +++ b/src/frontend/src/app/components/tree-string-renderer/tree-string-renderer.component.ts @@ -0,0 +1,128 @@ +import { + Component, + ElementRef, + OnInit, + Renderer2 as Renderer, + ViewChild, + Input, + SimpleChanges, + OnChanges, + AfterViewInit, + OnDestroy, +} from '@angular/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; + +// TODO Bring these to a more convenient place +const SEQUENCE_CHAR = '\u2794'; +const CHOICE_CHAR = '\u2715'; +const LOOP_CHAR = '\u21BA'; +const PARALLELISM_CHAR = '\u2227'; +const TAU_CHAR = '\u03C4'; + +@Component({ + selector: 'app-tree-string-renderer', + templateUrl: './tree-string-renderer.component.html', + styleUrls: ['./tree-string-renderer.component.css'], +}) +export class TreeStringRendererComponent + implements OnChanges, AfterViewInit, OnDestroy +{ + activityNameRegEx = new RegExp("'([^']*)'", 'g'); + activityColorMap: Map<string, string>; + + @ViewChild('styledText') styledTextDiv: ElementRef<HTMLDivElement>; + @Input() styled_tree_string: string; + + // Simple Class overwrite for local styling + @Input() custom_class: string; + + private _destroy$ = new Subject(); + + constructor( + private colorMapService: ColorMapService, + private renderer: Renderer + ) {} + + ngAfterViewInit() { + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + this.activityColorMap = colorMap; + + if (this.styled_tree_string) { + this.styleText(this.styled_tree_string); + } + }); + } + + ngOnChanges(changes: SimpleChanges): void { + const styled_tree_string = changes['styled_tree_string'].currentValue; + if (styled_tree_string && this.activityColorMap) { + this.styleText(styled_tree_string); + } + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + styleText(value: string) { + value = this.colorActivityNames(value); + value = this.replacePlaceHolderOperatorString(value); + + // This presents a possible vulnerability for remote code execution, add sanitisation or change input mode, when this presents a serious issue. + this.renderer.setProperty( + this.styledTextDiv.nativeElement, + 'innerHTML', + value + ); + } + + // Color activity names of known activities in the colormap color and highlight those of unknown name + colorActivityNames(value: any): string { + const matches = value.matchAll(this.activityNameRegEx); + let knownActivities = new Set(); + let unknowActivities = new Set(); + + for (let match of matches) { + if (this.activityColorMap.has(match[1])) { + knownActivities.add(match[1]); + } else { + unknowActivities.add(match[1]); + } + } + + knownActivities.forEach((activityName: string) => { + value = value.replace( + new RegExp("'" + activityName + "'", 'g'), + `'<b><span style="color:${this.activityColorMap.get(activityName)}">` + + activityName + + "</span></b>'" + ); + }); + + unknowActivities.forEach((activityName: string) => { + value = value.replace( + new RegExp("'" + activityName + "'", 'g'), + '\'<span class="warning-highlight">' + activityName + "</span>'" + ); + }); + + return value; + } + + // Replace + replacePlaceHolderOperatorString(value: string): string { + value = value + .replace(/\*tau\*/g, '<b>' + TAU_CHAR + '</b>') + .replace(/\*[\s]*\(/g, '<b>' + LOOP_CHAR + '</b>' + '(') + .replace(/X[\s]*\(/g, '<b>' + CHOICE_CHAR + '</b>' + '(') + .replace(/\+[\s]*\(/g, '<b>' + PARALLELISM_CHAR + '</b>' + '(') + .replace(/->[\s]*\(/g, '<b>' + SEQUENCE_CHAR + '</b>' + '('); + + return value; + } +} diff --git a/src/frontend/src/app/components/unavailable-info/unavailable-info.component.css b/src/frontend/src/app/components/unavailable-info/unavailable-info.component.css new file mode 100644 index 0000000000000000000000000000000000000000..987cf3844850f6d64f44da7a36102c9dc52746a0 --- /dev/null +++ b/src/frontend/src/app/components/unavailable-info/unavailable-info.component.css @@ -0,0 +1,6 @@ +.unavailable-warning{ + font-size: small; + margin: 15px; + text-align: center; + color: var(--bs-warning); +} diff --git a/src/frontend/src/app/components/unavailable-info/unavailable-info.component.html b/src/frontend/src/app/components/unavailable-info/unavailable-info.component.html new file mode 100644 index 0000000000000000000000000000000000000000..af5ee632321a2df300f56d4efb6eefe43cf21a19 --- /dev/null +++ b/src/frontend/src/app/components/unavailable-info/unavailable-info.component.html @@ -0,0 +1,5 @@ +<div class="unavailable-warning"> + <i class="b bi bi-info-lg" style="font-size: 2.5rem"></i> + <br /> + <ng-content></ng-content> +</div> diff --git a/src/frontend/src/app/components/unavailable-info/unavailable-info.component.spec.ts b/src/frontend/src/app/components/unavailable-info/unavailable-info.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..f1b0fb28d63e187f5065ea20a01821ef55dbdbee --- /dev/null +++ b/src/frontend/src/app/components/unavailable-info/unavailable-info.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UnavailableInfoComponent } from './unavailable-info.component'; + +describe('UnavailableInfoComponent', () => { + let component: UnavailableInfoComponent; + let fixture: ComponentFixture<UnavailableInfoComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UnavailableInfoComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UnavailableInfoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/unavailable-info/unavailable-info.component.ts b/src/frontend/src/app/components/unavailable-info/unavailable-info.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..a74867e396b286b302e0025bf2f1b8902410d067 --- /dev/null +++ b/src/frontend/src/app/components/unavailable-info/unavailable-info.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-unavailable-info', + templateUrl: './unavailable-info.component.html', + styleUrls: ['./unavailable-info.component.css'], +}) +export class UnavailableInfoComponent { + constructor() {} +} diff --git a/src/frontend/src/app/components/variant-conformance/variant-conformance.component.css b/src/frontend/src/app/components/variant-conformance/variant-conformance.component.css new file mode 100644 index 0000000000000000000000000000000000000000..b462ef122f59936c7071727a37fe7c26bb611b44 --- /dev/null +++ b/src/frontend/src/app/components/variant-conformance/variant-conformance.component.css @@ -0,0 +1,20 @@ +:host { + display: flex; + flex-direction: column; + overflow: auto; + position: absolute; +} + +.nav-tabs { + padding-bottom: 5px; +} + +.color-map { + padding: 10px; + display: flex; +} + +.card { + background-color: transparent; + border: 0; +} diff --git a/src/frontend/src/app/components/variant-conformance/variant-conformance.component.html b/src/frontend/src/app/components/variant-conformance/variant-conformance.component.html new file mode 100644 index 0000000000000000000000000000000000000000..2282cd85a9634f5e9682b34e886e9034f23637f3 --- /dev/null +++ b/src/frontend/src/app/components/variant-conformance/variant-conformance.component.html @@ -0,0 +1,39 @@ +<ul class="nav nav-tabs bg-dark" role="tablist"> + <li class="nav-item" role="presentation"> + <button + class="nav-link active button" + id="variant-colormap-tab" + data-bs-toggle="tab" + data-bs-target="#variantColormap" + role="tab" + aria-controls="variantColormap" + aria-selected="true" + #colorMapTab + > + Color Map + </button> + </li> +</ul> + +<div class="tab-content" id="myTabContent"> + <div + class="tab-pane fade show active color-map-tab" + id="variantColormap" + role="tabpanel" + aria-labelledby="variant-colormap-tab" + > + <div class="card text-white mb-3 w-50"> + <div class="card-body"> + <h5 class="card-title">Conformance Color Map</h5> + + <div class="mb-3"> + <app-color-map + [colorMapValues]="conformanceColorMapValues" + [timeBasedLabel]="false" + suffix="%" + ></app-color-map> + </div> + </div> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/variant-conformance/variant-conformance.component.spec.ts b/src/frontend/src/app/components/variant-conformance/variant-conformance.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..332454ef1e276788b90b576b91fb9398fe186bfc --- /dev/null +++ b/src/frontend/src/app/components/variant-conformance/variant-conformance.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ConformanceTabComponent } from './variant-conformance.component'; + +describe('VariantConformanceComponent', () => { + let component: ConformanceTabComponent; + let fixture: ComponentFixture<ConformanceTabComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ConformanceTabComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConformanceTabComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-conformance/variant-conformance.component.ts b/src/frontend/src/app/components/variant-conformance/variant-conformance.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..c212f0734a1dca5267a2e81768a93ac7633418a8 --- /dev/null +++ b/src/frontend/src/app/components/variant-conformance/variant-conformance.component.ts @@ -0,0 +1,114 @@ +import { + AfterViewInit, + Component, + ElementRef, + Inject, + OnDestroy, + Renderer2, + ViewChild, +} from '@angular/core'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { ConformanceCheckingService } from 'src/app/services/conformanceChecking/conformance-checking.service'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { ModelViewModeService } from 'src/app/services/viewModeServices/model-view-mode.service'; +import { VariantViewModeService } from 'src/app/services/viewModeServices/variant-view-mode.service'; +import { ColorMapValue } from '../performance/color-map/color-map.component'; + +@Component({ + selector: 'app-conformance-tab', + templateUrl: './conformance-tab.component.html', + styleUrls: ['./conformance-tab.component.css'], +}) +export class ConformanceTabComponent + extends LayoutChangeDirective + implements AfterViewInit, OnDestroy +{ + @ViewChild('colorMapTab') colorMapTab: ElementRef; + + private _destroy$ = new Subject(); + public conformanceColorMapValues: ColorMapValue[]; + + public VM = ViewMode; + + constructor( + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef, + renderer: Renderer2, + private conformanceCheckingService: ConformanceCheckingService, + private variantViewModeService: VariantViewModeService, + public modelViewModeService: ModelViewModeService, + public processTreeService: ProcessTreeService + ) { + super(elRef.nativeElement, renderer); + + const colorMap = this.conformanceCheckingService.variantConformanceColorMap; + const min = colorMap.domain()[0]; + const max = colorMap.domain()[colorMap.domain().length - 1]; + const increment = (max - min) / (colorMap.range().length - 2); + + this.conformanceColorMapValues = colorMap + .range() + .slice(1) + .map((v, i) => { + const t = min + i * increment; + + return { + lowerBound: Math.round(t * 100), + color: v, + }; + }) + .concat([ + { + lowerBound: max * 100, + color: null, + }, + ]); + } + + ngAfterViewInit(): void { + this.variantViewModeService.viewMode$ + .pipe(takeUntil(this._destroy$)) + .subscribe((viewMode) => { + if (viewMode === ViewMode.CONFORMANCE) + this.colorMapTab.nativeElement.click(); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + + handleVisibilityChange(visibility: boolean): void {} + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} + + public performanceStats: any; + public colorScale; + public title; + + public conformanceWeightMethodChange(event): void { + const value = event.target.value; + if (value == 'weighted_equally') + this.conformanceCheckingService.isConformanceWeighted = false; + else this.conformanceCheckingService.isConformanceWeighted = true; + } +} + +export namespace ConformanceTabComponent { + export const componentName = 'VariantConformanceComponent'; +} diff --git a/src/frontend/src/app/components/variant-explorer/arc-diagram/arcs-view-mode.ts b/src/frontend/src/app/components/variant-explorer/arc-diagram/arcs-view-mode.ts new file mode 100644 index 0000000000000000000000000000000000000000..7fe0b0756861d1fbbe054c11be30428c69dc7049 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/arc-diagram/arcs-view-mode.ts @@ -0,0 +1,6 @@ +export enum ArcsViewMode { + INITIAL, + SHOW_ALL, + SHOW_SOME, + HIDE_ALL, +} diff --git a/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter-params.ts b/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter-params.ts new file mode 100644 index 0000000000000000000000000000000000000000..fe16cc7fcd9a39ef862ba2abd59a367b3eb9f994 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter-params.ts @@ -0,0 +1,37 @@ +import { ActivitiesSelection, MultiRangeFilter } from './filter.component'; + +export class FilterParams { + lengthRange: MultiRangeFilter; + sizeRange: MultiRangeFilter; + distanceRange: MultiRangeFilter; + activitiesSelection: ActivitiesSelection; + constructor() { + this.distanceRange = { + low: 0, + high: 20, + options: { + step: 1, + floor: 0, + ceil: 2, + showTicks: true, + }, + }; + this.sizeRange = { + ...this.distanceRange, + low: 1, + options: { + ...this.distanceRange.options, + floor: 1, + }, + }; + + this.lengthRange = { + ...this.sizeRange, + }; + + this.activitiesSelection = { + selectedItems: new Set<string>(), + activitiesList: new Set<string>(), + }; + } +} diff --git a/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter.component.html b/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter.component.html new file mode 100644 index 0000000000000000000000000000000000000000..0a1b2fe3da8b238bfbcd407e128691e9f3bd0412 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter.component.html @@ -0,0 +1,57 @@ +<form (ngSubmit)="onSubmit()" class="form-group p-3 d-flex flex-column"> + <div> + <label class="primary-text">Size:</label> + <div class="custom-slider"> + <ngx-slider + [(value)]="model.sizeRange.low" + [(highValue)]="model.sizeRange.high" + [options]="model.sizeRange.options" + ></ngx-slider> + </div> + </div> + <div> + <label class="primary-text">Length:</label> + <div class="custom-slider"> + <ngx-slider + [(value)]="model.lengthRange.low" + [(highValue)]="model.lengthRange.high" + [options]="model.lengthRange.options" + ></ngx-slider> + </div> + </div> + <div> + <label class="primary-text">Distance:</label> + <div class="custom-slider"> + <ngx-slider + [(value)]="model.distanceRange.low" + [(highValue)]="model.distanceRange.high" + [options]="model.distanceRange.options" + ></ngx-slider> + </div> + </div> + <div class="d-flex flex-column"> + <label class="primary-text">Include Activites: {{ model.activitiesSelection.selectedItems.size }}</label> + <div class="d-flex flex-row justify-content-start"> + <button type="button" class="button activities-selection-btn" (click)="toggleActivitiesSelection()">{{ activitiesSelectionBtnText }}</button> + </div> + </div> + <div class="container"> + <div class="row justify-content-start"> + <div *ngFor="let act of Array.from(model.activitiesSelection.activitiesList)" class="col-md d-flex flex-row"> + <input class="form-check-input" type="checkbox" (change)="onChangeCheckbox(act)" + [value]="act" [checked]="model.activitiesSelection.selectedItems.has(act)" style="margin-right: 5px;" /> + <svg + appVariantDrawer + [variant]="{ variant: activityDummyVariants.get(act) }" + [computeActivityColor]="computeActivityColor" + [addCursorPointer]="false" + ></svg> + </div> + </div> + </div> + <div class="py-3 flex-end"> + <button type="submit" class="button submit-button"> + Filter + </button> + </div> +</form> diff --git a/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter.component.scss b/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..7eedb71c825704aa77b3aedc720701f686988042 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter.component.scss @@ -0,0 +1,88 @@ +:host ::ng-deep { + .form-group { + resize: both; + overflow: auto; + } + + .custom-slider .ngx-slider .ngx-slider-bar { + background: #5b5b5b; + height: 2px; + } + + .custom-slider .ngx-slider .ngx-slider-selection { + background: var(--text-secondary); + } + + .custom-slider .ngx-slider .ngx-slider-pointer { + width: 8px; + height: 16px; + top: auto; /* to remove the default positioning */ + bottom: 0; + background-color: var(--text-secondary); + border-top-left-radius: 3px; + border-top-right-radius: 3px; + } + + .custom-slider .ngx-slider .ngx-slider-pointer::after { + display: none; + } + + .custom-slider .ngx-slider .ngx-slider-bubble { + bottom: 14px; + color: var(--text-secondary); + } + + .custom-slider .ngx-slider .ngx-slider-limit { + font-weight: lighter; + color: #5b5b5b; + } + + .custom-slider .ngx-slider .ngx-slider-tick { + width: 1px; + height: 10px; + margin-left: 4px; + border-radius: 0; + background: #5b5b5b; + top: -1px; + } + + .custom-slider .ngx-slider .ngx-slider-tick.ngx-slider-selected { + background: var(--text-secondary); + } + + .submit-button { + background: rgb(119 117 117); + border-radius: 3px; + } + + .dropdown-list { + position: relative !important; + } + + .form-select { + background-color: var(--box-background-color); + padding: 0 !important; + margin-top: 6px; + resize: both; + } + + .activities-selection-btn { + border-style: solid; + border-width: thin; + border-radius: 3px; + opacity: 0.5; + } + + .reset-activities-btn:hover { + filter: brightness(1.75); + } + + .row { + gap: 5px; + } + + .d-flex { + gap: 10px; + } + +} diff --git a/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter.component.spec.ts b/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..a911c2837ff0d589865533b3d6bb38dbc49d49d9 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter.component.spec.ts @@ -0,0 +1,20 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ArcDiagramFilterComponent } from './filter.component'; + +describe('ArcDiagramFilterComponent', () => { + let component: ArcDiagramFilterComponent; + let fixture: ComponentFixture<ArcDiagramFilterComponent>; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ArcDiagramFilterComponent], + }); + fixture = TestBed.createComponent(ArcDiagramFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter.component.ts b/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..3c1e7b9ca333e5f6ee34152834a20ae442d91efd --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/arc-diagram/filter/filter.component.ts @@ -0,0 +1,133 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FilterParams } from './filter-params'; +import { Options } from 'ngx-slider-v2'; +import { takeUntil } from 'rxjs/operators'; +import { LogService } from '../../../../services/logService/log.service'; +import { Subject } from 'rxjs'; +import { ColorMapService } from '../../../../services/colorMapService/color-map.service'; +import { computeActivityColor } from '../../../../utils/render-utils'; +import { LeafNode } from '../../../../objects/Variants/variant_element'; + +const SELECT_ALL_TEXT = 'Select All'; +const DESELECT_ALL_TEXT = 'Deselect All'; + +@Component({ + selector: 'app-arc-diagram-filter-form', + templateUrl: './filter.component.html', + styleUrls: ['./filter.component.scss'], +}) +export class ArcDiagramFilterComponent implements OnInit { + constructor( + private logService: LogService, + private colorMapService: ColorMapService + ) {} + + activityDummyVariants: Map<string, LeafNode> = new Map<string, LeafNode>(); + + colorMap: Map<string, string> = new Map<string, string>(); + computeActivityColor = computeActivityColor.bind(this); + + activitiesSelectionBtnText: string = DESELECT_ALL_TEXT; + + @Output() + filterArcDiagrams = new EventEmitter<FilterParams>(); + @Output() + newActivitiesLoaded = new EventEmitter<Set<string>>(); + + @Input() set arcsMaxValues(values: MaxValues) { + for (const [type, value] of Object.entries(values)) { + this.setRangeFilters(type, value); + } + } + @Input() + filtering: boolean; + + private _destroy$ = new Subject(); + + model: FilterParams = new FilterParams(); + + ngOnInit() { + this.logService.activitiesInEventLog$ + .pipe(takeUntil(this._destroy$)) + .subscribe((activities) => { + this.model.activitiesSelection.activitiesList = new Set(); + Object.entries(activities).forEach(([activity], idx: number) => { + this.model.activitiesSelection.activitiesList.add(activity); + this.setActivityDummyVariants(activity); + }); + this.model.activitiesSelection.selectedItems = new Set( + this.model.activitiesSelection.activitiesList + ); + this.newActivitiesLoaded.emit( + this.model.activitiesSelection.selectedItems + ); + }); + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((map) => { + this.colorMap = map; + }); + } + createNewOptionsObject(rangeFilter: Options, value: number) { + const newOptions: Options = Object.assign({}, rangeFilter); + newOptions.ceil = value + 1; + return newOptions; + } + + setRangeFilters(type: string, value: number) { + if (!this.filtering) { + this.model[`${type}Range`].high = value + 1; + } + this.model[`${type}Range`].options = this.createNewOptionsObject( + this.model[`${type}Range`].options, + value + ); + } + onSubmit() { + this.filterArcDiagrams.emit(this.model); + } + + toggleActivitiesSelection() { + if (this.model.activitiesSelection.selectedItems.size > 0) { + this.model.activitiesSelection.selectedItems.clear(); + this.activitiesSelectionBtnText = SELECT_ALL_TEXT; + } else { + this.model.activitiesSelection.selectedItems = new Set( + this.model.activitiesSelection.activitiesList + ); + this.activitiesSelectionBtnText = DESELECT_ALL_TEXT; + } + } + + setActivityDummyVariants(activity: string) { + const leaf = new LeafNode([activity]); + leaf.setExpanded(true); + this.activityDummyVariants.set(activity, leaf); + } + + onChangeCheckbox(activity: string) { + if (this.model.activitiesSelection.selectedItems.has(activity)) { + this.model.activitiesSelection.selectedItems.delete(activity); + } else { + this.model.activitiesSelection.selectedItems.add(activity); + } + } + protected readonly Array = Array; +} + +export class MultiRangeFilter { + low: number; + high: number; + options: Options; +} + +export class ActivitiesSelection { + activitiesList: Set<string>; + selectedItems: Set<string>; +} + +export class MaxValues { + size: number; + length: number; + distance: number; +} diff --git a/src/frontend/src/app/components/variant-explorer/case-explorer/case-explorer.component.css b/src/frontend/src/app/components/variant-explorer/case-explorer/case-explorer.component.css new file mode 100644 index 0000000000000000000000000000000000000000..0dfd19797427ba0ef1150f472c27c0dd45a4343d --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/case-explorer/case-explorer.component.css @@ -0,0 +1,114 @@ +.main-variant-explorer { + overflow: auto; + background-color: var(--box-background-color); + } + + .chart-variant-percentage { + margin-left: 4px; + display: inline-flex; + flex-direction: column; + + /* + min-width: 50px; + */ + font-size: .8rem; + color: whitesmoke; + color: var(--text-secondary); + } + + :host { + position: absolute; + overflow: hidden; + } + + .variant-info-cell { + align-items: center; + display: flex; + } + + .btn-tool-bar{ + min-height: 28px; + display: flex; + align-items: center; + border-top: 0; + position: sticky; + top: 0; + left: 0; + } + + .variant-cell { + width: 100%; + } + + .variant { + padding: 5px; + width: fit-content; + cursor: pointer; + } + + .svg-rendering-status { + color: var(--text-secondary); + } + + + /* Move all below to central place - also used in variant explorer */ + + .container-variant-explorer { + min-height: 100%; + width: calc(100% - 20px); + position: relative; + border-left: 1px solid var(--thin-border-color); + margin-left: 20px; + } + +.activity-overview-container { + background-color: var(--box-background-color); +} + +.table-font{ + font-size: small; +} + +.resizeable-header-element{ + padding : 0.2rem; +} + +.table-header-sort-group{ + display: flex; + flex-direction: column; + align-items: center; +} + +.table-container { + overflow: auto auto; + background-color: var(--box-background-color); +} + +.toggle-select{ + cursor : pointer; +} + +thead th { + vertical-align: top; +} + +thead tr:nth-child(1) th { + position: static; + top: 0; + z-index: 10; +} + +tbody tr { + padding-bottom: .25rem; + padding-top: .25rem; +} + +.border-color { + border-color: var(--line-color)!important; +} + +.activity-overview-table-header { + position: sticky; + top: 0; + z-index: auto; +} \ No newline at end of file diff --git a/src/frontend/src/app/components/variant-explorer/case-explorer/case-explorer.component.html b/src/frontend/src/app/components/variant-explorer/case-explorer/case-explorer.component.html new file mode 100644 index 0000000000000000000000000000000000000000..105542699efc51ebd585b8e00da4965f77979e50 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/case-explorer/case-explorer.component.html @@ -0,0 +1,162 @@ +<app-performance-progress-bar></app-performance-progress-bar> + +<app-variant-explorer-sidebar></app-variant-explorer-sidebar> + +<div class="d-flex flex-column mh-100 h-100 container-variant-explorer"> + <div class="table-container flex-grow-1 table-responsive"> + <table + class="table table-sm table-font table-hover table-striped table-borderless table-dark mb-0" + *ngIf="mainVariant" + > + <thead class="activity-overview-table-header"> + <tr class="user-select-none"> + <th + resizeable + scope="col" + class="bg-dark text-center toggle-select resizeable-header-element" + (click)="toggleSort('act_id')" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + ngbTooltip="The event name" + triggers="hover" + > + <div class="user-select-none mx-1">Event</div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-alpha-down-alt': !ascending, + 'bi-sort-alpha-down': ascending, + invisible: sortKey !== 'act_id' + }" + ></i> + </div> + </th> + <th + resizeable + scope="col" + class="bg-dark text-center toggle-select resizeable-header-element" + (click)="toggleSort('start_timestamp')" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + ngbTooltip="The starting timestamp of the event" + triggers="hover" + > + <div class="user-select-none mx-1">Start timestamp</div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-numeric-down-alt': !ascending, + 'bi-sort-numeric-down': ascending, + invisible: sortKey !== 'start_timestamp' + }" + ></i> + </div> + </th> + <th + resizeable + scope="col" + class="bg-dark text-center toggle-select resizeable-header-element" + (click)="toggleSort('end_timestamp')" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + ngbTooltip="The ending timestamp of the event" + triggers="hover" + > + <div class="user-select-none mx-1">End timestamp</div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-numeric-down-alt': !ascending, + 'bi-sort-numeric-down': ascending, + invisible: sortKey !== 'end_timestamp' + }" + ></i> + </div> + </th> + <th + resizeable + scope="col" + class="bg-dark text-center toggle-select resizeable-header-element" + (click)="toggleSort('duration')" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + ngbTooltip="The duration the event lasted" + triggers="hover" + > + <div class="user-select-none mx-1">Duration</div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-numeric-down-alt': !ascending, + 'bi-sort-numeric-down': ascending, + invisible: sortKey !== 'duration' + }" + ></i> + </div> + </th> + <th + *ngFor="let key of activityPropertyKeys" + resizeable + scope="col" + (click)="toggleSort(key)" + class="bg-dark text-center toggle-select resizeable-header-element" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + > + <div ngbTooltip="Other properties of the event" triggers="hover"> + <div class="user-select-none mx-1">{{ key }}</div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-down': !ascending, + 'bi-sort-down-alt': ascending, + invisible: sortKey !== key + }" + ></i> + </div> + </div> + </th> + </tr> + </thead> + + <tbody> + <ng-container *ngIf="caseActivities"> + <tr + *ngFor=" + let act of caseActivities | tableSorting : sortKey : ascending + " + > + <td class="text-center user-select-none"> + {{ act.act_id }} + </td> + <td class="text-center user-select-none"> + {{ act.start_timestamp }} + </td> + <td class="text-center user-select-none"> + {{ act.end_timestamp }} + </td> + <td class="text-center user-select-none"> + {{ act.duration }} + </td> + <td + *ngFor="let key of activityPropertyKeys" + class="text-center user-select-none" + > + {{ act.property.hasOwnProperty(key) ? act.property[key] : "-" }} + </td> + </tr> + </ng-container> + </tbody> + </table> + </div> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/case-explorer/case-explorer.component.spec.ts b/src/frontend/src/app/components/variant-explorer/case-explorer/case-explorer.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..00183537aa8dce4e3cac260c7c27b3429118985e --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/case-explorer/case-explorer.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CaseExplorerComponent } from './case-explorer.component'; + +describe('CaseExplorerComponent', () => { + let component: CaseExplorerComponent; + let fixture: ComponentFixture<CaseExplorerComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [CaseExplorerComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(CaseExplorerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/case-explorer/case-explorer.component.ts b/src/frontend/src/app/components/variant-explorer/case-explorer/case-explorer.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..9fdbbd65e9cad42afba9860f38f9f414d159e2e1 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/case-explorer/case-explorer.component.ts @@ -0,0 +1,272 @@ +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { LogService } from 'src/app/services/logService/log.service'; +import { + Component, + OnInit, + ElementRef, + Inject, + Renderer2, + AfterViewInit, + ChangeDetectorRef, + OnDestroy, + Output, +} from '@angular/core'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; +import { DropzoneConfig } from 'src/app/components/drop-zone/drop-zone.component'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { BackendService } from 'src/app/services/backendService/backend.service'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { VariantPerformanceService } from 'src/app/services/variant-performance.service'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { IVariant } from 'src/app/objects/Variants/variant_interface'; +import { LoopCollapsedVariant } from 'src/app/objects/Variants/loop_collapsed_variant'; +import { Dictionary } from 'lodash'; + +@Component({ + selector: 'app-case-explorer', + templateUrl: './case-explorer.component.html', + styleUrls: ['./case-explorer.component.css'], +}) +export class CaseExplorerComponent + extends LayoutChangeDirective + implements OnInit, AfterViewInit, OnDestroy +{ + @Output() + mainVariant: Variant; + index: number; + caseId: string; + constructor( + private colorMapService: ColorMapService, + private logService: LogService, + private variantService: VariantService, + private processTreeService: ProcessTreeService, + private backendService: BackendService, + private ref: ChangeDetectorRef, + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef, + renderer: Renderer2, + private variantPerformanceService: VariantPerformanceService + ) { + super(elRef.nativeElement, renderer); + let state = this.container.initialState; + this.mainVariant = state['variant'] as IVariant; + this.index = state['index'] as number; + this.caseId = state['case_id'] as string; + } + + activityColorMap: Map<string, string>; + activitiesInTree: Set<string> = new Set<string>(); + startActivities: Set<string>; + endActivities: Set<string>; + activitiesInLog: any; + activityFields: ActivityField[]; + caseActivities: Map<string, number>[]; + activityPropertyKeys: any; //how to improve + + sortKey: string = 'end_timestamp'; + ascending: boolean = true; + + activityOverviewOutOfFocus: boolean = false; + + dropZoneConfig: DropzoneConfig; + + resetAvailable: boolean = false; + + private _destroy$ = new Subject(); + + ngOnInit(): void { + this.dropZoneConfig = new DropzoneConfig( + '.xes', + 'false', + 'false', + '<large> Import <strong>Event Log</strong> .xes file</large>' + ); + + this.activityFields = []; + + this.backendService + .getCaseActivities(this.index - 1, this.caseId) + .subscribe((caseActivities: Map<string, any>[]) => { + this.caseActivities = caseActivities['statistics']; + this.activityPropertyKeys = caseActivities['keys']; + }); + + this.variantService.cachedChange$ + .pipe(takeUntil(this._destroy$)) + .subscribe((change) => { + this.resetAvailable = change; + }); + } + + ngAfterViewInit(): void { + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + this.activityColorMap = colorMap; + + if (this.activityFields) { + for (let activityField of this.activityFields) { + activityField.color = this.activityColorMap.get( + activityField.activityName + ); + } + } + }); + + // Handle change of current activies in the loaded model + this.processTreeService.activitiesInCurrentTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((activitiesInTree) => { + for (let field of this.activityFields) { + field.inModel = activitiesInTree.has(field.activityName); + } + }); + + this.variantService.variants$ + .pipe(takeUntil(this._destroy$)) + .subscribe(() => { + if (this.activityColorMap) { + this.resetActivityFields(); + } + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + resetActivityFields() { + this.startActivities = this.logService.startActivitiesInEventLog; + this.endActivities = this.logService.endActivitiesInEventLog; + this.activitiesInLog = this.logService.activitiesInEventLog; + this.activitiesInTree = this.processTreeService.activitiesInCurrentTree; + + this.activityFields = []; + for (let activity in this.activitiesInLog) { + this.activityFields.push( + new ActivityField( + activity, + this.activitiesInLog[activity], + this.activityColorMap.get(activity), + this.activitiesInTree.has(activity), + this.startActivities.has(activity), + this.endActivities.has(activity) + ) + ); + } + } + + toggleBlur(event) { + this.activityOverviewOutOfFocus = event; + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + + handleVisibilityChange(visibility: boolean): void {} + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} + + toggleSort(sortKey: string) { + // On the first Click always make descending + if (this.sortKey != sortKey) { + this.sortKey = sortKey; + this.ascending = false; + } else { + // Make it toggle between on subsequent clicks + this.ascending = !this.ascending; + } + } + + deleteActivity(e: Event, activity: ActivityField) { + this.variantService.deleteActivity(activity.activityName).subscribe(); + this.variantPerformanceService.resetVariantPerformance(); + this.resetActivityFields(); + } + + changeActivityColor(activityField: ActivityField, color: string) { + if (color) { + activityField.color = color; + this.colorMapService.changeActivityColor( + activityField.activityName, + color + ); + } + } + + resetActivityColors(): void { + this.colorMapService.createColorMap( + Array.from(this.activityColorMap.keys()) + ); + } + + resetActivityNames(): void { + if (this.activityFields) { + for (let activityField of this.activityFields) { + activityField.inputActivityName = activityField.activityName; + } + } + } + + // TODO: refactor this to shared data service + applyActivityNameChanges( + oldActivityName: string, + newActivityName: string + ): void { + if (oldActivityName !== newActivityName) { + this.variantService + .renameActivity(oldActivityName, newActivityName) + .subscribe(); + // Changing activity field table + this.resetActivityFields(); + } + } + + revertLastChange(e: Event) { + e.stopPropagation(); + this.resetAvailable = false; + this.variantService.revertChangeInBackend(); + } +} + +export class ActivityField { + activityName: string; + occurences: number; + inModel: boolean; + isStart: boolean; + isEnd: boolean; + color: string; + inputActivityName: string; // Storing the input name from user + + constructor( + activityName: string, + occurences: number, + color: string, + inModel: boolean, + isStart: boolean, + isEnd: boolean + ) { + this.activityName = activityName; + this.occurences = occurences; + this.inModel = inModel; + this.isStart = isStart; + this.isEnd = isEnd; + this.color = color; + this.inputActivityName = activityName; + } +} + +export namespace CaseExplorerComponent { + export const componentName = 'CaseExplorerComponent'; +} diff --git a/src/frontend/src/app/components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component.html b/src/frontend/src/app/components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component.html new file mode 100644 index 0000000000000000000000000000000000000000..acd91318c3701678f4ac81fc45078177342d1442 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component.html @@ -0,0 +1,98 @@ +<div class="modal-header h-line-modal-bottom"> + <h5 class="modal-title text-light" id="clusteringSettingsLabel"> + Variant Clustering Settings + </h5> + + <span style="margin-left: 37%"> + <i + class="bi bi-question-circle-fill font-large ms-1 align-middle secondary-text cursor-help question-icon" + container="body" + (click)="openDocumentation('Variant Clustering')" + ></i> + </span> + + <button + type="button" + class="btn-close btn-close-white" + (click)="modal.dismiss('Cross click')" + aria-label="Close" + ></button> +</div> + +<div class="modal-body"> + <div class="d-flex flex-column"> + <div class="form-select-element"> + <label ngbAutofocus class="input-label">Clustering Method: </label> + <select + [(ngModel)]="selectedClusteringAlgorithm" + class="form-select input-selector cursor-pointer" + > + <option *ngFor="let algo of options" [ngValue]="algo" selected> + {{ getDisplayName(algo) }} + </option> + </select> + </div> + <div + class="form-select-element" + *ngIf=" + selectedClusteringAlgorithm === 'AGGLOMERATIVE_EDIT_DISTANCE_CLUSTERING' + " + > + <label for="maxDistance" class="input-label" + >Max. Variant Edit Distance Within a Cluster: + </label> + <input + id="maxDistance" + type="number" + class="input-field-number" + [(ngModel)]="maxDistance" + aria-describedby="nSeqHelp" + placeholder="max distance" + min="0" + /> + </div> + <div + class="form-select-element" + *ngIf="selectedClusteringAlgorithm === 'LABEL_VECTOR_CLUSTERING'" + > + <label for="nClusters" class="input-label">Number of Clusters: </label> + <input + id="nClusters" + type="number" + class="input-field-number" + [(ngModel)]="nClusters" + aria-describedby="nSeqHelp" + placeholder="n clusters" + min="1" + [max]="numberOfVariants" + /> + </div> + </div> +</div> + +<div class="modal-footer h-line-modal-top"> + <button + type="button" + class="button" + data-bs-dismiss="modal" + (click)="onReset()" + > + <i class="bi bi-arrow-clockwise btn-icon text-danger"></i> + Reset + </button> + + <button + type="button" + class="button" + data-bs-dismiss="modal" + (click)="modal.dismiss('cancel click')" + > + <i class="bi bi-x-lg btn-icon text-danger"></i> + Close + </button> + + <button type="button" class="button" (click)="onApply()"> + <i class="bi bi-save btn-icon text-success"></i> + Apply + </button> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component.scss b/src/frontend/src/app/components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..ba1522839adadb0336b8c60790c1a832ffbfd860 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component.scss @@ -0,0 +1,54 @@ +.modal-content { + background-color: var(--box-background-color) !important; +} + +.form-select-element{ + padding-left: 2.5px; + width: 100%; + display: flex; + align-items: stretch; + flex-flow: column wrap; +} + +.input-label{ + font-size: 0.85rem; + height: 20px; +} + +.input-selector{ + padding: 0.125rem 0.25rem 0.125rem 0.35rem; + font-size: 0.85rem; + color: whitesmoke; + background-color: #343a40; + border: none; + margin: 7px; + width : 280px; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='whitesmoke' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); +} + +.input-field-number{ + margin: 7px 0 6px 7px; + width: 280px; + border-radius: 3px; + background-color: #343a40; + box-shadow: none; + border: none; + color: whitesmoke; + padding: 0.125rem 0.25rem 0.125rem 0.35rem; + height: 26px; + font-size: small; +} + +.form-element{ + padding: 2.5px; +} + +.submit-button{ + background: rgb(119 117 117); + border-radius: 3px; +} + +.reset-button{ + background: var(--bs-danger); + border-radius: 3px; +} diff --git a/src/frontend/src/app/components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component.spec.ts b/src/frontend/src/app/components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..ff6a31faadec468a18b25ff7c54374a52e4a1125 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ClusteringSettingsDialogComponent } from './clustering-settings-dialog.component'; + +describe('ClusteringSettingsDialogComponent', () => { + let component: ClusteringSettingsDialogComponent; + let fixture: ComponentFixture<ClusteringSettingsDialogComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ClusteringSettingsDialogComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(ClusteringSettingsDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component.ts b/src/frontend/src/app/components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..bc4c3c771463c2a098b73dbd1d946eb6dc37b777 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/clustering-settings-dialog/clustering-settings-dialog.component.ts @@ -0,0 +1,96 @@ +import { + ChangeDetectionStrategy, + Component, + Input, + OnInit, +} from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ClusteringAlgorithm } from 'src/app/objects/ClusteringAlgorithm'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { DocumentationService } from '../../documentation/documentation.service'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'app-clustering-settings-dialog', + templateUrl: './clustering-settings-dialog.component.html', + styleUrls: ['./clustering-settings-dialog.component.scss'], +}) +export class ClusteringSettingsDialogComponent implements OnInit { + @Input() + numberOfVariants: number; + + selectedClusteringAlgorithm: ClusteringAlgorithm = + ClusteringAlgorithm.AGGLOMERATIVE_EDIT_DISTANCE_CLUSTERING; + + options: ClusteringAlgorithm[] = Object.values(ClusteringAlgorithm); + + maxDistance: number = 1; + nClusters: number = 1; + + constructor( + public modal: NgbActiveModal, + private variantService: VariantService, + private documentationService: DocumentationService + ) {} + + ngOnInit(): void { + const clusteringConfig = this.variantService.clusteringConfig; + if (clusteringConfig) { + this.selectedClusteringAlgorithm = clusteringConfig.algorithm; + + if ( + this.selectedClusteringAlgorithm === + ClusteringAlgorithm.AGGLOMERATIVE_EDIT_DISTANCE_CLUSTERING + ) { + this.maxDistance = clusteringConfig.params.maxDistance; + } else if ( + this.selectedClusteringAlgorithm === + ClusteringAlgorithm.LABEL_VECTOR_CLUSTERING + ) { + this.nClusters = clusteringConfig.params.nClusters; + } + } + } + + getDisplayName(algo: ClusteringAlgorithm) { + switch (algo) { + case ClusteringAlgorithm.AGGLOMERATIVE_EDIT_DISTANCE_CLUSTERING: + return 'Agglomerative edit distance clustering'; + case ClusteringAlgorithm.LABEL_VECTOR_CLUSTERING: + return 'Label vector clustering'; + } + } + + onApply() { + let params = {}; + + if ( + this.selectedClusteringAlgorithm == + ClusteringAlgorithm.AGGLOMERATIVE_EDIT_DISTANCE_CLUSTERING + ) { + params['maxDistance'] = this.maxDistance; + } else if ( + this.selectedClusteringAlgorithm == + ClusteringAlgorithm.LABEL_VECTOR_CLUSTERING + ) { + params['nClusters'] = this.nClusters; + } + + this.variantService.clusteringConfig = { + algorithm: this.selectedClusteringAlgorithm, + params: params, + }; + + this.modal.close(); + } + + onReset() { + this.variantService.clusteringConfig = null; + this.modal.dismiss('reset'); + } + + openDocumentation(heading: string) { + this.documentationService.showDocumentationDialog(heading); + this.modal.dismiss('cancel click'); + } +} diff --git a/src/frontend/src/app/components/variant-explorer/conformance-info/info-bar/conformance-info-bar.component.html b/src/frontend/src/app/components/variant-explorer/conformance-info/info-bar/conformance-info-bar.component.html new file mode 100644 index 0000000000000000000000000000000000000000..82bdc9bd60788dc35d3037ba719a02a45f8b0880 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/conformance-info/info-bar/conformance-info-bar.component.html @@ -0,0 +1,75 @@ +<div class="info-bar ps-2 pe-2"> + <!-- In case conformance statistics are not available yet --> + <span + class="float-start" + *ngIf=" + logStats?.totalNumberTraces && logStats?.numberFittingTraces === undefined + " + > + fitting traces: + <span> + - / {{ + logStats?.totalNumberTraces | number + }} + ( - %)</span + > + </span> + + <span + class="float-start" + *ngIf=" + (logStats?.numberFittingTraces || logStats?.numberFittingTraces >= 0) && + (logStats?.totalNumberTraces || logStats?.totalNumberTraces > 0) + " + > + fitting traces: + <span [ngClass]="!isConformanceOutdated ? '' : 'text-warning'"> + {{ logStats?.numberFittingTraces | number }} / {{ + logStats?.totalNumberTraces | number + }} + ({{ + logStats?.numberFittingTraces / logStats?.totalNumberTraces + | percent : ".1" + }})</span + > + </span> + + <!-- In case conformance statistics are not available yet --> + <span + class="float-start ms-4" + *ngIf=" + logStats?.totalNumberVariants && + logStats?.numberFittingVariants === undefined + " + > + fitting variants: + <span> + - / {{ + logStats?.totalNumberVariants | number + }} + ( - %)</span + > + </span> + + <span + class="float-start ms-4" + *ngIf=" + (logStats?.numberFittingVariants || + logStats?.numberFittingVariants >= 0) && + (logStats?.totalNumberVariants || logStats?.totalNumberVariants > 0) + " + > + fitting variants: + <span [ngClass]="!isConformanceOutdated ? '' : 'text-warning'"> + {{ logStats?.numberFittingVariants | number }} / {{ + logStats?.totalNumberVariants | number + }} + ({{ + logStats?.numberFittingVariants / logStats?.totalNumberVariants + | percent : ".1" + }}) + </span> + </span> + + <span class="float-end"> selected variants: {{ numSelectedVariants }} </span> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/conformance-info/info-bar/conformance-info-bar.component.spec.ts b/src/frontend/src/app/components/variant-explorer/conformance-info/info-bar/conformance-info-bar.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..076241ead1c20a57181cda0fedc77ad058a388d0 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/conformance-info/info-bar/conformance-info-bar.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConformanceInfoBarComponent } from './conformance-info-bar.component'; + +describe('InfoBarComponent', () => { + let component: ConformanceInfoBarComponent; + let fixture: ComponentFixture<ConformanceInfoBarComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ConformanceInfoBarComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConformanceInfoBarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/conformance-info/info-bar/conformance-info-bar.component.ts b/src/frontend/src/app/components/variant-explorer/conformance-info/info-bar/conformance-info-bar.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..48c766ac5f3c3b3aff654df77c77df7b7768d3d2 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/conformance-info/info-bar/conformance-info-bar.component.ts @@ -0,0 +1,17 @@ +import { Component, Input } from '@angular/core'; +import { LogStats } from 'src/app/services/logService/log.service'; + +@Component({ + selector: 'app-conformance-info-bar', + templateUrl: './conformance-info-bar.component.html', +}) +export class ConformanceInfoBarComponent { + @Input() + logStats: LogStats; + @Input() + isConformanceOutdated: boolean; + @Input() + numSelectedVariants: number; + + constructor() {} +} diff --git a/src/frontend/src/app/components/variant-explorer/conformance-info/variant-conformance-dialog/variant-conformance-dialog.component.html b/src/frontend/src/app/components/variant-explorer/conformance-info/variant-conformance-dialog/variant-conformance-dialog.component.html new file mode 100644 index 0000000000000000000000000000000000000000..7d8c03299c070b2ce6ddc7206f1a8673ca2a046e --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/conformance-info/variant-conformance-dialog/variant-conformance-dialog.component.html @@ -0,0 +1,77 @@ +<div + class="modal fade" + id="conformanceModalDialog" + tabindex="-1" + role="dialog" + aria-labelledby="conformanceModalLabel" + aria-hidden="true" +> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header h-line-modal-bottom"> + <h5 class="modal-title text-light" id="conformanceModalLabel"> + Increase conformance timeout + </h5> + <button + type="button" + class="btn-close btn-close-white" + data-bs-dismiss="modal" + aria-label="Close" + ></button> + </div> + <div class="modal-body"> + <p class="secondary-text"> + A previous conformance calculation for the selected variant has timed + out. Please increase the timeout for the selected variant. The + increased timeout will be applied once and will not be stored. + </p> + <form class="was-validated"> + <div class="form-group row mx-0"> + <label + for="timeout" + class="col-7 col-form-label text-light dialog-label" + >Conformance checking timeout + <i + class="bi bi-question-circle-fill font-large ms-1 align-middle secondary-text" + ngbTooltip="The calculation of conformance statistics stops after the configured timeout (in seconds)." + triggers="hover" + container="body" + > + </i> + </label> + <div class="col-5"> + <input + type="number" + class="form-control styled-input-field" + id="timeout" + aria-describedby="timeoutHelp" + placeholder="Enter timeout" + [(ngModel)]="conformanceTimeout" + [ngModelOptions]="{ standalone: true }" + required + /> + <div class="invalid-feedback"> + Please provide a valid timeout. + </div> + </div> + </div> + </form> + </div> + <div class="modal-footer h-line-modal-top"> + <button + id="close-modal-conformance" + type="button" + class="button" + data-bs-dismiss="modal" + > + <i class="bi bi-x-lg btn-icon text-danger"></i> + close without calculation + </button> + <button type="button" class="button" (click)="calculateConformance()"> + <i class="bi bi-save btn-icon text-success"></i> + update conformance + </button> + </div> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/conformance-info/variant-conformance-dialog/variant-conformance-dialog.component.scss b/src/frontend/src/app/components/variant-explorer/conformance-info/variant-conformance-dialog/variant-conformance-dialog.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/variant-explorer/conformance-info/variant-conformance-dialog/variant-conformance-dialog.component.spec.ts b/src/frontend/src/app/components/variant-explorer/conformance-info/variant-conformance-dialog/variant-conformance-dialog.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..38a07efaa7386e9f2ec8232e96d84053467c3d8e --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/conformance-info/variant-conformance-dialog/variant-conformance-dialog.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantConformanceDialogComponent } from './variant-conformance-dialog.component'; + +describe('VariantConformanceDialogComponent', () => { + let component: VariantConformanceDialogComponent; + let fixture: ComponentFixture<VariantConformanceDialogComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantConformanceDialogComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantConformanceDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/conformance-info/variant-conformance-dialog/variant-conformance-dialog.component.ts b/src/frontend/src/app/components/variant-explorer/conformance-info/variant-conformance-dialog/variant-conformance-dialog.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..4a1efd7b7d808c73e59b3f4e3b8f48a39d804421 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/conformance-info/variant-conformance-dialog/variant-conformance-dialog.component.ts @@ -0,0 +1,56 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { BackendService } from 'src/app/services/backendService/backend.service'; +import { ConformanceCheckingService } from 'src/app/services/conformanceChecking/conformance-checking.service'; + +declare var $: any; + +@Component({ + selector: 'app-variant-conformance-dialog', + templateUrl: './variant-conformance-dialog.component.html', + styleUrls: ['./variant-conformance-dialog.component.scss'], +}) +export class VariantConformanceDialogComponent implements OnInit, OnDestroy { + variant: Variant; + conformanceTimeout: number = 30; + callback; + + private _destroy$ = new Subject(); + + constructor( + private backendService: BackendService, + private conformanceCheckingService: ConformanceCheckingService + ) {} + + ngOnInit(): void { + this.conformanceCheckingService.showConformanceCheckingTimeoutDialog + .pipe(takeUntil(this._destroy$)) + .subscribe(([variant, callback]) => { + this.callback = callback; + this.variant = variant; + this.backendService + .getConfiguration() + .pipe(takeUntil(this._destroy$)) + .subscribe((config) => { + this.conformanceTimeout = + config.timeoutCVariantAlignmentComputation + 30; + $('#conformanceModalDialog').modal('show'); + }); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + hideModal(): void { + document.getElementById('close-modal-conformance').click(); + } + + calculateConformance(): void { + this.callback(this.variant, this.conformanceTimeout); + this.hideModal(); + } +} diff --git a/src/frontend/src/app/components/variant-explorer/functions/export-variant-explorer.ts b/src/frontend/src/app/components/variant-explorer/functions/export-variant-explorer.ts new file mode 100644 index 0000000000000000000000000000000000000000..e45c7df01ffb9af5bf4a2d8cf260f5b0acf246fd --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/functions/export-variant-explorer.ts @@ -0,0 +1,125 @@ +import { element } from 'protractor'; +import * as d3 from 'd3'; +import { LeafNode } from 'src/app/objects/Variants/variant_element'; + +export function exportVariantDrawer() { + let svgs: SVGGraphicsElement[] = []; + let state: boolean[] = []; + + this.svgRenderingInProgress = true; + + const visibleComponents = this.variantVisualisations; + + // Collect the SVG and pass them to the SVG Service + visibleComponents.forEach((c) => + svgs.push(c.variantDrawer.getSVGGraphicElement()) + ); + + // Add Frequency and Percentage information to the SVG + svgs = svgs.map((c, i) => + addVariantExportInformation( + c, + this.variants[i].count, + this.variants[i].percentage + ) + ); + + // TODO Create the Legend Element and add it + const legend = d3.create('svg').attr('x', '10').attr('y', '10'); + + let leafnodes: LeafNode[] = []; + + for (let activity in this.logService.activitiesInEventLog) { + leafnodes.push(new LeafNode([activity])); + } + + svgs.forEach((svg) => { + svg.removeAttribute('ng-reflect-variant'); + svg.removeAttribute('ng-reflect-on-click-cb-fc'); + svg.removeAttribute('ng-reflect-performance-mode'); + svg.removeAttribute('ng-reflect-compute-activity-color'); + svg.removeAttribute('appVariantDrawer'); + svg.removeAttribute('class'); + d3.select(svg).selectAll('text').attr('data-bs-original-title', null); + }); + + this.polygonDrawingService.drawLegend(leafnodes, legend, this.colorMap); + + svgs.unshift(legend.node()); + svgs.push( + d3 + .select('#infixDotsForDrawer') + .attr('width', 0) + .attr('height', 0) + .node() as SVGGraphicsElement + ); + + // Send all Elements to the export service + this.imageExportService.export('variant_explorer', 0, 0, ...svgs); + + // Hide the Spinner + this.svgRenderingInProgress = false; +} + +export function addVariantExportInformation( + svgElement: SVGGraphicsElement, + variantAbs: number, + variantPerc: number +): SVGGraphicsElement { + const exportMarginX: number = 65; + const exportMarginY: number = 15; + + const svgElement_copy = svgElement.cloneNode(true) as SVGGraphicsElement; + + // Shift all Elements to the right using transform chaining + svgElement_copy.setAttribute( + 'width', + (svgElement.clientWidth + exportMarginX).toString() + ); + svgElement_copy.setAttribute( + 'height', + (svgElement.clientHeight + exportMarginY).toString() + ); + + d3.select(svgElement_copy) + .select('g') + .selectChildren() + .each(function (this: SVGGraphicsElement) { + this.setAttribute( + 'transform', + (this.getAttribute('transform') + ? this.getAttribute('transform') + ',' + : '') + `translate(${exportMarginX}, 0)` + ); + }); + // Add the Frequency Information + const textfield = d3 + .select(svgElement_copy) + .append('text') + .attr( + 'transform', + `translate(20, ${(svgElement.clientHeight - 25) / 2 + 10})` + ) + .attr('height', 20) + .attr('width', 50) + .attr('font-size', 9) + .attr('fill', 'black'); + + textfield + .append('tspan') + .attr('x', 0) + .attr('dy', 0) + .attr('height', 9) + .attr('fill', 'black') + .text(variantPerc + '%'); + + textfield + .append('tspan') + .attr('x', 0) + .attr('dy', 10) + .attr('height', 9) + .attr('fill', 'black') + .text('(' + variantAbs + ')'); + + return svgElement_copy; +} diff --git a/src/frontend/src/app/components/variant-explorer/functions/variant-drawer-callbacks.ts b/src/frontend/src/app/components/variant-explorer/functions/variant-drawer-callbacks.ts new file mode 100644 index 0000000000000000000000000000000000000000..3f1c0ce569bca451087e20055395c20165c3f778 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/functions/variant-drawer-callbacks.ts @@ -0,0 +1,157 @@ +import { VariantDrawerDirective } from 'src/app/directives/variant-drawer/variant-drawer.directive'; +import { + getLowestSelectionActionableElement, + SelectableState, +} from 'src/app/objects/Variants/infix_selection'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { + VariantElement, + LeafNode, +} from 'src/app/objects/Variants/variant_element'; +import { ViewMode } from 'src/app/objects/ViewMode'; + +export function computePerformanceButtonColor(variant: Variant) { + let tree; + tree = this.performanceService.variantsPerformance.get(variant); + + if (!tree) { + return null; + } + + let selectedScale = this.performanceColorService.selectedColorScale; + const colorScale = this.performanceColorService + .getVariantComparisonColorScale() + .get(tree.id); + if ( + colorScale && + tree.performance?.[selectedScale.performanceIndicator]?.[ + selectedScale.statistic + ] !== undefined + ) { + return colorScale.getColor( + tree.performance[selectedScale.performanceIndicator][ + selectedScale.statistic + ] + ); + } + return '#d3d3d3'; +} + +export function clickCallback( + drawer: VariantDrawerDirective, + element: VariantElement, + variant: Variant +) { + if (this.variantViewModeService.viewMode === ViewMode.PERFORMANCE) { + drawer.changeSelected(element); + if (element.serviceTime) { + this.variantPerformanceService.setPerformanceStatsSelectedVariantElement( + element.serviceTime, + true + ); + } + if (element.waitingTime) { + this.variantPerformanceService.setPerformanceStatsSelectedVariantElement( + element.waitingTime, + false + ); + } + } else if (this.traceInfixSelectionMode) { + let lowestSelectableNode = getLowestSelectionActionableElement(element); + + if (lowestSelectableNode != variant.variant) { + if ( + lowestSelectableNode.infixSelectableState === + SelectableState.Unselectable + ) + lowestSelectableNode.setAllChildrenUnselected(); + else lowestSelectableNode.setAllChildrenSelected(); + + variant.variant.updateSelectionAttributes(); + drawer.redraw(); + } + } else { + variant.variant.setExpanded(!variant.variant.getExpanded()); + if (variant.alignment) { + variant.alignment.setExpanded(variant.variant.getExpanded()); + } + drawer.redraw(); + } +} + +export function contextMenuCallback( + self: VariantDrawerDirective, + element: VariantElement, + variant: Variant, + event: PointerEvent +) { + this.contextMenu_xPos = event.clientX; + this.contextMenu_yPos = event.clientY; + this.contextMenu_variant = variant.variant; + this.contextMenu_element = element; + this.contextMenu_directive = self; +} + +export function activityColor( + self: VariantDrawerDirective, + element: VariantElement, + variant: Variant +) { + let color; + + if (element instanceof LeafNode) { + switch (this.variantViewModeService.viewMode) { + default: + color = this.colorMap.get(element.asLeafNode().activity[0]); + + // in this case cuts were not applicable anymore. + // The resulting chevron is displayed in gray + if (element.activity.length > 1) { + color = '#d3d3d3'; // lightgray + } + break; + + case ViewMode.PERFORMANCE: + if (element.serviceTime?.mean !== undefined) { + let stat = this.variantPerformanceService.serviceTimeStatistic; + color = this.serviceTimeColorMap.getColor(element.serviceTime[stat]); + if (element.serviceTime[stat] === 0) { + color = 'url(#whiteStriped)'; + } + if (color == undefined) { + color = '#d3d3d3'; // lightgrey + } + } else if (variant.variant?.serviceTime) { + color = '#d3d3d3'; + } + break; + + case ViewMode.CONFORMANCE: + if (variant.alignment && !variant.isConformanceOutdated) { + const p = element.asLeafNode().conformance[0]; + if (p === 0) color = 'url(#variantConformanceStriped)'; + else + color = + this.conformanceCheckingService.variantConformanceColorMap.getColor( + p + ); + } else color = '#d3d3d3'; + break; + } + } else if ( + this.variantViewModeService.viewMode === ViewMode.PERFORMANCE && + element.waitingTime?.mean !== undefined + ) { + let stat = this.variantPerformanceService.waitingTimeStatistic; + color = this.waitingTimeColorMap.getColor(element.waitingTime[stat]); + if (element.waitingTime[stat] === 0) { + color = 'url(#whiteStriped)'; + } + } + + if (!color) { + color = '#d3d3d3'; // lightgrey + } + + return color; +} diff --git a/src/frontend/src/app/components/variant-explorer/search/search.component.html b/src/frontend/src/app/components/variant-explorer/search/search.component.html new file mode 100644 index 0000000000000000000000000000000000000000..a3d25d39265ed02fe6cfa3deb7994a2ccdfa928f --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/search/search.component.html @@ -0,0 +1,94 @@ +<div class="btn-group align-baseline dropDownParent dropdown ms-auto"> + <button + class="button dropdown-toggle" + type="button" + id="sortDropdown" + data-bs-toggle="dropdown" + aria-expanded="false" + > + <i class="bi bi-sort-alpha-down btn-icon"></i> + </button> + <div + class="dropdown-menu custom-dropdown" + id="sortDropdownMenu" + aria-labelledby="sortDropdown" + > + <div class="fst-italic fw-bold ps-2 text-center">Sort</div> + <div class="fst-italic ps-2 text-primary dropdown-label">Order</div> + <div + class="dropdown-item" + (click)="onSortOrderChanged(true)" + [ngClass]="isAscendingOrder ? 'selected-dropdown-item' : ''" + > + <i class="bi bi-sort-down-alt btn-icon"></i> + <span class="ms-3">ascending</span> + </div> + <div + class="dropdown-item" + (click)="onSortOrderChanged(false)" + [ngClass]="!isAscendingOrder ? 'selected-dropdown-item' : ''" + > + <i class="bi bi-sort-down btn-icon"></i> + <span class="ms-3">descending</span> + </div> + <div class="fst-italic ps-2 text-primary dropdown-label">Feature</div> + <div + class="dropdown-item" + (click)="sort('number_of_activities')" + [ngClass]=" + sortingFeature === 'number_of_activities' + ? 'selected-dropdown-item' + : '' + " + > + <i class="bi bi-chevron-double-right btn-icon"></i> + <span class="ms-3">activities</span> + </div> + <div + class="dropdown-item" + (click)="sort('conformance')" + [ngClass]=" + sortingFeature === 'conformance' ? 'selected-dropdown-item' : '' + " + > + <i class="bi bi-check-square btn-icon"></i> + <span class="ms-3">conformance</span> + </div> + <div + class="dropdown-item" + (click)="sort('count')" + [ngClass]="sortingFeature === 'count' ? 'selected-dropdown-item' : ''" + > + <i class="bi bi-123 btn-icon"></i> + <span class="ms-3">frequency</span> + </div> + <div + class="dropdown-item" + (click)="sort('length')" + [ngClass]="sortingFeature === 'length' ? 'selected-dropdown-item' : ''" + > + <i class="bi bi-three-dots btn-icon"></i> + <span class="ms-3">length</span> + </div> + <div + class="dropdown-item" + (click)="sort('sub_variants')" + [ngClass]=" + sortingFeature === 'sub_variants' ? 'selected-dropdown-item' : '' + " + > + <i class="bi bi-bar-chart-steps"></i> + <span class="ms-3">sub-variants</span> + </div> + <div + class="dropdown-item" + (click)="sort('userDefined')" + [ngClass]=" + sortingFeature === 'userDefined' ? 'selected-dropdown-item' : '' + " + > + <i class="bi bi-person-circle"></i> + <span class="ms-3">user created</span> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/search/search.component.scss b/src/frontend/src/app/components/variant-explorer/search/search.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..f431494fabcec846995978f0e3698c860c8ca7bb --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/search/search.component.scss @@ -0,0 +1,25 @@ +.dropdown-sort { + font-size: small; + max-height: 90vh; + user-select: none; +} + +.dropdown-menu { + border-radius: 0; + background-color: lightgray; +} + +.selected-dropdown-item { + background-color: var(--bs-blue); + color: var(--bs-white); +} + +.dropdown-label{ + font-weight: initial; + margin: 8px 0 2px; +} + +.dropdown-item{ + padding-top: 8px; + padding-bottom: 8px; +} diff --git a/src/frontend/src/app/components/variant-explorer/search/search.component.spec.ts b/src/frontend/src/app/components/variant-explorer/search/search.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..bb8443bfa6ae2dc3894a9745cfdfba065aaaf559 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/search/search.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture<SearchComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SearchComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/search/search.component.ts b/src/frontend/src/app/components/variant-explorer/search/search.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..b50d584dfd844220bb18f37e6861b24608130ab6 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/search/search.component.ts @@ -0,0 +1,40 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; + +@Component({ + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], +}) +export class SearchComponent implements OnInit { + // default values + @Input() + isAscendingOrder: any = false; + @Input() + sortingFeature: any = 'count'; + + @Output() + public sortEvent: EventEmitter<any> = new EventEmitter(); + + constructor() {} + + ngOnInit(): void { + this.emit(); + } + + onSortOrderChanged(isAscendingOrder: boolean) { + this.isAscendingOrder = isAscendingOrder; + this.emit(); + } + + sort(feature: string) { + this.sortingFeature = feature; + this.emit(); + } + + emit() { + this.sortEvent.emit({ + isAscendingOrder: this.isAscendingOrder, + feature: this.sortingFeature, + }); + } +} diff --git a/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariant-explorer.component.css b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariant-explorer.component.css new file mode 100644 index 0000000000000000000000000000000000000000..6be9ee4b0a2d3522bdddbab60d6abd524dda9cdb --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariant-explorer.component.css @@ -0,0 +1,62 @@ +.main-variant-explorer { + overflow: auto; + background-color: var(--box-background-color); +} + +.chart-variant-percentage { + margin-left: 4px; + display: inline-flex; + flex-direction: column; + + /* + min-width: 50px; + */ + font-size: .8rem; + color: whitesmoke; + color: var(--text-secondary); +} + +:host { + position: absolute; + overflow: hidden; +} + +.variant-info-cell { + align-items: center; + display: flex; +} + +.btn-tool-bar{ + min-height: 28px; + display: flex; + align-items: center; + border-top: 0; + position: sticky; + top: 0; + left: 0; +} + +.variant-cell { + width: 100%; +} + +.variant { + padding: 5px; + width: fit-content; + cursor: pointer; +} + +.svg-rendering-status { + color: var(--text-secondary); +} + + +/* Move all below to central place - also used in variant explorer */ + +.container-variant-explorer { + min-height: 100%; + width: calc(100% - 20px); + position: relative; + border-left: 1px solid var(--thin-border-color); + margin-left: 20px; +} diff --git a/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariant-explorer.component.html b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariant-explorer.component.html new file mode 100644 index 0000000000000000000000000000000000000000..29f1e9aedc5492799a1b4022c59ce39252f1f0ec --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariant-explorer.component.html @@ -0,0 +1,202 @@ +<app-performance-progress-bar></app-performance-progress-bar> + +<app-variant-explorer-sidebar></app-variant-explorer-sidebar> + +<div class="d-flex flex-column h-100 container-variant-explorer"> + <div + class="main-variant-explorer flex-grow-1" + [class.blur-out-of-focus]=" + variantPerformanceService.performanceUpdateIsInProgress + " + > + <div class="bg-dark btn-tool-bar"> + <div *ngIf="svgRenderingInProgress" class="full-body-spinner"> + <div class="svg-rendering-status"> + <div class="spinner-border spinner-border-sm" role="status"></div> + Exporting Subvariants View... + </div> + </div> + <div class="vr ms-auto"></div> + <ng-template #tooltip1> + Sort subvariants by frequency + <br />Click to change sort order <br />Current sort order: ascending + </ng-template> + <div + *ngIf="sortAscending" + class="btn-group align-baseline" + [ngbTooltip]="tooltip1" + triggers="hover" + container="body" + > + <button + class="button" + type="button" + data-bs-toggle="dropdown" + aria-expanded="false" + (click)="toggleSortOrder()" + > + <i + [ngClass]=" + sortAscending + ? 'bi bi-sort-numeric-down btn-icon' + : 'bi bi-sort-numeric-down-alt btn-icon' + " + ></i> + </button> + </div> + <ng-template #tooltip2> + Sort subvariants by frequency + <br />Click to change sort order <br />Current sort order: descending + </ng-template> + <div + *ngIf="!sortAscending" + class="btn-group align-baseline" + [ngbTooltip]="tooltip2" + triggers="hover" + container="body" + > + <button + class="button" + type="button" + data-bs-toggle="dropdown" + aria-expanded="false" + (click)="toggleSortOrder()" + > + <i + [ngClass]=" + sortAscending + ? 'bi bi-sort-numeric-down btn-icon' + : 'bi bi-sort-numeric-down-alt btn-icon' + " + ></i> + </button> + </div> + <div class="vr"></div> + <button + class="button" + ngbTooltip="export the view as an .svg" + triggers="hover" + container="body" + (click)="exportSubvariantSVG()" + > + <i class="bi bi-save"></i> + </button> + </div> + <div class="d-flex"> + <div class="chart-variant-percentage"> + <table *ngIf="containsLoopCollapsedVariants"> + <tr> + <td style="padding-right: 15px; padding-left: 5px">Super-Parent</td> + <td> + <app-variant-info + [selectable]="false" + [variant]="mainVariant" + (updateConformance)=" + updateConformanceForSingleVariantClicked($event) + " + ></app-variant-info> + </td> + <td class="variant-cell"> + <div class="variant" style=""> + <svg + appVariantDrawer + #fragment + [variant]="mainVariant" + [onClickCbFc]="variantClickCallBack" + [computeActivityColor]="computeActivityColor" + ></svg> + </div> + </td> + </tr> + </table> + <div + *ngFor=" + let variantWithSubvariants of subvariants | keyvalue; + let i = index + " + [ngClass]="containsLoopCollapsedVariants ? 'ms-5' : ''" + > + <!-- Using the same components as on the main explorer to visualize the base variant of the subvariant explorer---> + <table> + <tr> + <td style="padding-right: 15px; padding-left: 5px"> + <ng-container *ngIf="containsLoopCollapsedVariants" + >Parent {{ index }}.{{ i + 1 }}</ng-container + > + <ng-container *ngIf="!containsLoopCollapsedVariants" + >Parent</ng-container + > + </td> + <td> + <app-variant-info + [selectable]="false" + [variant]="variantWithSubvariants.key" + (updateConformance)=" + updateConformanceForSingleVariantClicked($event) + " + ></app-variant-info> + </td> + <td class="variant-cell"> + <div class="variant" style=""> + <svg + appVariantDrawer + #fragment + [variant]="variantWithSubvariants.key" + [onClickCbFc]="variantClickCallBack" + [computeActivityColor]="computeActivityColor" + ></svg> + </div> + </td> + </tr> + <tr + *ngFor=" + let subVariant of variantWithSubvariants.value[0]; + let j = index + " + > + <td style="padding-right: 15px; padding-left: 5px"> + <ng-container *ngIf="containsLoopCollapsedVariants" + >{{ index }}.{{ i + 1 }}.{{ j + 1 }}</ng-container + > + <ng-container *ngIf="!containsLoopCollapsedVariants" + >{{ index }}.{{ j + 1 }}</ng-container + > + </td> + <td style="text-align: start"> + <ng-template #tooltip3> + sub-variant describes ~{{ subVariant.percentage }}% of all + traces of the main-variant<br /> + <span class="text-secondary" + >sub-variant occurs {{ subVariant.count | number }} time(s) + in total</span + > + </ng-template> + <small + class="cursor-help" + [ngbTooltip]="tooltip3" + triggers="hover" + container="body" + > + {{ subVariant.percentage }}%<br /> + ({{ subVariant.count | number }}) + </small> + </td> + <td style="padding: 5px 5px 5px 50px"> + <app-sub-variant + class="cursor-pointer" + (click)="toggleExpanded()" + [expanded]="mainVariant.variant.expanded" + [variant]="subVariant.variant" + [colorMap]="colorMap" + [onClickCbFc]="subvariantClickCallBack.bind(this)" + [mainVariant]="variantWithSubvariants.key.variant" + > + </app-sub-variant> + </td> + </tr> + </table> + </div> + </div> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariant-explorer.component.spec.ts b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariant-explorer.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..6a0f9c6be31ab62ce349b02855a4a7690a8a5738 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariant-explorer.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SubvariantExplorerComponent } from './subvariant-explorer.component'; + +describe('SubvariantExplorerComponent', () => { + let component: SubvariantExplorerComponent; + let fixture: ComponentFixture<SubvariantExplorerComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SubvariantExplorerComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SubvariantExplorerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariant-explorer.component.ts b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariant-explorer.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..4c3a67c92c1d5a4384c17cb4f8d06c76ca9c37d2 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariant-explorer.component.ts @@ -0,0 +1,463 @@ +import { ColorMapService } from '../../../services/colorMapService/color-map.service'; +import { + AfterViewInit, + Component, + ElementRef, + Inject, + OnDestroy, + OnInit, + QueryList, + Renderer2, + ViewChild, + ViewChildren, +} from '@angular/core'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; +import { SubVariantComponent } from './subvariants/sub-variant/sub-variant.component'; +import { ImageExportService } from 'src/app/services/imageExportService/image-export-service'; +import { PolygonDrawingService } from 'src/app/services/polygon-drawing.service'; +import * as d3 from 'd3'; +import { LogService } from 'src/app/services/logService/log.service'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { VariantDrawerDirective } from 'src/app/directives/variant-drawer/variant-drawer.directive'; +import { + deserialize, + LeafNode, + VariantElement, +} from 'src/app/objects/Variants/variant_element'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { BackendService } from 'src/app/services/backendService/backend.service'; +import { VariantPerformanceService } from 'src/app/services/variant-performance.service'; +import { SubvariantVisualization } from 'src/app/objects/Variants/subvariant'; +import { VariantViewModeService } from 'src/app/services/viewModeServices/variant-view-mode.service'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { activityColor } from '../functions/variant-drawer-callbacks'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { + AlignmentType, + ConformanceCheckingService, +} from 'src/app/services/conformanceChecking/conformance-checking.service'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { IVariant } from 'src/app/objects/Variants/variant_interface'; +import { LoopCollapsedVariant } from 'src/app/objects/Variants/loop_collapsed_variant'; + +@Component({ + selector: 'app-subvariant-explorer', + templateUrl: './subvariant-explorer.component.html', + styleUrls: ['./subvariant-explorer.component.css'], // Consider also importing the base style from the normal variant explorer scss +}) +export class SubvariantExplorerComponent + extends LayoutChangeDirective + implements AfterViewInit, OnInit, OnDestroy +{ + mainVariant: Variant; + containsLoopCollapsedVariants: boolean = false; + subvariants = new Map<Variant, any>(); + public colorMap: Map<string, string>; + public serviceTimeColorMap: any; + public waitingTimeColorMap: any; + public index: number; + + @ViewChildren(VariantDrawerDirective) + mainvariantDrawers: QueryList<VariantDrawerDirective>; + + @ViewChildren(SubVariantComponent) + subVariantComponents: QueryList<SubVariantComponent>; + + public sortAscending: boolean; + public svgRenderingInProgress: boolean; + + private _destroy$ = new Subject(); + + constructor( + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef, + renderer: Renderer2, + private colorMapService: ColorMapService, + private logService: LogService, + private imageExportService: ImageExportService, + private polygonDrawingService: PolygonDrawingService, + private backendService: BackendService, + public variantPerformanceService: VariantPerformanceService, + public variantViewModeService: VariantViewModeService, + private conformanceCheckingService: ConformanceCheckingService, + private processTreeService: ProcessTreeService + ) { + super(elRef.nativeElement, renderer); + let state = this.container.initialState; + this.mainVariant = state['variant'] as IVariant; + this.index = state['index'] as number; + this.colorMap = this.colorMapService.colorMap; + this.sortAscending = false; + this.svgRenderingInProgress = false; + this.serviceTimeColorMap = + variantPerformanceService.serviceTimeColorMap.getValue(); + this.waitingTimeColorMap = + variantPerformanceService.waitingTimeColorMap.getValue(); + } + + ngOnInit(): void { + let underlyingVariants = []; + if (this.mainVariant instanceof LoopCollapsedVariant) { + underlyingVariants = this.mainVariant.variants; + } else { + underlyingVariants.push(this.mainVariant); + } + + underlyingVariants.forEach((v) => { + this.backendService + .getSubvariantsForVariant(v.bid) + .pipe(takeUntil(this._destroy$)) + .subscribe((subvariant) => { + this.addSubvariantToVariant(v, subvariant); + }); + }); + } + + addSubvariantToVariant(variant, subvariant) { + if (this.subvariants.has(variant)) { + this.subvariants.get(variant).push(subvariant); + } else { + this.subvariants.set(variant, [subvariant]); + } + + if (variant.variant.asString() !== this.mainVariant.variant.asString()) { + this.containsLoopCollapsedVariants = true; + } + } + + ngAfterViewInit() { + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((cMap) => { + this.colorMap = cMap; + this.mainvariantDrawers.forEach((d) => d.redraw()); + }); + + this.variantPerformanceService.serviceTimeColorMap + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + if (colorMap !== undefined) { + this.serviceTimeColorMap = colorMap; + this.mainvariantDrawers.forEach((d) => d.redraw()); + } + }); + + this.variantPerformanceService.waitingTimeColorMap + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + if (colorMap !== undefined) { + this.waitingTimeColorMap = colorMap; + this.mainvariantDrawers.forEach((d) => d.redraw()); + } + }); + + this.variantViewModeService.viewMode$ + .pipe(takeUntil(this._destroy$)) + .subscribe((viewMode: ViewMode) => { + this.onViewModeChange(viewMode); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + // Implements responsive changes, such as triggering animations, if the layout and thus the components size changes + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + + handleVisibilityChange(visibility: boolean): void { + if (visibility && this.mainvariantDrawers) { + this.mainvariantDrawers.forEach((d) => d.redraw()); + this.subVariantComponents.forEach((svc) => svc.draw()); + } + } + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} + + public setIndex(index: number) { + this.index = index; + } + + subvariantClickCallBack(vis: SubvariantVisualization) { + this.mainvariantDrawers.forEach((d) => d.changeSelected(null)); + this.subVariantComponents.forEach((svc) => svc.changeSelection(vis)); + } + + public toggleExpanded() { + if (this.variantViewModeService.viewMode === ViewMode.PERFORMANCE) { + return; + } + let expanded = this.mainVariant.variant.expanded; + this.mainvariantDrawers.forEach((d) => d.setExpanded(!expanded)); + this.setExpandedSubVariants(!expanded); + } + + public setExpandedSubVariants(expanded) { + this.subVariantComponents.forEach((svc) => svc.setExpanded(expanded)); + } + + variantClickCallBack = ( + drawer: VariantDrawerDirective, + element: VariantElement, + variant: VariantElement + ) => { + this.toggleExpanded(); + if (this.variantViewModeService.viewMode === ViewMode.PERFORMANCE) { + drawer.changeSelected(element); + this.subVariantComponents.forEach((svc) => svc.changeSelection(null)); + if (element.serviceTime) { + this.variantPerformanceService.setPerformanceStatsSelectedVariantElement( + element.serviceTime, + true + ); + } + if (element.waitingTime) { + this.variantPerformanceService.setPerformanceStatsSelectedVariantElement( + element.waitingTime, + false + ); + } + } + }; + + toggleSortOrder(): void { + this.sortAscending = !this.sortAscending; + this.sortSubvariants('count'); + } + + sortSubvariants(sortAttribute: string): void { + const order = this.sortAscending ? 1 : -1; + const subvariantSortFunction = (a, b) => { + if (a[0][sortAttribute] < b[0][sortAttribute]) { + return -order; + } else if (a[0][sortAttribute] > b[0][sortAttribute]) { + return order; + } else return order; + }; + + this.subvariants.forEach((v, _) => { + v.sort(subvariantSortFunction); + }); + } + + exportSubvariantSVG(): void { + // Prepare an array for the svg elements + let svgs: SVGGraphicsElement[] = []; + + // Temporarily expand all subvariants + let expanded = this.mainVariant.variant.expanded; + if (!expanded) { + this.toggleExpanded(); + } + + // Turn on the rendering spinner + this.svgRenderingInProgress = true; + + let mainVarDrawer = this.mainvariantDrawers.filter( + (v) => v.variant == this.mainVariant + )[0]; + // Add the main variant to the SVG array + const mainVariantSVG = this.addVariantExportInformation( + mainVarDrawer.getSVGGraphicElement(), + 100, + 100, + true + ); + svgs.push(mainVariantSVG); + + // Temporarily change text color to black for readability in the svg + this.subVariantComponents.forEach((svc) => svc.draw('black')); + + // Insert the subvariants svg to the array + this.subVariantComponents.forEach((svc) => + svgs.push(svc.svgElement.nativeElement) + ); + + // Prepare frequency informations of the subvariants + const counts = []; + const percentages = []; + for (let subVariant of this.subvariants) { + counts.push(subVariant[0].count); + percentages.push(subVariant[0].percentage); + } + + // Add frequency informations of the subvariants + // The first svg is the main variant, so index starts from 1 + for (let i = 1; i < svgs.length; i++) { + svgs[i] = this.addVariantExportInformation( + svgs[i], + counts[i - 1], + percentages[i - 1], + false + ); + } + + // Draw the legend and insert it to the start of the svg array + const legend = d3.create('svg').attr('x', '10').attr('y', '10'); + let leafnodes: LeafNode[] = []; + for (let activity in this.logService.activitiesInEventLog) { + leafnodes.push(new LeafNode([activity])); + } + this.polygonDrawingService.drawLegend( + leafnodes, + legend, + this.colorMap, + 'Subvariants' + ); + svgs.unshift(legend.node()); + + // Export to an SVG file + this.imageExportService.export( + `subvariants-for-${this.mainVariant.bid}`, + 0, + 0, + ...svgs + ); + + // Reset everything back to normal + if (!expanded) { + this.toggleExpanded(); + } + this.subVariantComponents.forEach((svc) => svc.draw('whitesmoke')); + + // Turn off the spinner + this.svgRenderingInProgress = false; + } + + addVariantExportInformation( + svgElement: any, + variantAbs: number, + variantPerc: number, + mainVariant: boolean = false + ): SVGGraphicsElement { + const exportMarginX: number = 80; + const exportMarginY: number = 15; + + const svgElement_copy = svgElement.cloneNode(true) as SVGGraphicsElement; + + // Shift all Elements to the right using transform chaining + svgElement_copy.setAttribute( + 'width', + (svgElement.clientWidth + exportMarginX).toString() + ); + svgElement_copy.setAttribute( + 'height', + (svgElement.clientHeight + exportMarginY).toString() + ); + + d3.select(svgElement_copy) + .selectChildren() + .each(function (this: SVGGraphicsElement) { + this.setAttribute( + 'transform', + (this.getAttribute('transform') + ? this.getAttribute('transform') + ',' + : '') + `translate(${exportMarginX}, 0)` + ); + }); + + // Add text field to the left of the variants + const textfield = d3 + .select(svgElement_copy) + .append('text') + .attr( + 'transform', + `translate(20, ${(svgElement.clientHeight - 25) / 2 + 10})` + ) + .attr('height', 20) + .attr('width', 50) + .attr('font-size', 9) + .attr('fill', 'black'); + + if (!mainVariant) { + // If the variant is not the main variant, then add frequency informations + textfield + .append('tspan') + .attr('x', 0) + .attr('dy', -7) + .attr('height', 9) + .attr('fill', 'black') + .text(variantPerc + '%'); + + textfield + .append('tspan') + .attr('x', 0) + .attr('dy', 10) + .attr('height', 9) + .attr('fill', 'black') + .text('(' + variantAbs + ')'); + } else { + // If the variant is the main variant, add an indicating text next to it + textfield + .append('tspan') + .attr('x', 0) + .attr('dy', 8) + .attr('height', 9) + .attr('fill', 'black') + .attr('font-size', 14) + .text('Parent'); + } + return svgElement_copy; + } + + private onViewModeChange(viewMode: ViewMode) { + switch (viewMode) { + case ViewMode.PERFORMANCE: + this.setExpandedSubVariants(true); + break; + default: + if (!this.mainVariant.variant.expanded) + this.setExpandedSubVariants(false); + break; + } + } + + computeActivityColor = activityColor.bind(this); + + updateConformanceForSingleVariantClicked(variant: Variant): void { + if (variant.isTimeouted) { + this.conformanceCheckingService.showConformanceTimeoutDialog( + variant, + this.updateConformanceForVariant.bind(this) + ); + } else { + this.updateConformanceForVariant(variant, 0); + } + } + + updateConformanceForVariant(variant: IVariant, timeout: number): void { + let underlyingVariants = []; + if (variant instanceof LoopCollapsedVariant) { + underlyingVariants = variant.variants; + } else { + underlyingVariants = [variant]; + } + + underlyingVariants.forEach((v) => { + v.calculationInProgress = true; + v.deviations = undefined; + + this.conformanceCheckingService.calculateConformance( + v.id, + v.infixType, + this.processTreeService.currentDisplayedProcessTree, + v.variant.serialize(1), + timeout, + AlignmentType.VariantAlignment + ); + }); + } +} + +export namespace SubvariantExplorerComponent { + export const componentName = 'SubvariantExplorerComponent'; +} diff --git a/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariants/sub-variant/sub-variant.component.html b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariants/sub-variant/sub-variant.component.html new file mode 100644 index 0000000000000000000000000000000000000000..4df674ddeb2fdfb3bdf0b664d3bca6ed62d2847a --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariants/sub-variant/sub-variant.component.html @@ -0,0 +1 @@ +<svg #svg></svg> diff --git a/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariants/sub-variant/sub-variant.component.scss b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariants/sub-variant/sub-variant.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariants/sub-variant/sub-variant.component.spec.ts b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariants/sub-variant/sub-variant.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..b200405e7c00b4c4a4365d40a21d921036004c4b --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariants/sub-variant/sub-variant.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SubVariantComponent } from './sub-variant.component'; + +describe('SubVariantComponent', () => { + let component: SubVariantComponent; + let fixture: ComponentFixture<SubVariantComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SubVariantComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SubVariantComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariants/sub-variant/sub-variant.component.ts b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariants/sub-variant/sub-variant.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..7395c22c6e40112daea7b28dcc4e0f2d2c7094d1 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/subvariant-explorer/subvariants/sub-variant/sub-variant.component.ts @@ -0,0 +1,583 @@ +import { VARIANT_Constants } from '../../../../../constants/variant_element_drawer_constants'; +import { + AfterViewInit, + Component, + ElementRef, + Input, + OnDestroy, + ViewChild, +} from '@angular/core'; +import * as d3 from 'd3'; +import { Selection } from 'd3'; +import { SharedDataService } from 'src/app/services/sharedDataService/shared-data.service'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; + +import { VariantPerformanceService } from 'src/app/services/variant-performance.service'; +import { SubvariantVisualization } from 'src/app/objects/Variants/subvariant'; +import { VariantViewModeService } from 'src/app/services/viewModeServices/variant-view-mode.service'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { + LeafNode, + ParallelGroup, + SequenceGroup, + FallthroughGroup, + VariantElement, +} from 'src/app/objects/Variants/variant_element'; + +@Component({ + selector: 'app-sub-variant', + templateUrl: './sub-variant.component.html', + styleUrls: ['./sub-variant.component.scss'], +}) +export class SubVariantComponent implements AfterViewInit, OnDestroy { + @ViewChild('svg') + svgElement: ElementRef; + + @Input() + set variant(value) { + this._variant = value; + if (this.isLoaded) { + this.draw(); + } + } + + private _variant; + + @Input() + private expanded = false; + + @Input() + onClickCbFc: (SubvariantVisualization) => void; + + @Input() + private mainVariant: VariantElement; + + private isLoaded = false; + + svg: Selection<any, any, any, any>; + public colorMap: Map<string, string>; + public serviceTimeColorMap: any; + public waitingTimeColorMap: any; + + private _destroy$ = new Subject(); + + constructor( + private sharedDataService: SharedDataService, + private colorMapService: ColorMapService, + private variantPerformanceService: VariantPerformanceService, + private variantViewModeService: VariantViewModeService + ) { + this.serviceTimeColorMap = + variantPerformanceService.serviceTimeColorMap.getValue(); + this.waitingTimeColorMap = + variantPerformanceService.waitingTimeColorMap.getValue(); + } + + ngAfterViewInit(): void { + this.svg = d3.select(this.svgElement.nativeElement); + this.isLoaded = true; + this.expanded = + this.variantViewModeService.viewMode == ViewMode.PERFORMANCE; + + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((cMap) => { + this.colorMap = cMap; + if (this._variant) { + this.draw(); + } + }); + + this.variantPerformanceService.serviceTimeColorMap + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + if (colorMap !== undefined) { + this.serviceTimeColorMap = colorMap; + this.draw(); + } + }); + + this.variantPerformanceService.waitingTimeColorMap + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + if (colorMap !== undefined) { + this.waitingTimeColorMap = colorMap; + this.draw(); + } + }); + + this.variantViewModeService.viewMode$ + .pipe(takeUntil(this._destroy$)) + .subscribe((viewMode: ViewMode) => { + this.draw(); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + draw(textColor: string = 'whitesmoke'): void { + const intervalWidth = !this.expanded + ? VARIANT_Constants.INTERVAL_LENGTH + : VARIANT_Constants.INTERVAL_LENGTH * 1.5; + + this.svg.selectAll('g').remove(); + this.svg.selectAll('rect').remove(); + this.svg.selectAll('line').remove(); + + const [data, xValues] = this.buildData(); + let dataArray = Array.from(data.values()); + + const xScale = (x) => + VARIANT_Constants.POINT_RADIUS + x * intervalWidth + 5; + const yScale = (y) => + 4 * VARIANT_Constants.POINT_RADIUS + + y * VARIANT_Constants.LEAF_HEIGHT * 1.5; + + const maxYIndex = Math.max(...dataArray.map((d) => d.yIndex)); + const maxXEnd = Math.max(...dataArray.map((d) => d.xEnd)); + + const height = yScale(maxYIndex + 1); + const width = xScale(maxXEnd) + VARIANT_Constants.POINT_RADIUS + 5; + + this.svg.attr('height', height); + this.svg.attr('width', width); + + const helpLineOpacity = + this.variantViewModeService.viewMode === ViewMode.PERFORMANCE + ? 0.1 + : 0.04; + + this.svg + .selectAll('line') + .data(xValues) + .enter() + .append('line') + .attr('x1', (x) => xScale(x)) + .attr('x2', (x) => xScale(x)) + .attr('y1', 0) + .attr('y2', height) + .attr('stroke', 'lightgrey') + .attr('stroke-width', 2 * VARIANT_Constants.POINT_RADIUS) + .attr('stroke-opacity', helpLineOpacity); + + if (this.variantViewModeService.viewMode === ViewMode.PERFORMANCE) { + dataArray = dataArray.concat(this.buildWaitingTimeData(data)); + + this.svg + .append('rect') + .classed('subvariant-rect', true) + .datum(() => { + let d = new SubvariantVisualization(); + d.activity = 'GLOBAL'; + d.performanceStats = this._variant.global_performance_stats; + + return d; + }) + .style('fill', (d) => 'lightgrey') + .attr('x', 0) + .attr('y', 0) + .attr('width', width) + .attr('height', height) + .attr('fill-opacity', 0.5) + .attr('rx', 8) + .attr('ry', 8) + .on('click', (_, d) => { + if (this.onClickCbFc) { + this.onClickCbFc(d); + } + + this.variantPerformanceService.setPerformanceStatsSelectedVariantElement( + d.performanceStats, + !d.isWaitingTimeNode + ); + }); + } + + const g = this.svg.selectAll().data(dataArray).join('g'); + + g.append('rect') + .classed('subvariant-rect', true) + .style('fill', (d) => this.computeActivityColor(d)) + .attr('x', (d) => xScale(d.xStart) - VARIANT_Constants.POINT_RADIUS) + .attr('y', (d) => yScale(d.yIndex) - VARIANT_Constants.POINT_RADIUS) + .attr('rx', 8) + .attr('ry', 8) + .attr( + 'width', + (d) => + xScale(d.xEnd) - xScale(d.xStart) + 2 * VARIANT_Constants.POINT_RADIUS + ) + .attr('height', VARIANT_Constants.POINT_RADIUS * 2) + .attr('data-bs-toggle', (d) => { + if (d.isWaitingTimeNode) return null; + return 'tooltip'; + }) + .attr('title', (d) => d.activity) + .on('click', (_, d) => { + if (this.onClickCbFc) { + this.onClickCbFc(d); + } + + this.variantPerformanceService.setPerformanceStatsSelectedVariantElement( + d.performanceStats, + !d.isWaitingTimeNode + ); + }); + + const texts = g + .append('text') + .filter((d) => !d.isWaitingTimeNode) + .attr('x', (d) => xScale(d.xStart + (d.xEnd - d.xStart) / 2)) + .attr('y', (d) => yScale(d.yIndex) - VARIANT_Constants.POINT_RADIUS - 5) + .style('text-anchor', 'middle') + .style('fill', textColor) + .text((d) => d.activity); + + texts.each((a, b, c) => { + const sel = d3.select(c[b]); + const xStart = xScale(a.xStart); + const xEnd = xScale(a.xEnd); + this.wrapInnerLabelText( + sel, + sel.text(), + xEnd - xStart - 2 * VARIANT_Constants.POINT_RADIUS + ); + }); + } + + private computeActivityColor(subvariantData: SubvariantVisualization) { + switch (this.variantViewModeService.viewMode) { + case ViewMode.STANDARD: + return this.colorMap.get(subvariantData.activity); + case ViewMode.PERFORMANCE: + if (!subvariantData.isWaitingTimeNode) { + let stat = this.variantPerformanceService.serviceTimeStatistic; + return this.serviceTimeColorMap.getColor( + subvariantData.performanceStats[stat] + ); + } + + let stat = this.variantPerformanceService.waitingTimeStatistic; + return this.waitingTimeColorMap.getColor( + subvariantData.performanceStats[stat] + ); + default: + return this.colorMap.get(subvariantData.activity); + } + } + + private wrapInnerLabelText( + textSelection: Selection<any, any, any, any>, + text: string, + maxWidth: number + ): boolean { + const originalText = text; + let textLength = this.getComputedTextLength(textSelection); + let truncated = false; + while (textLength > maxWidth && text.length > 1) { + text = text.slice(0, -1); + textSelection.text(text + '..'); + textLength = this.getComputedTextLength(textSelection); + truncated = true; + } + + textSelection.attr('data-bs-toggle', 'tooltip').attr('title', originalText); + return truncated; + } + + private getComputedTextLength( + textSelection: Selection<any, any, any, any> + ): number { + let textLength; + + if ( + this.sharedDataService.computedTextLengthCache.has(textSelection.text()) + ) { + textLength = this.sharedDataService.computedTextLengthCache.get( + textSelection.text() + ); + } else { + textLength = textSelection.node().getComputedTextLength(); + } + this.sharedDataService.computedTextLengthCache.set( + textSelection.text(), + textLength + ); + + textLength = textSelection.node().getComputedTextLength(); //added + return textLength; + } + + private buildData(): [Map<string, SubvariantVisualization>, Set<number>] { + const intervalWidth = VARIANT_Constants.INTERVAL_LENGTH; + const gapLength = (20 + VARIANT_Constants.POINT_RADIUS) / intervalWidth; + + let xValues = new Set<number>(); + const starts = new Map<string, [number, number]>(); + const data = new Map<string, SubvariantVisualization>(); + let activeYIndices = new Set<number>(); + + let [yIndicesFromMainVariant, _] = this.computeYIndicesFromVariantElement( + this.mainVariant, + new Map<string, number[]>(), + 0 + ); + + let xIndex = 0; + this._variant.subvariant.forEach((group) => { + let starting = group.filter( + (subvariantNode) => subvariantNode.lifecycle === 'start' + ); + let completing = group.filter( + (subvariantNode) => subvariantNode.lifecycle === 'complete' + ); + starting.forEach((subvariantNode) => { + let yIndicesForActivity = yIndicesFromMainVariant.get( + subvariantNode.activity + ); + let yIndex = yIndicesForActivity.shift(); + yIndicesFromMainVariant.set( + subvariantNode.activity, + yIndicesForActivity + ); + + // The tracking of active y-indices is necessary to ensure that we do not draw multiple overlapping subvariant nodes at the same y index. + // This is only necessary if there are two parallel activity instances with the same label (activity name). + // E.g. in the following subvariant, we have to ensure that the 'b' node and the second 'a' node are not drawn both at y-index 0, because they would overlap. + // x--a--x x--b--x + // x-----a-----x + while (activeYIndices.has(yIndex)) { + yIndex++; + } + + activeYIndices.add(yIndex); + + starts[subvariantNode.activity + subvariantNode.activity_instance] = [ + xIndex, + yIndex, + ]; + }); + + completing.forEach((subvariantNode) => { + let startIndices = + starts[subvariantNode.activity + subvariantNode.activity_instance]; + + let m = new SubvariantVisualization(); + m.activity = subvariantNode.activity; + m.performanceStats = subvariantNode.performance_stats; + m.xStart = startIndices[0]; + m.xEnd = xIndex; + m.yIndex = startIndices[1]; + m.isWaitingTimeNode = false; + + xValues.add(m.xStart); + xValues.add(m.xEnd); + + data.set(subvariantNode.activity + subvariantNode.activity_instance, m); + activeYIndices.delete(m.yIndex); + + starts.delete( + (subvariantNode.activity, subvariantNode.activity_instance) + ); + }); + + const nRunning = Array.from(starts.values()).length; + if (nRunning <= 0) { + xIndex += gapLength; + } else { + xIndex += 1; + } + }); + + return [data, xValues]; + } + + private buildWaitingTimeData( + nodesData: Map<string, SubvariantVisualization> + ): SubvariantVisualization[] { + let result = []; + + this._variant.waiting_time_events.forEach((waitingTimeEvent) => { + let xStart = 0; + let xEnd = 0; + let yIndex = 0; + + let startActivityData = nodesData.get( + waitingTimeEvent.start.activity + + waitingTimeEvent.start.activity_instance + ); + let completeActivityData = nodesData.get( + waitingTimeEvent.complete.activity + + waitingTimeEvent.complete.activity_instance + ); + + if (waitingTimeEvent.start.lifecycle == 'start') { + xStart = startActivityData.xStart; + } else { + xStart = startActivityData.xEnd + 0.2; + } + if (waitingTimeEvent.complete.lifecycle == 'start') { + xEnd = completeActivityData.xStart - 0.2; + } else { + xEnd = completeActivityData.xEnd; + } + + if (waitingTimeEvent.anchor == 'start') { + yIndex = startActivityData.yIndex; + } else { + yIndex = completeActivityData.yIndex; + } + + let m = new SubvariantVisualization(); + m.activity = 'WAITING TIME NODE'; + m.performanceStats = waitingTimeEvent.performance_stats; + m.xStart = xStart; + m.xEnd = xEnd; + m.yIndex = yIndex; + m.isWaitingTimeNode = true; + + result.push(m); + }); + + // find duplicates in x-positions between Waiting Time Nodes and Subvariant Nodes; then, introduce gaps + const yData = this.getSubvariantVisualizationsXPositionMapPerYIndex( + Array.from(nodesData.values()) + ); + + for (let [i, wtEvent] of result.entries()) { + if (yData.get(wtEvent.yIndex).indexOf(wtEvent.xStart) > -1) { + result[i].xStart += 0.2; + } + + if (yData.get(wtEvent.yIndex).indexOf(wtEvent.xEnd) > -1) { + result[i].xEnd -= 0.2; + } + } + + // handle remaining overlapping waiting time events + for (let r1 of result) { + for (let [j, r2] of result.entries()) { + if (r1 === r2) { + continue; + } + + if (r1.y != r2.y) { + continue; + } + + if (r1.xEnd === r2.xStart) { + result[j].xStart += 0.2; + } + } + } + + return result; + } + + private getSubvariantVisualizationsXPositionMapPerYIndex( + data: SubvariantVisualization[] + ): Map<number, number[]> { + const yData = new Map<number, number[]>(); + data.forEach((subvariant: SubvariantVisualization) => { + if (!yData.has(subvariant.yIndex)) { + yData.set(subvariant.yIndex, []); + } + + let yDataForIndex = yData.get(subvariant.yIndex); + yDataForIndex.push(subvariant.xStart); + yDataForIndex.push(subvariant.xEnd); + yData.set(subvariant.yIndex, yDataForIndex); + }); + + return yData; + } + + private computeYIndicesFromVariantElement( + variantElement: VariantElement, + results: Map<string, number[]>, + currentYIndex: number + ): [Map<string, number[]>, number] { + if (variantElement instanceof LeafNode) { + for (let i = 0; i < variantElement.activity.length; i++) { + let activity = variantElement.activity[i]; + if (results.has(activity)) { + let currentValues = results.get(activity); + currentValues.push(currentYIndex); + results.set(activity, currentValues); + } else { + results.set(activity, [currentYIndex]); + } + } + + return [results, currentYIndex]; + } + + if (variantElement instanceof FallthroughGroup) { + for (let child of variantElement.elements) { + if (child instanceof LeafNode) { + let activity = child.activity[0]; + if (results.has(activity)) { + let currentValues = results.get(activity); + currentValues.push(currentYIndex); + results.set(activity, currentValues); + } else { + results.set(activity, [currentYIndex]); + } + } + } + + return [results, currentYIndex]; + } + + if (variantElement instanceof SequenceGroup) { + let maxIndices: number[] = []; + let maxIndex = 0; + for (let child of variantElement.elements) { + [results, maxIndex] = this.computeYIndicesFromVariantElement( + child, + results, + currentYIndex + ); + maxIndices.push(maxIndex); + } + + return [results, Math.max(...maxIndices)]; + } + + if (variantElement instanceof ParallelGroup) { + let maxYIndex = currentYIndex; + for (let child of variantElement.elements) { + [results, maxYIndex] = this.computeYIndicesFromVariantElement( + child, + results, + maxYIndex + ); + maxYIndex++; + } + + return [results, maxYIndex - 1]; + } + return [results, 0]; + } + + public setExpanded(expanded: boolean): void { + this.expanded = expanded; + this.draw(); + } + + public toggleExpanded() { + this.expanded = !this.expanded; + this.draw(); + } + + changeSelection(sel: SubvariantVisualization) { + d3.selectAll('.subvariant-rect').classed( + 'selected-subvariant', + (d) => sel === d + ); + } +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component.css b/src/frontend/src/app/components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component.css new file mode 100644 index 0000000000000000000000000000000000000000..6127f19963fe6d0e96cc00492be5b7575a27cd0a --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component.css @@ -0,0 +1,23 @@ +.context-menu{ + display : block; + position : fixed; + color: white; + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity));; + border-radius: 2px; + z-index : 100; + +} + +.context-menu-list{ + list-style-type:none; + padding: 5px; + margin: 0; +} + +.button:hover:enabled { + background-color: #4d4e50; +} + +.drop-down-button:hover:enabled { + background-color: #c7c9cc; +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component.html b/src/frontend/src/app/components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component.html new file mode 100644 index 0000000000000000000000000000000000000000..683f25471c5bcaf3efb39d239285f79a898330b6 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component.html @@ -0,0 +1,17 @@ +<div + class="context-menu" + [style.top.px]="yPos" + [style.left.px]="xPos" + *ngIf="displayMenu" +> + <ul class="context-menu-list"> + <li *ngFor="let option of contextMenuOptions"> + <button class="button align-bottom" (click)="option.onClick()"> + <div> + <i class="bi btn-icon pe-2" [class]="option.icon"></i> + <span>{{ option.text }}</span> + </div> + </button> + </li> + </ul> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..1d5f49788df30a7bc29de3da7e7c70501413872d --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantExplorerContextMenuComponent } from './variant-explorer-context-menu.component'; + +describe('VariantExplorerContextMenuComponent', () => { + let component: VariantExplorerContextMenuComponent; + let fixture: ComponentFixture<VariantExplorerContextMenuComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantExplorerContextMenuComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantExplorerContextMenuComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component.ts b/src/frontend/src/app/components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..896440df8677bd0c6f140ba70dd82b8440e94997 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component.ts @@ -0,0 +1,72 @@ +import { + AfterViewInit, + Component, + HostListener, + Input, + OnChanges, + SimpleChanges, +} from '@angular/core'; +import { VariantDrawerDirective } from 'src/app/directives/variant-drawer/variant-drawer.directive'; +import { VariantElement } from 'src/app/objects/Variants/variant_element'; + +@Component({ + selector: 'app-variant-explorer-context-menu', + templateUrl: './variant-explorer-context-menu.component.html', + styleUrls: ['./variant-explorer-context-menu.component.css'], +}) +export class VariantExplorerContextMenuComponent + implements OnChanges, AfterViewInit +{ + @Input() + xPos: number; + + @Input() + yPos: number; + + displayMenu: boolean = false; + + @Input() + contextMenuOptions: Array<ContextMenuItem>; + + constructor() {} + + ngAfterViewInit(): void { + this.displayMenu = false; + } + + ngOnChanges(changes: SimpleChanges): void { + if (!(changes.xPos.isFirstChange() && changes.yPos.isFirstChange())) { + this.displayMenu = true; + } + } + + @HostListener('window:click', ['$event']) + public onClick(event: any): void { + this.displayMenu = false; + } +} + +export class ContextMenuItem { + constructor( + text: string, + icon: string, + onClick: ( + variant: VariantElement, + element: VariantElement, + directive: VariantDrawerDirective + ) => {} + ) { + this.icon = icon; + this.text = text; + this.onClick = onClick; + } + + onClick: ( + variant: VariantElement, + element: VariantElement, + directive: VariantDrawerDirective + ) => {}; + + icon: string; + text: string; +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component.css b/src/frontend/src/app/components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component.css new file mode 100644 index 0000000000000000000000000000000000000000..f62cd66973e1ff746173c9909275a0e2e4048b2e --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component.css @@ -0,0 +1,38 @@ +.sidebar{ + height: 20px; + position: absolute; + display: flex; + transform: rotate(90deg) translate(0,-20px); + transform-origin: left top; + top: 0; + background: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); + z-index: 4; + -webkit-font-smoothing: subpixel-antialiased; + filter: blur(0); + backface-visibility: hidden; +} + +.sidebar-button{ + transform: rotate(180deg); + font-size: 12px; + margin-right: 5px; + color: #ddd; + background: var(--box-background-color); + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; + margin-bottom: 2px; + border-bottom: none; + padding: 0 10px 5px; + cursor : pointer; +} + +.sidebar-button-text{ + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.active { + background: #777575 !important; +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component.html b/src/frontend/src/app/components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component.html new file mode 100644 index 0000000000000000000000000000000000000000..5000047355203f184bd8e4672c1398804718aa3d --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component.html @@ -0,0 +1,35 @@ +<div class="sidebar" [style.width.px]="sidebarHeight"> + <div + class="sidebar-button" + [ngClass]="variantViewModeService.viewMode === VM.STANDARD ? 'active' : ''" + (click)="setViewModeClicked(VM.STANDARD)" + > + <span class="sidebar-button-text user-select-none"> Standard View</span> + </div> + + <ng-container *ngIf="!variantService.areVariantLoopsCollapsed"> + <div + class="sidebar-button" + [ngClass]=" + variantViewModeService.viewMode === VM.PERFORMANCE ? 'active' : '' + " + (click)="setViewModeClicked(VM.PERFORMANCE)" + > + <span class="sidebar-button-text user-select-none"> + Performance View + </span> + </div> + + <div + class="sidebar-button" + [ngClass]=" + variantViewModeService.viewMode === VM.CONFORMANCE ? 'active' : '' + " + (click)="setViewModeClicked(VM.CONFORMANCE)" + > + <span class="sidebar-button-text user-select-none"> + Conformance View + </span> + </div> + </ng-container> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..6fc2a4e52305c5cfcbd1957eda47f2fc16f8e122 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantExplorerSidebarComponent } from './variant-explorer-sidebar.component'; + +describe('VariantExplorerSidebarComponent', () => { + let component: VariantExplorerSidebarComponent; + let fixture: ComponentFixture<VariantExplorerSidebarComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantExplorerSidebarComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantExplorerSidebarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component.ts b/src/frontend/src/app/components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..20855b30aeeefc1d5b8939fd379dacf197e6d894 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-explorer-sidebar/variant-explorer-sidebar.component.ts @@ -0,0 +1,47 @@ +import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { VariantPerformanceService } from 'src/app/services/variant-performance.service'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { VariantViewModeService } from 'src/app/services/viewModeServices/variant-view-mode.service'; + +@Component({ + selector: 'app-variant-explorer-sidebar', + templateUrl: './variant-explorer-sidebar.component.html', + styleUrls: ['./variant-explorer-sidebar.component.css'], +}) +export class VariantExplorerSidebarComponent implements OnInit, OnDestroy { + @Input() + public sidebarHeight: number = 0; + + public VM = ViewMode; + + private _destroy$ = new Subject(); + + constructor( + public variantViewModeService: VariantViewModeService, + private variantPerformanceService: VariantPerformanceService, + public variantService: VariantService + ) {} + + ngOnInit(): void { + return; + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + public setViewModeClicked(viewMode: ViewMode) { + if ( + viewMode === ViewMode.PERFORMANCE && + !this.variantPerformanceService.performanceInformationLoaded + ) + this.variantPerformanceService + .addPerformanceInformationToVariants() + .pipe(takeUntil(this._destroy$)) + .subscribe(); + else this.variantViewModeService.viewMode = viewMode; + } +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-explorer.component.html b/src/frontend/src/app/components/variant-explorer/variant-explorer.component.html new file mode 100644 index 0000000000000000000000000000000000000000..4d40c47177c20584abffabecbac7ab562ba145d6 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-explorer.component.html @@ -0,0 +1,942 @@ +<app-performance-progress-bar> </app-performance-progress-bar> + +<app-variant-explorer-sidebar + [sidebarHeight]="sidebarHeight" +></app-variant-explorer-sidebar> + +<div + class="d-flex flex-column h-100 container-variant-explorer" + #variantExplorerContainer + [class.blur-out-of-focus]=" + variantPerformanceService.performanceUpdateIsInProgress + " +> + <div class="bg-dark btn-tool-bar"> + <ng-template #tooltip1> + Selected (marked with <i class="bi bi-check2-circle"></i>) + <b>non-fitting</b> variants will be added to the process model + <hr /> + Selected (marked with <i class="bi bi-check2-circle"></i>) + <b>fitting</b> variants will remain in the process tree's language when + incrementally adding new variants + </ng-template> + <i + class="bi bi-question-circle-fill font-large ms-1 align-middle secondary-text cursor-help question-icon" + [ngbTooltip]="tooltip1" + triggers="hover" + container="body" + (click)="openDocumentation('Variant Explorer')" + > + </i> + + <div class="vr ms-1"></div> + + <ng-template #toolTip2> + calculate conformance checking statistics + <br /><i class="bi bi-question-square text-secondary"> unknown</i> + <br /><i class="bi bi-hourglass-split text-secondary"> + being calculated</i + > + <br /><i class="bi bi-check-square text-success"> variant fits model</i> + <br /><i class="bi bi-x-square text-danger"> + variant does not fit model</i + > + <br /><i class="bi bi-check-square text-warning"></i> + <i class="bi bi-x-square text-warning"> + outdated results (model has changed)</i + > + <br /><i class="bi bi-hourglass-bottom text-warning"> timeout</i> + </ng-template> + <button + [ngbTooltip]="toolTip2" + triggers="hover" + container="body" + class="button" + (click)="updateAlignments()" + [disabled]=" + !currentlyDisplayedProcessTree?.isValid() || + isAlignmentCalculationInProgress() || + !correctTreeSyntax + " + > + <i class="bi bi-layers-fill btn-icon"></i> + <div @collapseText class="button-text px-1" *ngIf="!collapse"> + conformance check + </div> + </button> + + <div class="vr"></div> + + <button + class="button" + ngbTooltip="add selected, non-fitting variant(s) to current process model" + triggers="hover" + container="body" + [disabled]=" + isNoVariantSelected() || + !currentlyDisplayedProcessTree?.isValid() || + isAlignmentCalculationInProgress() + " + (click)="addSelectedVariantsToModel()" + > + <i + class="bi bi-plus-lg btn-icon" + [ngClass]="{ + 'text-success': !( + isNoVariantSelected() || + !currentlyDisplayedProcessTree?.isValid() || + isAlignmentCalculationInProgress() + ) + }" + ></i> + <div @collapseText class="button-text px-1" *ngIf="!collapse"> + add variant(s) to model + </div> + </button> + + <div class="vr"></div> + + <ng-template #tooltip3> + discover an initial model from the selected variants using the standard + <em>Inductive Miner</em> algorithm<br /><b + ><i class="bi bi-exclamation-triangle text-warning"></i> overwrites the + existing model</b + > + </ng-template> + <button + class="button" + [ngbTooltip]="tooltip3" + triggers="hover" + container="body" + [disabled]=" + isNoVariantSelected() || + isAlignmentCalculationInProgress() || + isInfixSelected() + " + (click)="discoverInitialModel()" + > + <i + class="bi bi-diagram-2-fill btn-icon" + [ngClass]="{ + 'text-success': + isAnyVariantSelected() && + !isAlignmentCalculationInProgress() && + !isInfixSelected() + }" + ></i> + <div @collapseText class="button-text px-1" *ngIf="!collapse"> + discover initial model + </div> + <ng-template #infixSelectedTooltip> + Initial model discovery is not supported for infixes! <br /> + First deselect all infixes. + </ng-template> + <i + class="bi bi-exclamation-triangle text-warning" + *ngIf="isInfixSelected()" + [ngbTooltip]="infixSelectedTooltip" + triggers="hover" + container="body" + ></i> + </button> + + <div class="vr"></div> + + <div class="vr"></div> + <ng-template #tooltip4> + sort variants by one of the following attributes: + <br /><i class="bi bi-chevron-double-right"> + total number of activities</i + > + <br /><i class="bi bi-check-square"> conformace</i> <br /><i + class="bi bi-123" + > + frequency</i + > + <br /><i class="bi bi-three-dots"> maximal trace length</i> <br /><i + class="bi bi-person-circle" + > + user created</i + > + </ng-template> + <div + class="btn-group align-baseline dropDownParent dropdown ms-auto" + [ngbTooltip]="tooltip4" + triggers="hover" + container="body" + > + <button + class="button dropdown-toggle" + type="button" + id="sortDropdown" + data-bs-toggle="dropdown" + aria-expanded="false" + > + <i class="bi bi-sort-alpha-down btn-icon"></i> + </button> + <div + class="dropdown-menu custom-dropdown general-dropdown" + id="sortDropdownMenu" + aria-labelledby="sortDropdown" + > + <div class="fst-italic fw-bold ps-2 text-center">Sort</div> + <div class="fst-italic ps-2 text-dropdown">Order</div> + <div> + <button + class="dropdown-item" + (click)="onSortOrderChanged(true)" + [ngClass]="isAscendingOrder ? 'selected-dropdown-item' : ''" + > + <i class="bi bi-sort-down-alt btn-icon"></i> + <span class="ms-3">ascending</span> + </button> + </div> + <div> + <button + class="dropdown-item" + (click)="onSortOrderChanged(false)" + [ngClass]="!isAscendingOrder ? 'selected-dropdown-item' : ''" + > + <i class="bi bi-sort-down btn-icon"></i> + <span class="ms-3">descending</span> + </button> + </div> + <div class="fst-italic ps-2 text-dropdown">Feature</div> + <div> + <button + class="dropdown-item" + (click)="sort('number_of_activities')" + [ngClass]=" + sortingFeature === 'number_of_activities' + ? 'selected-dropdown-item' + : '' + " + > + <i class="bi bi-chevron-double-right btn-icon"></i> + <span class="ms-3">activities</span> + </button> + </div> + <div> + <button + class="dropdown-item" + (click)="sort('conformance')" + [ngClass]=" + sortingFeature === 'conformance' ? 'selected-dropdown-item' : '' + " + > + <i class="bi bi-check-square btn-icon"></i> + <span class="ms-3">conformance</span> + </button> + </div> + <div> + <button + class="dropdown-item" + (click)="sort('count')" + [ngClass]=" + sortingFeature === 'count' ? 'selected-dropdown-item' : '' + " + > + <i class="bi bi-123 btn-icon"></i> + <span class="ms-3">frequency</span> + </button> + </div> + <div> + <button + class="dropdown-item" + (click)="sort('length')" + [ngClass]=" + sortingFeature === 'length' ? 'selected-dropdown-item' : '' + " + > + <i class="bi bi-three-dots btn-icon"></i> + <span class="ms-3">length</span> + </button> + </div> + <div> + <button + class="dropdown-item" + (click)="sort('sub_variants')" + [ngClass]=" + sortingFeature === 'sub_variants' ? 'selected-dropdown-item' : '' + " + > + <i class="bi bi-bar-chart-steps"></i> + <span class="ms-3">sub-variants</span> + </button> + </div> + <div> + <button + class="dropdown-item" + (click)="sort('userDefined')" + [ngClass]=" + sortingFeature === 'userDefined' ? 'selected-dropdown-item' : '' + " + > + <i class="bi bi-person-circle"></i> + <span class="ms-3">user created</span> + </button> + </div> + </div> + </div> + + <div class="vr"></div> + + <div + class="dropdown" + ngbTooltip="Select the time granularity" + triggers="hover" + container="body" + > + <button + class="button dropdown-toggle" + type="button" + id="granularityDropdown" + data-bs-toggle="dropdown" + aria-expanded="false" + > + <i class="bi bi-clock btn-icon"></i> + </button> + <ul + class="dropdown-menu custom-dropdown general-dropdown" + aria-labelledby="granularityDropdown" + > + <li *ngFor="let unit of $any(timeUnit) | keyvalue : originalOrder"> + <button + (click)="onGranularityChange(unit.value)" + [ngClass]="{ + 'selected-dropdown-item': selectedGranularity === unit.value + }" + class="dropdown-item" + > + {{ unit.value }} + </button> + </li> + </ul> + </div> + + <div class="vr"></div> + + <div + class="dropdown" + ngbTooltip="Functions" + triggers="hover" + container="body" + > + <button + class="button dropdown-toggle" + type="button" + id="FuntionDropdown" + data-bs-toggle="dropdown" + aria-expanded="false" + > + <i class="bi bi-list btn-icon"></i> + </button> + <div + class="dropdown-menu custom-dropdown general-dropdown" + id="sortDropdownMenu" + aria-labelledby="sortDropdown" + > + <ng-container *ngIf="variantViewModeService.viewMode === VM.STANDARD"> + <div> + <button + *ngIf="variantService.areVariantLoopsCollapsed" + class="dropdown-item" + style="color: green" + (click)="variantService.expandCollapseLoopsInVariants()" + > + <i + class="bi bi-arrow-repeat btn-icon cursor-pointer text-success" + ></i> + <span class="ms-3">Expand loops in variants</span> + </button> + </div> + <div> + <button + *ngIf="!variantService.areVariantLoopsCollapsed" + class="dropdown-item" + (click)="variantService.expandCollapseLoopsInVariants()" + > + <i class="bi bi-arrow-repeat btn-icon cursor-pointer"></i> + <span class="ms-3">Collapse loops in variants</span> + </button> + </div> + </ng-container> + <ng-container + *ngIf="variantViewModeService.viewMode !== VM.PERFORMANCE" + > + <div> + <button + *ngIf="areAllVariantsExpanded()" + class="dropdown-item" + (click)="expandCollapseAll()" + > + <i + class="bi bi-arrows-collapse btn-icon cursor-pointer rotate-90" + ></i> + <span class="ms-3">Collapse all variants</span> + </button> + </div> + <div> + <button + *ngIf="!areAllVariantsExpanded()" + class="dropdown-item" + (click)="expandCollapseAll()" + > + <i + class="bi bi-arrows-expand btn-icon cursor-pointer rotate-90" + ></i> + <span class="ms-3">Expand all variants</span> + </button> + </div> + </ng-container> + <ng-container *ngIf="variantViewModeService.viewMode === VM.STANDARD"> + <div> + <button + class="dropdown-item" + (click)="showVariantSequentializerDialog()" + > + <i class="bi bi-bar-chart-steps btn-icon cursor-pointer"></i> + <span class="ms-3">Variant sequentializer</span> + </button> + </div> + </ng-container> + <div> + <button + *ngIf=" + variantViewModeService.viewMode === VM.STANDARD && + !traceInfixSelectionMode + " + class="dropdown-item" + (click)="toggleTraceInfixSelectionMode()" + > + <i class="bi bi-ui-checks-grid"></i> + <span class="ms-3">Trace fragment selection mode</span> + </button> + </div> + <div> + <button class="dropdown-item" (click)="toggleArcsVisibility()"> + <i class="bi bi-rainbow"></i> + <span + class="ms-3" + *ngIf=" + arcsViewMode === ArcsViewMode.SHOW_ALL || + arcsViewMode === ArcsViewMode.SHOW_SOME + " + >Hide all arc diagrams</span + > + <span + class="ms-3" + *ngIf=" + arcsViewMode === ArcsViewMode.INITIAL || + arcsViewMode === ArcsViewMode.HIDE_ALL + " + >Show all arc diagrams</span + > + </button> + </div> + <div> + <button + *ngIf=" + variantViewModeService.viewMode === VM.STANDARD && + traceInfixSelectionMode + " + class="dropdown-item" + style="color: green" + (click)="toggleTraceInfixSelectionMode()" + > + <i class="bi bi-ui-checks-grid"></i> + <span class="ms-3">Exit trace fragment selection mode</span> + </button> + </div> + <div> + <button + class="dropdown-item" + (click)="openClusteringSettingsDialog()" + > + <i class="bi bi-grid-1x2"></i> + <span class="ms-3">Variant clustering</span> + </button> + </div> + <div> + <button class="dropdown-item" (click)="exportVariantSVG()"> + <i class="bi bi-save"></i> + <span class="ms-3">Export the view as an .svg</span> + </button> + </div> + </div> + </div> + + <div class="vr"></div> + </div> + <div class="d-flex flex-row"> + <div + class="variant-query-button flex-row px-2" + role="button" + (click)="showFilterMenu = !showFilterMenu" + > + <i class="bi bi-funnel"></i> + <span class="ms-2 user-select-none">Filter</span> + </div> + <div + [class.d-none]=" + variantService.areVariantLoopsCollapsed || !showFilterMenu + " + class="variant-query-button accordion d-flex flex-column" + id="accordion" + > + <div + class="flex-row px-2" + role="button" + (click)="showFilterMenu = !showFilterMenu" + > + <i class="bi-arrows-angle-contract"></i> + <span class="ms-2 user-select-none">Filter</span> + </div> + <div class="accordion-item"> + <div class="accordion-header d-flex flex-row" id="headingVariantQuery"> + <div + class="query-button accordion-button me-auto py-2 collapsed" + role="button" + data-bs-toggle="collapse" + data-bs-target="#variantQueryPanel" + aria-expanded="false" + aria-controls="variantQueryPanel" + > + <span class="ms-2 user-select-none secondary-text" + >Variant Query</span + > + <div class="ms-2"> + <button + type="button" + class="query-info-button" + title="Variant Query Language" + (click)="toggleQueryInfo($event)" + > + <i + class="bi bi-question-circle-fill font-large secondary-text fs-6 cursor-help question-icon" + > + </i> + </button> + </div> + <div class="me-2 dropdown"> + <button + class="query-info-button" + type="button" + id="Options" + data-bs-toggle="dropdown" + aria-expanded="false" + > + <i + class="bi bi-gear font-large secondary-text fs-6 question-icon" + ></i> + </button> + <ul + class="dropdown-menu query-bar-drop query-bar-dropdown" + aria-labelledby="Files" + > + <li> + <div class="form-check form-switch"> + <input + class="form-check-input" + type="checkbox" + id="flexSwitchCheckChecked" + checked + (change)=" + changeQueryOption($event, 'highlightActivityNames') + " + /> + <label class="form-check-label" for="flexSwitchCheckChecked" + >Syntax Highlighting</label + > + </div> + </li> + </ul> + </div> + </div> + </div> + <div + class="query-app-container accordion-collapse collapse" + id="variantQueryPanel" + aria-labelledby="headingVariantQuery" + data-bs-parent="#accordion" + > + <app-variant-query + [active]="true" + [options]="options" + (executeFilteredVariantsAction)=" + executeRemovalActionOnFilteredVariants($event) + " + ></app-variant-query> + </div> + </div> + <div class="accordion-item"> + <div class="accordion-header" id="flush-headingOne"> + <button + class="query-button accordion-button collapsed py-2" + data-bs-toggle="collapse" + data-bs-target="#flush-collapseOne" + aria-expanded="false" + aria-controls="flush-collapseOne" + > + <span class="ms-2 secondary-text">Arc Visualisation</span> + </button> + </div> + <div + id="flush-collapseOne" + class="accordion-collapse collapse" + aria-labelledby="flush-headingOne" + data-bs-parent="#accordionFlushExample" + > + <app-arc-diagram-filter-form + (filterArcDiagrams)="filterArcDiagrams($event)" + (newActivitiesLoaded)="newActivitiesLoaded($event)" + [arcsMaxValues]="arcsMaxValues" + [filtering]="filtering" + ></app-arc-diagram-filter-form> + </div> + </div> + </div> + </div> + <div + class="main-variant-explorer flex-grow-1" + (scroll)="onScroll()" + #variantExplorer + > + <div *ngIf="svgRenderingInProgress" class="full-body-spinner"> + <div + class="spinner-border spinner-border-sm text-primary" + role="status" + ></div> + <div class="ms-1" style="color: var(--text-primary)"> + Exporting Variant View... + </div> + </div> + <div class="d-flex"> + <div class="chart-variant-percentage"> + <table> + <thead> + <tr class="user-select-none"> + <th class="centered"> + <div class="variant-filter-container">No.</div> + </th> + <th> + <div class="variant-filter-container"> + <app-variant-selection-button + [isSelected]="areAllDisplayedVariantsSelected()" + (selectionChanged)="unSelectAllChanged($event)" + tooltipText="(un)select all variants" + > + </app-variant-selection-button> + Info + </div> + </th> + <th class="centered"> + <div class="variant-filter-container">Sub-Variants</div> + </th> + <th + *ngIf=" + currentlyDisplayedProcessTree?.isValid() && + variantViewModeService.viewMode !== VM.STANDARD + " + class="centered" + > + Model Projection + <ng-container [ngSwitch]="variantViewModeService.viewMode"> + <ng-container *ngSwitchCase="VM.CONFORMANCE"> + <i + class="bi bi-x-circle-fill cursor-pointer fs-6" + [ngStyle]="{ + display: + conformanceCheckingService.anyTreeConformanceActive() + ? 'inline' + : 'none' + }" + ngbTooltip="hide all model projections" + triggers="hover" + container="body" + (click)="handleTreeConformanceClear()" + ></i> + </ng-container> + <ng-container *ngSwitchCase="VM.PERFORMANCE"> + <i + class="bi bi-x-circle-fill cursor-pointer fs-6" + [ngStyle]="{ + display: performanceService.anyTreePerformanceActive() + ? 'inline' + : 'none' + }" + ngbTooltip="hide all model projections" + triggers="hover" + container="body" + (click)="handleTreePerformanceClear()" + ></i> + </ng-container> + </ng-container> + </th> + <th + *ngIf=" + currentlyDisplayedProcessTree?.isValid() && + variantViewModeService.viewMode !== VM.STANDARD + " + class="centered" + > + <ng-container [ngSwitch]="variantViewModeService.viewMode"> + <ng-container *ngSwitchCase="VM.CONFORMANCE"> + Tree-Conformance + </ng-container> + <ng-container *ngSwitchCase="VM.PERFORMANCE"> + {{ performanceColumnHeader() }} + </ng-container> + </ng-container> + </th> + + <th class="text-start variant-header"> + <div class="variant-filter-container"> + <div> + <span>Variant </span> + <span + class="variant-number" + [ngClass]="{ + 'text-primary': + displayed_variants.length !== variants.length && + !variantService.areVariantLoopsCollapsed + }" + >({{ + displayed_variants.length === variants.length || + variantService.areVariantLoopsCollapsed + ? displayed_variants.length + : displayed_variants.length + "/" + variants.length + }})</span + > + </div> + + <div class="filter-container"> + <div + *ngFor="let filter of filterMap | keyvalue" + class="badge-container" + > + <button + class="btn badge-button" + (click)="removeFilter(filter.key)" + > + <span + class="badge rounded-pill bg-danger badge-close-position cursor-pointer" + ><i class="bi bi-x-lg close-icon"></i> + </span> + </button> + <span + class="badge text-bg-primary ms-1 cursor-pointer" + [ngbTooltip]="filter.value.tooltip" + container="body" + triggers="hover" + (click)="toggleQueryFilterDialog()" + > + <i class="bi bi-funnel-fill"> </i> {{ filter.key }} + </span> + </div> + </div> + </div> + </th> + <th> + <!-- header for fixed-right (infix/deletion) buttons --> + </th> + </tr> + </thead> + <!-- start cluster view--> + + <ng-container + *ngFor=" + let cluster of displayed_variants + | groupBy : 'clusterId' + | keyvalue; + let i = index + " + > + <tr> + <td colspan="3"> + <div + *ngIf="cluster.value[0].clusterId !== -1" + class="m-2 badge bg-secondary justify-content-center align-items-center cluster-badge" + > + <div + *ngIf="cluster.value[0].clusterId !== -1" + style="gap: 4px" + class="d-flex flex-row" + > + <button + class="btn control-button" + type="button" + (click)="toggle(i)" + > + <i + *ngIf="hideRuleContent[i]" + class="bi bi-chevron-right btn-icon" + ></i> + <i + *ngIf="!hideRuleContent[i]" + class="bi bi-chevron-down btn-icon" + ></i> + </button> + + <span class="text-nowrap cluster-badge-text-primary" + >Cluster {{ i + 1 }}</span + > + <app-search + class="cluster-app-search" + (sortEvent)="handleClusterSort($event, cluster.key)" + [isAscendingOrder]=" + clusterSortSettings[i]?.isAscendingOrder + " + [sortingFeature]="clusterSortSettings[i]?.feature" + ></app-search> + </div> + + <div + *ngIf="cluster.value[0].clusterId !== -1" + class="d-flex flex-row" + > + <span class="text-nowrap cluster-badge-text-secondary" + >({{ cluster.value.length }} of + {{ logStats?.totalNumberVariants }} variants | </span + > + <span class="text-nowrap cluster-badge-text-secondary" + >{{ + calculateTotalTracesInCluster(cluster.value) | number + }} + of + {{ logStats?.totalNumberTraces | number }} traces)</span + > + </div> + </div> + </td> + </tr> + + <ng-container + *ngFor=" + let variant of cluster.value + | variantSort + : clusterSortSettings[cluster.key]?.isAscendingOrder + : clusterSortSettings[cluster.key]?.feature; + let j = index + " + > + <ng-container *ngIf="!hideRuleContent[i]"> + <tr + app-variant + [index]="j" + [variant]="variant" + [processTreeAvailable]=" + processTreeService.currentDisplayedProcessTree?.isValid() + " + [traceInfixSelectionMode]="traceInfixSelectionMode" + [rootElement]="variantExplorerDiv" + class="hover-variant-row" + > + <ng-template #treeButton> + <ng-container [ngSwitch]="variantViewModeService.viewMode"> + <ng-container *ngSwitchCase="VM.CONFORMANCE"> + <app-tree-conformance-button + [variant]="variant" + ></app-tree-conformance-button> + </ng-container> + <ng-container *ngSwitchCase="VM.PERFORMANCE"> + <app-tree-performance-button + [variant]="variant" + ></app-tree-performance-button> + </ng-container> + </ng-container> + </ng-template> + + <ng-template #variantInfo> + <app-variant-info + [variant]="variant" + (selectionChanged)=" + selectionChangedForVariant(variant, $event) + " + (updateConformance)=" + updateConformanceForSingleVariantClicked($event) + " + (variantInfoEvent)=" + createVariantInfoView(i + 1, j + 1, variant.id) + " + > + </app-variant-info> + </ng-template> + + <ng-template #subvariantButton> + <div + *ngIf="variant.nSubVariants > 0" + class="subvariants" + (click)="createSubVariantView(i + 1, j + 1, variant.id)" + > + {{ variant.nSubVariants }} + </div> + </ng-template> + + <ng-template #variantDrawer> + <app-variant-visualisation + [variant]="variant" + [traceInfixSelectionMode]="traceInfixSelectionMode" + [colorMap]="colorMap" + [arcsCache]="arcsCache" + [arcsViewMode]="arcsViewMode" + [filterParams]="filterParams" + ></app-variant-visualisation> + <ng-template #infixSelection> + <app-infix-selection-controlls + [variant]="variant" + (selectTraceInfix)="handleSelectInfix($event)" + [variantDrawer]="drawer" + ></app-infix-selection-controlls> + </ng-template> + </ng-template> + <ng-template #removeVariantButton> + <app-variant-action-buttons + [variant]="variant" + [variantVisualisations]="variantVisualisations" + (showArcDiagram)="showSingleArcDiagram($event)" + ></app-variant-action-buttons> + </ng-template> + </tr> + </ng-container> + </ng-container> + </ng-container> + </table> + </div> + </div> + </div> + + <div class="bg-dark user-select-none"> + <app-conformance-info-bar + [logStats]="logStats" + [isConformanceOutdated]="this.isConformanceOutdated()" + [numSelectedVariants]="this.getSelectedVariants().length" + ></app-conformance-info-bar> + </div> + + <div role="tooltip" #tooltipContainer> + <div class="tooltip-inner"></div> + </div> +</div> + +<app-variant-query-info [(showInfo)]="showQueryInfo"></app-variant-query-info> + +<app-variant-explorer-context-menu + [xPos]="contextMenu_xPos" + [yPos]="contextMenu_yPos" + [contextMenuOptions]="contextMenuOptions" +></app-variant-explorer-context-menu> + +<svg display="none" id="infixDotsForDrawer"> + <symbol + width="20" + height="20" + fill="currentColor" + id="infixDots" + transform-origin="10 10" + > + <path + d="M3 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z" + /> + </symbol> +</svg> diff --git a/src/frontend/src/app/components/variant-explorer/variant-explorer.component.scss b/src/frontend/src/app/components/variant-explorer/variant-explorer.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..36faf074018a8f1b96f15102b362dc129092e9e1 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-explorer.component.scss @@ -0,0 +1,307 @@ +.chart-variant-percentage { + display: inline-flex; + flex-direction: column; + + /* + min-width: 50px; + */ + font-size: 0.8rem; + color: var(--text-secondary); + width: 100%; +} + +:host { + position: absolute; + overflow: hidden; +} + +.variant-info-cell { + align-items: center; + display: flex; +} + +.subvariants { + text-align: center; + cursor: pointer; +} + +.variant-query-button { + right: 0; + bottom: 21px; + position: absolute; + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); + border-top-left-radius: 5px; + display: flex; + place-content: flex-end flex-start; + align-items: stretch; + flex-direction: column; + border-bottom: black solid 1px; + border-left: black solid 1px; + border-top: black solid 1px; + z-index: 2; + max-width: 500px; + + // max-height: 650px; + color: var(--text-secondary); + width: auto !important; + height: auto !important; +} + +.query-bar-drop { + background-color: var(--box-background-color) !important; + z-index: 100; + border-radius: 0; +} + +.query-bar-dropdown { + transform: translate(0, 22px) !important; + color: whitesmoke; + font-size: small; + position: absolute; + inset: 0 0 auto auto; + padding: 10px; + width: 15rem; + border-radius: 4px !important; +} + +.query-app-container { + width: 100%; + + // height: 100%; + // min-height: 100px; + background-color: var(--box-background-color); +} + +.query-button { + color: var(--text-secondary); + font-size: var(--standard-font-size); + cursor: pointer; +} + +.query-header { + color: var(--text-secondary); + font-size: var(--standard-font-size); + padding: 2px 0 2px 6px; +} + +.query-button:hover { + filter: brightness(1.75); +} + +.btn-tool-bar { + min-height: 28px; + display: flex; + align-items: center; + border-top: 0; +} + +.variant-cell { + width: 100%; +} + +.variant { + border-width: 1px !important; + padding: 5px; + width: fit-content; + border: dashed; +} + +.spacer { + height: 5px; +} + +.main-variant-explorer { + overflow: auto; + background-color: var(--box-background-color); + user-select: none; +} + +.container-variant-explorer { + min-height: 100%; + width: calc(100% - 20px); + position: relative; + border-left: 1px solid var(--thin-border-color); + margin-left: 20px; +} + +.variant-explorer-alert { + z-index: 1; + position: absolute; + bottom: 10px; + margin: auto; +} + +.badge-close-position { + transform: translate(-50%, -35%) scale(0.6); + left: 100%; + top: 0; + position: relative; +} + +.badge-close-position:hover { + filter: brightness(150%); +} + +.badge-button{ + padding: 0; + font-size: unset; + display: contents; +} + +.badge-container{ + margin-left : -20px; +} + +.close-icon { + color: white; +} + +.filter-container { + display: flex; + flex-flow: row wrap; + gap: 5px; + max-width: 50%; + place-content: flex-start center; + align-items: flex-start; + height: 100%; + align-self: baseline; +} + +.variant-filter-container { + display: flex; + flex-flow: row wrap; + align-content: center; + align-items: center; + width: 100%; +} + +.variant-activity-tooltip { + position: absolute; + display: none; + background-color: white; + border: 2px solid; + border-radius: 5px; + padding: 5px; +} + +.button-text { + display: inline-block; +} + +.rotate-90 { + display: inline-block; + transform: rotate(90deg); +} + +.full-body-spinner { + width: 100%; + height: calc(100% - 28px); + position: absolute; + display: flex; + background-color: var(--box-background-color); + justify-content: center; + align-items: center; +} + +.dropdown-sort { + font-size: small; + max-height: 90vh; + user-select: none; +} + +.dropdown-menu { + border-radius: 0; + overflow-y: auto; + color: lightgray; +} + +.selected-dropdown-item { + background-color: #66686b; + color: lightgray; +} + +.dropdown-item { + color: var(--bs-white); +} + +.variant-number { + font-size: smaller; + font-weight: 400; +} + +.query-info-button { + background-color: rgb(var(--bs-accordion-active-bg)); + font-size: 12px; + color: #ddd; + border: none; +} + +.question-icon:hover { + filter: brightness(1.75); +} + +.hover-variant-row:hover { + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); +} + +th { + padding-left: 15px; + padding-bottom: 2px; +} + +th:first-child { + padding-left: 15px + 4px; +} + +th.centered { + text-align: center; +} + +.variant-header { + padding-left: 15 + 5px; +} + +thead { + position: sticky; + top: 0; + z-index: 1; + background-color: var(--box-background-color); + box-shadow: inset 0 -2px 1px var(--thin-border-color); +} + +.cluster-badge-text-primary{ + line-height: 22px; +} + +.cluster-badge-text-secondary{ + color: #c6c6c6; + margin-bottom: 4px; +} + +.cluster-badge{ + width: 100%; +} + +.cluster-app-search{ + margin: 2px 0 0 auto; +} + +.button-blue { + color: var(--bs-primary); +} + +.control-button{ + color: whitesmoke; + font-size: 6px; + padding: 0; + box-shadow: none; +} + +.form-switch .form-check-input:checked { + background-color: #161693; + border-color: whitesmoke; +} + +.text-dropdown { + color: var(--bs-white); +} \ No newline at end of file diff --git a/src/frontend/src/app/components/variant-explorer/variant-explorer.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant-explorer.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..bb9ade490e6d8140bb97b9903ca3580a865a0ba7 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-explorer.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantExplorerComponent } from './variant-explorer.component'; + +describe('VariantExplorerComponent', () => { + let component: VariantExplorerComponent; + let fixture: ComponentFixture<VariantExplorerComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantExplorerComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantExplorerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant-explorer.component.ts b/src/frontend/src/app/components/variant-explorer/variant-explorer.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..2807b08b372a0d16a920c205e3c79e2f92073b81 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-explorer.component.ts @@ -0,0 +1,1368 @@ +import { + VariantFilter, + VariantFilterService, +} from '../../services/variantFilterService/variant-filter.service'; + +import { + AfterViewInit, + ChangeDetectorRef, + Component, + ElementRef, + HostListener, + Inject, + OnDestroy, + OnInit, + QueryList, + Renderer2, + ViewChild, + ViewChildren, +} from '@angular/core'; + +import { + ComponentContainer, + ComponentItem, + ComponentItemConfig, + GoldenLayout, + LayoutManager, + LogicalZIndex, + Stack, +} from 'golden-layout'; +import { from, Subject } from 'rxjs'; +import { + concatMap, + delay, + filter, + mergeMap, + retryWhen, + take, + takeUntil, + tap, +} from 'rxjs/operators'; +import { GoldenLayoutHostComponent } from 'src/app/components/golden-layout-host/golden-layout-host.component'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { VariantDrawerDirective } from 'src/app/directives/variant-drawer/variant-drawer.directive'; + +import { TimeUnit } from 'src/app/objects/TimeUnit'; +import { HumanizeDurationPipe } from 'src/app/pipes/humanize-duration.pipe'; +import { + AlignmentType, + ConformanceCheckingService, +} from 'src/app/services/conformanceChecking/conformance-checking.service'; +import { GoldenLayoutComponentService } from 'src/app/services/goldenLayoutService/golden-layout-component.service'; +import { LogService, LogStats } from 'src/app/services/logService/log.service'; +import { ModelPerformanceColorScaleService } from 'src/app/services/performance-color-scale.service'; +import { PerformanceService } from 'src/app/services/performance.service'; +import { PolygonDrawingService } from 'src/app/services/polygon-drawing.service'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { VariantPerformanceService } from 'src/app/services/variant-performance.service'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { originalOrder } from 'src/app/utils/util'; +import { BackendService } from '../../services/backendService/backend.service'; +import { ColorMapService } from '../../services/colorMapService/color-map.service'; +import { ImageExportService } from '../../services/imageExportService/image-export-service'; +import { SharedDataService } from '../../services/sharedDataService/shared-data.service'; +import { DropzoneConfig } from '../drop-zone/drop-zone.component'; +import { SubvariantExplorerComponent } from './subvariant-explorer/subvariant-explorer.component'; +import { VariantInfoExplorerComponent } from './variant-info-explorer/variant-info-explorer.component'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { + deserialize, + ParallelGroup, + SequenceGroup, + VariantElement, +} from 'src/app/objects/Variants/variant_element'; +import { exportVariantDrawer } from './functions/export-variant-explorer'; +import { + fadeInOutComponent, + openCloseComponent, +} from 'src/app/animations/component-animations'; +import { collapsingText } from 'src/app/animations/text-animations'; +import { textColorForBackgroundColor } from 'src/app/utils/render-utils'; +import { processTreesEqual } from 'src/app/objects/ProcessTree/utility-functions/process-tree-integrity-check'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { VariantViewModeService } from 'src/app/services/viewModeServices/variant-view-mode.service'; +import { EditorOptions } from './variant-query/variant-query.component'; +import { ContextMenuItem } from './variant-explorer-context-menu/variant-explorer-context-menu.component'; +import { ToastService } from 'src/app/services/toast/toast.service'; +import { ProcessTree } from 'src/app/objects/ProcessTree/ProcessTree'; +import { IVariant } from 'src/app/objects/Variants/variant_interface'; +import { LoopCollapsedVariant } from 'src/app/objects/Variants/loop_collapsed_variant'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { ClusteringSettingsDialogComponent } from './clustering-settings-dialog/clustering-settings-dialog.component'; +import _ from 'lodash'; +import { InfixType } from 'src/app/objects/Variants/infix_selection'; +import { DocumentationService } from '../documentation/documentation.service'; +import * as d3 from 'd3'; +import { Arc, Pair } from '../../directives/arc-diagram/data'; +import { VariantVisualisationComponent } from './variant/subcomponents/variant-visualisation/variant-visualisation.component'; +import { FilterParams } from './arc-diagram/filter/filter-params'; +import { MaxValues } from './arc-diagram/filter/filter.component'; +import { ArcsViewMode } from './arc-diagram/arcs-view-mode'; +import { ArcDiagramService } from '../../services/arcDiagramService/arc-diagram.service'; +import { ArcDiagramComputationResult } from '../../services/arcDiagramService/model'; + +@Component({ + selector: 'app-variant-explorer', + templateUrl: './variant-explorer.component.html', + styleUrls: ['./variant-explorer.component.scss'], + animations: [collapsingText, fadeInOutComponent, openCloseComponent], +}) +export class VariantExplorerComponent + extends LayoutChangeDirective + implements OnInit, AfterViewInit, OnDestroy +{ + constructor( + private colorMapService: ColorMapService, + private sharedDataService: SharedDataService, + public variantService: VariantService, + private variantFilterService: VariantFilterService, + private backendService: BackendService, + private logService: LogService, + private imageExportService: ImageExportService, + private polygonDrawingService: PolygonDrawingService, + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + public processTreeService: ProcessTreeService, + elRef: ElementRef, + private renderer: Renderer2, + public performanceService: PerformanceService, + private performanceColorService: ModelPerformanceColorScaleService, + public variantPerformanceService: VariantPerformanceService, + public conformanceCheckingService: ConformanceCheckingService, + public arcDiagramService: ArcDiagramService, + private goldenLayoutComponentService: GoldenLayoutComponentService, + public variantViewModeService: VariantViewModeService, + private toastService: ToastService, + private modalService: NgbModal, + private changeDetectorRef: ChangeDetectorRef, + private documentationService: DocumentationService + ) { + super(elRef.nativeElement, renderer); + this.explorerElement = elRef; + } + explorerElement: ElementRef; + + collapse: boolean = false; + maximized: boolean = false; + + public variants: Variant[] = []; + public displayed_variants: IVariant[] = []; + public colorMap: Map<string, string>; + public sidebarHeight = 0; + + public logStats: LogStats = null; + + public currentlyDisplayedProcessTree; + protected unsubscribe: Subject<void> = new Subject<void>(); + + public correctTreeSyntax = false; + expansionState: Map<string, boolean> = new Map<string, boolean>(); + serviceTimeColorMap: any; + waitingTimeColorMap: any; + + public VM = ViewMode; + + public svgRenderingInProgress: boolean = false; + public variantExplorerOutOfFocus: boolean = false; + + _goldenLayoutHostComponent: GoldenLayoutHostComponent; + _goldenLayout: GoldenLayout; + _subvariantcomponentItemsMap: Map<string, ComponentItem> = new Map< + string, + ComponentItem + >(); + + dropZoneConfig: DropzoneConfig; + public isAscendingOrder: boolean = false; + public sortingFeature: string = 'count'; + queryActive: boolean = false; + showQueryInfo: boolean = false; + + contextMenu_xPos: number = 10; + contextMenu_yPos: number = 10; + contextMenu_element: VariantElement; + contextMenu_variant: VariantElement; + contextMenu_directive: VariantDrawerDirective; + + filterMap: Map<string, VariantFilter> = new Map<string, VariantFilter>(); + + public options: EditorOptions = new EditorOptions(); + + // Exporter + exportVariantSVG = exportVariantDrawer.bind(this); + + public traceInfixSelectionMode: boolean = false; + + @ViewChild('variantExplorer', { static: true }) + variantExplorerDiv: ElementRef<HTMLDivElement>; + + @ViewChild('variantExplorerContainer') + variantExplorerContainer: ElementRef<HTMLDivElement>; + + @ViewChild('tooltipContainer') + tooltipContainer: ElementRef<HTMLDivElement>; + + @ViewChildren(VariantVisualisationComponent) + variantVisualisations: QueryList<VariantVisualisationComponent>; + + public visibleVariantsHeight = 1000; + + public deletedVariants: Variant[][] = []; + + timeUnit = TimeUnit; + + selectedGranularity = TimeUnit.SEC; + + originalOrder = originalOrder; + + public arcs: { [id: number]: Arc[] } = {}; + public arcsMaxValues: MaxValues = { + size: 1, + length: 1, + distance: 1, + }; + public showFilterMenu: boolean = false; + public lastArcsActivitiesFilter = new Set<string>(); + public arcsCache: { [bid: string]: Pair[] } = {}; + public arcsViewMode: ArcsViewMode = ArcsViewMode.INITIAL; + public filterParams: FilterParams = new FilterParams(); + public filtering: boolean; + + deleteVariant = function () { + const bids = this.variantService.variants + .filter((v) => v.variant === this.contextMenu_variant) + .map((v) => v.bid); + + this.variantService.deleteVariants(bids); + }.bind(this); + + contextMenuOptions: Array<ContextMenuItem> = [ + new ContextMenuItem('Delete Variant', 'bi-trash', this.deleteVariant), + ]; + + // stores the sort settings for each cluster + // if no clustering algo is applied we only have the key + // 'unefined' which is the default cluster key + clusterSortSettings: {} = {}; + + public hideRuleContent: boolean[] = []; + public buttonName: any = 'Expand'; + + toggle(index) { + // toggle based on index + this.hideRuleContent[index] = !this.hideRuleContent[index]; + } + + private _destroy$ = new Subject(); + + ngOnInit(): void { + // initialize variables and initial variants + this.init(); + // update variant explorer on log change + this.listenForLogChange(); + // redraw variants on color map change + this.listenForColorMapChange(); + // update view when activity names change + this.listenForCorrectSyntax(); + this.listenForProcessTreeChange(); + this.conformanceCheckingService.connect(); + this.arcDiagramService.connect(); + this.subscribeForConformanceCheckingResults(); + this.subscribeForArcDiagramsComputationsResults(); + this.listenForLogGranularityChange(); + this.listenForLogStatChange(); + this.listenForViewModeChange(); + this.listenForLoopCollapsedVariantsChange(); + + const resizeObserver = new ResizeObserver((entries) => { + if (entries.length === 1) { + const newHeight = entries[0].contentRect.height; + d3.select(this.explorerElement.nativeElement) + .select('.dropdown-menu') + .style('max-height', newHeight.toString() + 'px'); + } + }); + resizeObserver.observe(this.variantExplorerDiv.nativeElement); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + @HostListener('window:keydown.control.q', ['$event']) + onopenComponent(e) { + this.toggleQueryFilterDialog(); + } + + ngAfterViewInit() { + this.polygonDrawingService.setElementRefereneces( + this.variantExplorerContainer, + this.tooltipContainer + ); + + this._goldenLayoutHostComponent = + this.goldenLayoutComponentService.goldenLayoutHostComponent; + this._goldenLayout = this.goldenLayoutComponentService.goldenLayout; + + const variantExplorerItem = this._goldenLayout.findFirstComponentItemById( + VariantExplorerComponent.componentName + ); + + variantExplorerItem.focus(); + + this.variantService.variants$ + .pipe(takeUntil(this._destroy$)) + .subscribe((variants) => { + this.variantService.areVariantLoopsCollapsed = false; + this.variants = variants; + this.displayed_variants = variants.filter((v) => v.isDisplayed); + this.sort(this.sortingFeature); + this.closeAllSubvariantWindows(); + this.redraw_components(); + this.arcsCache = {}; + }); + + this.variantFilterService.variantFilters$.subscribe((filterMap) => { + this.filterMap = filterMap; + + if (filterMap.size > 0) { + const intersectSets = function (a: Set<number>, b: Set<number>) { + const c: Set<number> = new Set<number>(); + a.forEach((v) => b.has(v) && c.add(v)); + return c; + }; + + const filterSet = Array.from(filterMap.values()) + .map((f) => f.bids) + .reduce((a, b) => intersectSets(a, b)); + + this.displayed_variants = this.variants.filter((v) => { + if (filterSet.has(v.bid)) { + v.isDisplayed = true; + return true; + } else { + v.isDisplayed = false; + } + }); + } else { + this.displayed_variants = this.variants; + this.variants.forEach((v) => (v.isDisplayed = true)); + } + + this.updateAllSubvariantWindows(); + this.redraw_components(); + }); + + this.variantPerformanceService.serviceTimeColorMap + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + if (colorMap !== undefined) { + this.serviceTimeColorMap = colorMap; + this.redraw_components(); + } + }); + + this.variantPerformanceService.waitingTimeColorMap + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + if (colorMap !== undefined) { + this.waitingTimeColorMap = colorMap; + this.redraw_components(); + } + }); + } + + private init() { + console.warn('Running Init'); + this.displayed_variants = []; + this.backendService + .resetLogCache() // for now show the sample log again on reload + .pipe(retryWhen((errors) => errors.pipe(delay(500), take(50)))) // backend might need some time to start up + .pipe( + mergeMap(() => + // Time granularity is null because the granularity is determined in the backend + this.backendService.getLogPropsAndUpdateState(null, 'preload') + ), + takeUntil(this._destroy$) + ) + .subscribe((val) => { + this.selectedGranularity = val.timeGranularity; + }); + } + + private listenForProcessTreeChange() { + this.processTreeService.currentDisplayedProcessTree$ + .pipe( + takeUntil(this._destroy$), + filter( + (tree) => !processTreesEqual(tree, this.currentlyDisplayedProcessTree) + ) + ) + .subscribe((tree) => { + this.currentlyDisplayedProcessTree = tree?.copy(); + + this.variants.forEach((variant) => { + if (variant.usedTreeForConformanceChecking) + variant.isConformanceOutdated = !processTreesEqual( + tree, + variant.usedTreeForConformanceChecking + ); + }); + this.redraw_components(); + }); + } + + private listenForCorrectSyntax() { + this.processTreeService.correctTreeSyntax$ + .pipe(takeUntil(this._destroy$)) + .subscribe((res) => { + this.correctTreeSyntax = res; + }); + } + + private listenForColorMapChange() { + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + this.colorMap = colorMap; + this.redraw_components(); + }); + } + + private listenForLogStatChange() { + this.logService.logStatistics$ + .pipe(takeUntil(this._destroy$)) + .subscribe((logStat) => { + this.logStats = logStat; + }); + } + + private listenForLogChange() { + this.logService.loadedEventLog$ + .pipe( + tap(() => { + this.closeAllSubvariantWindows(); + this.variantViewModeService.viewMode = ViewMode.STANDARD; + this.variantService.areVariantLoopsCollapsed = false; + this.variantService.clusteringConfig = null; // reset applied clustering + this.arcsCache = {}; + }) + ) + .pipe(takeUntil(this._destroy$)) + .subscribe(); + } + + private redraw_components() { + if (this.variantVisualisations) { + for (let component of this.variantVisualisations) { + component.variantDrawer.redraw(); + this.renderer.setStyle( + component.arcDiagram.svgHtmlElement.nativeElement, + 'display', + 'none' + ); + this.arcsViewMode = ArcsViewMode.HIDE_ALL; + } + } + } + + subscribeForConformanceCheckingResults(): void { + this.conformanceCheckingService.varResults + .pipe(takeUntil(this._destroy$)) + .subscribe( + (res) => { + if ('error' in res) { + this.variants.forEach((v) => { + v.calculationInProgress = false; + }); + + this.updateAlignmentStatistics(); + this.redraw_components(); + return; + } + + const variant = this.variants.find((v) => v.id == res.id); + variant.calculationInProgress = false; + variant.isTimeouted = res.isTimeout; + variant.isConformanceOutdated = res.isTimeout; + + if (!res.isTimeout) { + variant.alignment = deserialize(res.alignment); + variant.alignment.setExpanded(variant.variant.getExpanded()); + variant.deviations = res.deviations; + variant.usedTreeForConformanceChecking = res.processTree; + } + + this.updateAlignmentStatistics(); + this.variantVisualisations + .find((vv) => vv.id == res.id) + ?.variantDrawer?.redraw(); + }, + (_) => { + this.variants.forEach((v) => { + v.calculationInProgress = false; + }); + + this.updateAlignmentStatistics(); + this.redraw_components(); + } + ); + } + + updateAlignments(): void { + this.variants.forEach((v) => { + this.updateConformanceForVariant(v, 0); + }); + } + + // @ Refactor into Alignment Service + updateAlignmentStatistics(): void { + let numberFittingVariants = 0; + let numberFittingTraces = 0; + + this.variants.forEach((v) => { + if (v.deviations == 0) { + numberFittingVariants++; + numberFittingTraces += v.count; + } + }); + + this.logService.update_log_stats( + numberFittingTraces, + numberFittingVariants + ); + } + + updateConformanceForVariant(variant: IVariant, timeout: number): void { + let underlyingVariants = []; + if (variant instanceof LoopCollapsedVariant) { + underlyingVariants = variant.variants; + } else { + underlyingVariants = [variant]; + } + + underlyingVariants.forEach((v) => { + v.calculationInProgress = true; + v.deviations = undefined; + + const resubscribe = this.conformanceCheckingService.calculateConformance( + v.id, + v.infixType, + this.processTreeService.currentDisplayedProcessTree, + v.variant.serialize(1), + timeout, + AlignmentType.VariantAlignment + ); + + if (resubscribe) { + this.subscribeForConformanceCheckingResults(); + } + }); + } + + updateConformanceForSingleVariantClicked(variant: IVariant): void { + if (variant.isTimeouted) { + this.conformanceCheckingService.showConformanceTimeoutDialog( + variant, + this.updateConformanceForVariant.bind(this) + ); + } else { + this.updateConformanceForVariant(variant, 0); + } + } + + computePerformanceButtonColor = (variant: Variant) => { + let tree; + tree = this.performanceService.variantsTreePerformance.get(variant); + + if (!tree) { + return null; + } + + let selectedScale = this.performanceColorService.selectedColorScale; + const colorScale = this.performanceColorService + .getVariantComparisonColorScale() + .get(tree.id); + if ( + colorScale && + tree.performance?.[selectedScale.performanceIndicator]?.[ + selectedScale.statistic + ] !== undefined + ) { + return colorScale.getColor( + tree.performance[selectedScale.performanceIndicator][ + selectedScale.statistic + ] + ); + } + return '#d3d3d3'; + }; + + removeFilter(filter_name: string) { + this.variantFilterService.removeVariantFilter(filter_name); + } + + handleSelectInfix(variant: Variant) { + this.variantService.addSelectedTraceInfix( + this.variants.filter((v) => v.bid === variant.bid)[0], + this.sortingFeature, + this.isAscendingOrder + ); + } + + discoverInitialModel(): void { + const variants = this.getSelectedVariants(); + + this.backendService + .discoverProcessModelFromConcurrencyVariants(variants) + .pipe(takeUntil(this._destroy$)) + .subscribe((tree) => + this.refreshConformanceIconsAfterModelChange(true, tree) + ); + } + + changeQueryOption(event, option) { + const newOptions: EditorOptions = new EditorOptions(); + Object.entries(this.options).forEach((v) => (newOptions[v[0]] = v[1])); + newOptions[option] = event.target.checked; + + this.options = newOptions; + } + + genSimpleVariants(variant: VariantElement): any { + if (variant instanceof SequenceGroup) { + return variant.elements; + } else if (variant instanceof ParallelGroup) { + } else { + return [variant.asLeafNode().activity]; + } + } + + mapVariantToEventList(variant): any { + return { + events: variant + .flat() + .filter((v) => v[1].toLowerCase() === 'complete') + .map((v) => `${v[0]}`), + }; + } + + selectionChangedForVariant(variant: Variant, isSelected: boolean): void { + variant.isSelected = isSelected; + } + + addSelectedVariantsToModel(): void { + const selectedVariants = this.getSelectedVariants(); + + // TODO we currently distinguish two cases here: 1. outdated conformance and 2. known conformance + // in the future, we want to use caching in the backend and use only a single call from frontend + if (this.isAnyVariantOutdated(selectedVariants)) { + this.addSelectedVariantsToModelForOutdatedConformance(selectedVariants); + return; + } + + this.addSelectedVariantsToModelForGivenConformance(selectedVariants); + } + + handleTreePerformanceClear() { + this.performanceService.hideTreePerformance(); + } + + /** + * Create subvariant tab + * @param clusterId id of the cluster + * @param idx position in the cluster + * @param variant_id id of the variant + */ + createSubVariantView(clusterId, idx, variant_id) { + // find variant by id + let variant = _.find( + this.displayed_variants, + (variant) => variant_id === variant.id + ); + + const currently_maximized = this.maximized; + + const LocationSelectors: LayoutManager.LocationSelector[] = [ + { + typeId: LayoutManager.LocationSelector.TypeId.FocusedStack, + index: undefined, + }, + ]; + + this.cleanUpSubVariantMap(); + + const id = SubvariantExplorerComponent.componentName + variant_id; + + let componentItem = this._subvariantcomponentItemsMap.get(id); + + // Check if the component item reference already is stored and if the item still exists + // Saves on a search by ID + if (componentItem) { + componentItem.focus(); + + // Instantiate a new Subvariant Component for this variant if it did not exist or is closed + } else { + const variantExplorerItem = this._goldenLayout.findFirstComponentItemById( + VariantExplorerComponent.componentName + ); + + variantExplorerItem.focus(); + + const itemConfig: ComponentItemConfig = { + id: id, + type: 'component', + title: 'Sub-Variants for ' + idx + ' (Cluster ' + clusterId + ')', + isClosable: true, + reorderEnabled: true, + componentState: { + variant: variant, + index: idx, + }, + maximised: true, + componentType: SubvariantExplorerComponent.componentName, + }; + + this._goldenLayout.addItemAtLocation(itemConfig, LocationSelectors); + componentItem = this._goldenLayout.findFirstComponentItemById(id); + this._subvariantcomponentItemsMap.set(id, componentItem); + + // Keep the stack maximized + if (currently_maximized) { + const stack = componentItem.container.parent.parent as Stack; + stack.toggleMaximise(); + } + + variantExplorerItem.focus(); + } + } + + /** + * Create subvariant tab + * @param clusterId id of the cluster + * @param idx position in the cluster + * @param variant_id id of the variant + */ + createVariantInfoView(clusterId, idx, variant_id) { + // find variant by id + let variant = _.find( + this.displayed_variants, + (variant) => variant_id === variant.id + ); + const currently_maximized = this.maximized; + const LocationSelectors: LayoutManager.LocationSelector[] = [ + { + typeId: LayoutManager.LocationSelector.TypeId.FocusedStack, + index: undefined, + }, + ]; + this.cleanUpSubVariantMap(); + + const id = VariantInfoExplorerComponent.componentName + variant_id; + + let componentItem = this._subvariantcomponentItemsMap.get(id); + // Check if the component item reference already is stored and if the item still exists + // Saves on a search by ID + if (componentItem) { + componentItem.focus(); + // Instantiate a new Subvariant Component for this variant if it did not exist or is closed + } else { + const variantExplorerItem = this._goldenLayout.findFirstComponentItemById( + VariantExplorerComponent.componentName + ); + variantExplorerItem.focus(); + const itemConfig: ComponentItemConfig = { + id: id, + type: 'component', + title: 'Cases (Var.' + idx + ')', + isClosable: true, + reorderEnabled: true, + componentState: { + variant: variant, + index: idx, + clusterId: clusterId, + variant_id: variant_id, + }, + maximised: true, + componentType: VariantInfoExplorerComponent.componentName, + }; + this._goldenLayout.addItemAtLocation(itemConfig, LocationSelectors); //erroe here + componentItem = this._goldenLayout.findFirstComponentItemById(id); + this._subvariantcomponentItemsMap.set(id, componentItem); + // Keep the stack maximized + if (currently_maximized) { + const stack = componentItem.container.parent.parent as Stack; + stack.toggleMaximise(); + } + + variantExplorerItem.focus(); + } + } + + closeAllSubvariantWindows(): void { + this._subvariantcomponentItemsMap.forEach((value) => { + if ( + value && + this._goldenLayoutHostComponent.getComponentRef(value.container) + ) { + value.close(); + } + }); + + // Reset the Map to empty + this._subvariantcomponentItemsMap = new Map<string, ComponentItem>(); + } + + updateAllSubvariantWindows(): void { + this._subvariantcomponentItemsMap.forEach((value) => { + if (value) { + value.setTitle('Sub-Variant'); + } + }); + + for (let index = 0; index < this.displayed_variants.length; index++) { + const id = + SubvariantExplorerComponent.componentName + + this.displayed_variants[index].id; + let componentItem = this._subvariantcomponentItemsMap.get(id); + if (componentItem) { + componentItem.setTitle('Sub-Variants for ' + (index + 1)); + let c = componentItem.component as SubvariantExplorerComponent; + c.setIndex(index + 1); + } + } + } + + cleanUpSubVariantMap() { + for (let index = 0; index < this.variants.length; index++) { + const id = + SubvariantExplorerComponent.componentName + this.variants[index].id; + const componentItem = this._subvariantcomponentItemsMap.get(id); + if ( + componentItem && + !this._goldenLayoutHostComponent.getComponentRef( + componentItem.container + ) + ) { + this._subvariantcomponentItemsMap.delete(id); + } + } + for (let index = 0; index < this.variants.length; index++) { + const id = + VariantInfoExplorerComponent.componentName + this.variants[index].id; + const componentItem = this._subvariantcomponentItemsMap.get(id); + if ( + componentItem && + !this._goldenLayoutHostComponent.getComponentRef( + componentItem.container + ) + ) { + this._subvariantcomponentItemsMap.delete(id); + } + } + } + + getSelectedVariants(): Variant[] { + return this.variants.filter((v) => v.isSelected); + } + + isAnyVariantOutdated(variants: Variant[]): boolean { + return variants.some((v) => v.isConformanceOutdated); + } + + isConformanceOutdated(): boolean { + return this.isAnyVariantOutdated(this.variants); + } + + isAlignmentCalculationInProgress(): boolean { + return this.variants.some((v) => v.calculationInProgress); + } + + addSelectedVariantsToModelForOutdatedConformance( + selectedVariants: Variant[] + ): void { + this.backendService + .addConcurrencyVariantsToProcessModelForUnknownConformance( + selectedVariants + ) + .pipe(takeUntil(this._destroy$)) + .subscribe((tree) => { + this.refreshConformanceIconsAfterModelChange(false, tree); + }); + } + + addSelectedVariantsToModelForGivenConformance( + selectedVariants: Variant[] + ): void { + const fittingVariants = selectedVariants + .filter((v) => v.deviations == 0) + .map((v) => v); + const variantsToAdd = selectedVariants + .filter((v) => v.deviations > 0) + .map((v) => v); + + this.backendService + .addConcurrencyVariantsToProcessModel(variantsToAdd, fittingVariants) + .pipe(takeUntil(this._destroy$)) + .subscribe((tree) => { + this.refreshConformanceIconsAfterModelChange(false, tree); + }); + } + + refreshConformanceIconsAfterModelChange( + wasInitialDiscovery: boolean, + pt: ProcessTree + ): void { + if (wasInitialDiscovery) { + this.variants.forEach((v) => { + v.deviations = undefined; + v.calculationInProgress = false; + v.usedTreeForConformanceChecking = undefined; + v.isConformanceOutdated = true; + }); + } + + this.getSelectedVariants().forEach((v) => { + v.isAddedFittingVariant = true; + v.deviations = 0; + // Make variant as fitting alignment + v.alignment = v.variant; + v.alignment.updateConformance(1); + v.usedTreeForConformanceChecking = pt; + + v.calculationInProgress = false; + v.isConformanceOutdated = false; + v.isTimeouted = false; + }); + + // redraw if in conformance view + if (this.variantViewModeService.viewMode === ViewMode.CONFORMANCE) + this.getSelectedVariants().forEach((v) => { + this.variantVisualisations + .find((vv) => vv.id == v.id) + .variantDrawer.redraw(); + }); + } + + isAnyVariantSelected(): boolean { + return this.variants.some((v) => v.isSelected); + } + + isNoVariantSelected(): boolean { + return !this.isAnyVariantSelected(); + } + + isInfixSelected(): boolean { + return this.variants.some( + (v) => v.isSelected && v.infixType !== InfixType.NOT_AN_INFIX + ); + } + + areAllDisplayedVariantsSelected(): boolean { + return this.displayed_variants.every((v) => v.isSelected); + } + + unSelectAllChanged(isSelected: boolean): void { + this.displayed_variants.forEach((v) => (v.isSelected = isSelected)); + } + + areAllVariantsExpanded(): boolean { + if ( + this.variantVisualisations === undefined || + (this.variants && this.variants.length < 1) + ) { + return false; + } + + const unexpandedVariantsExist = this.variants.some( + (v) => !v.variant.expanded + ); + return !unexpandedVariantsExist; + } + + expandCollapseAll(): void { + const shouldExpand = !this.areAllVariantsExpanded(); + + this.variantVisualisations.forEach((vv) => { + if ( + this.variantViewModeService.viewMode !== ViewMode.PERFORMANCE && + shouldExpand != vv.variantDrawer.variant.variant.expanded + ) { + vv.variantDrawer.setExpanded(shouldExpand); + vv.variantDrawer.redraw(); + if (vv.arcsViewMode !== ArcsViewMode.HIDE_ALL) { + vv.drawArcs(); + } + } + }); + + // Necessary, because there are only variant drawers for children that are rendered. + // This is often only a subset of variants because of lazy loading. + this.variants.forEach((v) => v.variant.setExpanded(shouldExpand)); + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void { + this.collapse = width < 875; + + this.sidebarHeight = height; + } + + handleVisibilityChange(visibility: boolean): void {} + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void { + this.maximized = logicalZIndex === 'stackMaximised'; + } + + meanPerformance(): string { + let p = this.performanceService.mergedTreePerformance?.performance; + let selectedScale = this.performanceColorService.selectedColorScale; + let pValue = + p[selectedScale.performanceIndicator]?.[selectedScale.statistic]; + return HumanizeDurationPipe.apply(pValue * 1000, { round: true }); + } + + variantPerformanceColor(): string { + let tree = this.performanceService.mergedTreePerformance; + if (!tree) { + return null; + } + let selectedScale = this.performanceColorService.selectedColorScale; + const colorScale = this.performanceColorService + .getVariantComparisonColorScale() + .get(tree.id); + if ( + colorScale && + tree.performance?.[selectedScale.performanceIndicator]?.[ + selectedScale.statistic + ] !== undefined + ) { + return colorScale.getColor( + tree.performance[selectedScale.performanceIndicator][ + selectedScale.statistic + ] + ); + } + return '#d3d3d3'; + } + + textColorForBackgroundColor(): string { + if (this.variantPerformanceColor() === null) { + return 'white'; + } + return textColorForBackgroundColor(this.variantPerformanceColor()); + } + + toggleQueryInfo(event: Event): void { + this.openDocumentation('Variant Querying'); + // this.showQueryInfo = !this.showQueryInfo; + event.stopPropagation(); + } + + openDocumentation(heading: string) { + this.documentationService.showDocumentationDialog(heading); + } + + toggleBlur(event) { + this.variantExplorerOutOfFocus = event; + } + + toggleQueryFilterDialog() { + this.queryActive = !this.queryActive; + } + + filterToggle = true; // true by default (i.e. displayed activities are filtered) + toggleAppliedQueryFilter() { + // toggle the query filter... + if (this.filterToggle) { + this.variantFilterService.variantFilters = this.filterMap; + } else { + this.displayed_variants = this.variants; + this.variants.forEach((v) => (v.isDisplayed = true)); + } + + this.updateAllSubvariantWindows(); + this.redraw_components(); + } + + sort(sortingFeature: string): void { + this.sortingFeature = sortingFeature; + // -1 is the keys of the default cluster (when no clustering was applied) + this.clusterSortSettings[-1] = { + feature: sortingFeature, + isAscendingOrder: this.isAscendingOrder, + }; + this.variantExplorerDiv.nativeElement.scroll(0, 0); + this.updateAllSubvariantWindows(); + // to avoid expression changed after checked error + this.changeDetectorRef.detectChanges(); + + if (this.variantService.clusteringConfig) { + this.sortAllClusters(sortingFeature); + } + } + + onSortOrderChanged(isAscending: boolean): void { + this.isAscendingOrder = isAscending; + this.sort(this.sortingFeature); + } + + toggleTraceInfixSelectionMode(): void { + this.traceInfixSelectionMode = !this.traceInfixSelectionMode; + this.redraw_components(); + } + + onGranularityChange(granularity): void { + if (this.processTreeService.currentDisplayedProcessTree) + this.performanceService.hideTreePerformance(); + + this.selectedGranularity = granularity; + this.backendService + .getLogPropsAndUpdateState(granularity, this.logService.loadedEventLog) + .pipe(takeUntil(this._destroy$)) + .subscribe(); + } + + listenForLogGranularityChange() { + this.logService.logGranularity$ + .pipe(takeUntil(this._destroy$)) + .subscribe((granularity) => { + this.selectedGranularity = granularity; + this.variantService.areVariantLoopsCollapsed = false; + }); + } + + onScroll(): void {} + + executeRemovalActionOnFilteredVariants(removeFiltered: boolean): void { + let bids = []; + let infoText = ''; + if (removeFiltered) { + // remove all filtered variants + bids = this.displayed_variants.map((v) => v.bid); + infoText = 'Removed all filtered variants. Filters are cleared.'; + } else { + // keep only filtered variants + bids = this.variants.filter((v) => !v.isDisplayed).map((v) => v.bid); + infoText = 'Removed all not filtered variants. Filters are cleared.'; + } + + this.variantService.deleteVariants(bids).subscribe(); + + for (let filter of this.filterMap.keys()) { + this.removeFilter(filter); + } + + this.toastService.showSuccessToast( + 'Variants removed', + infoText, + 'bi-trash' + ); + } + + private listenForViewModeChange() { + this.variantViewModeService.viewMode$ + .pipe(takeUntil(this._destroy$)) + .subscribe((viewMode) => { + if (viewMode !== ViewMode.STANDARD && this.traceInfixSelectionMode) + this.toggleTraceInfixSelectionMode(); + }); + } + + private listenForLoopCollapsedVariantsChange() { + this.variantService.collapsedVariants$ + .pipe(takeUntil(this._destroy$)) + .subscribe((variants) => { + if (variants !== null) { + this.traceInfixSelectionMode = false; + this.displayed_variants = variants; + this.sort(this.sortingFeature); + } else { + this.displayed_variants = this.variants; + } + }); + } + + openClusteringSettingsDialog() { + const clusteringModel = this.modalService.open( + ClusteringSettingsDialogComponent, + { + ariaLabelledBy: 'modal-basic-title', + } + ); + + clusteringModel.componentInstance.numberOfVariants = this.variants.length; + } + + handleClusterSort(sortEvent, clusterId) { + this.clusterSortSettings[clusterId] = sortEvent; + this.updateAllSubvariantWindows(); + // detect changes manually to avoid expression changed after checked + this.changeDetectorRef.detectChanges(); + } + + sortAllClusters(sortingFeature: string) { + const numOfClusters = Math.max( + ...this.displayed_variants.map((o) => o.clusterId) + ); + + for (let i = 0; i <= numOfClusters; i++) { + this.clusterSortSettings[i] = { + feature: sortingFeature, + isAscendingOrder: this.isAscendingOrder, + }; + } + + // -1 is the keys of the default cluster (when no clustering was applied) + this.clusterSortSettings[-1] = { + feature: sortingFeature, + isAscendingOrder: this.isAscendingOrder, + }; + } + + calculateTotalTracesInCluster(cluster) { + const count = cluster.reduce((a, b) => +a + +b.count, 0); + return count; + } + + showVariantSequentializerDialog() { + this.variantService.showVariantSequentializerDialog.next(); + } + + handleTreeConformanceClear() { + this.conformanceCheckingService.hideTreeConformance(); + } + + performanceColumnHeader() { + const selectedColorScale = this.performanceColorService.selectedColorScale; + return `${selectedColorScale.performanceIndicator}\n(${selectedColorScale.statistic})`; + } + + setupVariantVisualisationForArcDiagrams( + variantViz: VariantVisualisationComponent, + computedArcs: Pair[] + ) { + const { maxDistance } = variantViz.arcDiagram.parseInput(computedArcs); + this.arcsMaxValues = { + ...this.arcsMaxValues, + distance: Math.max(maxDistance, this.arcsMaxValues.distance), + }; + this.filterParams.distanceRange.options.ceil = Math.max( + this.filterParams.distanceRange.high, + this.arcsMaxValues.distance + ); + this.filterParams.lengthRange.options.ceil = Math.max( + this.filterParams.lengthRange.high, + this.arcsMaxValues.length + ); + this.filterParams.sizeRange.options.ceil = Math.max( + this.filterParams.sizeRange.high, + this.arcsMaxValues.size + ); + + return variantViz; + } + + subscribeForArcDiagramsComputationsResults() { + this.arcDiagramService.arcDiagramsResult + .pipe(takeUntil(this._destroy$)) + .subscribe((res: ArcDiagramComputationResult) => { + this.arcsMaxValues = { + ...this.arcsMaxValues, + size: Math.max(res.maximal_values.size, this.arcsMaxValues.size), + length: Math.max( + res.maximal_values.length, + this.arcsMaxValues.length + ), + }; + for (let [bid, pairs] of Object.entries(res['pairs'])) { + this.arcsCache[bid] = pairs; + const variantViz: VariantVisualisationComponent = + this.variantVisualisations.find( + (vv: VariantVisualisationComponent) => + vv.bid == (bid as unknown as number) + ); + if (variantViz) { + this.setupVariantVisualisationForArcDiagrams( + variantViz, + pairs + ).drawArcs(this.filterParams); + } + } + }); + } + + showSingleArcDiagram(bids: string[] | number[]) { + this.arcsViewMode = ArcsViewMode.SHOW_SOME; + this.computeAndDrawArcDiagram(bids); + } + + computeAndDrawArcDiagram(bids: string[] | number[]) { + let resubscribe = this.arcDiagramService.computeArcDiagrams( + bids, + this.filterParams + ); + if (resubscribe) { + this.subscribeForArcDiagramsComputationsResults(); + } + } + + filterArcDiagrams(filterParams: FilterParams) { + this.filtering = true; + this.filterParams = _.cloneDeep(filterParams); + this.computeAndDrawArcDiagram(Object.keys(this.arcsCache)); + this.lastArcsActivitiesFilter = new Set( + filterParams.activitiesSelection.selectedItems + ); + } + + newActivitiesLoaded(newActivities: Set<string>) { + this.lastArcsActivitiesFilter = new Set(newActivities); + } + + toggleArcsVisibility() { + if ( + this.arcsViewMode == ArcsViewMode.SHOW_ALL || + this.arcsViewMode == ArcsViewMode.SHOW_SOME + ) { + this.arcsViewMode = ArcsViewMode.HIDE_ALL; + this.variantVisualisations.forEach((vv) => + this.renderer.setStyle( + vv.arcDiagram.svgHtmlElement.nativeElement, + 'display', + 'none' + ) + ); + } else { + this.arcsViewMode = ArcsViewMode.SHOW_ALL; + + const paramsObs = from( + Array(Math.ceil(this.variants.length / 30)) + .fill(0) + .map((_, idx) => + this.variants.slice(30 * idx, 30 * (idx + 1)).map((v) => v.bid) + ) + ); + + paramsObs + .pipe( + takeUntil(this._destroy$), + concatMap(async (param) => this.computeAndDrawArcDiagram(param)) + ) + .subscribe(); + } + } + + protected readonly ArcsViewMode = ArcsViewMode; +} + +export namespace VariantExplorerComponent { + export const componentName = 'VariantExplorerComponent'; +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-info-explorer/variant-info-explorer.component.css b/src/frontend/src/app/components/variant-explorer/variant-info-explorer/variant-info-explorer.component.css new file mode 100644 index 0000000000000000000000000000000000000000..5a252e053a12472fd87262e9d09e3d1930c0ac10 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-info-explorer/variant-info-explorer.component.css @@ -0,0 +1,114 @@ +.main-variant-explorer { + overflow: auto; + background-color: var(--box-background-color); +} + +.chart-variant-percentage { + margin-left: 4px; + display: inline-flex; + flex-direction: column; + + /* + min-width: 50px; + */ + font-size: .8rem; + color: whitesmoke; + color: var(--text-secondary); +} + +:host { + position: absolute; + overflow: hidden; +} + +.variant-info-cell { + align-items: center; + display: flex; +} + +.btn-tool-bar{ + min-height: 28px; + display: flex; + align-items: center; + border-top: 0; + position: sticky; + top: 0; + left: 0; +} + +.variant-cell { + width: 100%; +} + +.variant { + padding: 5px; + width: fit-content; + cursor: pointer; +} + +.svg-rendering-status { + color: var(--text-secondary); +} + + +/* Move all below to central place - also used in variant explorer */ + +.container-variant-explorer { + min-height: 100%; + width: calc(100% - 20px); + position: relative; + border-left: 1px solid var(--thin-border-color); + margin-left: 20px; +} + +.activity-overview-container { +background-color: var(--box-background-color); +} + +.table-font{ +font-size: small; +} + +.resizeable-header-element{ +padding : 0.2rem; +} + +.table-header-sort-group{ +display: flex; +flex-direction: column; +align-items: center; +} + +.table-container { +overflow: auto auto; +background-color: var(--box-background-color); +} + +.toggle-select{ +cursor : pointer; +} + +thead th { +vertical-align: top; +} + +thead tr:nth-child(1) th { +position: static; +top: 0; +z-index: 10; +} + +tbody tr { +padding-bottom: .25rem; +padding-top: .25rem; +} + +.border-color { +border-color: var(--line-color)!important; +} + +.activity-overview-table-header { +position: sticky; +top: 0; +z-index: auto; +} \ No newline at end of file diff --git a/src/frontend/src/app/components/variant-explorer/variant-info-explorer/variant-info-explorer.component.html b/src/frontend/src/app/components/variant-explorer/variant-info-explorer/variant-info-explorer.component.html new file mode 100644 index 0000000000000000000000000000000000000000..2ddc958e7f9ccd16d1028f13f749b5bac77f2a56 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-info-explorer/variant-info-explorer.component.html @@ -0,0 +1,151 @@ +<app-performance-progress-bar></app-performance-progress-bar> + +<app-variant-explorer-sidebar></app-variant-explorer-sidebar> + +<div class="d-flex flex-column mh-100 h-100 container-variant-explorer"> + <div class="table-container flex-grow-1 table-responsive"> + <table + class="table table-sm table-font table-hover table-striped table-borderless table-dark mb-0" + *ngIf="mainVariant" + > + <thead class="activity-overview-table-header"> + <tr class="user-select-none"> + <th + resizeable + scope="col" + class="bg-dark text-center toggle-select resizeable-header-element" + (click)="toggleSort('case_id')" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + ngbTooltip="Unique ID of the case" + triggers="hover" + > + <div class="user-select-none mx-1">Case ID</div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-alpha-down': !ascending, + 'bi-sort-alpha-down-alt': ascending, + invisible: sortKey !== 'case_id' + }" + ></i> + </div> + </th> + <th + resizeable + scope="col" + class="bg-dark text-center toggle-select resizeable-header-element" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + ngbTooltip="Number of activity occurrences in the case" + triggers="hover" + > + <div class="user-select-none mx-1">Number of activities</div> + </div> + </th> + <th + resizeable + scope="col" + class="bg-dark text-center toggle-select resizeable-header-element" + (click)="toggleSort('earliest_time')" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + ngbTooltip="The earliest timestamp recorded in the case" + triggers="hover" + > + <div class="user-select-none mx-1">Earliest timestamp</div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-numeric-down': !ascending, + 'bi-sort-numeric-down-alt': ascending, + invisible: sortKey !== 'earliest_time' + }" + ></i> + </div> + </th> + <th + resizeable + scope="col" + class="bg-dark text-center toggle-select resizeable-header-element" + (click)="toggleSort('latest_time')" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + ngbTooltip="The latest timestamp recorded in the case" + triggers="hover" + > + <div class="user-select-none mx-1">Latest timestamp</div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-numeric-down': !ascending, + 'bi-sort-numeric-down-alt': ascending, + invisible: sortKey !== 'latest_time' + }" + ></i> + </div> + </th> + <th + resizeable + scope="col" + class="bg-dark text-center toggle-select resizeable-header-element" + (click)="toggleSort('total_duration')" + [margin]="-7" + > + <div + class="d-flex flex-row justify-content-center table-header-sort-group" + ngbTooltip="Duration of the case" + triggers="hover" + > + <div class="user-select-none mx-1">Total duration</div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-numeric-down': !ascending, + 'bi-sort-numeric-down-alt': ascending, + invisible: sortKey !== 'total_duration' + }" + ></i> + </div> + </th> + </tr> + </thead> + + <tbody> + <ng-container *ngIf="caseStatistics"> + <tr + *ngFor=" + let case of caseStatistics | tableSorting : sortKey : ascending + " + class="cursor-pointer" + (click)="createCaseInfoView(case.case_id)" + > + <td class="text-center user-select-none"> + {{ case.case_id }} + </td> + <td class="text-center user-select-none"> + {{ case.activity_num }} + </td> + <td class="text-center user-select-none"> + {{ case.earliest_time }} + </td> + <td class="text-center user-select-none"> + {{ case.latest_time }} + </td> + <td class="text-center user-select-none"> + {{ case.total_duration }} + </td> + </tr> + </ng-container> + </tbody> + </table> + </div> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/variant-info-explorer/variant-info-explorer.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant-info-explorer/variant-info-explorer.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..68845c371a8a25daac4b23fa55972f9d244e56b0 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-info-explorer/variant-info-explorer.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantInfoExplorerComponent } from './variant-info-explorer.component'; + +describe('VariantInfoExplorerComponent', () => { + let component: VariantInfoExplorerComponent; + let fixture: ComponentFixture<VariantInfoExplorerComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantInfoExplorerComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(VariantInfoExplorerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant-info-explorer/variant-info-explorer.component.ts b/src/frontend/src/app/components/variant-explorer/variant-info-explorer/variant-info-explorer.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..1848dae13f340c8c82dfc048a5a2ca22b0719e49 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-info-explorer/variant-info-explorer.component.ts @@ -0,0 +1,413 @@ +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { LogService } from 'src/app/services/logService/log.service'; +import { + Component, + EventEmitter, + OnInit, + ElementRef, + Inject, + Renderer2, + AfterViewInit, + ChangeDetectorRef, + OnDestroy, + Output, +} from '@angular/core'; +import { + ComponentContainer, + ComponentItem, + ComponentItemConfig, + GoldenLayout, + LayoutManager, + LogicalZIndex, + Stack, +} from 'golden-layout'; +import { GoldenLayoutHostComponent } from 'src/app/components/golden-layout-host/golden-layout-host.component'; +import { GoldenLayoutComponentService } from 'src/app/services/goldenLayoutService/golden-layout-component.service'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; +import { DropzoneConfig } from 'src/app/components/drop-zone/drop-zone.component'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { BackendService } from 'src/app/services/backendService/backend.service'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { VariantPerformanceService } from 'src/app/services/variant-performance.service'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { IVariant } from 'src/app/objects/Variants/variant_interface'; +import { LoopCollapsedVariant } from 'src/app/objects/Variants/loop_collapsed_variant'; +import { Dictionary } from 'lodash'; +import { CaseExplorerComponent } from '../case-explorer/case-explorer.component'; +import { SubvariantExplorerComponent } from '../subvariant-explorer/subvariant-explorer.component'; +import _ from 'lodash'; + +@Component({ + selector: 'app-variant-info-explorer', + templateUrl: './variant-info-explorer.component.html', + styleUrls: ['./variant-info-explorer.component.css'], +}) +export class VariantInfoExplorerComponent + extends LayoutChangeDirective + implements OnInit, AfterViewInit, OnDestroy +{ + @Output() + mainVariant: Variant; + index: number; + constructor( + private colorMapService: ColorMapService, + private logService: LogService, + private variantService: VariantService, + private processTreeService: ProcessTreeService, + private backendService: BackendService, + private ref: ChangeDetectorRef, + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef, + renderer: Renderer2, + private variantPerformanceService: VariantPerformanceService, + private goldenLayoutComponentService: GoldenLayoutComponentService + ) { + super(elRef.nativeElement, renderer); + let state = this.container.initialState; + this.mainVariant = state['variant'] as IVariant; + this.index = state['index'] as number; + } + + public variants: Variant[] = []; + public displayed_variants: IVariant[] = []; //delete later + + activityColorMap: Map<string, string>; + activitiesInTree: Set<string> = new Set<string>(); + startActivities: Set<string>; + endActivities: Set<string>; + activitiesInLog: any; + activityFields: ActivityField[]; + caseStatistics: Map<string, number>[]; + + sortKey: string = 'case_id'; + ascending: boolean = false; + + maximized: boolean = false; + + activityOverviewOutOfFocus: boolean = false; + + dropZoneConfig: DropzoneConfig; + + resetAvailable: boolean = false; + + private _destroy$ = new Subject(); + + _goldenLayoutHostComponent: GoldenLayoutHostComponent; + _goldenLayout: GoldenLayout; + _subvariantcomponentItemsMap: Map<string, ComponentItem> = new Map< + string, + ComponentItem + >(); + + ngOnInit(): void { + this.dropZoneConfig = new DropzoneConfig( + '.xes', + 'false', + 'false', + '<large> Import <strong>Event Log</strong> .xes file</large>' + ); + + this.activityFields = []; + + this.backendService + .calculateCaseStatistics(this.index - 1) + .subscribe((caseStatistics: Map<string, number>[]) => { + this.caseStatistics = caseStatistics['statistics']; + }); + + this.variantService.cachedChange$ + .pipe(takeUntil(this._destroy$)) + .subscribe((change) => { + this.resetAvailable = change; + }); + } + + ngAfterViewInit(): void { + this._goldenLayoutHostComponent = + this.goldenLayoutComponentService.goldenLayoutHostComponent; + this._goldenLayout = this.goldenLayoutComponentService.goldenLayout; + + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + this.activityColorMap = colorMap; + + if (this.activityFields) { + for (let activityField of this.activityFields) { + activityField.color = this.activityColorMap.get( + activityField.activityName + ); + } + } + }); + + // Handle change of current activies in the loaded model + this.processTreeService.activitiesInCurrentTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((activitiesInTree) => { + for (let field of this.activityFields) { + field.inModel = activitiesInTree.has(field.activityName); + } + }); + + this.variantService.variants$ + .pipe(takeUntil(this._destroy$)) + .subscribe(() => { + if (this.activityColorMap) { + this.resetActivityFields(); + } + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + resetActivityFields() { + this.startActivities = this.logService.startActivitiesInEventLog; + this.endActivities = this.logService.endActivitiesInEventLog; + this.activitiesInLog = this.logService.activitiesInEventLog; + this.activitiesInTree = this.processTreeService.activitiesInCurrentTree; + + this.activityFields = []; + for (let activity in this.activitiesInLog) { + this.activityFields.push( + new ActivityField( + activity, + this.activitiesInLog[activity], + this.activityColorMap.get(activity), + this.activitiesInTree.has(activity), + this.startActivities.has(activity), + this.endActivities.has(activity) + ) + ); + } + } + + toggleBlur(event) { + this.activityOverviewOutOfFocus = event; + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + + handleVisibilityChange(visibility: boolean): void {} + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void { + this.maximized = logicalZIndex === 'stackMaximised'; + } + + toggleSort(sortKey: string) { + // On the first Click always make descending + if (this.sortKey != sortKey) { + this.sortKey = sortKey; + this.ascending = false; + } else { + // Make it toggle between on subsequent clicks + this.ascending = !this.ascending; + } + } + + deleteActivity(e: Event, activity: ActivityField) { + this.variantService.deleteActivity(activity.activityName).subscribe(); + this.variantPerformanceService.resetVariantPerformance(); + this.resetActivityFields(); + } + + changeActivityColor(activityField: ActivityField, color: string) { + if (color) { + activityField.color = color; + this.colorMapService.changeActivityColor( + activityField.activityName, + color + ); + } + } + + resetActivityColors(): void { + this.colorMapService.createColorMap( + Array.from(this.activityColorMap.keys()) + ); + } + + resetActivityNames(): void { + if (this.activityFields) { + for (let activityField of this.activityFields) { + activityField.inputActivityName = activityField.activityName; + } + } + } + + // TODO: refactor this to shared data service + applyActivityNameChanges( + oldActivityName: string, + newActivityName: string + ): void { + if (oldActivityName !== newActivityName) { + this.variantService + .renameActivity(oldActivityName, newActivityName) + .subscribe(); + // Changing activity field table + this.resetActivityFields(); + } + } + + revertLastChange(e: Event) { + e.stopPropagation(); + this.resetAvailable = false; + this.variantService.revertChangeInBackend(); + } + + // + createCaseInfoView(case_id) { + const state = this.container.getState(); + + // find variant by id + let variant = state['variant']; + + const currently_maximized = this.maximized; + const LocationSelectors: LayoutManager.LocationSelector[] = [ + { + typeId: LayoutManager.LocationSelector.TypeId.FocusedStack, + index: undefined, + }, + ]; + + this.cleanUpSubVariantMap(); + + const id = + CaseExplorerComponent.componentName + state['variant_id'] + case_id; + + let componentItem = this._subvariantcomponentItemsMap.get(id); + + // Check if the component item reference already is stored and if the item still exists + // Saves on a search by ID + if (componentItem) { + componentItem.focus(); + + // Instantiate a new Subvariant Component for this variant if it did not exist or is closed + } else { + const subvariantInfoExplorerItem = + this._goldenLayout.findFirstComponentItemById( + VariantInfoExplorerComponent.componentName + state['variant_id'] + ); + + subvariantInfoExplorerItem.focus(); + + const itemConfig: ComponentItemConfig = { + id: id, + type: 'component', + title: 'Case ' + case_id + ' (Var. ' + state['index'] + ')', + isClosable: true, + reorderEnabled: true, + componentState: { + variant: variant, + index: state['index'], + clusterId: state['clusterId'], + variant_id: state['variant_id'], + case_id: case_id, + }, + maximised: true, + componentType: CaseExplorerComponent.componentName, + }; + + this._goldenLayout.addItemAtLocation(itemConfig, LocationSelectors); + componentItem = this._goldenLayout.findFirstComponentItemById(id); + this._subvariantcomponentItemsMap.set(id, componentItem); + + // Keep the stack maximized + if (currently_maximized) { + const stack = componentItem.container.parent.parent as Stack; + stack.toggleMaximise(); + } + + subvariantInfoExplorerItem.focus(); + } + } + + cleanUpSubVariantMap() { + const state = this.container.getState(); + for (let index = 0; index < this.variants.length; index++) { + const id = + SubvariantExplorerComponent.componentName + this.variants[index].id; + const componentItem = this._subvariantcomponentItemsMap.get(id); + if ( + componentItem && + !this._goldenLayoutHostComponent.getComponentRef( + componentItem.container + ) + ) { + this._subvariantcomponentItemsMap.delete(id); + } + } + for (let index = 0; index < this.variants.length; index++) { + const id = + VariantInfoExplorerComponent.componentName + this.variants[index].id; + const componentItem = this._subvariantcomponentItemsMap.get(id); + if ( + componentItem && + !this._goldenLayoutHostComponent.getComponentRef( + componentItem.container + ) + ) { + this._subvariantcomponentItemsMap.delete(id); + } + } + for (let caseInfo of this.caseStatistics) { + const id = + CaseExplorerComponent.componentName + + state['variant_id'] + + caseInfo['case_id']; + const componentItem = this._subvariantcomponentItemsMap.get(id); + if ( + componentItem && + !this._goldenLayoutHostComponent.getComponentRef( + componentItem.container + ) + ) { + this._subvariantcomponentItemsMap.delete(id); + } + } + } +} + +export class ActivityField { + activityName: string; + occurences: number; + inModel: boolean; + isStart: boolean; + isEnd: boolean; + color: string; + inputActivityName: string; // Storing the input name from user + + constructor( + activityName: string, + occurences: number, + color: string, + inModel: boolean, + isStart: boolean, + isEnd: boolean + ) { + this.activityName = activityName; + this.occurences = occurences; + this.inModel = inModel; + this.isStart = isStart; + this.isEnd = isEnd; + this.color = color; + this.inputActivityName = activityName; + } +} + +export namespace VariantInfoExplorerComponent { + export const componentName = 'VariantInfoExplorerComponent'; +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component.html b/src/frontend/src/app/components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component.html new file mode 100644 index 0000000000000000000000000000000000000000..5cab3d87bddf6002c604bcf0945ecf2d69724939 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component.html @@ -0,0 +1,417 @@ +<div *ngIf="showInfo" @flyInDiv class="variant-query-info user-select-none"> + <div class="variant-query-info-container"> + <div class="variant-query-info-header"> + <button class="button button-heading" (click)="requestClose()"> + <i class="bi bi-x-lg"></i> + </button> + + <h5>Variant Query Language</h5> + </div> + + <div class="variant-query-info-content" ngNonBindable> + <div class="my-3"></div> + <hr /> + A valid <b>Query</b> is made up of <b>Activities</b> and <b>Operators</b>, + which together form expressions that can be linked by logical operators to + form more complex queries. For syntactic reasons, every query ends with a + semicolon ; . Operators come either as unary or binary operators, which + express the relationships between a single or multiple activities and the + variant. As an example for a unary operator, the following is a query made + from a single unary expression that checks if the activity '<span + class="activity" + >A</span + >' is an event happening in the variant. + + <div class="example-text"> + '<span class="activity">A</span>' + <span class="logical-operator">isContained</span>; + </div> + + Similarly, a query from a binary expression that checks if every '<span + class="activity" + >A</span + >' activity in the variant is followed by a '<span class="activity" + >B</span + >' activity, can be written as: + + <div class="example-text"> + '<span class="activity">A</span>' + <span class="logical-operator">isDF</span> '<span class="activity" + >B</span + >'; + </div> + + <hr /> + <div class="my-3"></div> + <table class="table table-dark"> + <thead> + <tr> + <th>Activities</th> + <th>Meaning</th> + </tr> + </thead> + <tbody> + <tr> + <td>'<span class="activity">Activity</span>'</td> + <td>Activity names are written in apostrophes</td> + </tr> + <tr> + <td> + <span style="white-space: nowrap" + ><span class="logical-operator fw-bold">ANY</span> { '<span + class="activity" + >A</span + >', '<span class="activity">B</span>' }</span + > + </td> + <td> + Evalutated in an expression, returns True if any activity for the + operator returns True + </td> + </tr> + <tr> + <td> + <span class="logical-operator fw-bold">ALL</span> { '<span + class="activity" + >A</span + >', '<span class="activity">B</span>' } + </td> + <td> + Evalutated in an expression, returns True if all activities for + the operator returns True + </td> + </tr> + <tr> + <td><b>~</b></td> + <td> + Written in front of a group; it represents the group consisting of + all activites besides the activites in the brackets + </td> + </tr> + </tbody> + </table> + <div class="my-3"></div> + <hr /> + <div> + Groups can be used both in unary and binary operators to replace single + activities. However, this is restricted to only one side of a binary + expression. In case of binary expressions, if the group is located on + the left-side of the expression, it is evaluated by simply checking for + every member of the group and the right-hand side, if the expression + would be fulfilled. The case of a right-hand side group will be covered + below. + </div> + <hr /> + <div class="my-3"></div> + <table class="table table-dark"> + <thead> + <tr> + <th>Unary Operator</th> + <th>Meaning</th> + </tr> + </thead> + <tbody> + <tr> + <td> + <span class="logical-operator"><b>isS</b>tart</span> + </td> + <td>Returns True if the activity is a start activity</td> + </tr> + <tr> + <td> + <span class="logical-operator"><b>isE</b>nd</span> + </td> + <td>Returns True if the activity is an end activity</td> + </tr> + <tr> + <td> + <span class="logical-operator"><b>isC</b>ontained</span> + </td> + <td> + Returns True if the activity is contained inside the variant + </td> + </tr> + </tbody> + </table> + <div class="my-3"></div> + <hr /> + Unary operators express the relationship between a single activity and the + variant. The following query evaluates to True if '<span class="activity" + >A</span + >' is a start activity of the variant. Note that it is not necessarily a + unique start activity. + + <div class="example-text"> + '<span class="activity">A</span>' + <span class="logical-operator">isStart</span>; + </div> + + For convenience, instead of writing out the full operator name for unary + and binary operators, the letters in bold can be used as a shorthand; + thus, we can write for example '<span class="activity">A</span>' + <span class="logical-operator">isC</span> instead of '<span + class="activity" + >A</span + >' <span class="logical-operator">isContained</span>. + <hr /> + <div class="my-3"></div> + + <table class="table table-dark"> + <thead> + <tr> + <th>Binary Operator</th> + <th>Meaning</th> + </tr> + </thead> + <tbody> + <tr> + <td> + <span class="logical-operator" + ><b>isD</b>irectly<b>F</b>ollowed</span + > + </td> + <td> + Returns True if the right-hand activity always directly-follows + the left-hand activity + </td> + </tr> + <tr> + <td> + <span class="logical-operator" + ><b>isE</b>ventually<b>F</b>ollowed</span + > + </td> + <td> + Returns True if the right-hand activity always follows the + left-hand activity + </td> + </tr> + <tr> + <td> + <span class="logical-operator"><b>isP</b>arallel</span> + </td> + <td> + Returns True if the right-hand activity always happens parallel to + the left-hand activity + </td> + </tr> + </tbody> + </table> + <div class="my-3"></div> + <hr /> + + Binary Operators express the relationship between activities in a variant. + For example, '<span class="activity">A</span>' + <span class="logical-operator">isConcurrent</span> '<span class="activity" + >B</span + >' is fulfilled, if every occurence of '<span class="activity">A</span>' + happens concurrently to a '<span class="activity">B</span>' activity. To + add further expressive power, groups can be used on the right-hand side of + an binary expression to capture some deeper relations. That is the query + + <div class="example-text"> + '<span class="activity">A</span>' + <span class="logical-operator">isDF </span> + + <span class="logical-operator">ANY</span> { '<span class="activity" + >B</span + >', '<span class="activity">C</span>'}; + </div> + + is fulfilled, if every '<span class="activity">A</span>' activity is + directly followed by an '<span class="activity">B</span>' or '<span + class="activity" + >C</span + >' activity. This is different to the interpretation of every '<span + class="activity" + >A</span + >' needing to be followed by a '<span class="activity">B</span>' or every + '<span class="activity">A</span>' being followed by a '<span + class="activity" + >C</span + >'. + <hr /> + <div class="my-3"></div> + + <table class="table table-dark"> + <thead> + <tr> + <th>Quantifiers</th> + <th>Meaning</th> + </tr> + </thead> + <tbody> + <tr> + <td>> NUMBER</td> + <td> + Returns True if the preceding expression is appears more than + NUMBER of times + </td> + </tr> + <tr> + <td>= NUMBER</td> + <td> + Returns True if the preceding expression is appears exactly NUMBER + times + </td> + </tr> + <tr> + <td>< NUMBER</td> + <td> + Returns True if the preceding expression is appears less than + NUMBER of times + </td> + </tr> + </tbody> + </table> + <div class="my-3"></div> + + <div class="my-3"></div> + <hr /> + <div> + Quantifiers can be used to check for the frequency of relations. Instead + of checking if '<span class="activity">A</span>' is just contained any + number of times, + + <div class="example-text"> + '<span class="activity">A</span>' + <span class="logical-operator">isContained</span> + > 2 + </div> + + will only return True, if '<span class="activity">A</span>' appears at + least 3 times in the variant. For binary expressions, this works + similarly, thus '<span class="activity">A</span>' + <span class="logical-operator">isDF </span> '<span class="activity" + >B</span + >' = 2, will return True if '<span class="activity">A</span>' is + directly-followed 2 times by '<span class="activity">B</span>' in the + variant. Some attention needs to be payed when using Quantifiers in + conjunction with Groups, as the right-hand side rules also apply here. + Thus, + <div class="example-text"> + '<span class="activity">A</span>' + <span class="logical-operator">isDF </span> + <span class="logical-operator">ALL</span> { '<span + class="activity" + >B</span + >', '<span class="activity">C</span>'} > 1 + </div> + + will only be evaluated as True if at least two A activities are followed + by both a '<span class="activity">B</span>' and a '<span + class="activity" + >C</span + >' activity. + </div> + <hr /> + <div class="my-3"></div> + + <table class="table table-dark"> + <thead> + <tr> + <th>Logic Operator</th> + <th>Meaning</th> + </tr> + </thead> + <tbody> + <tr> + <td><span class="logical-operator fw-bold">AND</span></td> + <td>Returns True if all of the expressions are True</td> + </tr> + <tr> + <td><span class="logical-operator fw-bold">OR</span></td> + <td>Returns True if any of the expressions is True</td> + </tr> + <tr> + <td><span class="logical-operator fw-bold">NOT</span></td> + <td> + Returns True if the content of the following expression is False + </td> + </tr> + </tbody> + </table> + <div class="my-3"></div> + <hr /> + <br /> + Different unary and binary expressions can be linked using logical + operators to build complex queries. If we for example want to select all + variants in which activity '<span class="activity">A</span>' is either + directly followed by activity '<span class="activity">B</span>' or + eventually followed by activity '<span class="activity">E</span>', we can + write the following query: + + <div class="example-text"> + '<span class="activity">A</span>' + <span class="logical-operator fw-bold">isDF</span> '<span + class="activity" + >B</span + >' <span class="logical-operator fw-bold">OR</span> '<span + class="activity" + >A</span + >' <span class="logical-operator fw-bold">isEF</span> '<span + class="activity" + >E</span + >'; + </div> + + When linking multiple expressions, + <span class="logical-operator fw-bold">AND</span> and + <span class="logical-operator fw-bold">OR</span> operators linking + expressions can be nested inside each other by using + <b> ( ) </b>parenthesis. We can use this to expand our previous example by + requiring that now every '<span class="activity">A</span>' activity needs + to be followed by an '<span class="activity">E</span>' activity and that + every '<span class="activity">E</span>' needs to be followed by an '<span + class="activity" + >F</span + >' activity: + <div class="example-text"> + '<span class="activity">A</span>' + <span class="logical-operator fw-bold">isDF</span> '<span + class="activity" + >B</span + >' <span class="logical-operator fw-bold">OR</span> ('<span + class="activity" + >A</span + >' <span class="logical-operator fw-bold">isEF</span> '<span + class="activity" + >E</span + >' <span class="logical-operator fw-bold">AND</span> '<span + class="activity" + >E</span + >' <span class="logical-operator fw-bold">isEF</span> '<span + class="activity" + >F</span + >' ); + </div> + + Multiple instances of the same operator on the same level can be linked + without the need of parenthesis. + <span class="logical-operator fw-bold">NOT</span> can be used to negate + the expression written after it in <b> ( ) </b>. As an example, if we want + to get all variants that have '<span class="activity">B</span>' as the + unique and only start actvitiy, we can write the following query: + <div class="example-text"> + '<span class="activity">B</span>' + <span class="logical-operator fw-bold">isStart </span> + <span class="logical-operator fw-bold">AND </span> + <span class="logical-operator fw-bold">NOT </span> ( ~ + <span class="logical-operator fw-bold">ANY</span> { '<span + class="activity" + >B</span + >'} <span class="logical-operator fw-bold">isStart</span> ); + </div> + + The first term checks if '<span class="activity">B</span>' is a start + activity, while the second expression would be fulfilled if any activity + that is not '<span class="activity">B</span>' would be a start activity. + Now, as we negate it, the expression can only be true if '<span + class="activity" + >B</span + >' is a start activity and no other activity is a start activity. + </div> + <hr /> + <div class="my-3"></div> + </div> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component.scss b/src/frontend/src/app/components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..b107d067e3b2fc1c0e59337c5aba40258af66459 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component.scss @@ -0,0 +1,57 @@ +.variant-query-info-container{ + width : 100%; + height : 100%; + background-color: black; + overflow: auto; + padding: 10px 0; + color: var(--text-secondary); +} + +.variant-query-info{ + margin-top: 25px; + position: fixed; + top: 0; + left: 65%; + height: calc(100vh - 45px); + z-index: 100; +} + + +.variant-query-info-header{ + padding: 5px 20px; + border-bottom:grey solid 2px; + width : 100%; + display: flex; + justify-content: flex-start; + flex-direction: row; + align-items: baseline; +} + +.variant-query-info-content{ + padding: 0 20px; +} + +.logical-operator{ + color :rgb(65 141 213); + padding: none; + inline-size: 12px; + user-select: text; +} + +.example-text { + text-align: center; + font-weight: bold; + user-select: text; + margin: 5px; +} + +.activity{ + color : green; + padding: none; + inline-size: 12px; +} + +tbody tr { + padding-bottom: .25rem; + padding-top: .25rem; +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..315b1cd63162e5fae0940cf96cb98c1d62e8ec27 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantQueryInfoComponent } from './variant-query-info.component'; + +describe('VariantQueryInfoComponent', () => { + let component: VariantQueryInfoComponent; + let fixture: ComponentFixture<VariantQueryInfoComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantQueryInfoComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantQueryInfoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component.ts b/src/frontend/src/app/components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..f985d10e392c3c77be3f186320cac59181f109ba --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-query/query-info/variant-query-info/variant-query-info.component.ts @@ -0,0 +1,20 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { flyInComponent } from 'src/app/animations/component-animations'; + +@Component({ + selector: 'app-variant-query-info', + templateUrl: './variant-query-info.component.html', + styleUrls: ['./variant-query-info.component.scss'], + animations: [flyInComponent], +}) +export class VariantQueryInfoComponent { + constructor() {} + + @Input() showInfo: boolean; + @Output() showInfoChange = new EventEmitter<boolean>(); + + public requestClose() { + this.showInfo = false; + this.showInfoChange.emit(false); + } +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-query/variant-query.component.html b/src/frontend/src/app/components/variant-explorer/variant-query/variant-query.component.html new file mode 100644 index 0000000000000000000000000000000000000000..b3623a60e1baf1ab99b046940dddfbedd39fbe0c --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-query/variant-query.component.html @@ -0,0 +1,84 @@ +<div class="query-container"> + <form [formGroup]="variantQueryInput" (ngSubmit)="onSubmit()" class="form d-flex flex-column"> + <div class="form-container"> + <app-editor-zone + (editor)="onEditorChange($event)" + [formControl]="variantQuery" + ></app-editor-zone> + </div> + + <div class="syntax-error-container"> + <ul + *ngIf=" + (!variantQuery.valid && + (variantQuery.dirty || variantQuery.touched)) || + backendErrorMessage + " + class="syntax-error" + > + <div *ngIf="variantQuery.errors?.['monaco']"> + <li *ngFor="let parserError of variantQuery.errors?.['monaco'].value"> + Error {{ parserError }} + </li> + </div> + <li *ngIf="variantQuery.errors?.['backendError']" class="backend-error"> + <span> {{ variantQuery.errors?.['backendError'] }} </span> + </li> + </ul> + </div> + <div class="variant-query-tool-bar" *ngIf="active"> + <button + type="submit" + class="button" + [disabled]="!active || variantQuery.invalid" + > + <i class="bi bi-funnel"></i> Execute Query + </button> + + <button + *ngIf="queryfilteractive" + type="button" + class="button" + [disabled]="!active" + (click)="resetQuery()" + > + <i class="bi bi-x-lg text-danger"></i> Remove query filter + </button> + + <div class="dropdown" *ngIf="queryfilteractive"> + <button + class="button dropdown-toggle" + type="button" + id="filterRemovalDropdown" + data-bs-toggle="dropdown" + aria-expanded="false" + > + <i class="bi bi-trash text-danger"></i> Delete variants by query + </button> + + <ul + class="dropdown-menu custom-dropdown" + aria-labelledby="filterRemovalDropdown" + > + <li> + <button + (click)="executeRemovalActionOnFilteredVariants(true)" + class="dropdown-item" + > + remove variants satisfying the current query (visible variants) + </button> + </li> + <li> + <button + (click)="executeRemovalActionOnFilteredVariants(false)" + class="dropdown-item" + > + remove variants non-satisfying the current query (filtered + variants) + </button> + </li> + </ul> + </div> + </div> + </form> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/variant-query/variant-query.component.scss b/src/frontend/src/app/components/variant-explorer/variant-query/variant-query.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..4d1d92ff2acc2ca1b76345a32ed949b0fbe53bfa --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-query/variant-query.component.scss @@ -0,0 +1,109 @@ +.query-container{ + width : 100%; + height : 100%; +} + +.form-container{ + width: 90%; + height: 65%; + display: block; + transform: translateZ(0); + text-size-adjust: none; + margin: 0.75rem auto 0.5rem; +} + +.form{ + width: 100%; + height: 100%; + display: flex; + flex-flow: row wrap; + place-content: stretch center; + align-items: stretch; +} + + +.backend-error{ + color : var(--bs-danger); +} + +.query-editor-highlights { + white-space: pre-wrap; + word-wrap: break-word; + color: var(--text-secondary); + +} + +.query-editor-backdrop{ + position: absolute; + z-index: 1; + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); + overflow: auto; + border-radius: 3px; + pointer-events: none; + user-select : none; + width: 100%; + height : 100%; +} + +.syntax-error-container{ + width: 100%; + overflow: scroll; + max-height: 3rem; + margin-right: 0.25rem; + margin-left: 0.25rem; +} + +.syntax-error{ + color : var(--bs-warning); + font-size : x-small; +} + +.query-editor{ + display: block; + position: absolute; + z-index: 2; + margin: 0; + border-radius: 3px; + color: rgb(255 255 255 / 7%); + background-color: transparent; + caret-color: rgb(255 255 255); + overflow: auto; + resize: none; + width: 100%; + height : 100%; +} + +.query-editor-highlights, textarea { + padding: 10px; + font-size: var(--standard-font-size); + letter-spacing: 0.25px; +} + +textarea:focus{ + outline: none; + box-shadow: none; +} + + +.query-field{ + width : 100%; + height : 100%; +} + +.variant-query-tool-bar{ + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); + display: flex; + flex-flow: row nowrap; + align-items: flex-start; + width: 100%; + place-content: flex-start flex-start; + + // position: absolute; + // bottom: 0; +} + +.dropdown-menu { + border-radius: 0; + background-color: lightgray; +} + diff --git a/src/frontend/src/app/components/variant-explorer/variant-query/variant-query.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant-query/variant-query.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..48c82e6ad869410577f9bfe4cc266b1b613f710f --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-query/variant-query.component.spec.ts @@ -0,0 +1,27 @@ +/* tslint:disable:no-unused-variable */ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { DebugElement } from '@angular/core'; + +import { VariantQueryComponent } from './variant-query.component'; + +describe('VariantQueryComponent', () => { + let component: VariantQueryComponent; + let fixture: ComponentFixture<VariantQueryComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [VariantQueryComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantQueryComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant-query/variant-query.component.ts b/src/frontend/src/app/components/variant-explorer/variant-query/variant-query.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..d05c7611c7b8d4aaf33565d896f2a033a97ebc8d --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-query/variant-query.component.ts @@ -0,0 +1,289 @@ +import { EditorService } from './../../../services/editorService/editor.service'; +import { VariantFilterService } from './../../../services/variantFilterService/variant-filter.service'; +import { LogService } from 'src/app/services/logService/log.service'; +import { BackendService } from 'src/app/services/backendService/backend.service'; +import { + Component, + ElementRef, + OnInit, + ViewChild, + Renderer2, + AfterViewInit, + HostListener, + Input, + OnDestroy, + OnChanges, + SimpleChanges, + EventEmitter, + Output, +} from '@angular/core'; +import { UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; +import { Subject } from 'rxjs'; +import { distinctUntilChanged, takeUntil } from 'rxjs/operators'; +import { EditorZoneComponent } from '../../editor-zone/editor-zone.component'; + +import * as Monaco from 'monaco-editor'; +import { generateVQLTheme } from '../../editor-zone/editor-languages/vql-language-theme'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { VariantQueryService } from 'src/app/services/variantQueryService/variant-query.service'; +declare var monaco: typeof Monaco; +@Component({ + selector: 'app-variant-query', + templateUrl: './variant-query.component.html', + styleUrls: ['./variant-query.component.scss'], +}) +export class VariantQueryComponent + implements OnInit, AfterViewInit, OnDestroy, OnChanges +{ + variantQueryInput: UntypedFormGroup; + variantQuery: UntypedFormControl; + + @ViewChild('queryEditor') queryEditor: ElementRef<HTMLTextAreaElement>; + @ViewChild(EditorZoneComponent) editorZone: EditorZoneComponent; + @ViewChild('queryEditorBackdrop') + queryEditorBackdrop: ElementRef<HTMLDivElement>; + + @Input() + active: boolean = false; + + @Input() + options: EditorOptions = new EditorOptions(); + + @Output() + executeFilteredVariantsAction: EventEmitter<boolean> = + new EventEmitter<boolean>(); + + queryfilteractive: boolean = false; + + apostropheString = '<span class="syntax-operator">\'</span>'; + + activityNameRegEx = new RegExp( + this.apostropheString + "([^']*)" + this.apostropheString, + 'g' + ); + + activityColorMap: Map<string, string>; + + activites: Set<string>; + backendErrorMessage: boolean = false; + backendErrorIndex: number; + + editorInstance: Monaco.editor.IStandaloneCodeEditor; + + private _destroy$ = new Subject(); + + constructor( + private renderer: Renderer2, + private variantQueryService: VariantQueryService, + private colorMapService: ColorMapService, + private logService: LogService, + private backendService: BackendService, + private variantFilterService: VariantFilterService, + private editorService: EditorService, + private variantService: VariantService + ) {} + + ngOnChanges(changes: SimpleChanges): void { + if (this.editorInstance) { + this.editorService.options = this.options; + this.editorService.updateTheme(); + } + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + ngOnInit() { + (this.variantQuery = new UntypedFormControl('', { + validators: [], + updateOn: 'change', + })), + (this.variantQueryInput = new UntypedFormGroup({ + variantQuery: this.variantQuery, + })); + + this.variantQuery.valueChanges + .pipe(takeUntil(this._destroy$), distinctUntilChanged()) + .subscribe((query) => { + this.variantQueryService.variantQuery = query; + }); + + this.variantQueryService.variantQuery$ + .pipe(takeUntil(this._destroy$)) + .subscribe((query) => { + if (this.variantQuery.value !== query) + this.variantQuery.setValue(query); + }); + + this.variantService.nameChanges.subscribe((v) => { + if (v !== null) { + let [oldName, newName] = v; + this.onRenameActivity(oldName, newName); + } + }); + } + + ngAfterViewInit(): void { + this.logService.activitiesInEventLog$ + .pipe(takeUntil(this._destroy$)) + .subscribe((act) => { + this.activites = new Set(Object.keys(act)); + }); + + this.variantFilterService.variantFilters$.subscribe((filter) => { + this.queryfilteractive = filter.has('query filter'); + }); + } + + onSubmit() { + this.backendService + .variantQuery(this.variantQuery.value) + .pipe(takeUntil(this._destroy$)) + .subscribe((res) => { + if (!res.error) { + this.variantFilterService.addVariantFilter( + 'query filter', + new Set(res.ids as Array<number>), + this.variantQuery.value + ); + } else { + this.variantQuery.setErrors({ backendError: res.error }); + this.backendErrorIndex = res.error_index; + } + }); + } + + resetQuery() { + this.variantFilterService.removeVariantFilter('query filter'); + } + + executeRemovalActionOnFilteredVariants(removeFiltered: boolean) { + this.executeFilteredVariantsAction.emit(removeFiltered); + } + + onEditorChange(value) { + this.editorZone.registerValidatorFunction(this.validateMonaco); + this.editorZone.registerOnErrorStatusChange(this.onErrorStatusChange); + this.editorZone.registerOnTouched(this.onErrorStatusChange); + this.editorInstance = value; + } + + @HostListener('window:keydown.control.enter', ['$event']) + onRunQuery(e) { + if (this.variantQuery.valid) { + this.onSubmit(); + } + } + + private onErrorStatusChange = function () { + this.variantQuery.updateValueAndValidity(); + }.bind(this); + + private onRenameActivity(oldName: string, newName: string) { + let model = this.editorZone.model; + for (let match of model.findMatches( + "'" + oldName + "'", + true, + true, + true, + null, + true + )) { + model.applyEdits([{ range: match.range, text: "'" + newName + "'" }]); + } + } + + private validateMonaco = function (model: Monaco.editor.ITextModel) { + const markers = []; + // lines start at 1 + + for (let match of model.findMatches( + "'([^']*)'", + true, + true, + true, + null, + true + )) { + if (!this.activites.has(match.matches[1])) { + const actvityRange = match.range; + markers.push({ + message: + 'Unknown Activity ' + + match.matches[1] + + ' in Line ' + + actvityRange.startLineNumber, + severity: monaco.MarkerSeverity.Warning, + startLineNumber: actvityRange.startLineNumber, + startColumn: actvityRange.startColumn + 1, + endLineNumber: actvityRange.endLineNumber, + endColumn: actvityRange.endColumn - 1, + }); + } + } + + const semicolon_matches = model.findMatches( + ';', + true, + true, + true, + null, + true + ); + + if (semicolon_matches.length > 1) { + for (let match of semicolon_matches.slice(1)) { + const semicolonRange = match.range; + + markers.push({ + message: 'Too many Semicolons', + severity: monaco.MarkerSeverity.Error, + startLineNumber: semicolonRange.startLineNumber, + startColumn: semicolonRange.startColumn, + endLineNumber: semicolonRange.endLineNumber, + endColumn: semicolonRange.endColumn, + }); + } + } else if (semicolon_matches.length > 0) { + const semicolonRange = semicolon_matches[0].range; + + const firstWhiteSpace = model.getLineLastNonWhitespaceColumn( + semicolonRange.endLineNumber + ); + + if (firstWhiteSpace !== semicolonRange.startColumn + 1) { + markers.push({ + message: 'Input after Semicolon', + severity: monaco.MarkerSeverity.Error, + startLineNumber: semicolonRange.endLineNumber, + startColumn: semicolonRange.endColumn, + endLineNumber: semicolonRange.endLineNumber, + endColumn: model.getLineMaxColumn(semicolonRange.endLineNumber), + }); + } + } else { + const line = model.getLineCount(); + const last = model.getLineMaxColumn(line); + markers.push({ + message: 'Missing Semicolon', + severity: monaco.MarkerSeverity.Warning, + startLineNumber: line, + startColumn: last, + endLineNumber: line, + endColumn: last, + }); + } + + monaco.editor.setModelMarkers(model, 'owner', markers); + }.bind(this); +} + +export class EditorOptions { + highlightActivityNames: boolean; + + constructor() { + this.highlightActivityNames = true; + } +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component.css b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component.css new file mode 100644 index 0000000000000000000000000000000000000000..08536ec98f528eda7423fa2bbacdbc924d87d29c --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component.css @@ -0,0 +1,46 @@ +.pattern-editor { + display: flex; + width: 100%; + height: 100%; + background-color: var(--box-background-color); + flex-direction: column; + border-bottom: 1px; + border-color: var(--thin-border-color); +} + +.zoom-group-variant { + width: 100%; + height: 100%; + max-height: 200px; + min-height: 200px; +} + +.strategy-selected { + background-color: #515a64; +} + +.round-corners { + border-radius: 2px; + overflow: hidden; +} + +.button-area-disabled { + opacity: 0.5; + user-select: none; + pointer-events: none; +} + +.button-text { + display: inline-block; +} + +.redundancy-warning { + position: absolute; + left: 0; + bottom: 0; + color: var(--bs-warning); + background-color: rgb(0 0 0 / 100%); + padding: 6px 5px 2.5px; + font-size: small; + border-top-right-radius: 4px; +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component.html b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component.html new file mode 100644 index 0000000000000000000000000000000000000000..664dd349420aa437f3eb4b286722827b966c41e7 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component.html @@ -0,0 +1,227 @@ +<div class="pattern-editor"> + <ng-content #patternTitle></ng-content> + <div #ToolBar class="bg-dark btn-tool-bar"> + <span class="vl mx-2"></span> + + <div class="btn-group round-corners" role="group"> + <button + type="button" + class="button" + (click)="selectedStrategy = insertionStrategy.infront" + [ngClass]=" + selectedStrategy === insertionStrategy.infront + ? 'strategy-selected' + : '' + " + ngbTooltip="insert new activities infront the selected activtiy" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-bar-left"></i> + </button> + + <button + type="button" + class="button" + (click)="selectedStrategy = insertionStrategy.behind" + [ngClass]=" + selectedStrategy === insertionStrategy.behind + ? 'strategy-selected' + : '' + " + ngbTooltip="insert new activities behind of the selected activtiy" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-bar-right"></i> + </button> + + <button + type="button" + class="button" + (click)="selectedStrategy = insertionStrategy.parallel" + [ngClass]=" + selectedStrategy === insertionStrategy.parallel + ? 'strategy-selected' + : '' + " + ngbTooltip="insert new activities parallel of the selected activtiy" + triggers="hover" + container="body" + > + <i class="bi bi-arrows-expand"></i> + </button> + + <button + type="button" + class="button" + (click)="selectedStrategy = insertionStrategy.choice" + [ngClass]=" + selectedStrategy === insertionStrategy.choice + ? 'strategy-selected' + : '' + " + ngbTooltip="add an activity as an alternative candidate to the currently selected activity" + triggers="hover" + container="body" + > + <i class="bi bi-slash"></i> + </button> + + <button + type="button" + class="button" + (click)="selectedStrategy = insertionStrategy.fallthrough" + [ngClass]=" + selectedStrategy === insertionStrategy.fallthrough + ? 'strategy-selected' + : '' + " + ngbTooltip="create fallthrough using an activity" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-down"></i> + </button> + + <button + type="button" + class="button" + (click)="selectedStrategy = insertionStrategy.replace" + [ngClass]=" + selectedStrategy === insertionStrategy.replace + ? 'strategy-selected' + : '' + " + ngbTooltip="replace the currently selected activity" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-repeat"></i> + </button> + </div> + + <span class="vl mx-2"></span> + + <button + class="button btn-fixed-width" + (click)="undo()" + [disabled]="!(cachedVariants.length - 1 > 0 && cacheIdx !== 0)" + ngbTooltip="undo" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-counterclockwise btn-icon"></i> + <span + class="text-secondary" + *ngIf="cachedVariants.length - 1 > 0 && cacheIdx !== 0" + > + ({{ cacheIdx }}) + </span> + </button> + + <button + class="button btn-fixed-width" + (click)="redo()" + [disabled]="!(cacheIdx < cachedVariants.length - 1)" + ngbTooltip="redo" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-clockwise btn-icon"></i> + <span class="text-secondary" *ngIf="cacheIdx < cachedVariants.length - 1"> + ({{ cachedVariants.length - 1 - cacheIdx }}) + </span> + </button> + + <span class="vl mx-2"></span> + + <button + class="button" + (click)="removeSelection()" + [disabled]="!selectedElement" + ngbTooltip="remove current selection" + triggers="hover" + container="body" + > + <i class="bi bi-dash-square-dotted"></i> + </button> + + <span class="vl mx-2"></span> + + <button + class="button" + (click)="onDeleteSelected()" + ngbTooltip="remove the currently selected activity" + triggers="hover" + container="body" + [disabled]="emptyVariant || !selectedElement" + > + <i + class="bi bi-trash" + [ngClass]="{ + 'text-warning': !emptyVariant + }" + ></i> + + <div @collapseText class="button-text px-1" *ngIf="!collapse"> + remove selected chevron(s) + </div> + </button> + + <span class="vl mx-2"></span> + + <button + class="button" + (click)="onDeleteVariant()" + ngbTooltip="remove the current variant" + triggers="hover" + container="body" + [disabled]="emptyVariant" + > + <i + class="bi bi-x-octagon" + [ngClass]="{ + 'text-danger': !emptyVariant + }" + ></i> + <div @collapseText class="button-text px-1" *ngIf="!collapse"> + remove current variant + </div> + </button> + </div> + + <app-activity-button-area + [activityNames]="activityNames" + [referenceVariant]="referenceVariant" + [ifSource]="ifSource" + [redrawSingal]="false" + (activityButtonClick)="handleActivityButtonClick($event)" + [ngClass]=" + (ifSource && checkSingleParallel()) || checkActivityDisable() + ? 'button-area-disabled' + : '' + " + > + </app-activity-button-area> + + <app-zoom-field + #ZoomField + [zoomScale]="[0.1, 3]" + [computeFocusOffsets]="computeFocusOffset" + > + <svg + #content + #VariantMainGroup + appVariantDrawer + id="PatternVariantMainGroup" + [variant]="{ variant: currentVariant }" + (selection)="handleRedraw($event)" + [computeActivityColor]="computeActivityColor" + [infixType]="curInfixType" + [keepStandardView]="true" + class="zoom-group-variant pattern-variant" + ></svg> + </app-zoom-field> + <div class="invalid-feedback">Please provide a valid input.</div> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..6d3274704f1ff27a3000f3309795bc3c8cb0371e --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PatternEditorComponent } from './pattern-editor.component'; + +describe('PatternEditorComponent', () => { + let component: PatternEditorComponent; + let fixture: ComponentFixture<PatternEditorComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PatternEditorComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PatternEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component.ts b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..2484b7c2932bcd65d44ce3b82d22ca5e59aff654 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/pattern-editor/pattern-editor.component.ts @@ -0,0 +1,1033 @@ +import { ZoomFieldComponent } from 'src/app/components/zoom-field/zoom-field.component'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { BackendService } from 'src/app/services/backendService/backend.service'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; +import { + Component, + ElementRef, + EventEmitter, + HostListener, + Input, + OnChanges, + OnDestroy, + OnInit, + Output, + SimpleChanges, + ViewChild, +} from '@angular/core'; +import * as d3 from 'd3'; +import { LogService } from 'src/app/services/logService/log.service'; +import { VariantDrawerDirective } from 'src/app/directives/variant-drawer/variant-drawer.directive'; +import { InfixType } from 'src/app/objects/Variants/infix_selection'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { + ChoiceGroup, + FallthroughGroup, + LeafNode, + ParallelGroup, + SequenceGroup, + VariantElement, +} from 'src/app/objects/Variants/variant_element'; +import { collapsingText } from 'src/app/animations/text-animations'; +import { findPathToSelectedNode } from 'src/app/objects/Variants/utility_functions'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +declare var $; + +@Component({ + selector: 'app-pattern-editor', + templateUrl: './pattern-editor.component.html', + styleUrls: ['./pattern-editor.component.css'], + animations: [collapsingText], +}) +export class PatternEditorComponent implements OnInit, OnDestroy, OnChanges { + activityNames: Array<String> = []; + + public colorMap: Map<string, string>; + + @ViewChild('ToolBar') + toolBar: ElementRef; + + @ViewChild('VariantMainGroup') + variantElement: ElementRef; + + @ViewChild(ZoomFieldComponent) + editor: ZoomFieldComponent; + + @ViewChild(VariantDrawerDirective) + variantDrawer: VariantDrawerDirective; + + @Input() ifSource: boolean; + @Input() referenceVariant: VariantElement; + + @Output() variantChange = new EventEmitter(); + + currentVariant: VariantElement = null; + cachedVariants: VariantElement[] = [null]; + cacheSize = 100; + cacheIdx = 0; + + emptyVariant = true; + + selectedElement = false; + multiSelect = false; + multipleSelected = false; + + infixType = InfixType; + curInfixType = InfixType.NOT_AN_INFIX; + + newLeaf; + + collapse: boolean = false; + + insertionStrategy = activityInsertionStrategy; + selectedStrategy = this.insertionStrategy.behind; + + // @ts-ignore + variantEnrichedSelection: Selection<any, any, any, any>; + zoom: any; + + redundancyWarning = false; + private _destroy$ = new Subject(); + constructor( + private variantService: VariantService, + private backendService: BackendService, + public logService: LogService, + private colorMapService: ColorMapService + ) { + const a = 1; + } + + ngOnInit(): void { + this.logService.activitiesInEventLog$ + .pipe(takeUntil(this._destroy$)) + .subscribe((activities) => { + this.activityNames = []; + const newActivityNames = []; + for (const activity in activities) { + this.activityNames.push(activity); + this.activityNames.sort(); + newActivityNames.push(activity.valueOf()); + newActivityNames.sort(); + } + + this.activityNames.push(String('...')); + this.activityNames.sort(); + /* + newActivityNames.push('...') + newActivityNames.sort(); + this.colorMapService.createColorMap(newActivityNames) + */ + }); + + this.logService.loadedEventLog$ + .pipe(takeUntil(this._destroy$)) + .subscribe((newLog) => { + if (newLog) { + this.emptyVariant = true; + } + }); + + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((map) => { + this.colorMap = map; + if (this.variantDrawer) { + this.variantDrawer.redraw(); + } + }); + } + + @HostListener('window:resize', ['$event']) + onResize(event: Event) { + this.checkButtonCollapse(); + } + + ngOnChanges(changes: SimpleChanges) { + this.logService.activitiesInEventLog$ + .pipe(takeUntil(this._destroy$)) + .subscribe((activities) => { + this.activityNames = []; + for (const activity in activities) { + this.activityNames.push(activity); + this.activityNames.sort(); + } + this.activityNames.push('...'); + this.activityNames.sort(); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + checkButtonCollapse() { + if (this.toolBar.nativeElement.offsetWidth < 766) { + //according to the width of toolbar + this.collapse = true; + } else { + this.collapse = false; + } + } + + computeActivityColor = ( + self: VariantDrawerDirective, + element: VariantElement, + variant: Variant + ) => { + let color; + color = this.colorMap.get(element.asLeafNode().activity[0]); + + if ( + !color || + this.findParent(this.currentVariant, element) instanceof FallthroughGroup + ) { + color = '#d3d3d3'; // lightgrey + } + + return color; + }; + + computeFocusOffset = (svg) => { + const path = findPathToSelectedNode( + this.currentVariant, + svg.select('.selected-variant-g').data()[0] + ).slice(1); + let translateX = 0; + + for (const element of svg + .selectAll('g') + .filter((d: VariantElement) => { + return path.indexOf(d) > -1; + }) + .nodes()) { + const transform = d3 + .select(element) + .attr('transform') + .match(/[\d.]+/g); + translateX += parseFloat(transform[0]); + } + + return [-translateX, 0]; + }; + + triggerRedraw() { + setTimeout(() => this.variantDrawer.redraw(), 1); + } + + //there is no nested parallel group in variant sequentializer. The parallel could only contain leaf, choice and fallthrough + compareNode(node1, node2) { + if (!(node1 instanceof LeafNode)) { + return false; + } else if (!(node2 instanceof LeafNode)) { + return true; + } else { + return node1.asLeafNode().activity[0] > node2.asLeafNode().activity[0]; + } + } + sortParallel(variant) { + const children = variant.getElements(); + for (let i = 1; i < children.length; i++) { + const temp = children[i]; + let j = i - 1; + while (j >= 0 && this.compareNode(children[j], temp)) { + children[j + 1] = children[j]; + j--; + } + children[j + 1] = temp; + } + return children; + } + findParent(parent, node) { + const children = parent.getElements(); + if (!children) { + return null; + } else { + const index = children.indexOf(node); + if (index > -1) { + return parent; + } else { + for (const child of children) { + if (this.findParent(child, node) != null) { + return this.findParent(child, node); + } + } + return null; + } + } + } // check is node is a child of parent + + reconstructVariant(variant: VariantElement) { + const children = variant.getElements(); + if (!children) { + return variant; + } else { + if (variant instanceof ParallelGroup) { + return new ParallelGroup(children); + } else if (variant instanceof ChoiceGroup) { + return new ChoiceGroup(children); + } else if (variant instanceof FallthroughGroup) { + return new FallthroughGroup(children); + } else { + return new SequenceGroup(children); + } + } + } + + handleActivityButtonClick(event) { + if (this.selectedElement || this.emptyVariant) { + const leaf = new LeafNode([event.activityName]); + this.newLeaf = leaf; + + if (this.emptyVariant) { + const variantGroup = new SequenceGroup([leaf]); + variantGroup.setExpanded(true); + this.currentVariant = variantGroup; + this.emptyVariant = false; + this.selectedElement = true; + this.editor.centerContent(250); + this.variantChange.emit({ + variant: this.currentVariant ? this.currentVariant.copy() : null, + }); + } else { + leaf.setExpanded(true); + const selectedElement = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data()[0]; + switch (this.selectedStrategy) { + case this.insertionStrategy.infront: + if (!this.multipleSelected) { + this.handleInfrontInsert( + this.currentVariant, + leaf, + selectedElement + ); + const grandParent = this.findParent( + this.currentVariant, + this.findParent(this.currentVariant, leaf) + ); + if (grandParent instanceof ParallelGroup) { + this.sortParallel(grandParent); + } + } + break; + case this.insertionStrategy.behind: + if (!this.multipleSelected) { + this.handleBehindInsert( + this.currentVariant, + leaf, + selectedElement + ); + const grandParent = this.findParent( + this.currentVariant, + this.findParent(this.currentVariant, leaf) + ); + if (grandParent instanceof ParallelGroup) { + this.sortParallel(grandParent); + } + } + break; + case this.insertionStrategy.parallel: + if (!this.multipleSelected) { + this.handleParallelInsert( + this.currentVariant, + leaf, + selectedElement + ); + } + this.sortParallel(this.findParent(this.currentVariant, leaf)); + break; + case this.insertionStrategy.choice: + if (!this.multipleSelected) { + this.handleChoice(this.currentVariant, leaf, selectedElement); + } + break; + case this.insertionStrategy.fallthrough: + if (!this.multipleSelected) { + this.handleFallthrough( + this.currentVariant, + leaf, + selectedElement + ); + } + break; + case this.insertionStrategy.replace: + if (!this.multipleSelected) { + this.handleReplace(this.currentVariant, leaf, selectedElement); + } + break; + } + this.variantChange.emit({ + variant: this.currentVariant ? this.currentVariant.copy() : null, + }); + this.triggerRedraw(); + } + this.variantChange.emit({ + variant: this.currentVariant ? this.currentVariant.copy() : null, + }); + this.cacheCurrentVariant(); + } + } + + handleParallelInsert( + variant: VariantElement, + leaf: LeafNode, + selectedElement + ) { + const children = variant.getElements(); + + if (children) { + const index = children.indexOf(selectedElement); + if (variant && variant === selectedElement) { + variant.setElements([ + new ParallelGroup([leaf, this.reconstructVariant(variant)]), + ]); + } else if (index > -1) { + // Handle parent ParallelGroup + if (variant instanceof ParallelGroup) { + children.splice(index, 0, leaf); + } else { + // If the selected element is a parallel group, insert into its children + if (selectedElement instanceof ParallelGroup) { + selectedElement.getElements().push(leaf); + + // Else create a new parallel group for leaf and selected + } else { + children.splice( + index, + 1, + new ParallelGroup([leaf, selectedElement]) + ); + } + } + + // variant.setElements(children); + } else { + for (const child of children) { + this.handleParallelInsert(child, leaf, selectedElement); + } + } + } + } + + checkOverlapInsert() { + if (this.emptyVariant || !this.variantEnrichedSelection) { + return false; + } else { + const selectedElement = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data()[0]; + const parent = this.findParent(this.currentVariant, selectedElement); + if (parent && !(parent instanceof ParallelGroup)) { + return false; + } else { + if (!parent) { + return false; + } else { + const siblings = parent.getElements(); + for (const s of siblings) { + if (s instanceof SequenceGroup && s.getElements().length > 1) { + return true; + } + } + return false; + } + } + } + } + + checkNeighborSelection() { + const selectedElements = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data(); + + if ( + !( + this.findParent(this.currentVariant, selectedElements[0]) instanceof + SequenceGroup + ) + ) { + return false; + } + + for (let i = 0; i < selectedElements.length - 1; i++) { + const firstParent = this.findParent( + this.currentVariant, + selectedElements[i] + ); + const secondParent = this.findParent( + this.currentVariant, + selectedElements[i + 1] + ); + if ( + firstParent != secondParent || + firstParent.getElements().indexOf(selectedElements[i + 1]) != + firstParent.getElements().indexOf(selectedElements[i]) + 1 + ) { + return false; + } + } + return true; + } + + checkChoiceDisable() { + if (this.emptyVariant || !this.variantEnrichedSelection) { + return false; + } else { + const selectedElements = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data()[0] as any; + if (selectedElements instanceof LeafNode) { + return false; + } else { + return true; + } + } + } + + checkSingleParallel() { + if (!this.selectedElement || this.multipleSelected) { + return false; + } else if (this.emptyVariant || !this.variantEnrichedSelection) { + return false; + } else { + const selectedElements = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data()[0] as any; + if ( + this.currentVariant.getElements().indexOf(selectedElements) >= 0 && + (this.selectedStrategy === this.insertionStrategy.infront || + this.selectedStrategy === this.insertionStrategy.behind) + ) { + return true; + } else { + return false; + } + } + } + + checkInsideFallthrough() { + if (this.emptyVariant || !this.variantEnrichedSelection) { + return false; + } else { + const selectedElements = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data() as any; + for (const ele of selectedElements) { + if ( + this.findParent(this.currentVariant, ele) instanceof FallthroughGroup + ) { + return true; + } + } + return false; + } + } + + checkNotSelectedLeaf() { + if (this.emptyVariant || !this.variantEnrichedSelection) { + return false; + } else { + const selectedElements = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data()[0] as any; + if (selectedElements instanceof LeafNode) { + return false; + } else { + return true; + } + } + } + + checkActivityDisable() { + const result = + (this.selectedStrategy === this.insertionStrategy.choice && + (this.multipleSelected || + (this.selectedElement && this.checkChoiceDisable()))) || + (this.selectedElement && + !this.multipleSelected && + (this.selectedStrategy === this.insertionStrategy.infront || + this.selectedStrategy === this.insertionStrategy.behind) && + this.checkOverlapInsert()) || + (this.multipleSelected && + !( + this.checkNeighborSelection() && + this.selectedStrategy === this.insertionStrategy.parallel + )) || + (!this.selectedElement && !this.emptyVariant) || + (this.selectedStrategy !== this.insertionStrategy.fallthrough && + this.checkInsideFallthrough()) || + (this.selectedStrategy === this.insertionStrategy.fallthrough && + (this.multipleSelected || this.checkNotSelectedLeaf())); + return result; + } + + handleBehindInsert(variant: VariantElement, leaf: LeafNode, selectedElement) { + const children = variant.getElements(); + + if (children) { + const index = children.indexOf(selectedElement); + if (variant && variant === selectedElement) { + children.splice(children.length, 0, leaf); + } else if (index > -1) { + // Handling Parent Parallel Group Cases + if (variant instanceof ParallelGroup) { + // Inserting behind a leafNode inside a ParallelGroup + if (selectedElement instanceof LeafNode) { + children.splice( + index, + 1, + new SequenceGroup([selectedElement, leaf]) + ); + } else { + // Inserting behind a ParallelGroup inside a ParallelGroup + if (selectedElement instanceof ParallelGroup) { + children.splice( + children.indexOf(selectedElement), + 1, + new SequenceGroup([selectedElement, leaf]) + ); + + // Inserting behind a SequeneGroup inside a ParallelGroup + } else { + const selectedChildren = selectedElement.getElements(); + selectedChildren.push(leaf); + } + } + + // Else the variant is a SequenceGroup and we can simply insert after the selected Element + } else { + children.splice(index + 1, 0, leaf); + } + + // Recursing into the Children + } else { + for (const child of children) { + this.handleBehindInsert(child, leaf, selectedElement); + } + } + } + } + + handleInfrontInsert( + variant: VariantElement, + leaf: LeafNode, + selectedElement + ) { + const children = variant.getElements(); + + if (children) { + const index = children.indexOf(selectedElement); + if (variant && variant === selectedElement) { + children.splice(0, 0, leaf); + } else if (index > -1) { + if (variant instanceof ParallelGroup) { + // Inserting infront a leafNode inside a ParallelGroup + if (selectedElement instanceof LeafNode) { + children.splice( + index, + 1, + new SequenceGroup([leaf, selectedElement]) + ); + } else { + // Inserting infront a ParallelGroup inside a ParallelGroup + if (selectedElement instanceof ParallelGroup) { + children.splice( + children.indexOf(selectedElement), + 1, + new SequenceGroup([leaf, selectedElement]) + ); + + // Inserting infront a SequeneGroup inside a ParallelGroup + } else { + const selectedChildren = selectedElement.getElements(); + selectedChildren.unshift(leaf); + } + } + } else { + children.splice(index, 0, leaf); + } + } else { + for (const child of children) { + this.handleInfrontInsert(child, leaf, selectedElement); + } + } + } + } + + handleChoice(variant: VariantElement, leaf: LeafNode, selectedElement) { + const children = variant.getElements(); + + if (children) { + const index = children.indexOf(selectedElement); + if (variant && variant === selectedElement) { + variant.setElements([ + new ChoiceGroup([leaf, new SequenceGroup(children)]), + ]); + } else if (index > -1) { + // Handle parent ChoiceGroup + if (variant instanceof ChoiceGroup) { + children.splice(index, 0, leaf); + } else { + // If the selected element is a parallel group, insert into its children + if (selectedElement instanceof ChoiceGroup) { + selectedElement.getElements().push(leaf); + + // Else create a new choice group for leaf and selected + } else { + children.splice(index, 1, new ChoiceGroup([leaf, selectedElement])); + } + } + + // variant.setElements(children); + } else { + for (const child of children) { + this.handleChoice(child, leaf, selectedElement); + } + } + } + } + + handleFallthrough(variant: VariantElement, leaf: LeafNode, selectedElement) { + const children = variant.getElements(); + + if (children) { + const index = children.indexOf(selectedElement); + if (variant && variant === selectedElement) { + // Only SequenceGroup and Leaf could be selected here? + variant.setElements([ + new FallthroughGroup([leaf, new SequenceGroup(children)]), + ]); + } else if (index > -1) { + // Handle parent FallthroughGroup + if (variant instanceof FallthroughGroup) { + children.splice(index, 0, leaf); + } else { + // If the selected element is a parallel group, insert into its children + if (selectedElement instanceof FallthroughGroup) { + selectedElement.getElements().push(leaf); + + // Else create a new fallthrough group for leaf and selected + } else { + children.splice( + index, + 1, + new FallthroughGroup([leaf, selectedElement]) + ); + } + } + + // variant.setElements(children); + } else { + for (const child of children) { + this.handleFallthrough(child, leaf, selectedElement); + } + } + } + } + + /* + handleFallthrough(variant: VariantElement, leaf: LeafNode, selectedElement) { + const children = variant.getElements(); + + if (children) { + const index = children.indexOf(selectedElement); + if (variant && variant === selectedElement) { + const newLeaf = new LeafNode(selectedElement.asLeafNode().activity.concat(leaf.asLeafNode().activity).sort()); + this.newLeaf = newLeaf; + variant.setElements([newLeaf]); + } + if (index > -1) { + const newLeaf = new LeafNode(selectedElement.asLeafNode().activity.concat(leaf.asLeafNode().activity).sort()); + this.newLeaf = newLeaf; + children.splice(index, 1, newLeaf); + } else { + for (const child of children) { + this.handleFallthrough(child, leaf, selectedElement); + } + } + } + }*/ + + handleReplace(variant: VariantElement, leaf: LeafNode, selectedElement) { + const children = variant.getElements(); + + if (children) { + const index = children.indexOf(selectedElement); + if (variant && variant === selectedElement) { + variant.setElements([leaf]); + } + if (index > -1) { + children.splice(index, 1, leaf); + } else { + for (const child of children) { + this.handleReplace(child, leaf, selectedElement); + } + } + } + } + + cacheCurrentVariant() { + if (this.cacheIdx < this.cachedVariants.length - 1) { + this.cachedVariants = this.cachedVariants.slice(0, this.cacheIdx + 1); + } + + if (this.currentVariant) { + this.cachedVariants.push(this.currentVariant.copy()); + } else { + this.cachedVariants.push(null); + } + if (this.cachedVariants.length > this.cacheSize) { + this.cachedVariants.shift(); + } else { + if (!(this.cacheIdx == null)) { + this.cacheIdx += 1; + } else { + this.cacheIdx = this.cachedVariants.length - 1; + } + } + } + redo() { + this.selectedElement = false; + this.emptyVariant = false; + + this.cacheIdx++; + if (this.cachedVariants[this.cacheIdx] === null) { + this.currentVariant = null; + this.emptyVariant = true; + } else { + this.currentVariant = this.cachedVariants[this.cacheIdx].copy(); + } + this.newLeaf = null; + } + + undo() { + this.selectedElement = false; + this.emptyVariant = false; + + this.cacheIdx--; + if (this.cachedVariants[this.cacheIdx] === null) { + this.currentVariant = null; + this.emptyVariant = true; + } // edited + else { + this.currentVariant = this.cachedVariants[this.cacheIdx].copy(); + } + this.newLeaf = null; + } + + onDeleteSelected() { + const ElementsToDelete = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data(); + + if ( + ElementsToDelete.length === 1 && + ElementsToDelete[0] instanceof SequenceGroup && + this.currentVariant === ElementsToDelete[0] + ) { + this.onDeleteVariant(); + } // need further check. Is this nested function allowed? + else { + this.deleteElementFromVariant( + this.currentVariant, + this.currentVariant, + ElementsToDelete + ); + + this.multiSelect = false; + this.multipleSelected = false; + this.variantChange.emit({ + variant: this.currentVariant ? this.currentVariant.copy() : null, + }); + + this.cacheCurrentVariant(); + + this.triggerRedraw(); + } + } + + deleteElementFromVariant( + variant: VariantElement, + parent: VariantElement, + elementsToDelete + ) { + const children = variant.getElements(); + + if (children) { + for (const elementToDelete of elementsToDelete) { + const index = children.indexOf(elementToDelete); + if (index > -1) { + this.newLeaf = children[index - 1]; + + children.splice(index, 1); + } + } + + //handle nested + if ( + children.length === 1 && + variant instanceof SequenceGroup && + parent instanceof ParallelGroup && + (children[0] instanceof ParallelGroup || + children[0] instanceof LeafNode || + children[0] instanceof ChoiceGroup || + children[0] instanceof FallthroughGroup) + ) { + const childrenParent = parent.getElements(); + const aloneChild = children[0]; + if (aloneChild instanceof ParallelGroup) { + const parallelChildren = children[0].getElements(); + const deleteIndex = childrenParent.indexOf(variant); + childrenParent.splice(deleteIndex, 1); + for (const newNode of parallelChildren.reverse()) { + childrenParent.splice(deleteIndex, 0, newNode); + } + } else { + childrenParent.splice(childrenParent.indexOf(variant), 1, aloneChild); + } + parent.setElements(childrenParent); + } else if ( + children.length === 1 && + (variant instanceof ParallelGroup || + variant instanceof ChoiceGroup || + variant instanceof FallthroughGroup) && + parent instanceof SequenceGroup && + (children[0] instanceof SequenceGroup || + children[0] instanceof LeafNode || + children[0] instanceof ChoiceGroup || + children[0] instanceof FallthroughGroup) + ) { + const childrenParent = parent.getElements(); + const aloneChild = children[0]; + if (aloneChild instanceof SequenceGroup) { + const sequenceChildren = children[0].getElements(); + const deleteIndex = childrenParent.indexOf(variant); + childrenParent.splice(deleteIndex, 1); + for (const newNode of sequenceChildren.reverse()) { + childrenParent.splice(deleteIndex, 0, newNode); + } + } else { + childrenParent.splice(childrenParent.indexOf(variant), 1, aloneChild); + } + parent.setElements(childrenParent); + } + + // edited + if (children.length === 0) { + const childrenParent = parent.getElements(); + if (!(variant === this.currentVariant)) { + childrenParent.splice(childrenParent.indexOf(variant), 1); + parent.setElements(childrenParent); + } else { + this.currentVariant = null; + this.emptyVariant = true; + } + } else { + variant.setElements(children); + for (const child of children) { + this.deleteElementFromVariant(child, variant, elementsToDelete); + } + } + } + } + + onDeleteVariant() { + this.currentVariant = null; + this.emptyVariant = true; + + this.multiSelect = false; + this.multipleSelected = false; + + this.cacheCurrentVariant(); + + this.variantChange.emit({ + variant: this.currentVariant ? this.currentVariant.copy() : null, + }); + this.triggerRedraw(); + } + removeSelection() { + this.selectedElement = false; + this.multiSelect = false; + this.multipleSelected = false; + + this.triggerRedraw(); + this.newLeaf = null; + } + + // @ts-ignore + handleRedraw(selection: Selection<any, any, any, any>) { + selection.selectAll('g').on('click', function (event, d) { + event.stopPropagation(); + const select = d3.select(this as SVGElement); + toogleSelect(select); + }); + + const toogleSelect = function (svgSelection) { + if (!this.multiSelect) { + d3.selectAll('.pattern-variant') + .selectAll('.selected-polygon') + .classed('selected-polygon', false) + .attr('stroke', false); + + d3.selectAll('.pattern-variant') + .selectAll('.selected-variant-g') + .classed('selected-variant-g', false); + + svgSelection.classed('selected-variant-g', true); + + const poly = svgSelection.select('polygon'); + poly.classed('selected-polygon', true); + + this.multipleSelected = false; + } else { + this.multipleSelected = true; + + svgSelection.classed( + 'selected-variant-g', + !svgSelection.classed('selected-variant-g') + ); + + const poly = svgSelection.select('polygon'); + + poly.classed('selected-polygon', !poly.classed('selected-polygon')); + + // If one is selected reactivate insert + if ( + d3 + .selectAll('.pattern-variant') + .selectAll('.selected-variant-g') + .nodes().length == 1 + ) { + this.multipleSelected = false; + } + } + this.selectedElement = true; + }.bind(this); + + selection.selectAll('g').classed('selected-variant-g', (d) => { + return d === this.newLeaf; + }); + + if (!(selection.selectAll('.selected-variant-g').nodes().length > 0)) { + this.selectedElement = false; + } + + const poly = selection + .selectAll('.selected-variant-g') + .select('polygon') + .classed('selected-polygon', true); + + this.variantEnrichedSelection = selection; + } +} + +enum activityInsertionStrategy { + infront = 'infront', + behind = 'behind', + parallel = 'parallel', + replace = 'replace', + choice = 'choice', + fallthrough = 'fallthrough', +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-sequentializer/variant-sequentializer.component.css b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/variant-sequentializer.component.css new file mode 100644 index 0000000000000000000000000000000000000000..4be27cd5d6815f83a8a8033cc3a8d935e1f45f21 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/variant-sequentializer.component.css @@ -0,0 +1,38 @@ +.variant-sequentializer-editor { + display: block; + margin: 0; + border-radius: 3px; + color: var(--text-secondary); + resize: none; + width: 100%; + cursor: text; + padding: 10px; + font-size: var(--standard-font-size); + letter-spacing: 0.25px; + background-color: rgb(var(--bs-dark-rgb) var(--bs-bg-opacity)); +} + +.variant-sequentializer-editor:focus { + outline: none; + box-shadow: none; +} + +:host { + position: absolute; + overflow: hidden; +} + +.consistency-warning { + position: absolute; + left: 0; + bottom: 0; + color: var(--bs-warning); + background-color: rgb(0 0 0 / 100%); + padding: 6px 5px 2.5px; + font-size: small; + border-top-right-radius: 4px; +} + +.variant-sequentializer-modal { + --bs-modal-width: 80%; +} diff --git a/src/frontend/src/app/components/variant-explorer/variant-sequentializer/variant-sequentializer.component.html b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/variant-sequentializer.component.html new file mode 100644 index 0000000000000000000000000000000000000000..19b8d60dac4d90b6f88f78411d966a468da7c656 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/variant-sequentializer.component.html @@ -0,0 +1,94 @@ +<div + class="modal fade show variant-sequentializer-modal" + id="variantSequentializerModalDialog" + tabindex="-1" + role="dialog" + aria-labelledby="variantSequentializerModalLabel" + aria-hidden="true" +> + <div class="modal-dialog modal-xl" role="document"> + <div class="modal-content dialog"> + <div class="modal-header h-line-modal-bottom"> + <h5 class="modal-title text-light" id="variantSequentializerModalLabel"> + Variant Sequentializer + </h5> + <button + type="button" + class="btn-close btn-close-white" + data-bs-dismiss="modal" + aria-label="Close" + ></button> + </div> + <div class="consistency-warning" @fadeIn *ngIf="consistencyWarning"> + The source pattern and target pattern are not consistent! + </div> + <div class="modal-body"> + <app-pattern-editor + #SourceEditor + id="source-pattern" + [ifSource]="ifSource" + [referenceVariant]="targetPattern" + (variantChange)="handleSourceChange($event)" + > + <label #patternTitle class="text-light dialog-label"> + Source Pattern + </label> + </app-pattern-editor> + <app-pattern-editor + #TargetEditor + id="target-pattern" + [ifSource]="!ifSource" + [referenceVariant]="sourcePattern" + (variantChange)="handleTargetChange($event)" + > + <label #patternTitle class="text-light dialog-label"> + Target Pattern + </label> + </app-pattern-editor> + <div class="modal-footer h-line-modal-top"> + <button + id="close-modal" + type="button" + class="button" + data-bs-dismiss="modal" + > + <i class="bi bi-x btn-icon text-danger"></i> + Close + </button> + <button type="button" class="button" (click)="apply()"> + <i class="bi bi-save btn-icon text-success"></i> + Apply + </button> + </div> + </div> + </div> + </div> +</div> + +<div + class="modal fade" + id="warningModalDialog" + tabindex="-1" + role="dialog" + aria-labelledby="warningModalLabel" + aria-hidden="true" +> + <div class="modal-dialog modal-m" role="document"> + <div class="modal-content dialog"> + <div class="modal-header h-line-modal-bottom"> + <h5 class="modal-title text-light" id="warningModalLabel">Warning</h5> + <button + type="button" + class="btn-close btn-close-white" + data-bs-dismiss="modal" + aria-label="Close" + ></button> + </div> + <div class="modal-body"> + <p style="text-align: center; color: white"> + The source pattern and target pattern are not consistent! + </p> + </div> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/variant-sequentializer/variant-sequentializer.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/variant-sequentializer.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..7c5cc2301dbe4fb895006ed990ef1260391464e2 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/variant-sequentializer.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantSequentializerComponent } from './variant-sequentializer.component'; +import { VariantSequentializerComponent } from './variant-sequentializer.component'; + +describe('VariantSequentializerComponent', () => { + let component: VariantSequentializerComponent; + let fixture: ComponentFixture<VariantSequentializerComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantSequentializerComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantSequentializerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant-sequentializer/variant-sequentializer.component.ts b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/variant-sequentializer.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..3adccc6b36f6e351fde33fcf26c2bdba6d4d8615 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant-sequentializer/variant-sequentializer.component.ts @@ -0,0 +1,195 @@ +import { ZoomFieldComponent } from 'src/app/components/zoom-field/zoom-field.component'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { BackendService } from 'src/app/services/backendService/backend.service'; +import { VariantExplorerComponent } from 'src/app/components/variant-explorer/variant-explorer.component'; +import { GoldenLayoutComponentService } from 'src/app/services/goldenLayoutService/golden-layout-component.service'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; +import { SharedDataService } from 'src/app/services/sharedDataService/shared-data.service'; +import { + Component, + ElementRef, + Inject, + OnInit, + Renderer2, + ViewChild, + HostListener, + OnDestroy, +} from '@angular/core'; + +import { cloneDeep } from 'lodash'; +import { select, Selection } from 'd3'; +import * as objectHash from 'object-hash'; +import * as d3 from 'd3'; +import { LogService } from 'src/app/services/logService/log.service'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { VariantDrawerDirective } from 'src/app/directives/variant-drawer/variant-drawer.directive'; +import { InfixType, setParent } from 'src/app/objects/Variants/infix_selection'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { + VariantElement, + LeafNode, + SequenceGroup, + ParallelGroup, +} from 'src/app/objects/Variants/variant_element'; +import { collapsingText, fadeInText } from 'src/app/animations/text-animations'; +import { findPathToSelectedNode } from 'src/app/objects/Variants/utility_functions'; +import { Observable, of, Subject } from 'rxjs'; +import { first, takeUntil, tap } from 'rxjs/operators'; +import { + activityInsertionStrategy, + VariantModelerComponent, +} from '../../variant-modeler/variant-modeler.component'; +import { PatternEditorComponent } from './pattern-editor/pattern-editor.component'; +declare var $; + +@Component({ + selector: 'app-variant-sequentializer', + templateUrl: './variant-sequentializer.component.html', + styleUrls: ['./variant-sequentializer.component.css'], +}) +export class VariantSequentializerComponent implements OnInit, OnDestroy { + activityNames: Array<String> = []; + + public colorMap: Map<string, string>; + + @ViewChild('SourceEditor', { static: false }) + sourceEditor: PatternEditorComponent; + @ViewChild('TargetEditor', { static: false }) + targetEditor: PatternEditorComponent; + + consistencyWarning = false; + + ifSource: boolean = true; + redrawSignal: boolean = false; + sourcePattern: VariantElement = null; + targetPattern: VariantElement = null; + + collapse = false; + + zoom: any; + + redundancyWarning = false; + private _destroy$ = new Subject(); + + constructor( + private variantService: VariantService, + private backendService: BackendService, + private logService: LogService, + + private colorMapService: ColorMapService + ) { + const a = 1; + } + + ngOnInit(): void { + this.variantService.showVariantSequentializerDialog + .pipe(takeUntil(this._destroy$)) + .subscribe((_) => { + this.showModal(); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + showModal(): void { + $('#variantSequentializerModalDialog').modal('show'); + this.redrawSignal = true; + //this.logService.addActivityInEventLog('...'); + //this.colorMapService.createColorMap(Object.keys(this.logService.activitiesInEventLog)); + setTimeout(() => { + this.sourceEditor.checkButtonCollapse(); + this.targetEditor.checkButtonCollapse(); + }, 10); //make sure the function to be after the rendering + } + + hideModal(): void { + $('#variantSequentializerModalDialog').modal('hide'); + } + + activityExist(leaf: LeafNode, variant: VariantElement) { + const children = variant.getElements(); + if (variant instanceof LeafNode) { + return leaf.asLeafNode().activity[0] === variant.asLeafNode().activity[0]; + } else { + for (const child of children) { + if (this.activityExist(leaf, child)) { + return true; + } + } + return false; + } + } + + checkPattern(source: VariantElement, target: VariantElement) { + const children = source.getElements(); + if (source instanceof LeafNode) { + console.log('check ' + source.asLeafNode().activity[0]); + console.log('result ' + !this.activityExist(source, target)); + return this.activityExist(source, target); + } else { + for (const child of children) { + if (!this.checkPattern(child, target)) { + return false; + } + } + return true; + } + } + + VariantToPattern(parent: VariantElement): String { + const children = parent.getElements(); + if (parent instanceof LeafNode) { + return "'" + parent.asLeafNode().activity[0] + "'"; + } else { + var pattern = ''; + if (parent instanceof SequenceGroup) { + if (parent.getElements().length > 1) { + pattern = '->(' + pattern; + for (const child of children) { + pattern = pattern + ' ' + this.VariantToPattern(child); + } + pattern = pattern + ')'; + } else { + for (const child of children) { + pattern = pattern + ' ' + this.VariantToPattern(child); + } + } + } else if (parent instanceof ParallelGroup) { + pattern = '+(' + pattern; + for (const child of children) { + pattern = pattern + ' ' + this.VariantToPattern(child); + } + pattern = pattern + ')'; + } + } + return pattern; + } + + handleSourceChange(event) { + this.sourcePattern = event.variant; + } + handleTargetChange(event) { + this.targetPattern = event.variant; + } + + apply(): void { + if ( + this.checkPattern( + this.sourceEditor.currentVariant, + this.targetEditor.currentVariant + ) + ) { + this.backendService.applyVariantSequentializer( + this.sourceEditor.currentVariant.serialize(), + this.targetEditor.currentVariant.serialize() + ); + this.hideModal(); + } else { + this.consistencyWarning = true; + setTimeout(() => (this.consistencyWarning = false), 2500); + } + } +} diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/infix-selection-controlls/infix-selection-controlls.component.css b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/infix-selection-controlls/infix-selection-controlls.component.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/infix-selection-controlls/infix-selection-controlls.component.html b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/infix-selection-controlls/infix-selection-controlls.component.html new file mode 100644 index 0000000000000000000000000000000000000000..4b24976612ecf10ad40ccb65e2deb86ee73603d5 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/infix-selection-controlls/infix-selection-controlls.component.html @@ -0,0 +1,49 @@ +<div> + <td> + <button + [disabled]="!variant.variant.isAnyInfixSelected" + class="button" + (click)="addCurrentSelectedInfix()" + ngbTooltip="Add the currently selected infix to the variant explorer" + triggers="hover" + container="body" + > + <i + class="bi bi-scissors align-middle font-large" + [ngClass]=" + variant.variant.isAnyInfixSelected ? 'text-light' : 'text-secondary' + " + ></i> + </button> + </td> + <td> + <button + [disabled]="!variant.variant.isAnyInfixSelected" + class="button" + (click)="resetSelectionStatus()" + ngbTooltip="Reset trace infix selection of this variant" + triggers="hover" + container="body" + > + <i + class="bi bi-x-lg align-middle font-large" + [ngClass]=" + variant.variant.isAnyInfixSelected ? 'text-danger' : 'text-secondary' + " + ></i> + </button> + </td> + <td> + <button + class="button" + (click)="selectAll()" + ngbTooltip="Select the whole variant" + triggers="hover" + container="body" + > + <i + class="bi bi-plus-square-dotted align-middle font-large text-light" + ></i> + </button> + </td> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/infix-selection-controlls/infix-selection-controlls.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/infix-selection-controlls/infix-selection-controlls.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..191f76f1b57a59b0d685df996c52575729306d83 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/infix-selection-controlls/infix-selection-controlls.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InfixSelectionControllsComponent } from './infix-selection-controlls.component'; + +describe('InfixSelectionControllsComponent', () => { + let component: InfixSelectionControllsComponent; + let fixture: ComponentFixture<InfixSelectionControllsComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [InfixSelectionControllsComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(InfixSelectionControllsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/infix-selection-controlls/infix-selection-controlls.component.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/infix-selection-controlls/infix-selection-controlls.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..14d6cc049e4a1788e13afb34058120de0221c4ec --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/infix-selection-controlls/infix-selection-controlls.component.ts @@ -0,0 +1,37 @@ +import { VariantDrawerDirective } from 'src/app/directives/variant-drawer/variant-drawer.directive'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Variant } from 'src/app/objects/Variants/variant'; + +@Component({ + selector: 'app-infix-selection-controlls', + templateUrl: './infix-selection-controlls.component.html', + styleUrls: ['./infix-selection-controlls.component.css'], +}) +export class InfixSelectionControllsComponent { + constructor() {} + + @Input() + variant: Variant; + + @Input() + variantDrawer: VariantDrawerDirective; + + @Output() + public selectTraceInfix = new EventEmitter<Variant>(); + + addCurrentSelectedInfix(): void { + this.selectTraceInfix.emit(this.variant); + this.variantDrawer.redraw(); + } + + resetSelectionStatus(): void { + this.variant.variant.resetSelectionStatus(); + this.variantDrawer.redraw(); + } + + selectAll(): void { + this.variant.variant.setAllChildrenSelected(); + this.variant.variant.updateSelectionAttributes(); + this.variantDrawer.redraw(); + } +} diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-conformance-button/tree-conformance-button.component.css b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-conformance-button/tree-conformance-button.component.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-conformance-button/tree-conformance-button.component.html b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-conformance-button/tree-conformance-button.component.html new file mode 100644 index 0000000000000000000000000000000000000000..975c5d773c2e88bd0a8cedfeaa22264feb45516a --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-conformance-button/tree-conformance-button.component.html @@ -0,0 +1,42 @@ +<div + *ngIf="isConformanceCalcInProgress; else conformanceToggle" + class="d-flex flex-column align-items-center" +> + <div + class="spinner-border spinner-border-sm text-primary" + role="status" + ></div> + <div class="cursor-pointer" (click)="cancelRequest()"> + <i class="bi bi-x-lg"></i> + </div> +</div> +<ng-template #conformanceToggle> + <div + class="cursor-pointer" + (click)="toggleTreeConformance()" + [ngbTooltip]="tooltip" + triggers="hover" + container="body" + style="display: flex; flex-direction: column" + > + <ng-template #tooltip> + <div *ngIf="isConformanceActive; else tooltipConfNotAvailable"> + Conformance: {{ (conformanceValue * 100).toFixed(2) }}% + <hr class="tooltip-hr" /> + click to remove variant to conformance projection on model + </div> + + <ng-template #tooltipConfNotAvailable> + click to add variant to conformance projection on model + </ng-template> + </ng-template> + <i + class="bi fs-4" + [ngClass]="{ + 'bi-toggle2-on text-light': isConformanceActive, + 'bi-toggle2-off text-muted': !isConformanceActive + }" + > + </i> + </div> +</ng-template> diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-conformance-button/tree-conformance-button.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-conformance-button/tree-conformance-button.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..77d49f70319a7394a219bdb9fade2407f0df5e81 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-conformance-button/tree-conformance-button.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TreeConformanceButtonComponent } from './tree-conformance-button.component'; + +describe('TreeConformanceButtonComponent', () => { + let component: TreeConformanceButtonComponent; + let fixture: ComponentFixture<TreeConformanceButtonComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [TreeConformanceButtonComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TreeConformanceButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-conformance-button/tree-conformance-button.component.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-conformance-button/tree-conformance-button.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..d5007a8540dd2537c32bc81257ce85e81288a0b4 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-conformance-button/tree-conformance-button.component.ts @@ -0,0 +1,55 @@ +import { Component, Input, Output, EventEmitter } from '@angular/core'; +import { ProcessTree } from 'src/app/objects/ProcessTree/ProcessTree'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { ConformanceCheckingService } from 'src/app/services/conformanceChecking/conformance-checking.service'; + +@Component({ + selector: 'app-tree-conformance-button', + templateUrl: './tree-conformance-button.component.html', + styleUrls: ['./tree-conformance-button.component.css'], +}) +export class TreeConformanceButtonComponent { + @Input() + variant: Variant; + + constructor(public conformanceCheckingService: ConformanceCheckingService) {} + + toggleTreeConformance() { + if (this.conformanceCheckingService.isTreeConformanceActive(this.variant)) + this.conformanceCheckingService.removeFromTreeConformance(this.variant); + else this.conformanceCheckingService.addToTreeConformance(this.variant); + } + + cancelRequest() { + this.conformanceCheckingService.removeFromTreeConformance(this.variant); + } + + get conformanceValue() { + const tree = this.conformanceCheckingService.variantsTreeConformance.get( + this.variant + ); + + if (!tree) return null; + + return this.conformanceCheckingService.isConformanceWeighted && + tree.conformance?.weighted_by_counts != undefined + ? tree.conformance?.weighted_by_counts.value + : tree.conformance?.weighted_equally.value; + } + + get isConformanceActive() { + return this.conformanceCheckingService.isTreeConformanceActive( + this.variant + ); + } + + get isConformanceCalcInProgress() { + return this.conformanceCheckingService.isTreeConformanceCalcInProgress( + this.variant + ); + } + + get deleteButtonTooltip() { + return 'remove conformance values of this variant'; + } +} diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component.css b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component.css new file mode 100644 index 0000000000000000000000000000000000000000..5563419cbd3c3007ccbeaa62e24a509de0391d0b --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component.css @@ -0,0 +1,3 @@ +.variant-performance-icon { + color: white; +} \ No newline at end of file diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component.html b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component.html new file mode 100644 index 0000000000000000000000000000000000000000..c94a3e7276c3a01fac3f059a3691abaf3f2cdf22 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component.html @@ -0,0 +1,54 @@ +<div + *ngIf="isPerformanceCalcInProgress; else performanceToggle" + class="d-flex flex-column align-items-center" +> + <div + class="spinner-border spinner-border-sm text-primary" + role="status" + ></div> + <div class="cursor-pointer" (click)="cancelRequest()"> + <i class="bi bi-x-lg"></i> + </div> +</div> +<ng-template #performanceToggle> + <div + class="cursor-pointer" + (click)="toggleTreePerformance()" + [ngbTooltip]="tooltip" + triggers="hover" + container="body" + style="display: flex; flex-direction: column" + > + <ng-template #tooltip> + <div *ngIf="isPerformanceActive; else tooltipPerfNotAvailable"> + {{ tooltipText }} + <hr class="tooltip-hr" /> + click to remove variant to performance projection on model + <div *ngIf="!isPerformanceFitting"> + <hr class="tooltip-hr" /> + <i class="bi bi-exclamation-triangle-fill text-warning"> + Unfitting traces: possibly unreliable model performance values! + </i> + <br /> + Fitness: {{ variantFitness }} + </div> + </div> + + <ng-template #tooltipPerfNotAvailable> + click to add variant to performance projection on model + </ng-template> + </ng-template> + <i + class="bi fs-4" + [ngClass]="{ + 'bi-toggle2-on text-light': isPerformanceActive, + 'bi-toggle2-off text-muted': !isPerformanceActive + }" + ></i> + <i + *ngIf="!isPerformanceFitting && isPerformanceActive" + class="bi bi-exclamation-triangle-fill" + style="margin-top: -10px" + ></i> + </div> +</ng-template> diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..1a126a938f10bef5792a308566a163e77f279a23 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TreePerformanceButtonComponent } from './tree-performance-button.component'; + +describe('TreePerformanceButtonComponent', () => { + let component: TreePerformanceButtonComponent; + let fixture: ComponentFixture<TreePerformanceButtonComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [TreePerformanceButtonComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TreePerformanceButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..98178b844a8e2b4071df77926f5b3ce9f9e939f4 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/tree-buttons/tree-performance-button/tree-performance-button.component.ts @@ -0,0 +1,65 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { HumanizeDurationPipe } from 'src/app/pipes/humanize-duration.pipe'; +import { ModelPerformanceColorScaleService } from 'src/app/services/performance-color-scale.service'; +import { PerformanceService } from 'src/app/services/performance.service'; + +@Component({ + selector: 'app-tree-performance-button', + templateUrl: './tree-performance-button.component.html', + styleUrls: ['./tree-performance-button.component.css'], +}) +export class TreePerformanceButtonComponent { + constructor( + private performanceService: PerformanceService, + private modelPerformanceColorScaleService: ModelPerformanceColorScaleService + ) {} + + @Input() + variant: Variant; + + get isPerformanceActive() { + return this.performanceService.isTreePerformanceActive(this.variant); + } + + get isPerformanceCalcInProgress() { + return this.performanceService.isTreePerformanceCalcInProgress( + this.variant + ); + } + + get isPerformanceFitting() { + return this.performanceService.isTreePerformanceFitting(this.variant); + } + + toggleTreePerformance() { + if (this.performanceService.isTreePerformanceActive(this.variant)) + this.performanceService.removeFromTreePerformance(this.variant); + else this.performanceService.addToTreePerformance(this.variant); + } + + cancelRequest() { + this.performanceService.removeFromTreePerformance(this.variant); + } + + get variantFitness(): string { + return this.performanceService.fitness.get(this.variant)?.toFixed(2); + } + + get tooltipText(): string { + const selectedColorScale = + this.modelPerformanceColorScaleService.selectedColorScale; + let performance = this.performanceService.variantsTreePerformance.get( + this.variant + ).performance[selectedColorScale.performanceIndicator]?.[ + selectedColorScale.statistic + ]; + if (performance == undefined) { + performance = 0; + } + const humanizedPerf = HumanizeDurationPipe.apply(performance * 1000, { + round: true, + }); + return `${selectedColorScale.performanceIndicator} (${selectedColorScale.statistic}): ${humanizedPerf}`; + } +} diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-action-buttons/variant-action-buttons.component.css b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-action-buttons/variant-action-buttons.component.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-action-buttons/variant-action-buttons.component.html b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-action-buttons/variant-action-buttons.component.html new file mode 100644 index 0000000000000000000000000000000000000000..c304a58ff03b57bbe90a4278ca5b8db370ae3ba3 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-action-buttons/variant-action-buttons.component.html @@ -0,0 +1,19 @@ +<div class="d-flex flex-row"> + <div + class="cursor-pointer btn btn-outline-dark btn-sm remove-variant-button me-2 ms-2" + ngbTooltip="show arc diagram" + (click)="showArcDiagramBtnClicked()" + triggers="hover" + container="body" + ><i class="bi bi-rainbow text-light"></i> + </div> + <div + class="cursor-pointer btn btn-outline-dark btn-sm remove-variant-button me-2 ms-2" + (click)="deleteVariant()" + ngbTooltip="remove variant from event log" + triggers="hover" + container="body" + > + <i class="bi bi-trash text-light"></i> + </div> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-action-buttons/variant-action-buttons.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-action-buttons/variant-action-buttons.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..f89b0ded6b7b1c3fb6f01c0ca6c57f155f9b42f1 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-action-buttons/variant-action-buttons.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantActionButtonsComponent } from './variant-action-buttons.component'; + +describe('VariantDeleteButtonComponent', () => { + let component: VariantActionButtonsComponent; + let fixture: ComponentFixture<VariantActionButtonsComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantActionButtonsComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantActionButtonsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-action-buttons/variant-action-buttons.component.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-action-buttons/variant-action-buttons.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..1e0f9803606e0ff7d5b6e4bb821c590e6c3bc217 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-action-buttons/variant-action-buttons.component.ts @@ -0,0 +1,37 @@ +import { + Component, + EventEmitter, + Input, + Output, + QueryList, +} from '@angular/core'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { IVariant } from '../../../../../objects/Variants/variant_interface'; +import { Subject } from 'rxjs'; +import { VariantVisualisationComponent } from '../variant-visualisation/variant-visualisation.component'; + +@Component({ + selector: 'app-variant-action-buttons', + templateUrl: './variant-action-buttons.component.html', + styleUrls: ['./variant-action-buttons.component.css'], +}) +export class VariantActionButtonsComponent { + @Input() + private variant: IVariant; + @Input() + protected variantVisualisations: QueryList<VariantVisualisationComponent>; + @Output() + showArcDiagram = new EventEmitter<number[]>(); + + constructor(private variantService: VariantService) {} + + private _destroy$ = new Subject(); + + deleteVariant() { + this.variantService.deleteVariant(this.variant.bid); + } + + showArcDiagramBtnClicked() { + this.showArcDiagram.emit([this.variant.bid]); + } +} diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/conformance-status-icon/conformance-status-icon.component.css b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/conformance-status-icon/conformance-status-icon.component.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/conformance-status-icon/conformance-status-icon.component.html b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/conformance-status-icon/conformance-status-icon.component.html new file mode 100644 index 0000000000000000000000000000000000000000..71c3b56de96417542f2f146604b1d5f7d7d06e3d --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/conformance-status-icon/conformance-status-icon.component.html @@ -0,0 +1,54 @@ +<ng-container + *ngIf="!variant.calculationInProgress; else calculationInProgress" +> + <!-- timeout icon--> + <i + class="bi bi-hourglass-bottom font-large text-warning" + *ngIf="variant.isTimeouted" + ngbTooltip="(re)calculate conformance statistics" + triggers="hover" + container="body" + ></i> + + <!-- check-square icon--> + <i + class="bi bi-check-square font-large text-success" + *ngIf="variant.deviations === 0 && !variant.isConformanceOutdated" + ></i> + <i + class="bi bi-check-square font-large text-warning" + *ngIf="variant.deviations === 0 && variant.isConformanceOutdated" + ngbTooltip="(re)calculate conformance statistics" + triggers="hover" + container="body" + > + </i> + <!-- x-square icon--> + <i + class="bi bi-x-square font-large text-danger" + *ngIf="variant.deviations > 0 && !variant.isConformanceOutdated" + > + </i> + <i + class="bi bi-x-square font-large text-warning" + *ngIf="variant.deviations > 0 && variant.isConformanceOutdated" + ngbTooltip="(re)calculate conformance statistics" + triggers="hover" + container="body" + > + </i> + + <!-- question mark icon--> + <i + class="bi bi-question-square text-secondary align-middle font-large" + *ngIf="variant.deviations === undefined && !variant.isTimeouted" + ngbTooltip="(re)calculate conformance statistics" + triggers="hover" + container="body" + > + </i> +</ng-container> +<ng-template #calculationInProgress> + <!-- hourglass-split icon--> + <i class="bi bi-hourglass-split font-large text-secondary"></i> +</ng-template> diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/conformance-status-icon/conformance-status-icon.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/conformance-status-icon/conformance-status-icon.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..33d3834d204095bba78ae9db4ee34881c5076805 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/conformance-status-icon/conformance-status-icon.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConformanceStatusIconComponent } from './conformance-status-icon.component'; + +describe('ConformanceStatusIconComponent', () => { + let component: ConformanceStatusIconComponent; + let fixture: ComponentFixture<ConformanceStatusIconComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ConformanceStatusIconComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConformanceStatusIconComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/conformance-status-icon/conformance-status-icon.component.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/conformance-status-icon/conformance-status-icon.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..508d5372f17be768fe9fbd3ccdbca862d9b46e01 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/conformance-status-icon/conformance-status-icon.component.ts @@ -0,0 +1,13 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Variant } from 'src/app/objects/Variants/variant'; + +@Component({ + selector: 'app-conformance-status-icon', + templateUrl: './conformance-status-icon.component.html', + styleUrls: ['./conformance-status-icon.component.css'], +}) +export class ConformanceStatusIconComponent { + @Input() + variant: Variant; + constructor() {} +} diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/variant-info.component.css b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/variant-info.component.css new file mode 100644 index 0000000000000000000000000000000000000000..aa4a56c09d015ff615a1890a7869644cb2f312f6 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/variant-info.component.css @@ -0,0 +1,4 @@ +.variant-info-cell { + align-items: center; + display: flex; +} diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/variant-info.component.html b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/variant-info.component.html new file mode 100644 index 0000000000000000000000000000000000000000..8c867d4815769725dc69bb9c92a31b39354b61df --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/variant-info.component.html @@ -0,0 +1,88 @@ +<div class="variant-info-cell"> + <app-variant-selection-button + *ngIf="selectable" + [isSelected]="variant.isSelected" + (selectionChanged)="selectionChanged.emit($event)" + > + </app-variant-selection-button> + + <div + (click)="conformanceIconClicked()" + [ngClass]="isConformanceUpdatePossible() ? 'cursor-pointer' : ''" + *ngIf="processTreeIsPresent" + > + <app-conformance-status-icon + [variant]="variant" + ></app-conformance-status-icon> + </div> + + <ng-template #variantInfoTooltip + >variant describes ~{{ variant.percentage }}% of all traces in the event + log<br /> + <span class="text-secondary" + >variant occurs {{ variant.count | number }} time(s) in total</span + ></ng-template + > + + <small *ngIf="!variant.userDefined" class="ms-1 float-end"> + <span + class="cursor-help" + [ngbTooltip]="variantInfoTooltip" + triggers="hover" + placement="end" + container="body" + > + {{ variant.percentage }}%<br /> + </span> + <span class="cursor-pointer" (click)="emitVariantInfoWindowEvent()"> + ({{ variant.count | number }}) + </span> + </small> + + <small + *ngIf="variant.userDefined" + class="ms-1 float-end cursor-help" + ngbTooltip="User created Variant" + triggers="hover" + placement="end" + container="body" + > + <i class="bi bi-person-circle fs-5 ms-2"></i> + </small> + + <ng-template #variantUserDefinedTooltip> + <div class="text-start"> + <span class="fw-bold text-secondary"> #Variants </span> that contain the + fragment at least once: + {{ variantOccurrences ?? "-" }} + <span>(~{{ variantOccurrencesFraction | percent : "0.0-2" }})</span> + </div> + <div class="text-start"> + <span class="fw-bold text-secondary">#Fragment occurrences</span> among + all variants: + {{ variant.fragmentStatistics?.totalOccurrences ?? "-" }} + </div> + <div class="text-start"> + <span class="fw-bold text-secondary"> #Traces </span> that contain the + fragment at least once: + {{ traceOccurrences ?? "-" }} + <span>(~{{ traceOccurrencesFraction | percent : "0.0-2" }})</span> + </div> + <div class="text-start"> + <span class="fw-bold text-secondary">#Fragment occurrences</span> among + all traces: + {{ variant.fragmentStatistics?.totalTraceOccurrences ?? "-" }} + </div> + </ng-template> + + <small + *ngIf="variant.userDefined && variant.infixType !== 4" + class="ms-1 float-end cursor-help" + [ngbTooltip]="variantUserDefinedTooltip" + triggers="hover" + placement="end" + container="body" + > + <i class="bi bi-info fs-5 ms-2"></i> + </small> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/variant-info.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/variant-info.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..c7900c08f92d6e2a37271315aeae1791b4895a5a --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/variant-info.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantInfoComponent } from './variant-info.component'; + +describe('VariantInfoComponent', () => { + let component: VariantInfoComponent; + let fixture: ComponentFixture<VariantInfoComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantInfoComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantInfoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/variant-info.component.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/variant-info.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..f2077d403dd5fd2393ee0f28a4547330fbb8a103 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-info/variant-info.component.ts @@ -0,0 +1,92 @@ +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { + Component, + EventEmitter, + Input, + OnDestroy, + OnInit, + Output, +} from '@angular/core'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { InfixType } from 'src/app/objects/Variants/infix_selection'; + +@Component({ + selector: 'app-variant-info', + templateUrl: './variant-info.component.html', + styleUrls: ['./variant-info.component.css'], +}) +export class VariantInfoComponent implements OnInit, OnDestroy { + @Input() + variant: Variant; + + @Input() + selectable: boolean = true; + + @Output() + public selectionChanged = new EventEmitter<boolean>(); + + @Output() + public updateConformance = new EventEmitter<Variant>(); + + @Output() + public variantInfoEvent = new EventEmitter<void>(); + + public processTreeIsPresent: boolean = false; + + private _destroy$ = new Subject(); + + variantOccurrences: number; + traceOccurrences: number; + totalVariantOccurrences: number; + totalTraceOccurrences: number; + traceOccurrencesFraction: number; + variantOccurrencesFraction: number; + + constructor(private processTreeService: ProcessTreeService) {} + + ngOnInit(): void { + this.processTreeService.currentDisplayedProcessTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((t) => { + this.processTreeIsPresent = t?.isValid(); + }); + + if (this.variant.infixType != InfixType.NOT_AN_INFIX) { + let fragmentStatistics: any = this.variant.fragmentStatistics; + + this.variantOccurrences = fragmentStatistics.variantOccurrences; + this.traceOccurrences = fragmentStatistics.traceOccurrences; + this.totalVariantOccurrences = fragmentStatistics.totalOccurrences; + this.totalTraceOccurrences = fragmentStatistics.totalTraceOccurrences; + this.variantOccurrencesFraction = + fragmentStatistics.variantOccurrencesFraction; + this.traceOccurrencesFraction = + fragmentStatistics.traceOccurrencesFraction; + } + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + conformanceIconClicked(): void { + if (this.isConformanceUpdatePossible()) { + this.updateConformance.emit(this.variant); + } + } + + isConformanceUpdatePossible(): boolean { + return ( + !this.variant.calculationInProgress && + (this.variant.isConformanceOutdated || + this.variant.isTimeouted || + this.variant.deviations === undefined) + ); + } + + emitVariantInfoWindowEvent() { + this.variantInfoEvent.emit(); + } +} diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-selection-button/variant-selection-button.component.css b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-selection-button/variant-selection-button.component.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-selection-button/variant-selection-button.component.html b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-selection-button/variant-selection-button.component.html new file mode 100644 index 0000000000000000000000000000000000000000..f422d01824f8ec4f148ef8c7b7026f5c4e22af9a --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-selection-button/variant-selection-button.component.html @@ -0,0 +1,21 @@ +<i + *ngIf="tooltipText" + class="bi font-large me-2 cursor-pointer" + [ngClass]=" + isSelected ? 'bi-check2-circle text-light' : 'bi-circle text-muted' + " + (click)="onButtonSelected()" + [ngbTooltip]="tooltipText" + triggers="hover" + container="body" +> +</i> +<i + *ngIf="!tooltipText" + class="bi font-large me-2 cursor-pointer" + [ngClass]=" + isSelected ? 'bi-check2-circle text-light' : 'bi-circle text-muted' + " + (click)="onButtonSelected()" +> +</i> diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-selection-button/variant-selection-button.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-selection-button/variant-selection-button.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..de5ed8bbc7199ec1c1d9614807b47f599ba3b739 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-selection-button/variant-selection-button.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantSelectionButtonComponent } from './variant-selection-button.component'; + +describe('VariantSelectionButtonComponent', () => { + let component: VariantSelectionButtonComponent; + let fixture: ComponentFixture<VariantSelectionButtonComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantSelectionButtonComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantSelectionButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-selection-button/variant-selection-button.component.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-selection-button/variant-selection-button.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..28887c0a36c16acd23ebcc8fa03c8be46f7174a9 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-selection-button/variant-selection-button.component.ts @@ -0,0 +1,21 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; + +@Component({ + selector: 'app-variant-selection-button', + templateUrl: './variant-selection-button.component.html', + styleUrls: ['./variant-selection-button.component.css'], +}) +export class VariantSelectionButtonComponent { + @Input() + isSelected: boolean; + + @Input() + tooltipText: string; + + @Output() + public selectionChanged = new EventEmitter<boolean>(); + + onButtonSelected(): void { + this.selectionChanged.emit(!this.isSelected); + } +} diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-visualisation/variant-visualisation.component.css b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-visualisation/variant-visualisation.component.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-visualisation/variant-visualisation.component.html b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-visualisation/variant-visualisation.component.html new file mode 100644 index 0000000000000000000000000000000000000000..af94d8e9419d11675e3f64ac985764f444ac456a --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-visualisation/variant-visualisation.component.html @@ -0,0 +1,38 @@ +<div + class="variant d-flex flex-column" + [ngStyle]="{ + 'border-color': variant.isSelected + ? 'unset' + : 'transparent' + }" + style="white-space: nowrap" +> + <div *ngIf="arcsRenderingInProgress" class="full-body-spinner"> + <div class="svg-rendering-status"> + <div class="spinner-border spinner-border-sm" role="status"></div> + </div> + </div> + + <svg + #arcDiagram="arcDiagram" + appArcDiagram + [variant]="variant" + [style.display]="arcsViewMode==ArcsViewMode.SHOW_ALL ? 'block' : 'none'" + > + <g id="arcGroup"></g> + </svg> + + <svg + appVariantDrawer + #drawer="variantDrawer" + [variant]="variant" + [onClickCbFc]="variantClickCallBack" + [onRightMouseClickCbFc]="openContextCallback" + [traceInfixSelectionMode]="traceInfixSelectionMode" + [computeActivityColor]="computeActivityColor" + [infixType]="variant.infixType" + (redrawArcsIfComputed)="arcsViewMode !== ArcsViewMode.HIDE_ALL && drawArcs()" + class="zoom-group-variant" + style="display: inline-block" + ></svg> +</div> diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-visualisation/variant-visualisation.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-visualisation/variant-visualisation.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..1ac0b4cdc14f5d8be81c4969e6931a1fc394e885 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-visualisation/variant-visualisation.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantVisualisationComponent } from './variant-visualisation.component'; + +describe('VariantVisualisationComponent', () => { + let component: VariantVisualisationComponent; + let fixture: ComponentFixture<VariantVisualisationComponent>; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [VariantVisualisationComponent], + }); + fixture = TestBed.createComponent(VariantVisualisationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-visualisation/variant-visualisation.component.ts b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-visualisation/variant-visualisation.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..25a4e7556ef5c34918b794933edc286d81f2b7e3 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/subcomponents/variant-visualisation/variant-visualisation.component.ts @@ -0,0 +1,135 @@ +import { + AfterViewInit, + Component, + Input, + OnInit, + ViewChild, +} from '@angular/core'; +import { + activityColor, + clickCallback, + contextMenuCallback, +} from '../../../functions/variant-drawer-callbacks'; +import { IVariant } from '../../../../../objects/Variants/variant_interface'; +import { VariantViewModeService } from '../../../../../services/viewModeServices/variant-view-mode.service'; +import { ArcDiagramDirective } from '../../../../../directives/arc-diagram/arc-diagram.directive'; +import { VariantDrawerDirective } from '../../../../../directives/variant-drawer/variant-drawer.directive'; +import { Arc, Pair } from '../../../../../directives/arc-diagram/data'; +import { FilterParams } from '../../../arc-diagram/filter/filter-params'; +import { ArcsViewMode } from '../../../arc-diagram/arcs-view-mode'; +import { VariantPerformanceService } from '../../../../../services/variant-performance.service'; +import { takeUntil } from 'rxjs/operators'; +import { Subject } from 'rxjs'; +import { ConformanceCheckingService } from '../../../../../services/conformanceChecking/conformance-checking.service'; + +@Component({ + selector: 'app-variant-visualisation', + templateUrl: './variant-visualisation.component.html', + styleUrls: ['./variant-visualisation.component.css'], +}) +export class VariantVisualisationComponent implements OnInit, AfterViewInit { + public id: string; + public bid: number; + public arcsRenderingInProgress: boolean = false; + + private _destroy$ = new Subject(); + + constructor( + public variantViewModeService: VariantViewModeService, + public variantPerformanceService: VariantPerformanceService, + public conformanceCheckingService: ConformanceCheckingService + ) {} + + ngOnInit() { + this.id = this.variant.id; + this.bid = this.variant.bid; + if ( + Object.keys(this.arcsCache).length != 0 && + !(this.bid in this.arcsCache) && + this.arcsViewMode == ArcsViewMode.SHOW_ALL + ) { + this.arcsRenderingInProgress = true; + } + + if ( + this.bid in this.arcsCache && + this.arcsViewMode !== ArcsViewMode.HIDE_ALL && + this.arcDiagram + ) { + this.drawArcs(); + } + } + + ngAfterViewInit() { + this.variantPerformanceService.serviceTimeColorMap + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + if (colorMap !== undefined) { + this.serviceTimeColorMap = colorMap; + } + }); + + this.variantPerformanceService.waitingTimeColorMap + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + if (colorMap !== undefined) { + this.waitingTimeColorMap = colorMap; + } + }); + } + + // Define Callbacks + variantClickCallBack = clickCallback.bind(this); + openContextCallback = contextMenuCallback.bind(this); + computeActivityColor = activityColor.bind(this); + + serviceTimeColorMap: any; + waitingTimeColorMap: any; + + @Input() + traceInfixSelectionMode: boolean; + @Input() + variant: IVariant; + @Input() + colorMap: Map<string, string>; + @Input() + arcsCache: { [bid: string]: Pair[] }; + @Input() + arcsViewMode: ArcsViewMode; + @Input() + filterParams: FilterParams; + + @ViewChild(ArcDiagramDirective) + arcDiagram: ArcDiagramDirective; + @ViewChild(VariantDrawerDirective) + variantDrawer: VariantDrawerDirective; + + filterArcs(arcs: Arc[], filterParams: FilterParams) { + return arcs.filter((arc) => { + let patternSize = arc.activities.length; + return ( + patternSize <= filterParams.sizeRange.high && + patternSize >= filterParams.sizeRange.low && + arc.numberEle <= filterParams.lengthRange.high && + arc.numberEle >= filterParams.lengthRange.low && + arc.distanceBetweenPairs <= filterParams.distanceRange.high && + arc.distanceBetweenPairs >= filterParams.distanceRange.low + ); + }); + } + + drawArcs(filterParams?: FilterParams) { + if (!(this.bid in this.arcsCache)) { + return; + } + let { arcs } = this.arcDiagram.parseInput(this.arcsCache[this.bid]); + if (!filterParams) { + filterParams = this.filterParams; + } + arcs = this.filterArcs(arcs, filterParams); + this.arcDiagram.draw(this.variantDrawer, arcs); + this.arcsRenderingInProgress = false; + } + + protected readonly ArcsViewMode = ArcsViewMode; +} diff --git a/src/frontend/src/app/components/variant-explorer/variant/variant.component.html b/src/frontend/src/app/components/variant-explorer/variant/variant.component.html new file mode 100644 index 0000000000000000000000000000000000000000..e37b1ddaa7504c238723ab8d9b56b7f690dc8cde --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/variant.component.html @@ -0,0 +1,97 @@ +<td #row style="text-align: center">{{ index + 1 }}.</td> + +<ng-container *ngIf="isVisible; else loadingPlaceholder"> + <td> + <div [ngTemplateOutlet]="variantInfo"></div> + </td> + + <td> + <ng-container [ngTemplateOutlet]="subvariantButton"> </ng-container> + </td> + + <td + *ngIf=" + processTreeAvailable && variantViewModeService.viewMode !== VM.STANDARD + " + style="text-align: center" + > + <div [ngTemplateOutlet]="treeButton"></div> + </td> + <td + *ngIf=" + processTreeAvailable && variantViewModeService.viewMode !== VM.STANDARD + " + > + <small + *ngIf=" + variantViewModeService.viewMode === VM.CONFORMANCE && + isTreeConformanceActive + " + class="tree-statistic-chip" + [style.background]="conformanceButtonColor" + [style.color]="conformanceTextColor" + > + {{ (treeConformanceValue * 100).toFixed(2) }}% + </small> + <small + class="tree-statistic-chip" + [style.background]="performanceButtonColor" + [style.color]="performanceTextColor" + *ngIf=" + variantViewModeService.viewMode === VM.PERFORMANCE && + isTreePerformanceActive + " + > + {{ treePerformanceValue | humanizeDuration : false : true : 3 : true }} + </small> + </td> + + <td class="variant-cell"> + <ng-container + *ngIf=" + !( + variant.userDefined && + variantViewModeService.viewMode === VM.PERFORMANCE + ); + else noPerformance + " + > + <ng-container [ngTemplateOutlet]="variantDrawer"> </ng-container> + </ng-container> + + <ng-template #noPerformance> + <tspan class="ms-2"> Performance not available </tspan> + </ng-template> + </td> + + <td + *ngIf=" + traceInfixSelectionMode && variantViewModeService.viewMode === VM.STANDARD + " + class="infix-selection-buttons-panel" + > + <ng-container [ngTemplateOutlet]="infixSelection"> </ng-container> + </td> + + <td + *ngIf=" + !traceInfixSelectionMode && + variantViewModeService.viewMode !== VM.PERFORMANCE + " + class="fixed-right" + style="padding-left: 0px" + > + <ng-container [ngTemplateOutlet]="removeVariantButton"></ng-container> + </td> +</ng-container> + +<ng-template #loadingPlaceholder> + <td> + <div + class="variant-spacer" + [ngStyle]="{ height: variant.variant.getHeight() + 'px' }" + > + Loading... + </div> + </td> +</ng-template> diff --git a/src/frontend/src/app/components/variant-explorer/variant/variant.component.scss b/src/frontend/src/app/components/variant-explorer/variant/variant.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..eb44209fa5bfc3be969943548cb35f18d4c7105f --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/variant.component.scss @@ -0,0 +1,39 @@ +.variant { + border-width: 1px !important; + padding: 5px; + width: fit-content; + border: dashed; +} + +.variant-cell { + width: 100%; +} + +.variant-spacer { + display: flex; + flex-direction: row; + align-items: center; +} + +.fixed-right { + right: 0; + position: sticky; + background-color: var(--box-background-color); + vertical-align: middle; +} + +td { + padding-left: 15px; +} + +td:first-child { + padding-left: 15px + 4px; +} + +.tree-statistic-chip { + border-radius: 6px; + padding: 4px; + display: block; + text-align: center; + width: 100%; +} diff --git a/src/frontend/src/app/components/variant-explorer/variant/variant.component.spec.ts b/src/frontend/src/app/components/variant-explorer/variant/variant.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..152a3642ed14944a2c1724f8cca935fb00ee2d02 --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/variant.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantComponent } from './variant.component'; + +describe('VariantComponent', () => { + let component: VariantComponent; + let fixture: ComponentFixture<VariantComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-explorer/variant/variant.component.ts b/src/frontend/src/app/components/variant-explorer/variant/variant.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..9f65e4fa2c7d29b94ec7ddb95ec021b2a7acb3bc --- /dev/null +++ b/src/frontend/src/app/components/variant-explorer/variant/variant.component.ts @@ -0,0 +1,182 @@ +import { + AfterViewInit, + Component, + ContentChild, + ElementRef, + EventEmitter, + Input, + Output, + TemplateRef, + ViewChild, +} from '@angular/core'; + +import { LazyLoadingServiceService } from 'src/app/services/lazyLoadingService/lazy-loading.service'; +import { InfixType } from 'src/app/objects/Variants/infix_selection'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { VariantViewModeService } from 'src/app/services/viewModeServices/variant-view-mode.service'; +import { PerformanceService } from 'src/app/services/performance.service'; +import { ConformanceCheckingService } from 'src/app/services/conformanceChecking/conformance-checking.service'; +import { ModelPerformanceColorScaleService } from 'src/app/services/performance-color-scale.service'; +import { textColorForBackgroundColor } from 'src/app/utils/render-utils'; +import { getCssStripes } from '../../performance/color-map/color-map.component'; + +@Component({ + // eslint-disable-next-line @angular-eslint/component-selector + selector: '[app-variant]', + templateUrl: './variant.component.html', + styleUrls: ['./variant.component.scss'], +}) +export class VariantComponent implements AfterViewInit { + @ContentChild('variantInfo') variantInfo!: TemplateRef<any>; + @ContentChild('treeButton') treeButton!: TemplateRef<any>; + @ContentChild('variantDrawer') variantDrawer!: TemplateRef<any>; + @ContentChild('subvariantButton') subvariantButton!: TemplateRef<any>; + @ContentChild('infixSelection') infixSelection!: TemplateRef<any>; + @ContentChild('removeVariantButton') removeVariantButton!: TemplateRef<any>; + + @Input() + index: number; + + @Input() + variant: Variant; + + @Input() + rootElement: ElementRef; + + @Input() + traceInfixSelectionMode: boolean = false; + + @Input() + processTreeAvailable: boolean = false; + + @Output() clickCbFc: EventEmitter<any> = new EventEmitter(); + + @ViewChild('row') + rowElement: ElementRef; + + isVisible: boolean = false; + + // necessary because one cannot use it directly in the template file + infixType = InfixType; + + public VM = ViewMode; + + constructor( + private lazyLoadingService: LazyLoadingServiceService, + public variantViewModeService: VariantViewModeService, + private conformanceCheckingService: ConformanceCheckingService, + private performanceService: PerformanceService, + private modelPerformanceColorScaleService: ModelPerformanceColorScaleService + ) {} + + ngAfterViewInit(): void { + const self = this; + + this.lazyLoadingService.addVariant( + this.rowElement.nativeElement.parentNode, + this.rootElement, + (isIntersecting) => { + self.isVisible = isIntersecting; + } + ); + } + + isExpanded(): boolean { + return this.variant.variant.expanded; + } + + get isTreeConformanceActive() { + return this.conformanceCheckingService.isTreeConformanceActive( + this.variant + ); + } + + get treeConformanceValue() { + const tree = this.conformanceCheckingService.variantsTreeConformance.get( + this.variant + ); + + if (!tree) return null; + + return this.conformanceCheckingService.isConformanceWeighted && + tree.conformance?.weighted_by_counts != undefined + ? tree.conformance?.weighted_by_counts.value + : tree.conformance?.weighted_equally.value; + } + + get isTreePerformanceActive() { + return this.performanceService.isTreePerformanceActive(this.variant); + } + + get treePerformanceValue() { + const selectedColorScale = + this.modelPerformanceColorScaleService.selectedColorScale; + let performance = this.performanceService.variantsTreePerformance.get( + this.variant + ).performance[selectedColorScale.performanceIndicator]?.[ + selectedColorScale.statistic + ]; + if (performance == undefined) { + performance = 0; + } + return performance; + } + + get performanceTextColor(): string { + const buttonColor = this.performanceButtonColor; + if (!buttonColor) return 'white'; + return textColorForBackgroundColor(buttonColor); + } + + get performanceButtonColor() { + if (this.isTreePerformanceActive) { + let tree; + tree = this.performanceService.variantsTreePerformance.get(this.variant); + + if (!tree) { + return null; + } + + let selectedScale = + this.modelPerformanceColorScaleService.selectedColorScale; + const colorScale = this.modelPerformanceColorScaleService + .getVariantComparisonColorScale() + .get(tree.id); + if ( + colorScale && + tree.performance?.[selectedScale.performanceIndicator]?.[ + selectedScale.statistic + ] !== undefined + ) { + if ( + tree.performance[selectedScale.performanceIndicator][ + selectedScale.statistic + ] == 0 + ) + return getCssStripes(); + else + return colorScale.getColor( + tree.performance[selectedScale.performanceIndicator][ + selectedScale.statistic + ] + ); + } + } + return '#d3d3d3'; + } + + get conformanceButtonColor() { + if (this.treeConformanceValue >= 0 && this.isTreeConformanceActive) + return this.conformanceCheckingService.modelConformanceColorMap.getColor( + this.treeConformanceValue + ); + else return '#d3d3d3'; + } + + get conformanceTextColor() { + const buttonColor = this.conformanceButtonColor; + if (!buttonColor) return 'white'; + return textColorForBackgroundColor(buttonColor); + } +} diff --git a/src/frontend/src/app/components/variant-miner/filter-options/filter-options.component.css b/src/frontend/src/app/components/variant-miner/filter-options/filter-options.component.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/variant-miner/filter-options/filter-options.component.html b/src/frontend/src/app/components/variant-miner/filter-options/filter-options.component.html new file mode 100644 index 0000000000000000000000000000000000000000..2bdeaf64bc1bb6219ef338b65653bd70cdacf169 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/filter-options/filter-options.component.html @@ -0,0 +1,10 @@ +<div *ngFor="let choice of checks; let i = index" class="col-md-2"> + <label> + <input + type="checkbox" + [value]="choice.value" + (change)="onCheckChange($event)" + /> + {{ choice.desc }} + </label> +</div> diff --git a/src/frontend/src/app/components/variant-miner/filter-options/filter-options.component.spec.ts b/src/frontend/src/app/components/variant-miner/filter-options/filter-options.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..2b2e084f4efd5272ed15643d0f069d5093636e59 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/filter-options/filter-options.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FilterOptionsComponent } from './filter-options.component'; + +describe('FilterOptionsComponent', () => { + let component: FilterOptionsComponent; + let fixture: ComponentFixture<FilterOptionsComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [FilterOptionsComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FilterOptionsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-miner/filter-options/filter-options.component.ts b/src/frontend/src/app/components/variant-miner/filter-options/filter-options.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..6e4a250086f75a161fb0c6ac80daf0f45dbf9de7 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/filter-options/filter-options.component.ts @@ -0,0 +1,30 @@ +import { SubvariantPattern } from 'src/app/objects/Variants/variant-miner-types'; +import { Component, Input, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-filter-options', + templateUrl: './filter-options.component.html', + styleUrls: ['./filter-options.component.css'], +}) +export class FilterOptionsComponent { + constructor() {} + + @Input() + checks: Array<Choice>; +} + +export class Choice { + desc: string; + value: boolean; + filterFnc: (p: SubvariantPattern) => boolean; + + constructor( + desc: string, + value: boolean, + filterFnc: (p: SubvariantPattern) => boolean + ) { + this.desc = desc; + this.value = value; + this.filterFnc = filterFnc; + } +} diff --git a/src/frontend/src/app/components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component.css b/src/frontend/src/app/components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component.css new file mode 100644 index 0000000000000000000000000000000000000000..f6e41ec0414629df8883fef6c93809eeb306f6f9 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component.css @@ -0,0 +1,53 @@ +.activity-button-area{ + color: var(--text-secondary); + width: 100%; + max-height: fit-content; + overflow: auto auto; + place-content: baseline center; + flex-flow: row wrap; + align-items: center; + display: flex; + row-gap: 1px; + padding-top: 10px; + padding-bottom: 10px; + border-top: var(--thin-border-color) 1px solid; + border-bottom: var(--thin-border-color) 1px solid; +} + +.header-first-col{ + margin-left: 4px; +} + +.activity-button-area-1{ + width: 100%; + color: var(--text-secondary); + padding-top: 10px; + padding-bottom: 10px; + border-top: var(--thin-border-color) 1px solid; + border-bottom: var(--thin-border-color) 1px solid; +} + +.activity-label{ + font-size: smaller; + padding: 0 2px; + margin: 0 4px 0 2px; + background: rgb(119 117 117); + border-radius: 10px; + vertical-align: middle; + color: whitesmoke; + position: relative; +} + +.filter-checkbox{ + margin-left: 8px; + cursor : pointer; +} + +.filter-toggle { + min-height: unset; + margin-left: 5px; +} + +.form-check-input { + cursor : pointer; +} diff --git a/src/frontend/src/app/components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component.html b/src/frontend/src/app/components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component.html new file mode 100644 index 0000000000000000000000000000000000000000..0e2675b196178db619652e1b783196b96949f9a8 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component.html @@ -0,0 +1,120 @@ +<div class="activity-button-area-1 bg-dark"> + <div class="container"> + <div class="row justify-content-around text-center align-items-center"> + <div class="col-3 header-first-col">Activity</div> + <div class="col">Filter</div> + <div class="col" style="text-align: left !important">Out/In</div> + <div class="col-3">Activity</div> + <div class="col">Filter</div> + <div class="col" style="text-align: left !important">Out/In</div> + </div> + + <div + *ngFor=" + let index of interleavedActivityNames; + let i = index; + let even = even + " + > + <div + class="row justify-content-center text-center align-items-center" + *ngIf="even" + > + <div class="col-3"> + <svg + appVariantDrawer + [variant]="{ + variant: activityDummyVariants.get(interleavedActivityNames[i]) + }" + [computeActivityColor]="computeActivityColor" + [addCursorPointer]="false" + ></svg> + </div> + <div class="col"> + <input + class="form-check-input filter-checkbox" + type="checkbox" + (change)="activityFilterChange($event, interleavedActivityNames[i])" + [(ngModel)]=" + activityFilterStates?.get(interleavedActivityNames[i])['checkbox'] + " + /> + </div> + <div class="col text-center"> + <div class="form-check form-switch text-center filter-toggle"> + <input + class="form-check-input" + type="checkbox" + (change)=" + activityFilterChange($event, interleavedActivityNames[i]) + " + [(ngModel)]=" + activityFilterStates?.get(interleavedActivityNames[i])['toggle'] + " + [disabled]=" + !activityFilterStates?.get(interleavedActivityNames[i])[ + 'checkbox' + ] + " + /> + </div> + </div> + + <div class="col-3" *ngIf="i + 1 < interleavedActivityNames.length"> + <svg + appVariantDrawer + [variant]="{ + variant: activityDummyVariants.get( + interleavedActivityNames[i + 1] + ) + }" + [computeActivityColor]="computeActivityColor" + [addCursorPointer]="false" + ></svg> + </div> + <div class="col" *ngIf="i + 1 < interleavedActivityNames.length"> + <input + class="form-check-input filter-checkbox" + type="checkbox" + (change)=" + activityFilterChange($event, interleavedActivityNames[i + 1]) + " + [(ngModel)]=" + activityFilterStates?.get(interleavedActivityNames[i + 1])[ + 'checkbox' + ] + " + /> + </div> + <div + class="col text-center" + *ngIf="i + 1 < interleavedActivityNames.length" + > + <div class="form-check form-switch text-center filter-toggle"> + <input + class="form-check-input filter-toggle-input" + type="checkbox" + (change)=" + activityFilterChange($event, interleavedActivityNames[i + 1]) + " + [(ngModel)]=" + activityFilterStates?.get(interleavedActivityNames[i + 1])[ + 'toggle' + ] + " + [disabled]=" + !activityFilterStates.get(interleavedActivityNames[i + 1])[ + 'checkbox' + ] + " + /> + </div> + </div> + <div + class="col-6" + *ngIf="i + 1 === interleavedActivityNames.length" + ></div> + </div> + </div> + </div> +</div> diff --git a/src/frontend/src/app/components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component.spec.ts b/src/frontend/src/app/components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..5a039674249106b92ccfae664109c771fa8b9de9 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantMinerActivitiesFIlterComponent } from './variant-miner-activities-filter.component'; + +describe('VariantMinerActivitiesFIlterComponent', () => { + let component: VariantMinerActivitiesFIlterComponent; + let fixture: ComponentFixture<VariantMinerActivitiesFIlterComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantMinerActivitiesFIlterComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(VariantMinerActivitiesFIlterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component.ts b/src/frontend/src/app/components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..32de75509db10279e9a0d26e388ea8fa4988b664 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/variant-miner-activities-filter/variant-miner-activities-filter.component.ts @@ -0,0 +1,184 @@ +import { + Component, + EventEmitter, + Input, + OnChanges, + OnDestroy, + OnInit, + Output, + QueryList, + SimpleChanges, + ViewChildren, +} from '@angular/core'; +import { ColorMapService } from '../../../services/colorMapService/color-map.service'; +import { ActvitiyFilterState } from '../variant-miner.component'; +import { + LeafNode, + VariantElement, +} from '../../../objects/Variants/variant_element'; +import { VariantDrawerDirective } from '../../../directives/variant-drawer/variant-drawer.directive'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { Variant } from '../../../objects/Variants/variant'; +import * as d3 from 'd3'; + +@Component({ + selector: 'app-variant-miner-activities-filter', + templateUrl: './variant-miner-activities-filter.component.html', + styleUrls: ['./variant-miner-activities-filter.component.css'], +}) +export class VariantMinerActivitiesFIlterComponent + implements OnChanges, OnInit, OnDestroy +{ + constructor(private colorMapService: ColorMapService) {} + + @Input() + activityNames: Array<string> = []; + interleavedActivityNames: Array<string> = []; + @Input() + activityNamesFilter: Map<string, ActvitiyFilterState> = new Map< + string, + ActvitiyFilterState + >(); + activityDummyVariants: Map<string, LeafNode> = new Map<string, LeafNode>(); + activityFilterStates: Map<string, { checkbox: boolean; toggle: boolean }>; + + @Output() + activityButtonClick = new EventEmitter(); + + @ViewChildren(VariantDrawerDirective) + activityButtons: QueryList<VariantDrawerDirective>; + + colorMap: Map<string, string> = new Map<string, string>(); + + private _destroy$ = new Subject(); + + ngOnInit() { + this.activityDummyVariants = new Map<string, LeafNode>(); + this.activityFilterStates = new Map< + string, + { checkbox: boolean; toggle: boolean } + >(); + + this.interleavedActivityNames = this.activityNames.slice(); + + this.interleavedActivityNames = this.interleaveArrays( + this.interleavedActivityNames + .splice(0, Math.ceil(this.interleavedActivityNames.length / 2)) + .sort(), + this.interleavedActivityNames.sort() + ); + + for (let activity of this.activityNames) { + const leaf = new LeafNode([activity]); + leaf.setExpanded(true); + this.activityDummyVariants.set(activity, leaf); + + const activityFilter = this.activityNamesFilter.get(activity); + switch (activityFilter) { + case ActvitiyFilterState.Default: + this.activityFilterStates.set(activity, { + checkbox: false, + toggle: false, + }); + break; + + case ActvitiyFilterState.In: + this.activityFilterStates.set(activity, { + checkbox: true, + toggle: true, + }); + break; + + case ActvitiyFilterState.Out: + this.activityFilterStates.set(activity, { + checkbox: true, + toggle: false, + }); + break; + } + } + + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((map) => { + this.colorMap = map; + if (this.activityButtons) { + for (let button of this.activityButtons) { + button.redraw(); + } + } + }); + } + + interleaveArrays( + array1: Array<string>, + array2: Array<string> + ): Array<string> { + const result = array1.reduce((arr, v, i) => { + return arr.concat(v, array2[i]); + }, []); + if (array1.length > array2.length) { + result.pop(); + } + return result; + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + computeActivityColor = ( + self: VariantDrawerDirective, + element: VariantElement, + variant: Variant + ) => { + let color; + color = this.colorMap.get(element.asLeafNode().activity[0]); + + if (!color) { + color = '#d3d3d3'; // lightgrey + } + + return color; + }; + + ngOnChanges(changes: SimpleChanges): void { + // A somewhat crude way to trigger a redraw after the value did change and preventing it from firing on the initalization + // Review when the colormap might change after init + this.activityDummyVariants = new Map<string, LeafNode>(); + + for (let activity of changes.activityNames.currentValue) { + const leaf = new LeafNode([activity]); + leaf.setExpanded(true); + this.activityDummyVariants.set(activity, leaf); + } + } + + public get actvitiyFilterState(): typeof ActvitiyFilterState { + return ActvitiyFilterState; + } + + // tslint:disable-next-line:typedef + activityFilterChange(event, activity) { + const checkbox = this.activityFilterStates.get(activity).checkbox; + const toggle = this.activityFilterStates.get(activity).toggle; + let filter = ActvitiyFilterState.Default; + + if (checkbox === false) { + filter = ActvitiyFilterState.Default; + this.activityFilterStates.set(activity, { + checkbox: false, + toggle: false, + }); + event.preventDefault(); + } else if (checkbox === true && toggle === false) { + filter = ActvitiyFilterState.Out; + } else if (checkbox === true && toggle === true) { + filter = ActvitiyFilterState.In; + } + + this.activityNamesFilter.set(activity, filter); + this.activityButtonClick.emit({ activityName: activity, filter }); + } +} diff --git a/src/frontend/src/app/components/variant-miner/variant-miner-pattern/variant-miner-pattern.component.css b/src/frontend/src/app/components/variant-miner/variant-miner-pattern/variant-miner-pattern.component.css new file mode 100644 index 0000000000000000000000000000000000000000..dfdd490952a5dbb7a8cdd93365b3a604611f292f --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/variant-miner-pattern/variant-miner-pattern.component.css @@ -0,0 +1,19 @@ +.border-lightgrey{ + border-color: rgb(106 106 106 / 60%) !important; +} + +.center-element{ + border-color: rgb(106 106 106 / 20%) !important; + border-right-width: 1px; + border-left-width: 1px; +} + +.variant-spacer { + display: flex; + flex-direction: row; + align-items: center; +} + +.text-size{ + font-size: 0.9rem; +} diff --git a/src/frontend/src/app/components/variant-miner/variant-miner-pattern/variant-miner-pattern.component.html b/src/frontend/src/app/components/variant-miner/variant-miner-pattern/variant-miner-pattern.component.html new file mode 100644 index 0000000000000000000000000000000000000000..4c55b7293d337b1457097bee181f7429b5296aa8 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/variant-miner-pattern/variant-miner-pattern.component.html @@ -0,0 +1,73 @@ +<td class="text-center text-size" #row>{{ id }}.</td> +<td class="text-center text-size"> + <app-variant-selection-button + *ngIf="!pattern.isSkipGroupPattern" + [isSelected]="pattern.isSelected" + (selectionChanged)="pattern.isSelected = !pattern.isSelected" + > + </app-variant-selection-button> +</td> +<td #row> + <div class="text-center text-size"> + {{ pattern.size }} + </div> +</td> + +<td *ngIf="showConformance"> + <div class="text-center"> + <app-conformance-status-icon + [variant]="pattern" + ></app-conformance-status-icon> + </div> +</td> + +<td> + <div class="text-center text-size"> + {{ pattern.support | number }} + </div> +</td> +<!-- +<td class="center-element"> + <div class="text-center"> + + </div> +</td> +<td> + <div class="text-center"> + + </div> +</td> +--> +<td> + <div class="text-center"> + <i class="bi bi-check2" *ngIf="pattern.closed"></i> + </div> +</td> +<td> + <div class="text-center"> + <i class="bi bi-check2" *ngIf="pattern.maximal"></i> + </div> +</td> + +<td class="ps-2 d-flex" *ngIf="isVisible"> + <div + style="width: 35px" + *ngIf=" + pattern.infixType === infixtype.PREFIX || + pattern.infixType === infixtype.NOT_AN_INFIX + " + ></div> + <ng-content></ng-content> +</td> + +<td *ngIf="!isVisible" class="ps-2"> + <div + class="variant-spacer" + [ngStyle]="{ + height: pattern.variant.getHeight() + 'px', + width: pattern.variant.getWidth() + 'px' + }" + > + Loading... + </div> +</td> diff --git a/src/frontend/src/app/components/variant-miner/variant-miner-pattern/variant-miner-pattern.component.spec.ts b/src/frontend/src/app/components/variant-miner/variant-miner-pattern/variant-miner-pattern.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..a979f31a0166e519e4801dde0ae439d38d218949 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/variant-miner-pattern/variant-miner-pattern.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantMinerPatternComponent } from './variant-miner-pattern.component'; + +describe('VariantMinerPatternComponent', () => { + let component: VariantMinerPatternComponent; + let fixture: ComponentFixture<VariantMinerPatternComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantMinerPatternComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantMinerPatternComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-miner/variant-miner-pattern/variant-miner-pattern.component.ts b/src/frontend/src/app/components/variant-miner/variant-miner-pattern/variant-miner-pattern.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..4537831494d94a63c5d3b57b71060c8213568e30 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/variant-miner-pattern/variant-miner-pattern.component.ts @@ -0,0 +1,59 @@ +import { LazyLoadingServiceService } from 'src/app/services/lazyLoadingService/lazy-loading.service'; +import { + Component, + ElementRef, + Input, + ViewChild, + AfterViewInit, +} from '@angular/core'; +import { VariantDrawerDirective } from 'src/app/directives/variant-drawer/variant-drawer.directive'; +import { InfixType } from 'src/app/objects/Variants/infix_selection'; +import { SubvariantPattern } from 'src/app/objects/Variants/variant-miner-types'; +import { SkipGroup } from 'src/app/objects/Variants/variant_element'; + +@Component({ + // eslint-disable-next-line @angular-eslint/component-selector + selector: '[app-variant-miner-pattern]', + templateUrl: './variant-miner-pattern.component.html', + styleUrls: ['./variant-miner-pattern.component.css'], +}) +export class VariantMinerPatternComponent implements AfterViewInit { + @Input() + pattern: SubvariantPattern; + infixtype = InfixType; + + @Input() + showConformance: boolean; + + @Input() + id: number; + + @ViewChild('row') + rowElement: ElementRef; + + @Input() + rootElement: ElementRef; + + @ViewChild(VariantDrawerDirective) + variantDrawer: VariantDrawerDirective; + + constructor(private lazyLoadingService: LazyLoadingServiceService) {} + + isVisible: boolean = false; + + ngAfterViewInit(): void { + const self = this; + + this.lazyLoadingService.addSubPattern( + this.rowElement.nativeElement.parentNode, + this.rootElement, + (isIntersecting) => { + self.isVisible = isIntersecting; + } + ); + } + + isSkipGroupPattern() { + return this.pattern.variant instanceof SkipGroup; + } +} diff --git a/src/frontend/src/app/components/variant-miner/variant-miner.component.html b/src/frontend/src/app/components/variant-miner/variant-miner.component.html new file mode 100644 index 0000000000000000000000000000000000000000..3b2a9c47e4a9a8a9de36d12c0d5e1001a9f98bb3 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/variant-miner.component.html @@ -0,0 +1,710 @@ +<div class="variant-miner-mainblock h-100 d-flex flex-column"> + <div class="variant-miner-container" #variantMiner> + <div *ngIf="showControls" @collapse> + <div class="control-container"> + <form + [formGroup]="variantMinerConfigInput" + (ngSubmit)="onSubmit()" + class="mine-config-form" + > + <div class="form-select-element"> + <label for="frequent_mining_strat" class="input-label" + >Support Counting Strategy: + </label> + <select + formControlName="frequent_mining_strat" + class="form-select input-selector cursor-pointer" + > + <option + [ngValue]="FrequentMiningStrategy.TraceTransaction" + selected + > + Trace Transaction + </option> + <option [ngValue]="FrequentMiningStrategy.VariantTransaction"> + Variant Transaction + </option> + <option [ngValue]="FrequentMiningStrategy.TraceOccurence"> + Trace Root-Occurence + </option> + <option [ngValue]="FrequentMiningStrategy.VariantOccurence"> + Variant Root-Occurence + </option> + </select> + </div> + + <div class="form-select-element"> + <label for="frequent_mining_algo" class="input-label" + >Algorithm: + </label> + <select + formControlName="frequent_mining_algo" + class="form-select input-selector cursor-pointer" + > + <option + [ngValue]="FrequentMiningAlgorithm.ValidTreeMiner" + selected + > + Valid Tree Miner + </option> + <option [ngValue]="FrequentMiningAlgorithm.ClosedMaximalMiner"> + Blanket Tree Miner + </option> + <option [ngValue]="FrequentMiningAlgorithm.EfPatternMiner"> + EF Pattern Miner + </option> + </select> + </div> + + <div + class="form-element d-none" + *ngIf=" + variantMinerConfigInput.value.frequent_mining_algo === + FrequentMiningAlgorithm.ClosedMaximalMiner + " + > + <label for="cm_tree_strategy" class="input-label">Type: </label> + <select + formControlName="cm_tree_strategy" + class="form-select input-selector" + > + <option + [ngValue]="FrequentMiningCMStrategy.ClosedMaximal" + selected + > + Closed and Maximal + </option> + <option [ngValue]="FrequentMiningCMStrategy.OnlyMaximal"> + Only Maximal + </option> + </select> + </div> + + <div class="form-select-element"> + <label for="size" class="input-label"> + Maximum Size: + <i + class="bi bi-question-circle-fill" + ngbTooltip="The size of a pattern is not the number of activities + but the number of nodes in its tree representation. Therefore the + size of a sequence without any parallelism is its number of + activities plus one." + triggers="hover" + container="body" + ></i> + </label> + <input + id="size" + type="number" + formControlName="size" + class="input-field-number" + step="1" + min="0" + /> + </div> + + <div class="form-select-element"> + <label for="min_sup" class="input-label">Support: </label> + <div> + <input + formControlName="rel_sup" + class="input-field-number" + type="number" + step=".01" + min="0" + />% + </div> + </div> + <div class="rel-sup-input"> + <div class="sup-selector"> + <ngx-slider + [(value)]="relSup" + [options]="supportSliderOptions" + (valueChange)="relSupChanged()" + ></ngx-slider> + </div> + </div> + <div class="form-element"> + <div class="abs-sup-input"> + <input + id="min_sup" + formControlName="min_sup" + class="input-field-number" + type="number" + step="1" + min="0" + max="{{ + variantMinerConfigInput.value.frequent_mining_strat === + FrequentMiningStrategy.TraceTransaction || + variantMinerConfigInput.value.frequent_mining_strat === + FrequentMiningStrategy.TraceOccurence + ? totalTraces + : totalVariants + }}" + /> + of + {{ + (variantMinerConfigInput.value.frequent_mining_strat === + FrequentMiningStrategy.TraceTransaction || + variantMinerConfigInput.value.frequent_mining_strat === + FrequentMiningStrategy.TraceOccurence + ? totalTraces + : totalVariants + ) | number + }} + </div> + </div> + + <div + class="form-element" + *ngIf=" + this.variantMinerConfigInput.value.frequent_mining_algo !== + FrequentMiningAlgorithm.EfPatternMiner + " + > + <input + id="artifical_start" + type="checkbox" + formControlName="artifical_start" + class="input-field" + /> + <label for="artifical_start" class="input-label" + >Mine prefixes and suffixes + </label> + </div> + + <div + class="form-element last-element" + *ngIf=" + this.variantMinerConfigInput.value.frequent_mining_algo !== + FrequentMiningAlgorithm.EfPatternMiner + " + > + <input + id="fold_loop" + type="checkbox" + formControlName="fold_loop" + class="input-field" + /> + <label for="fold_loop" class="input-label">Fold Loops</label> + </div> + + <div + class="form-select-element last-element" + *ngIf=" + this.variantMinerConfigInput.value.fold_loop && + this.variantMinerConfigInput.value.frequent_mining_algo !== + FrequentMiningAlgorithm.EfPatternMiner + " + > + <label for="loop" class="input-label">Loop Threshold: </label> + <input + id="loop" + type="number" + min="1" + step="1" + formControlName="loop" + class="input-field-number" + /> + </div> + + <div class="form-element last-element"> + <button type="submit" class="button variant-miner-submit-button"> + Mine + </button> + </div> + </form> + <div *ngIf="variantPatterns.length > 0" class="mining-result-overview"> + <span class="result-span"> + <span class="result-overview-label">Total Patterns:</span> + {{ nValid | number }} + </span> + <span class="result-span"> + <span class="result-overview-label">Closed Patterns:</span> + {{ nClosed | number }}</span + > + <span class="result-span"> + <span class="result-overview-label">Maximal Patterns:</span> + {{ nMaximal | number }} + </span> + <span></span> + <span class="result-span"> + <span class="result-overview-label">Maximal Support:</span> + {{ maxSup | number }}</span + > + </div> + </div> + </div> + + <div class="pattern-table-container"> + <div class="bg-dark btn-tool-bar"> + <ng-template #toolTip2> + calculate conformance checking statistics + <br/><i class="bi bi-question-square text-secondary"> unknown</i> + <br/><i class="bi bi-hourglass-split text-secondary"> + being calculated</i + > + <br/><i class="bi bi-check-square text-success"> + variant fits model</i + > + <br/><i class="bi bi-x-square text-danger"> + variant does not fit model</i + > + <br/><i class="bi bi-check-square text-warning"></i> + <i class="bi bi-x-square text-warning"> + outdated results (model has changed)</i + > + <br/><i class="bi bi-hourglass-bottom text-warning"> timeout</i> + </ng-template> + <button + [ngbTooltip]="toolTip2" + triggers="hover" + container="body" + class="button" + (click)="computeAlignments()" + [disabled]=" + !processTree || + lastExecutedMiningAlgorithm === + FrequentMiningAlgorithm.EfPatternMiner + " + > + <i class="bi bi-layers-fill btn-icon"></i> + <div @collapseText class="button-text px-1" *ngIf="!collapse"> + conformance check + </div> + </button> + + <div class="vr"></div> + <ng-container + *ngIf=" + !(areAllPatternSkipGroups() && displayedVariantsPatterns.length > 0) + " + > + <button + class="button" + [disabled]="!isAnyPatternSelected()" + (click)="addSelectedPatternsToLog()" + ngbTooltip="Add pattern(s) to log" + triggers="hover" + container="body" + > + <i + class="bi bi-database-add" + [ngClass]="{ + 'text-success': isAnyPatternSelected() + }" + ></i> + + <div @collapseText class="button-text px-1" *ngIf="!collapse"> + Add pattern(s) to log + </div> + </button> + <div class="vr"></div> + </ng-container> + + <button + *ngIf="addLpmFeatures" + container="body" + class="button" + (click)="discoverLpms()" + [disabled]=" + lastExecutedMiningAlgorithm !== + FrequentMiningAlgorithm.EfPatternMiner + " + > + <i class="bi bi-diagram-2-fill btn-icon"></i> + <div @collapseText class="button-text px-1" *ngIf="!collapse"> + discover local process models + </div> + </button> + + <div class="vr"></div> + + <button + class="button ms-auto" + ngbTooltip="apply filters to variants" + triggers="hover" + id="dropdownMenuButton1" + data-bs-toggle="dropdown" + data-bs-reference="parent" + data-bs-auto-close="false" + aria-expanded="false" + container="body" + (click)="filterDropDownOpen = !filterDropDownOpen" + #dropdownButton + > + <i class="bi bi-funnel"></i> + </button> + + <div + class="dropdown-menu filter-drop-down dropdown-menu-end" + aria-labelledby="dropdownMenuButton1" + [style.max-height.px]="currentHeight" + #activitiesFilter + > + <div class="filter-drop-down-content"> + <div class="filter-option-container"> + <span>Size:</span> + <div class="slider-container sup-selector"> + <ngx-slider + [(value)]="kFilter.low" + [(highValue)]="kFilter.high" + [options]="kFilter.config" + (userChangeEnd)="handleFilterChange($event)" + ></ngx-slider> + </div> + </div> + <div + class="radio-content" + *ngIf=" + lastExecutedMiningAlgorithm !== + FrequentMiningAlgorithm.EfPatternMiner + " + > + <span>Model Alignment:</span> + <div class="btn-group btn-group-sm radio-container" role="group"> + <ng-template + ngFor + let-choice + [ngForOf]="alignChecks" + let-i="index" + > + <input + checked + type="checkbox" + class="btn-check" + name="btncheckbox" + id="{{ 'AlignCheck' + i }}" + autocomplete="off" + (change)=" + onCheckChange($event, alignmentFilterList, choice); + this.handleFilterChange($event) + " + /> + <label + class="btn btn-outline-dark" + for="{{ 'AlignCheck' + i }}" + > + {{ choice.desc }}</label + > + </ng-template> + </div> + </div> + + <div class="filter-option-container"> + <span>Support:</span> + <div class="slider-container sup-selector"> + <ngx-slider + [(value)]="supFilter.low" + [(highValue)]="supFilter.high" + [options]="supFilter.config" + (userChangeEnd)="handleFilterChange($event)" + ></ngx-slider> + </div> + </div> + <div class="radio-content"> + <span> Type: </span> + <div class="btn-group btn-group-sm radio-container" role="group"> + <ng-template + ngFor + let-choice + [ngForOf]="closedMaximalChecks" + let-i="index" + > + <input + type="radio" + class="btn-check" + name="btnradio" + id="{{ 'Radio' + i }}" + autocomplete="off" + (change)=" + onCheckRadioChange(choice.desc, choice.filterFnc); + this.handleFilterChange($event) + " + [checked]="choice.desc === 'Valid'" + /> + <label class="btn btn-outline-dark" for="{{ 'Radio' + i }}"> + {{ choice.desc }}</label + > + </ng-template> + </div> + </div> + <div class="radio-content"> + <span> Infix Types:</span> + <div class="btn-group btn-group-sm radio-container" role="group"> + <ng-template + ngFor + let-choice + [ngForOf]="infixChecks" + let-i="index" + > + <input + checked + type="checkbox" + class="btn-check" + name="btncheckbox" + id="{{ 'InfixCheck' + i }}" + autocomplete="off" + (change)=" + onCheckChange($event, infixFilterList, choice); + this.handleFilterChange($event) + " + /> + <label + class="btn btn-outline-dark" + for="{{ 'InfixCheck' + i }}" + > + {{ choice.desc }}</label + > + </ng-template> + </div> + </div> + <app-variant-miner-activities-filter + *ngIf="filterDropDownOpen && minerVisibile" + [activityNames]="activityNames" + [activityNamesFilter]="activityNamesFilter" + (activityButtonClick)="handleActivityButtonClick($event)" + class="activities-filter" + > + </app-variant-miner-activities-filter> + </div> + </div> + + <button + class="button" + ngbTooltip="export the process variant" + triggers="hover" + container="body" + (click)="exportVariantMiner()" + > + <i class="bi bi-save"></i> + </button> + </div> + + <div class="control-button-container"> + <button + class="btn control-button" + type="button" + (click)="showControls = !showControls" + > + <i *ngIf="showControls" class="bi bi-chevron-left btn-icon"></i> + <i *ngIf="!showControls" class="bi bi-chevron-right btn-icon"></i> + </button> + </div> + + <div class="pattern-table-container-secondary"> + <table class="pattern-table"> + <thead class="user-select-none sticky-header-row"> + <tr> + <th class="text-center header-text">No.</th> + <th class="text-center header-text"> + <app-variant-selection-button + *ngIf=" + !( + areAllPatternSkipGroups() && + displayedVariantsPatterns.length > 0 + ) + " + [isSelected]=" + areAllPatternsSelected() && + displayedVariantsPatterns.length > 0 + " + (selectionChanged)="setAllPatternsSelectionState($event)" + tooltipText="(un)select all variants" + > + </app-variant-selection-button> + </th> + <th resizeable class="text-center" rowspan="1" [margin]="-4"> + <div class="header-text-container"> + <div + class="header-text" + (click)="sort(VariantSortKey.size)" + [ngClass]="{ + 'selected-header-text': + currentSortKey === VariantSortKey.size + }" + > + Size + </div> + </div> + </th> + <th + resizeable + class="text-center" + rowspan="1" + [margin]="-4" + *ngIf=" + lastExecutedMiningAlgorithm !== + FrequentMiningAlgorithm.EfPatternMiner + " + > + <div class="header-text-container"> + <div + class="header-text" + (click)="sort(VariantSortKey.conformance)" + [ngClass]="{ + 'selected-header-text': + currentSortKey === VariantSortKey.conformance + }" + > + Fitting + </div> + </div> + </th> + <th resizeable class="text-center" rowspan="1" [margin]="-4"> + <div class="header-text-container"> + <div + class="header-text" + (click)="sort(VariantSortKey.support)" + [ngClass]="{ + 'selected-header-text': + currentSortKey === VariantSortKey.support + }" + > + Support + </div> + </div> + </th> + <th resizeable class="text-center" colspan="2" [margin]="-4"> + <div class="header-text-container"> + <div + class="header-text" + (click)="sort(VariantSortKey.closed)" + > + Type + </div> + <i + *ngIf=" + currentSortKey === VariantSortKey.closed || + currentSortKey === VariantSortKey.maximal + " + [ngClass]="{ + 'bi-sort-down-alt': ascending, + 'bi-sort-down': !ascending + }" + ></i> + </div> + </th> + <th resizeable class="text-start" rowspan="1" [margin]="-4"> + <div + class="header-text-container variant-header" + [style.min-width.px]="maxWidth + 90" + > + <div class="header-text">Variant</div> + <i + class="bi" + [ngClass]="{ + 'bi-sort-up': ascending, + 'bi-sort-down': !ascending, + invisible: true + }" + ></i> + </div> + </th> + </tr> + <tr class="sticky-header-row"> + <th> + <!-- Placeholder for No. column --> + </th> + <th> + <!-- Placeholder for column showing selection --> + </th> + <th class="text-center"> + <i + [ngClass]="{ + 'bi-sort-numeric-down': ascending, + 'bi-sort-numeric-down-alt': !ascending, + invisible: !(currentSortKey === VariantSortKey.size) + }" + ></i> + </th> + <th + class="text-center" + *ngIf=" + lastExecutedMiningAlgorithm !== + FrequentMiningAlgorithm.EfPatternMiner + " + > + <i + [ngClass]="{ + 'bi-sort-numeric-down': ascending, + 'bi-sort-numeric-down-alt': !ascending, + invisible: !(currentSortKey === VariantSortKey.conformance) + }" + ></i> + </th> + <th class="text-center"> + <i + [ngClass]="{ + 'bi-sort-numeric-down': ascending, + 'bi-sort-numeric-down-alt': !ascending, + invisible: !(currentSortKey === VariantSortKey.support) + }" + ></i> + </th> + <th class="confidence-names text-center"> + <div + (click)="sort(VariantSortKey.closed)" + class="header-text" + [ngClass]="{ + 'selected-header-text': + currentSortKey === VariantSortKey.closed + }" + > + Closed + </div> + </th> + <th class="confidence-names text-center"> + <div + (click)="sort(VariantSortKey.maximal)" + class="header-text" + [ngClass]="{ + 'selected-header-text': + currentSortKey === VariantSortKey.maximal + }" + > + Maximal + </div> + </th> + <th class="confidence-names text-center"> + <div class="header-text"></div> + </th> + </tr> + </thead> + <tbody> + <tr + app-variant-miner-pattern + *ngFor="let pattern of displayedVariantsPatterns; let i = index" + [id]="i + 1" + [pattern]="pattern" + [showConformance]=" + lastExecutedMiningAlgorithm !== + FrequentMiningAlgorithm.EfPatternMiner + " + [rootElement]="variantMinerDiv" + > + <svg + appVariantDrawer + #fragment + [variant]="pattern" + [computeActivityColor]="computeActivityColor" + [onRightMouseClickCbFc]="openContextCallback" + [onClickCbFc]="onClickCbFc" + [infixType]="pattern.infixType" + [keepStandardView]="true" + [addCursorPointer]="false" + class="zoom-group-variant" + ></svg> + </tr> + </tbody> + </table> + </div> + </div> + </div> +</div> + +<app-variant-explorer-context-menu + [xPos]="contextMenu_xPos" + [yPos]="contextMenu_yPos" + [contextMenuOptions]="contextMenuOptions" +></app-variant-explorer-context-menu> diff --git a/src/frontend/src/app/components/variant-miner/variant-miner.component.scss b/src/frontend/src/app/components/variant-miner/variant-miner.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..4b257e9bda76762bfe9a247856922a07a520ff26 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/variant-miner.component.scss @@ -0,0 +1,445 @@ + +:host { + position: absolute; + overflow: hidden; +} + +.variant-miner-mainblock { + background-color: var(--box-background-color); + max-height: 100%; + position: relative; + border-left: 1px solid var(--thin-border-color); +} + +.rel-sup-input{ + width : 225px; +} + +.form-select-element{ + padding-left: 2.5px; + width: 100%; + display: flex; + align-items: stretch; + flex-flow: column wrap; +} + +.close-icon{ + color : white +} + +.badge-position{ + position: relative; + left: -25%; + top: -30%; + transform: scale(0.6); + display: inline; +} + +.badge-close{ + font-size: 8px; +} + +.badge-close-position:hover{ + filter: brightness(150%); +} + +.badge-button{ + padding: 0; + font-size: unset; + display: contents; +} + +.badge-container{ + margin-left : -20px; +} + +::ng-deep { + .sup-selector .ngx-slider .ngx-slider-pointer { + width: 8px; + height: 16px; + top: auto; /* to remove the default positioning */ + bottom: 0; + background-color: rgb(215 213 213); + border-top-left-radius: 3px; + border-top-right-radius: 3px; + } + + .sup-selector .ngx-slider .ngx-slider-pointer::after { + display: none; + } + + .ngx-slider .ngx-slider-bubble { + color: whitesmoke !important; + } + + .sup-selector .ngx-slider .ngx-slider-bubble { + bottom: 14px; + font-size: small; + } + + .sup-selector .ngx-slider .ngx-slider-tick { + width: 3.5px; + height: 12px; + margin-left: 3px; + border-radius: 0; + background-color: #d7d5d5; + top: -1px; + border-top-left-radius: 1px; + border-top-right-radius: 1px; +} + + .ngx-slider .ngx-slider-ticks-values-under .ngx-slider-tick-value { + display: none !important; + bottom: -24px !important; + } +} + +.pattern-table-container{ + color : var(--text-secondary); + width: 100%; + height: 100%; + overflow: auto; +} + +.pattern-table-container-secondary{ + overflow: auto; + height: calc(100% - 28px); + width: 100%; +} + +.form-check-input:focus { + border-color: none; + outline: 0; + box-shadow: none; +} + +.pattern-table{ + color : var(--text-secondary); + width : 100%; +} + +.button-text { + display: inline-block; +} + + +.mining-result-overview{ + color: whitesmoke; + font-size: small; + display: flex; + flex-direction: column; + place-content: space-around flex-end; + margin-top: 5px; +} + + +.variant-header{ + display: flex; + place-content: flex-start flex-start !important; + align-items: flex-start !important; +} + +.input-field{ + width: fit-content; + margin-right: 10px; + border-radius: 3px; + background-color: var(--box-background-color); + box-shadow: none; + border: none; + color: whitesmoke; + cursor: pointer; +} + +.input-field-number{ + margin: 7px 0 6px 7px; + width: fit-content; + width: 80px; + border-radius: 3px; + background-color: var(--box-background-color); + box-shadow: none; + border: none; + color: whitesmoke; + padding: 0.125rem 0.25rem 0.125rem 0.35rem; + height: 26px; + font-size: small; +} + +.abs-sup-input { + font-size: small; +} + +.last-element{ + margin-bottom: 6px; +} + +.input-label{ + font-size: 0.85rem; +} + +.selected-header-text{ + color : white; +} + +.header-text-container{ + display: flex; + flex-flow: row nowrap; + justify-content: space-evenly; + font-size: 0.9rem; +} + +.header-text{ + padding-left: 5px; + padding-right: 5px; + cursor: pointer; + user-select: none; +} + +.header-text:hover{ + color : whitesmoke; +} + +.filter-button{ + padding: 4px; + color: whitesmoke; + background-color: black; + font-size: 13px; + box-shadow: none; + border-radius: 0 0 0 5px; +} + +.control-button-container{ + position: absolute; + bottom: 0; + z-index:10; +} + +.control-button{ + color: whitesmoke; + background-color: black; + font-size: 6px; + padding: 0; + box-shadow: none; + border-radius: 0 5px 0 0; +} + + +.filter-drop-down-content{ + display: flex; + flex-flow: column wrap; + align-items: stretch; + align-content: center; +} + +.filter-button-container{ + position: absolute; + top: -4px; + right:0; + z-index: 15; +} + +.export-button-container{ + position: absolute; + right: 0; + z-index: 15; + bottom: 0; +} + +.export-button{ + color: whitesmoke; + background-color: black; + font-size: 6px; + padding: 2px 4px; + box-shadow: none; + border-radius: 5px 0 0; +} + +.filter-button:hover{ + color : white; +} + +.conformance-button{ + background: inherit; + border: none; + color: var(--bs-gray-300); + cursor:pointer; +} + +.conformance-button:disabled{ + cursor:default; + color: var(--bs-gray-700); +} + +.conformance-button:hover:enabled{ + color: var(--bs-gray-100); +} + +.filter-option-container{ + z-index: 12; + display: flex; + flex-flow: row nowrap; + align-items: baseline; + place-content: flex-end left; + padding: 0 10px; +} + +.slider-container{ + width : 25vw; + z-index: 12; + margin-left: auto; + margin-right: 0; +} + +.radio-content{ + display: flex; + flex-direction: row; + padding: 5px 10px; + align-items: center; + align-content: center; +} + +.radio-container{ + margin-left: auto; + margin-right: 0; +} + +.activities-filter { + width: 100%; + margin-top: 5px; +} + +.closed-and-maximal-radio-input{ + margin-top: 20px; +} + +.dropdown-menu { + border-radius: 0; + background-color: lightgray; +} + +.filter-drop-down{ + color: whitesmoke; + font-size: small; + border-radius: 0.25rem; + padding: 5px 10px 30px; + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); + overflow: auto scroll; + width: 35.5vw; + margin-right: 40px !important; +} + +.filter-toggle-drop-down{ + color: white; + border-radius: 0.25rem; + padding: 10px; + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); +} + +.confidence-names{ + font-size: x-small; + font-weight: 400; +} + +.sticky-header-row{ + position: sticky; + top: 0; + z-index : 10; + background-color: var(--box-background-color); + box-shadow: inset 0 -2px 1px var(--thin-border-color); +} + +.border-lightgrey{ + border-color: rgb(106 106 106 / 60%) !important; +} + +.center-element{ + border-color: rgb(106 106 106 / 20%) !important; + border-right-width: 1px; + border-left-width: 1px; +} + + + +.input-selector{ + padding: 0.125rem 0.25rem 0.125rem 0.35rem; + font-size: 0.85rem; + color: whitesmoke; + background-color: var(--box-background-color); + border: none; + margin: 7px; + width : 180px; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='whitesmoke' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); +} + +.variant-miner-submit-button{ + background: rgb(119 117 117); + border-radius: 3px; +} + +.form-element{ + padding: 2.5px; +} + +.mine-config-form{ + display: flex; + flex-flow: column nowrap; + place-content: space-around space-around; + height: fit-content; + width: fit-content; + align-items: flex-start; +} + +.result-span{ + user-select: none; +} + +.result-overview-label{ + color: var(--text-secondary); +} + +.control-container{ + width: fit-content; + height: fit-content; + height: 100%; + min-height: 100%; + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); + padding: 20px; + display: flex; + flex-flow: column nowrap; + place-content: center space-between; + align-items: flex-start; + color: whitesmoke; + border-right: black 0.5px solid; + overflow: visible scroll; +} + +.variant-miner-container{ + width : 100%; + height : 100%; + display : flex; + border-bottom: black 0.5px solid; +} + +.btn { + color: whitesmoke; + background-color: var(--box-background-color); + border-color: #999; + font-size: small; +} + +.btn-check + .btn, :not(.btn-check) + .btn, .btn:first-child, .btn.show { + color: #999; + background-color: var(--box-background-color); + border-color: #999; + font-size: small; +} + +.btn:first-child, :not(.btn-check) + .btn, .btn-check:hover + .btn, .btn.show { + color: whitesmoke; +} + +.btn-check:checked + .btn, :not(.btn-check) + .btn:active, .btn:first-child:active, .btn.active, .btn.show { + color: whitesmoke; + background-color: rgb(119 117 117); + border-color: rgb(119 117 117); + font-size: small; +} diff --git a/src/frontend/src/app/components/variant-miner/variant-miner.component.spec.ts b/src/frontend/src/app/components/variant-miner/variant-miner.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..0979d227197e9a335879ed4e6543a3ade75bca10 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/variant-miner.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantMinerComponent } from './variant-miner.component'; + +describe('VariantMinerComponent', () => { + let component: VariantMinerComponent; + let fixture: ComponentFixture<VariantMinerComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantMinerComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantMinerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-miner/variant-miner.component.ts b/src/frontend/src/app/components/variant-miner/variant-miner.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..5806fcfa1d9ebad221224020db0bae3b1e70ab43 --- /dev/null +++ b/src/frontend/src/app/components/variant-miner/variant-miner.component.ts @@ -0,0 +1,1199 @@ +import { PolygonDrawingService } from 'src/app/services/polygon-drawing.service'; +import { VariantFilterService } from './../../services/variantFilterService/variant-filter.service'; +import { LazyLoadingServiceService } from 'src/app/services/lazyLoadingService/lazy-loading.service'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { SharedDataService } from 'src/app/services/sharedDataService/shared-data.service'; +import { BackendService } from './../../services/backendService/backend.service'; +import { + AfterViewInit, + Component, + ElementRef, + Inject, + OnDestroy, + OnInit, + QueryList, + Renderer2, + ViewChild, + ViewChildren, +} from '@angular/core'; +import { + ComponentContainer, + ComponentItemConfig, + LayoutManager, + LogicalZIndex, + Side, +} from 'golden-layout'; + +import { DropzoneConfig } from '../drop-zone/drop-zone.component'; +import * as d3 from 'd3'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; +import { UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { Options } from 'ngx-slider-v2'; +import { animate, style, transition, trigger } from '@angular/animations'; +import { + AlignmentType, + ConformanceCheckingService, +} from 'src/app/services/conformanceChecking/conformance-checking.service'; +import { + FrequentMiningAlgorithm, + FrequentMiningCMStrategy, + FrequentMiningStrategy, + MiningConfig, + SubvariantPattern, + VariantSortKey, +} from '../../objects/Variants/variant-miner-types'; +import { processTreesEqual } from 'src/app/objects/ProcessTree/utility-functions/process-tree-integrity-check'; +import { LogService } from 'src/app/services/logService/log.service'; +import { VariantService } from 'src/app/services/variantService/variant.service'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { VariantDrawerDirective } from 'src/app/directives/variant-drawer/variant-drawer.directive'; +import { ProcessTree } from 'src/app/objects/ProcessTree/ProcessTree'; +import { InfixType, setParent } from 'src/app/objects/Variants/infix_selection'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { + VariantElement, + LeafNode, + deserialize, +} from 'src/app/objects/Variants/variant_element'; +import { contextMenuCallback } from '../variant-explorer/functions/variant-drawer-callbacks'; +import { ImageExportService } from 'src/app/services/imageExportService/image-export-service'; +import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators'; +import { Subject } from 'rxjs'; +import { VariantSorter } from 'src/app/objects/Variants/variant-sorter'; +import { ContextMenuItem } from '../variant-explorer/variant-explorer-context-menu/variant-explorer-context-menu.component'; +import { DecimalPipe } from '@angular/common'; +import { LpmExplorerComponent } from '../lpm-explorer/lpm-explorer.component'; +import { GoldenLayoutComponentService } from 'src/app/services/goldenLayoutService/golden-layout-component.service'; +import { LpmService } from 'src/app/services/lpmService/lpm.service'; +import { LocalProcessModelWithPatterns } from 'src/app/objects/LocalProcessModelWithPatterns'; +import { environment } from '../../../environments/environment'; +import * as objectHash from 'object-hash'; +@Component({ + selector: 'app-variant-miner', + templateUrl: './variant-miner.component.html', + styleUrls: ['./variant-miner.component.scss'], + animations: [ + trigger('collapse', [ + transition(':enter', [ + style({ opacity: '0', width: '0px', overflow: 'hidden' }), + animate('250ms ease-in', style({ width: '*' })), + ]), + transition(':leave', [ + animate('250ms ease-in', style({ opacity: '0.4', width: '0px' })), + ]), + ]), + ], +}) +export class VariantMinerComponent + extends LayoutChangeDirective + implements OnInit, AfterViewInit, OnDestroy +{ + constructor( + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + private backendService: BackendService, + private sharedDataService: SharedDataService, + private colorMapService: ColorMapService, + private conformanceCheckingService: ConformanceCheckingService, + private processTreeService: ProcessTreeService, + private lazyLoadingServiceService: LazyLoadingServiceService, + private logService: LogService, + private variantService: VariantService, + private variantFilterService: VariantFilterService, + private polygonDrawingService: PolygonDrawingService, + private imageExportService: ImageExportService, + private goldenLayoutComponentService: GoldenLayoutComponentService, + private lpmService: LpmService, + elRef: ElementRef, + private renderer: Renderer2, + private deciamlPipe: DecimalPipe + ) { + super(elRef.nativeElement, renderer); + + const activitites = this.logService.activitiesInEventLog; + + for (let activity in activitites) { + this.activityNames.push(activity); + this.activityNames.sort(); + this.activityNamesFilter.set(activity, ActvitiyFilterState.Default); + } + } + + @ViewChildren(VariantDrawerDirective) + variantDrawers: QueryList<VariantDrawerDirective>; + + @ViewChild('variantMiner', { static: false }) + variantMinerDiv: ElementRef<HTMLDivElement>; + + @ViewChild('dropdownButton') dropdownButton: ElementRef; + @ViewChild('activitiesFilter') activitiesFilter; + + FrequentMiningStrategy = FrequentMiningStrategy; + FrequentMiningAlgorithm = FrequentMiningAlgorithm; + FrequentMiningCMStrategy = FrequentMiningCMStrategy; + VariantSortKey = VariantSortKey; + currentSortKey: VariantSortKey; + lastExecutedMiningAlgorithm: FrequentMiningAlgorithm = + FrequentMiningAlgorithm.ValidTreeMiner; + + currentHeight: number; + private _destroy$ = new Subject(); + + activityNames = []; + activityNamesFilter: Map<string, ActvitiyFilterState> = new Map< + string, + ActvitiyFilterState + >(); + processTree: ProcessTree = null; + conformanceCheckedTree: ProcessTree = null; + + conformanceTimeout = 30; + math = Math; + + maxSup: number; + maxSize: number; + nClosed: number; + nValid: number; + nMaximal: number; + + filterDropDownOpen: boolean = false; + minerVisibile: boolean = true; + + contextMenu_xPos: number = 10; + contextMenu_yPos: number = 10; + contextMenu_element: VariantElement; + contextMenu_variant: VariantElement; + contextMenu_directive: VariantDrawerDirective; + collapse: boolean = false; + + kFilter: IntervalFilter = new IntervalFilter( + 'size', + 2, + 2, + 1, + 3, + 15, + this.deciamlPipe + ); + supFilter: IntervalFilter = new IntervalFilter( + 'support', + 100, + 200, + 1, + 0, + 1000, + this.deciamlPipe + ); + idFilter: IntervalFilter = new IntervalFilter( + 'id', + 1, + 2, + 1, + 0, + 15, + this.deciamlPipe + ); + cpConfFilter: IntervalFilter = new IntervalFilter( + 'child_parent_confidence', + 0.1, + 0.2, + 0.01, + 0, + 1, + this.deciamlPipe + ); + supConfFilter: IntervalFilter = new IntervalFilter( + 'subpattern_confidence', + 0.1, + 0.2, + 0.01, + 0, + 1, + this.deciamlPipe + ); + + openContextCallback = contextMenuCallback.bind(this); + + onClickCbFc() { + // hide tooltip + if (this.variantService.activityTooltipReference) { + this.variantService.activityTooltipReference.tooltip('hide'); + } + } + + exportSVG = function () { + let svgs: SVGGraphicsElement[] = []; + let state: boolean[] = []; + + const visibleComponents = this.contextMenu_directive; + svgs.push(visibleComponents.getSVGGraphicElement()); + + svgs.forEach((svg) => { + svg.removeAttribute('ng-reflect-variant'); + svg.removeAttribute('ng-reflect-on-click-cb-fc'); + svg.removeAttribute('ng-reflect-performance-mode'); + svg.removeAttribute('ng-reflect-compute-activity-color'); + svg.removeAttribute('appVariantDrawer'); + svg.removeAttribute('class'); + d3.select(svg).selectAll('text').attr('data-bs-original-title', null); + }); + + svgs.push( + d3 + .select('#infixDotsForDrawer') + .attr('width', 0) + .attr('height', 0) + .node() as SVGGraphicsElement + ); + + // Send all Elements to the export service + this.imageExportService.export('variant_explorer', 0, 0, ...svgs); + + // Return everything to its previous state + visibleComponents.forEach((c, i) => c.setExpanded(state[i])); + }.bind(this); + + filterInfix = function () { + const bids = this.displayedVariantsPatterns.filter( + (v) => v.variant === this.contextMenu_variant + )[0].bids; + + this.variantFilterService.addVariantFilter('infix filter', new Set(bids)); + }.bind(this); + + contextMenuOptions: Array<ContextMenuItem> = [ + new ContextMenuItem( + 'Use infix to filter concurrency variants', + 'bi-funnel-fill', + this.filterInfix + ), + new ContextMenuItem('Export pattern as SVG', 'bi-save', this.exportSVG), + ]; + + currentConfig: MiningConfig = null; + + showControls: boolean = true; + relSup = 25; + + supportSliderOptions: Options = { + floor: 0, + ceil: 100, + step: 0.01, + tickStep: 25, + showSelectionBar: true, + showTicks: true, + translate: (value: number): string => { + return +value.toFixed(1) + '%'; + }, + }; + + closedMaximalChecks: Choice[] = [ + new Choice('Maximal', (p: SubvariantPattern) => p.maximal), + new Choice('Closed', (p: SubvariantPattern) => p.closed), + new Choice('Valid', (p: SubvariantPattern) => true), + ]; + selClosedMaximal: string = 'Valid'; + + infixChecks: Choice[] = [ + new Choice( + 'Proper Infix', + (p: SubvariantPattern) => p.infixType === InfixType.PROPER_INFIX + ), + new Choice( + 'Suffix', + (p: SubvariantPattern) => p.infixType === InfixType.POSTFIX + ), + new Choice( + 'Prefix', + (p: SubvariantPattern) => p.infixType === InfixType.PREFIX + ), + new Choice( + 'Variant', + (p: SubvariantPattern) => p.infixType === InfixType.NOT_AN_INFIX + ), + ]; + + alignChecks: Choice[] = [ + new Choice('Fitting', (p: SubvariantPattern) => p.deviations === 0), + new Choice('Not Fitting', (p: SubvariantPattern) => p.deviations > 0), + new Choice('Unknown', (p: SubvariantPattern) => p.isConformanceOutdated), + ]; + + infixFilterList = this.infixChecks.map((c) => c); + alignmentFilterList = this.alignChecks.map((c) => c); + closedMaxFilter: (p: SubvariantPattern) => boolean = ( + p: SubvariantPattern + ) => { + return true; + }; + + ascending: boolean = false; + minsup: number = 0; + + maxWidth: number = 0; + + variantMinerResults: any; + colorMap; + + totalTraces: number; + totalVariants: number; + + showOnlyClosed: boolean = false; + showOnlyMaximal: boolean = false; + + variantPatterns: Array<SubvariantPattern> = new Array<SubvariantPattern>(); + displayedVariantsPatterns: Array<SubvariantPattern> = + new Array<SubvariantPattern>(); + + variantMinerConfigInput: UntypedFormGroup; + + addLpmFeatures = environment.showLpms; + + ngOnInit(): void { + this.subscribeForConformanceCheckingResults(); + + const rel_sup = new UntypedFormControl(this.relSup, { + updateOn: 'change', + }); + + const min_sup = new UntypedFormControl(1000, { + updateOn: 'change', + }); + + const frequent_mining_strat = new UntypedFormControl( + this.FrequentMiningStrategy.TraceTransaction, + { + updateOn: 'change', + } + ); + + this.variantMinerConfigInput = new UntypedFormGroup({ + size: new UntypedFormControl(20, { + updateOn: 'change', + }), + + min_sup, + rel_sup, + frequent_mining_strat, + + artifical_start: new UntypedFormControl(false, { + updateOn: 'change', + }), + + fold_loop: new UntypedFormControl(false, { + updateOn: 'change', + }), + loop: new UntypedFormControl(2, { + updateOn: 'change', + }), + + frequent_mining_algo: new UntypedFormControl( + this.FrequentMiningAlgorithm.ValidTreeMiner, + { + updateOn: 'change', + } + ), + + cm_tree_strategy: new UntypedFormControl( + this.FrequentMiningCMStrategy.ClosedMaximal, + { + updateOn: 'change', + } + ), + }); + + rel_sup.valueChanges + .pipe(debounceTime(10), distinctUntilChanged()) + .subscribe((relSup) => { + const min_sup_update = + this.variantMinerConfigInput.value.frequent_mining_strat === + FrequentMiningStrategy.TraceTransaction || + this.variantMinerConfigInput.value.frequent_mining_strat === + FrequentMiningStrategy.TraceOccurence + ? Math.round((relSup / 100) * this.totalTraces) + : Math.round((relSup / 100) * this.totalVariants); + + min_sup.setValue(min_sup_update, { emitEvent: false, onlySelf: true }); + this.relSup = relSup; + }); + + min_sup.valueChanges + .pipe(debounceTime(10), distinctUntilChanged()) + .subscribe((minSup) => { + // event.target.value + const max = + this.variantMinerConfigInput.value.frequent_mining_strat === + this.FrequentMiningStrategy.TraceTransaction || + this.variantMinerConfigInput.value.frequent_mining_strat === + this.FrequentMiningStrategy.TraceOccurence + ? this.totalTraces + : this.totalVariants; + + if (minSup < 0) { + this.variantMinerConfigInput + .get('min_sup') + .patchValue(0, { emitEvent: false, onlySelf: true }); + } else if (minSup > max) { + this.variantMinerConfigInput + .get('min_sup') + .patchValue(max, { emitEvent: false, onlySelf: true }); + } + + const minSupValue = this.variantMinerConfigInput.value.min_sup; + this.relSup = parseFloat(((minSupValue / max) * 100).toFixed(2)); + }); + + frequent_mining_strat.valueChanges.subscribe((strat) => { + if ( + strat == FrequentMiningStrategy.VariantTransaction || + strat == FrequentMiningStrategy.TraceTransaction + ) { + this.supportSliderOptions = { + floor: 0, + ceil: 100, + step: 0.01, + tickStep: 25, + showSelectionBar: true, + showTicks: true, + translate: (value: number): string => { + return +value.toFixed(1) + '%'; + }, + }; + } else { + this.supportSliderOptions = { + floor: 0, + ceil: 150, + step: 0.01, + tickStep: 25, + showSelectionBar: true, + showTicks: true, + translate: (value: number): string => { + return +value.toFixed(1) + '%'; + }, + }; + } + }); + + this.variantService.variants$.subscribe((variants) => { + this.totalTraces = variants + .map((variant) => { + return variant.count; + }) + .reduce((a: number, b: number) => a + b); + this.totalVariants = variants.length; + }); + + this.variantMinerConfigInput.patchValue({ rel_sup: this.relSup }); + } + + relSupChanged() { + this.variantMinerConfigInput.patchValue({ rel_sup: this.relSup }); + } + + onSubmit() { + console.log('SUBMIT', this.variantMinerConfigInput.value); + + const form_values = this.variantMinerConfigInput.value; + + let loop = 0; + if (form_values.fold_loop) { + loop = form_values.loop; + } + + this.currentConfig = new MiningConfig( + form_values.size, + form_values.min_sup, + form_values.frequent_mining_strat, + loop, + form_values.frequent_mining_algo, + form_values.artifical_start + ); + this.backendService.frequentSubtreeMining(this.currentConfig); + + this.minsup = form_values.min_sup; + this.resetActivitiesFilter(); + this.lastExecutedMiningAlgorithm = form_values.frequent_mining_algo; + } + + handleFilterChange(event) { + const pos = []; + const neg = []; + + this.activityNamesFilter.forEach((v, k) => { + switch (v) { + case ActvitiyFilterState.In: { + pos.push(k); + break; + } + case ActvitiyFilterState.Out: { + neg.push(k); + break; + } + } + }); + + this.displayedVariantsPatterns = this.variantPatterns.filter((vp) => { + if (!this.kFilter.apply(vp)) return false; + if (!this.supFilter.apply(vp)) return false; + if (!this.idFilter.apply(vp)) return false; + if (!this.cpConfFilter.apply(vp)) return false; + if (!this.supConfFilter.apply(vp)) return false; + if (!this.closedMaxFilter(vp)) return false; + if (!this.applyActivityNameFilter(vp, pos, neg)) return false; + if (!this.alignmentFilterList.map((f) => f.filterFnc(vp)).some((v) => v)) + return false; + if (!this.infixFilterList.map((f) => f.filterFnc(vp)).some((v) => v)) + return false; + + return true; + }); + } + + applyActivityNameFilter: ( + p: SubvariantPattern, + pos: Array<string>, + neg: Array<string> + ) => boolean = ( + p: SubvariantPattern, + pos: Array<string>, + neg: Array<string> + ) => { + if ( + neg.some((a) => p.activities.has(a)) || + (pos.length > 0 && !pos.some((a) => p.activities.has(a))) + ) { + return false; + } + + return true; + }; + + ngAfterViewInit(): void { + this.renderer.listen('window', 'click', (e) => { + if ( + e.target !== this.dropdownButton.nativeElement && + e.target.parentElement !== this.dropdownButton.nativeElement && + this.activitiesFilter && + !this.activitiesFilter.nativeElement.contains(e.target) + ) { + if (this.filterDropDownOpen) { + this.dropdownButton.nativeElement.click(); + } + } + }); + + this.logService.activitiesInEventLog$ + .pipe(takeUntil(this._destroy$)) + .subscribe((activities) => { + this.activityNames = []; + for (let activity in activities) { + this.activityNames.push(activity); + this.activityNames.sort(); + this.activityNamesFilter.set(activity, ActvitiyFilterState.Default); + } + }); + + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((cMap) => { + this.colorMap = cMap; + }); + + this.logService.loadedEventLog$ + .pipe(takeUntil(this._destroy$)) + .subscribe((log) => { + this.variantPatterns = []; + this.displayedVariantsPatterns = []; + this.resetActivitiesFilter(); + }); + + this.processTreeService.currentDisplayedProcessTree$ + .pipe(takeUntil(this._destroy$)) + .subscribe((tree) => { + this.processTree = tree; + + const treeHasChanged = !processTreesEqual( + this.conformanceCheckedTree, + this.processTree + ); + + if (treeHasChanged) { + this.variantPatterns.forEach((v) => { + v.isConformanceOutdated = true; + }); + } + }); + + this.backendService + .getConfiguration() + .pipe(takeUntil(this._destroy$)) + .subscribe((config) => { + this.conformanceTimeout = + config.timeoutCVariantAlignmentComputation + 30; + }); + + this.sharedDataService.frequentMiningResults$ + .pipe(takeUntil(this._destroy$)) + .subscribe((res) => { + if (res) { + this.variantPatterns = new Array<SubvariantPattern>(); + + res.forEach((p, i) => { + if (p.valid) { + const variant: VariantElement = deserialize(p.obj); + setParent(variant); + const [isPrefix, isSuffix] = this.checkInfix(p.obj); + let infixtype: InfixType; + + if (isPrefix && isSuffix) { + infixtype = InfixType.NOT_AN_INFIX; + } else if (isPrefix) { + infixtype = InfixType.PREFIX; + } else if (isSuffix) { + infixtype = InfixType.POSTFIX; + } else { + infixtype = InfixType.PROPER_INFIX; + } + const k = p.k - (+isSuffix + +isPrefix); + + variant.setExpanded(true); + + const pattern = new SubvariantPattern( + i, + k, + variant, + p.sup, + p.child_parent_confidence, + p.subpattern_confidence, + p.cross_support_confidence, + p.maximal, + p.valid, + p.closed, + infixtype, + p.bids + ); + + pattern.isConformanceOutdated = true; + pattern.isTimeouted = false; + + this.variantPatterns.push(pattern); + } + }); + + this.maxSup = Math.max(...this.variantPatterns.map((v) => v.support)); + this.minsup = Math.min(...this.variantPatterns.map((v) => v.support)); + this.maxSize = Math.max(...this.variantPatterns.map((v) => v.size)); + this.nClosed = this.variantPatterns.filter((v) => v.closed).length; + this.nValid = this.variantPatterns.filter((v) => v.valid).length; + this.nMaximal = this.variantPatterns.filter((v) => v.maximal).length; + + this.maxWidth = Math.max( + ...this.variantPatterns.map((v) => v.variant.getWidth(false)) + ); + + this.set_interval_filter_configs(); + this.displayedVariantsPatterns = this.variantPatterns; + } else { + this.variantPatterns = []; + this.displayedVariantsPatterns = this.variantPatterns; + + this.maxSup = 0; + this.maxSize = 0; + this.nClosed = 0; + this.nValid = 0; + this.nMaximal = 0; + } + }); + } + + checkInfix(obj) { + if ('follows' in obj) { + const isPrefix = 'start' in obj['follows'][0]; + const isSuffix = 'end' in obj['follows'][obj['follows'].length - 1]; + return [isPrefix, isSuffix]; + } + return [false, false]; + } + + sort(key: VariantSortKey) { + if (this.currentSortKey == key) { + this.ascending = !this.ascending; + } else { + this.ascending = false; + } + + this.displayedVariantsPatterns = VariantSorter.sort( + this.displayedVariantsPatterns, + key, + this.ascending + ) as SubvariantPattern[]; + this.currentSortKey = key; + } + + private set_interval_filter_configs() { + this.kFilter.set_config(3, this.maxSize); + this.supFilter.set_config( + this.minsup, + this.maxSup, + Math.round((this.maxSup - this.minsup) / 10), + Math.round((this.maxSup - this.minsup) / 20) + ); + this.idFilter.set_config(0, this.variantPatterns.length); + this.cpConfFilter.set_config(0, 1); + this.supConfFilter.set_config(0, 1); + + this.resetClosedMaximalFilter(); + this.resetAlignFilter(); + this.resetInfixFilter(); + } + + exportVariantMiner() { + let svgs: SVGGraphicsElement[] = []; + let state: boolean[] = []; + + const visibleComponents = this.variantDrawers; + + // Get current expansion state + visibleComponents.forEach((c) => state.push(c.isExpanded())); + + // Expand the elements and redraw them + visibleComponents.forEach((c) => c.setExpanded(true)); + + // Collect the SVG and pass them to the SVG Service + visibleComponents.forEach((c) => svgs.push(c.getSVGGraphicElement())); + + // TODO Create the Legend Element and add it + const legend = d3.create('svg').attr('x', '10').attr('y', '10'); + + let leafnodes: LeafNode[] = []; + + for (let activity in this.logService.activitiesInEventLog) { + leafnodes.push(new LeafNode([activity])); + } + + svgs.forEach((svg) => { + svg.removeAttribute('ng-reflect-variant'); + svg.removeAttribute('ng-reflect-on-click-cb-fc'); + svg.removeAttribute('ng-reflect-performance-mode'); + svg.removeAttribute('ng-reflect-compute-activity-color'); + svg.removeAttribute('appVariantDrawer'); + svg.removeAttribute('class'); + d3.select(svg).selectAll('text').attr('data-bs-original-title', null); + }); + + this.polygonDrawingService.drawLegend(leafnodes, legend, this.colorMap); + + svgs.unshift(legend.node()); + svgs.push( + d3 + .select('#infixDotsForDrawer') + .attr('width', 0) + .attr('height', 0) + .node() as SVGGraphicsElement + ); + + // Send all Elements to the export service + this.imageExportService.export('variant_explorer', 0, 0, ...svgs); + + // Return everything to its previous state + visibleComponents.forEach((c, i) => c.setExpanded(state[i])); + + // Hide the Spinner + } + + handleActivityButtonClick(e) { + this.handleFilterChange(null); + } + + resetActivitiesFilter() { + if (this.filterDropDownOpen) { + this.dropdownButton.nativeElement.click(); + } + this.activityNames.forEach((activity) => { + this.activityNamesFilter.set(activity, ActvitiyFilterState.Default); + }); + } + + computeActivityColor = ( + self: VariantDrawerDirective, + element: VariantElement, + variant: Variant + ) => { + let color; + + if (element instanceof LeafNode) { + color = this.colorMap.get(element.asLeafNode().activity[0]); + + if (element.activity.length > 1) { + color = '#d3d3d3'; // lightgray + } + } else { + color = '#d3d3d3'; + } + + return color; + }; + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void { + this.currentHeight = height; + this.collapse = width < 875; + } + + handleVisibilityChange(visibility: boolean): void { + this.minerVisibile = visibility; + console.log('Visibility', visibility); + } + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} + + computeAlignments() { + console.log('Requested Alignment!'); + this.displayedVariantsPatterns.forEach((pattern) => + this.updateConformanceForVariant(pattern, this.conformanceTimeout) + ); + + this.conformanceCheckedTree = this.processTree; + } + + discoverLpms() { + this.backendService + .discoverLpms( + this.displayedVariantsPatterns.map((p) => p.variant.serialize()) + ) + .subscribe((res: Object[]) => { + this.lpmService.localProcessModels = res.map( + (r) => + new LocalProcessModelWithPatterns( + ProcessTree.fromObj(r['lpm']), + r['patterns'].map((p) => { + let variant = deserialize(p); + variant.setExpanded(true); + setParent(variant); + return new SubvariantPattern( + -1, + -1, + variant, + -1, + -1, + -1, + -1, + false, + false, + false, + InfixType.PROPER_INFIX, + null + ); + }) + ) + ); + this.openLocalProcessModelExplorer(); + }); + } + + openLocalProcessModelExplorer() { + const componentID = LpmExplorerComponent.componentName; + const parentComponentID = VariantMinerComponent.componentName; + + const LocationSelectors: LayoutManager.LocationSelector[] = [ + { + typeId: LayoutManager.LocationSelector.TypeId.FocusedStack, + index: undefined, + }, + ]; + + const itemConfig: ComponentItemConfig = { + id: componentID, + type: 'component', + title: 'LPM Explorer', + isClosable: true, + reorderEnabled: true, + header: { + show: Side.left, + }, + componentType: componentID, + }; + + this.goldenLayoutComponentService.openWindow( + componentID, + parentComponentID, + LocationSelectors, + itemConfig + ); + } + + onCheckRadioChange(desc, func) { + this.selClosedMaximal = desc; + this.closedMaxFilter = func; + } + + resetClosedMaximalFilter() { + this.closedMaximalChecks = [ + new Choice('Maximal', (p: SubvariantPattern) => { + return p.maximal; + }), + new Choice('Closed', (p: SubvariantPattern) => { + return p.closed; + }), + new Choice('Valid', (p: SubvariantPattern) => { + return true; + }), + ]; + this.selClosedMaximal = 'Valid'; + this.closedMaxFilter = (p: SubvariantPattern) => { + return true; + }; + } + + resetAlignFilter() { + this.alignmentFilterList = this.alignChecks.map((c) => c); + } + + resetInfixFilter() { + this.infixFilterList = this.infixChecks.map((c) => c); + } + + onCheckChange(event, fList: Array<any>, choice) { + /* Selected */ + if (event.target.checked) { + fList.push(choice); + } else { + fList.forEach((c, i) => { + if (c.desc === choice.desc) fList.splice(i, 1); + }); + } + } + + updateConformanceForVariant( + pattern: SubvariantPattern, + timeout: number + ): void { + this.processTreeService.currentDisplayedProcessTree !== null; + //variant.calculationInProgress = true; + //variant.deviation = undefined; + + const resubscribe = this.conformanceCheckingService.calculateConformance( + pattern.id.toLocaleString(), + pattern.infixType, + this.processTreeService.currentDisplayedProcessTree, + pattern.variant.serialize(this.currentConfig.loop), + timeout, + AlignmentType.PatternAlignment + ); + + if (resubscribe) { + this.subscribeForConformanceCheckingResults(); + } + } + + subscribeForConformanceCheckingResults(): void { + this.conformanceCheckingService.patternResults.subscribe( + (res) => { + const pattern = this.variantPatterns.find( + (p) => p.id.toLocaleString() == res.id + ); + pattern.calculationInProgress = false; + pattern.isTimeouted = res.isTimeout; + pattern.isConformanceOutdated = res.isTimeout; + + if (!res.isTimeout) { + pattern.deviations = res.deviations; + } + }, + (_) => { + this.variantPatterns.forEach((p) => { + p.calculationInProgress = false; + p.alignment = undefined; + p.deviations = undefined; + }); + } + ); + } + + ngOnDestroy(): void { + this.sharedDataService.frequentMiningResults = null; + this.lazyLoadingServiceService.destoryVariantMinerObserver(); + this._destroy$.next(); + } + + getSelectedPatterns(): SubvariantPattern[] { + return this.displayedVariantsPatterns.filter((v) => v.isSelected); + } + + isAnyPatternSelected(): boolean { + return this.displayedVariantsPatterns.some((v) => v.isSelected); + } + + areAllPatternsSelected(): boolean { + return this.displayedVariantsPatterns.every((v) => v.isSelected); + } + + setAllPatternsSelectionState(selectionState: boolean): void { + this.displayedVariantsPatterns.forEach( + (v) => (v.isSelected = selectionState) + ); + } + + addSelectedPatternsToLog(): void { + this.getSelectedPatterns().forEach((pattern) => { + const newVariant = new Variant( + pattern.support, + pattern.variant, + false, + true, + false, + 0, + undefined, + true, + false, + true, + 0, + pattern.infixType + ); + newVariant.alignment = undefined; + newVariant.deviations = undefined; + newVariant.id = objectHash(newVariant); + + const isDuplicate = this.variantService.variants.some((v: Variant) => { + return newVariant.equals(v) || v.id === newVariant.id; + }); + + if (!isDuplicate) { + this.variantService.nUserVariants += 1; + newVariant.bid = -this.variantService.nUserVariants; + this.variantService.variants.push(newVariant); + + if (newVariant.infixType === InfixType.NOT_AN_INFIX) { + this.variantService + .addUserDefinedVariant(newVariant) + .subscribe((response) => { + if (this.variantService.clusteringConfig) { + // trigger new clustering + this.variantService.clusteringConfig = + this.variantService.clusteringConfig; + } else { + this.variantService.variants = this.variantService.variants; + } + }); + } else { + this.backendService + .countFragmentOccurrences(newVariant) + .subscribe((statistics) => { + newVariant.fragmentStatistics = statistics; + this.variantService + .addInfixToBackend(newVariant) + .subscribe((response) => { + if (this.variantService.clusteringConfig) { + // trigger new clustering + this.variantService.clusteringConfig = + this.variantService.clusteringConfig; + } else { + this.variantService.variants = this.variantService.variants; + } + }); + }); + } + } + }); + } + + areAllPatternSkipGroups(): boolean { + return this.displayedVariantsPatterns.every((v) => v.isSkipGroupPattern); + } +} + +export namespace VariantMinerComponent { + export const componentName = 'VariantMinerComponent'; +} + +export class IntervalFilter { + apply(p: SubvariantPattern) { + return ( + !p[this.attr] || (p[this.attr] >= this.low && p[this.attr] <= this.high) + ); + } + + low: number; + high: number; + config: Options; + attr: string; + tickStep: number; + tickValueStep: number; + step: number; + defaultLow: number; + defaultHigh: number; + + set_config(floor, ceil, tickStep?, tickValueStep?) { + this.tickStep = tickStep ? tickStep : this.tickStep; + this.tickValueStep = tickValueStep ? tickValueStep : this.tickStep; + + this.config = { + floor: floor, + ceil: ceil, + draggableRange: true, + showTicksValues: true, + tickStep: this.tickStep, + tickValueStep: this.tickValueStep, + step: this.step, + translate: (value: number): string => { + return this.deciamlPipe.transform(value, '1.0'); + }, + }; + 3; + + this.defaultLow = floor; + this.defaultHigh = ceil; + + this.low = floor; + this.high = ceil; + } + + reset_filter() { + this.low = this.defaultLow; + this.high = this.defaultHigh; + } + + touched() { + return this.low !== this.defaultLow || this.high !== this.defaultHigh; + } + + constructor( + attr, + tickStep: number, + tickValueStep: number, + step: number, + defaultLow: number, + defaultHigh: number, + private deciamlPipe: DecimalPipe + ) { + this.attr = attr; + this.tickStep = tickStep; + this.tickValueStep = tickValueStep; + this.step = step; + + this.set_config(defaultLow, defaultHigh); + } +} + +export class Choice { + desc: string; + filterFnc: (p: SubvariantPattern) => boolean; + + constructor(desc: string, filterFnc: (p: SubvariantPattern) => boolean) { + this.desc = desc; + this.filterFnc = filterFnc; + } +} + +export enum ActvitiyFilterState { + In = 1, + Out = 2, + Default = 3, +} diff --git a/src/frontend/src/app/components/variant-modeler/activity-button-area/activity-button-area.component.css b/src/frontend/src/app/components/variant-modeler/activity-button-area/activity-button-area.component.css new file mode 100644 index 0000000000000000000000000000000000000000..b960d8392bb6e380a3237d7788047a3bc575aabd --- /dev/null +++ b/src/frontend/src/app/components/variant-modeler/activity-button-area/activity-button-area.component.css @@ -0,0 +1,37 @@ +.activity-button-area{ + color: var(--text-secondary); + width: 100%; + max-height: fit-content; + overflow: auto auto; + place-content: baseline center; + flex-flow: row wrap; + align-items: center; + display: flex; + row-gap: 1px; + padding-top: 10px; + padding-bottom: 10px; + border-top: var(--thin-border-color) 1px solid; + border-bottom: var(--thin-border-color) 1px solid; +} + +.activity-button{ + cursor : pointer; +} + +.activity-label{ + font-size: smaller; + padding: 0 2px; + margin: 0 4px 0 2px; + background: rgb(119 117 117); + border-radius: 10px; + vertical-align: middle; + color: whitesmoke; + position: relative; +} + +.button-disabled{ + opacity: 0.5; + user-select: none; + pointer-events: none; + +} diff --git a/src/frontend/src/app/components/variant-modeler/activity-button-area/activity-button-area.component.html b/src/frontend/src/app/components/variant-modeler/activity-button-area/activity-button-area.component.html new file mode 100644 index 0000000000000000000000000000000000000000..fd3c49b350c70226c7f3d45313fccfde73184757 --- /dev/null +++ b/src/frontend/src/app/components/variant-modeler/activity-button-area/activity-button-area.component.html @@ -0,0 +1,21 @@ +<div class="activity-button-area bg-dark"> + <div class="activity-button-container" *ngFor="let activity of activityNames"> + <!-- <app-variant-drag-source [colorMap]="colorMap" [activity]="activity"> </app-variant-drag-source> --> + <svg + #ActivityButton + appVariantDrawer + [variant]="{ variant: activityDummyVariants.get(activity) }" + [computeActivityColor]="computeActivityColor" + [onMouseOverCbFc]="onMouseOverCbFc" + [highlightOnMouseover]="true" + (click)="onActivityButtonClick(ActivityButton, activity)" + class="activity-button" + [ngClass]=" + ifSource || + activityExist(activityDummyVariants.get(activity), referenceVariant) + ? 'activity-button' + : 'button-disabled' + " + ></svg> + </div> +</div> diff --git a/src/frontend/src/app/components/variant-modeler/activity-button-area/activity-button-area.component.spec.ts b/src/frontend/src/app/components/variant-modeler/activity-button-area/activity-button-area.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..14cceb8025d115decae799c828207960027210b6 --- /dev/null +++ b/src/frontend/src/app/components/variant-modeler/activity-button-area/activity-button-area.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ActivityButtonAreaComponent } from './activity-button-area.component'; + +describe('ActivityButtonAreaComponent', () => { + let component: ActivityButtonAreaComponent; + let fixture: ComponentFixture<ActivityButtonAreaComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ActivityButtonAreaComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ActivityButtonAreaComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-modeler/activity-button-area/activity-button-area.component.ts b/src/frontend/src/app/components/variant-modeler/activity-button-area/activity-button-area.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..5500f15e8eb30be95a7a677f49858fbb403ea18a --- /dev/null +++ b/src/frontend/src/app/components/variant-modeler/activity-button-area/activity-button-area.component.ts @@ -0,0 +1,178 @@ +import { + Component, + ChangeDetectionStrategy, + Input, + OnChanges, + SimpleChanges, + Output, + EventEmitter, + OnInit, + ViewChildren, + QueryList, + OnDestroy, +} from '@angular/core'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; +import * as d3 from 'd3'; +import { VariantDrawerDirective } from 'src/app/directives/variant-drawer/variant-drawer.directive'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { + LeafNode, + VariantElement, +} from 'src/app/objects/Variants/variant_element'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { ActvitiyFilterState } from '../../variant-miner/variant-miner.component'; + +@Component({ + selector: 'app-activity-button-area', + templateUrl: './activity-button-area.component.html', + styleUrls: ['./activity-button-area.component.css'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ActivityButtonAreaComponent + implements OnChanges, OnInit, OnDestroy +{ + constructor(private colorMapService: ColorMapService) {} + + @Input() + activityNames: Array<string> = []; + + @Input() + referenceVariant: VariantElement = null; + + @Input() + ifSource: boolean = null; + + @Input() + redrawSingal: boolean = false; + + activityDummyVariants: Map<string, LeafNode> = new Map<string, LeafNode>(); + + @Output() + activityButtonClick = new EventEmitter(); + + @ViewChildren(VariantDrawerDirective) + activityButtons: QueryList<VariantDrawerDirective>; + + colorMap: Map<string, string> = new Map<string, string>(); + + private _destroy$ = new Subject(); + + ngOnInit() { + this.activityDummyVariants = new Map<string, LeafNode>(); + + for (let activity of this.activityNames) { + const leaf = new LeafNode([activity]); + leaf.setExpanded(true); + this.activityDummyVariants.set(activity, leaf); + } + + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((map) => { + this.colorMap = map; + if (this.activityButtons) { + for (let button of this.activityButtons) { + button.redraw(); + } + } + }); + } + + ngOnChanges(changes: SimpleChanges): void { + // A somewhat crude way to trigger a redraw after the value did change and preventing it from firing on the initalization + // Review when the colormap might change after init + this.activityDummyVariants = new Map<string, LeafNode>(); + + for (let activity of changes.activityNames.currentValue) { + const leaf = new LeafNode([activity]); + leaf.setExpanded(true); + this.activityDummyVariants.set(activity, leaf); + } + if (this.activityButtons) { + for (let button of this.activityButtons) { + button.redraw(); + } + } + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + onActivityButtonClick(elem: SVGElement, activity: any) { + this.activityButtonClick.emit({ svg: elem, activityName: activity }); + } + + computeActivityColor = ( + self: VariantDrawerDirective, + element: VariantElement, + variant: Variant + ) => { + let color; + color = this.colorMap.get(element.asLeafNode().activity[0]); + + if (!color) { + color = '#d3d3d3'; // lightgrey + } + + return color; + }; + + onMouseOverCbFc = ( + drawerDirective: VariantDrawerDirective, + element: VariantElement, + variant: VariantElement, + selection + ) => { + selection + .on('mouseover', function (event, d) { + const rgb_code = d3 + .select(this) + .select('polygon') + .attr('style') + .match(/[\d.]+/g); + const lightend = rgb_code.map((d) => + parseInt(d) + 50 > 255 ? 255 : parseInt(d) + 50 + ); + + d3.select(this) + .select('polygon') + .style('fill', `rgb(${lightend[0]},${lightend[1]},${lightend[2]})`) + .style('stroke-width', 2); + }) + .on('mouseout', function (event, d) { + const rgb_code = d3 + .select(this) + .select('polygon') + .attr('style') + .match(/[\d.]+/g); + const darkend = rgb_code.map((d) => + parseInt(d) - 50 < 0 ? 0 : parseInt(d) - 50 + ); + + d3.select(this) + .select('polygon') + .style('fill', `rgb(${darkend[0]},${darkend[1]},${darkend[2]})`); + }); + }; + + activityExist(leaf: LeafNode, variant: VariantElement) { + if (!variant) { + return true; + } + const children = variant.getElements(); + if (variant instanceof LeafNode) { + return leaf.asLeafNode().activity[0] === variant.asLeafNode().activity[0]; + } else { + if (children) { + for (const child of children) { + if (this.activityExist(leaf, child)) { + return true; + } + } + } + return false; + } + } +} diff --git a/src/frontend/src/app/components/variant-modeler/activity-button-area/utility_functions/find_path_to_selected_element.ts b/src/frontend/src/app/components/variant-modeler/activity-button-area/utility_functions/find_path_to_selected_element.ts new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/app/components/variant-modeler/variant-modeler.component.css b/src/frontend/src/app/components/variant-modeler/variant-modeler.component.css new file mode 100644 index 0000000000000000000000000000000000000000..75a28e257eed28973d86aa639daba2a80b1ffdfd --- /dev/null +++ b/src/frontend/src/app/components/variant-modeler/variant-modeler.component.css @@ -0,0 +1,51 @@ +:host { + position: absolute; + overflow: hidden; +} + +.variant-modeler{ + display: flex; + width: 100%; + height: 100%; + background-color: var(--box-background-color); + flex-direction: column; + border-bottom: 1px; + border-color: var(--thin-border-color); +} + +.zoom-group-variant{ + width : 100%; + height: 100%; +} + +.strategy-selected{ + background-color: #515a64; +} + +.round-corners{ + border-radius: 2px; + overflow: hidden; +} + +.button-area-disabled{ + opacity: 0.5; + user-select: none; + pointer-events: none; + +} + +.button-text{ + display : inline-block; +} + +.redundancy-warning{ + position: absolute; + left: 0; + bottom: 0; + color: var(--bs-warning); + background-color: rgb(0 0 0 / 100%); + padding: 6px 5px 2.5px; + font-size: small; + border-top-right-radius: 4px; + +} diff --git a/src/frontend/src/app/components/variant-modeler/variant-modeler.component.html b/src/frontend/src/app/components/variant-modeler/variant-modeler.component.html new file mode 100644 index 0000000000000000000000000000000000000000..a1cefba5a39c59ffb0d6370202d60bf479786084 --- /dev/null +++ b/src/frontend/src/app/components/variant-modeler/variant-modeler.component.html @@ -0,0 +1,418 @@ +<div class="variant-modeler"> + <div class="bg-dark btn-tool-bar"> + <button + class="button" + (click)="addCurrentVariantToVariantList()" + [disabled]="emptyVariant" + ngbTooltip="Add variant to Log" + triggers="hover" + container="body" + > + <i + class="bi bi-database-add" + [ngClass]="{ + 'text-success': !emptyVariant + }" + ></i> + + <div @collapseText class="button-text px-1" *ngIf="!collapse"> + Add new variant to log + </div> + </button> + + <div class="vr mx-2"></div> + + <div class="btn-group round-corners" role="group"> + <input + type="radio" + class="btn-check" + (click)="handleInfixButtonClick(infixType.NOT_AN_INFIX)" + id="radio_variant" + /> + + <label + class="button" + for="radio_variant" + [ngClass]=" + curInfixType === infixType.NOT_AN_INFIX ? 'strategy-selected' : '' + " + ngbTooltip="model as full variant" + triggers="hover" + container="body" + > + <svg height="20" width="20"> + <use href="#variantChevron"></use> + </svg> + </label> + + <input + type="radio" + class="btn-check" + (click)="handleInfixButtonClick(infixType.PREFIX)" + id="radio_prefix" + /> + <label + class="button" + for="radio_prefix" + [ngClass]="curInfixType === infixType.PREFIX ? 'strategy-selected' : ''" + ngbTooltip="model as prefix" + triggers="hover" + container="body" + > + <svg height="20" width="20"> + <use href="#prefixChevron"></use> + </svg> + </label> + + <input + type="radio" + class="btn-check" + (click)="handleInfixButtonClick(infixType.PROPER_INFIX)" + id="radio_infix" + /> + <label + class="button" + for="radio_infix" + [ngClass]=" + curInfixType === infixType.PROPER_INFIX ? 'strategy-selected' : '' + " + ngbTooltip="model as infix" + triggers="hover" + container="body" + > + <svg height="20" width="35"> + <use href="#infixChevron"></use> + </svg> + </label> + + <input + type="radio" + class="btn-check" + (click)="handleInfixButtonClick(infixType.POSTFIX)" + id="radio_postfix" + /> + <label + class="button" + for="radio_postfix" + [ngClass]=" + curInfixType === infixType.POSTFIX ? 'strategy-selected' : '' + " + ngbTooltip="model as postfix" + triggers="hover" + container="body" + > + <svg height="20" width="20"> + <use href="#postfixChevron"></use> + </svg> + </label> + </div> + + <div class="vr mx-2"></div> + + <div class="btn-group round-corners" role="group"> + <button + type="button" + class="button" + (click)="selectedStrategy = insertionStrategy.infront" + [ngClass]=" + selectedStrategy === insertionStrategy.infront + ? 'strategy-selected' + : '' + " + ngbTooltip="insert new activities infront the selected activtiy" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-bar-left"></i> + </button> + + <button + type="button" + class="button" + (click)="selectedStrategy = insertionStrategy.behind" + [ngClass]=" + selectedStrategy === insertionStrategy.behind + ? 'strategy-selected' + : '' + " + ngbTooltip="insert new activities behind of the selected activtiy" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-bar-right"></i> + </button> + + <button + type="button" + class="button" + (click)="selectedStrategy = insertionStrategy.parallel" + [ngClass]=" + selectedStrategy === insertionStrategy.parallel + ? 'strategy-selected' + : '' + " + ngbTooltip="insert new activities parallel of the selected activtiy" + triggers="hover" + container="body" + > + <i class="bi bi-arrows-expand"></i> + </button> + + <button + type="button" + class="button" + (click)="selectedStrategy = insertionStrategy.replace" + [ngClass]=" + selectedStrategy === insertionStrategy.replace + ? 'strategy-selected' + : '' + " + ngbTooltip="replace the currently selected activity" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-repeat"></i> + </button> + </div> + + <div class="vr mx-2"></div> + + <button + class="button btn-fixed-width" + (click)="undo()" + [disabled]="!(cachedVariants.length - 1 > 0 && cacheIdx !== 0)" + ngbTooltip="undo" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-counterclockwise btn-icon"></i> + <span + class="text-secondary" + *ngIf="cachedVariants.length - 1 > 0 && cacheIdx !== 0" + > + ({{ cacheIdx }}) + </span> + </button> + + <button + class="button btn-fixed-width" + (click)="redo()" + [disabled]="!(cacheIdx < cachedVariants.length - 1)" + ngbTooltip="redo" + triggers="hover" + container="body" + > + <i class="bi bi-arrow-clockwise btn-icon"></i> + <span class="text-secondary" *ngIf="cacheIdx < cachedVariants.length - 1"> + ({{ cachedVariants.length - 1 - cacheIdx }}) + </span> + </button> + + <div class="vr mx-2"></div> + + <button + class="button" + (click)="removeSelection()" + [disabled]="!selectedElement" + ngbTooltip="remove current selection" + triggers="hover" + container="body" + > + <i class="bi bi-dash-square-dotted"></i> + </button> + + <span class="vl mx-2"></span> + + <button + class="button" + (click)="onDeleteSelected()" + ngbTooltip="remove the currently selected activity" + triggers="hover" + container="body" + [disabled]="emptyVariant || !selectedElement" + > + <i + class="bi bi-trash" + [ngClass]="{ + 'text-warning': !emptyVariant + }" + ></i> + + <div @collapseText class="button-text px-1" *ngIf="!collapse"> + remove selected chevron(s) + </div> + </button> + + <div class="vr mx-2"></div> + + <button + class="button" + (click)="onDeleteVariant()" + ngbTooltip="remove the current variant" + triggers="hover" + container="body" + [disabled]="emptyVariant" + > + <i + class="bi bi-x-octagon" + [ngClass]="{ + 'text-danger': !emptyVariant + }" + ></i> + <div @collapseText class="button-text px-1" *ngIf="!collapse"> + remove current variant + </div> + </button> + + <button + class="button ms-auto" + ngbTooltip="focus selected" + triggers="hover" + container="body" + (click)="focusSelected()" + [disabled]="emptyVariant || multipleSelected" + > + <i class="bi bi-eye-fill"></i> + </button> + + <button + class="button ms-auto" + ngbTooltip="move to the start of the variant" + triggers="hover" + container="body" + (click)="centerVariant()" + > + <i class="bi bi-arrows-fullscreen btn-icon text-light"></i> + </button> + </div> + <app-activity-button-area + [activityNames]="activityNames" + (activityButtonClick)="handleActivityButtonClick($event)" + [ngClass]=" + (selectedElement && + !multipleSelected && + (selectedStrategy === insertionStrategy.infront || + selectedStrategy === insertionStrategy.behind) && + checkOverlapInsert()) || + (multipleSelected && + !( + checkNeighborSelection() && + selectedStrategy === insertionStrategy.parallel + )) || + (!selectedElement && !emptyVariant) + ? 'button-area-disabled' + : '' + " + > + </app-activity-button-area> + + <app-zoom-field + [zoomScale]="[0.1, 3]" + [computeFocusOffsets]="computeFocusOffset" + > + <svg + #content + #VariantMainGroup + appVariantDrawer + id="VariantMainGroup" + [variant]="{ variant: currentVariant }" + (selection)="handleRedraw($event)" + [computeActivityColor]="computeActivityColor" + [infixType]="curInfixType" + [keepStandardView]="true" + class="zoom-group-variant in-variant-modeler" + ></svg> + </app-zoom-field> + <div class="redundancy-warning" @fadeIn *ngIf="redundancyWarning"> + This variant already exists + </div> +</div> + +<svg> + <symbol + xmlns="http://www.w3.org/2000/svg" + width="20" + height="20" + id="variantChevron" + transform-origin="10 10" + > + <path + fill="white" + fill-rule="evenodd" + d="M3.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L9.293 8 3.646 2.354a.5.5 0 0 1 0-.708z" + /> + <path + fill="white" + fill-rule="evenodd" + d="M7.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L13.293 8 7.646 2.354a.5.5 0 0 1 0-.708z" + /> + <path + fill="white" + fill-rule="evenodd" + d="M11.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L17.293 8 11.646 2.354a.5.5 0 0 1 0-.708z" + /> + </symbol> + + <symbol + xmlns="http://www.w3.org/2000/svg" + width="20" + height="20" + id="prefixChevron" + transform-origin="10 10" + > + <path + fill="white" + fill-rule="evenodd" + d="M-1.354 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L4.293 8 -1.354 2.354a.5.5 0 0 1 0-.708z" + transform="translate(1 1)" + ></path> + <g> + <circle r="1" fill="white" transform="translate(10 9)" /> + <circle r="1" fill="white" transform="translate(14 9)" /> + <circle r="1" fill="white" transform="translate(18 9)" /> + </g> + </symbol> + <symbol + xmlns="http://www.w3.org/2000/svg" + width="35" + height="20" + id="infixChevron" + transform-origin="10 10" + > + <g> + <circle r="1" fill="white" transform="translate(2 9)" /> + <circle r="1" fill="white" transform="translate(6 9)" /> + <circle r="1" fill="white" transform="translate(10 9)" /> + </g> + <path + fill="white" + fill-rule="evenodd" + d="M-1.354 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L4.293 8 -1.354 2.354a.5.5 0 0 1 0-.708z" + transform="translate(14 1)" + ></path> + <g> + <circle r="1" fill="white" transform="translate(24 9)" /> + <circle r="1" fill="white" transform="translate(28 9)" /> + <circle r="1" fill="white" transform="translate(32 9)" /> + </g> + </symbol> + <symbol + xmlns="http://www.w3.org/2000/svg" + width="20" + height="20" + id="postfixChevron" + transform-origin="10 10" + > + <g> + <circle r="1" fill="white" transform="translate(1 9)" /> + <circle r="1" fill="white" transform="translate(5 9)" /> + <circle r="1" fill="white" transform="translate(9 9)" /> + </g> + <path + fill="white" + fill-rule="evenodd" + d="M-1.354 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L4.293 8 -1.354 2.354a.5.5 0 0 1 0-.708z" + transform="translate(13 1)" + ></path> + </symbol> +</svg> diff --git a/src/frontend/src/app/components/variant-modeler/variant-modeler.component.spec.ts b/src/frontend/src/app/components/variant-modeler/variant-modeler.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..9b23c5ae6aa7ea72fdfe6845d769f0e937d54407 --- /dev/null +++ b/src/frontend/src/app/components/variant-modeler/variant-modeler.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { VariantModelerComponent } from './variant-modeler.component'; + +describe('VariantModelerComponent', () => { + let component: VariantModelerComponent; + let fixture: ComponentFixture<VariantModelerComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantModelerComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantModelerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-modeler/variant-modeler.component.ts b/src/frontend/src/app/components/variant-modeler/variant-modeler.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3dfc5a49fdc61af6c3dc5f7da1a7fc5e94b2416 --- /dev/null +++ b/src/frontend/src/app/components/variant-modeler/variant-modeler.component.ts @@ -0,0 +1,958 @@ +import { ZoomFieldComponent } from '../zoom-field/zoom-field.component'; +import { VariantService } from '../../services/variantService/variant.service'; +import { BackendService } from 'src/app/services/backendService/backend.service'; +import { VariantExplorerComponent } from '../variant-explorer/variant-explorer.component'; +import { GoldenLayoutComponentService } from '../../services/goldenLayoutService/golden-layout-component.service'; +import { ColorMapService } from '../../services/colorMapService/color-map.service'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; +import { SharedDataService } from 'src/app/services/sharedDataService/shared-data.service'; +import { + Component, + ElementRef, + Inject, + OnInit, + Renderer2, + ViewChild, + HostListener, + OnDestroy, +} from '@angular/core'; + +import { cloneDeep } from 'lodash'; +import { select, Selection } from 'd3'; +import * as objectHash from 'object-hash'; +import * as d3 from 'd3'; +import { LogService } from 'src/app/services/logService/log.service'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { VariantDrawerDirective } from 'src/app/directives/variant-drawer/variant-drawer.directive'; +import { InfixType, setParent } from 'src/app/objects/Variants/infix_selection'; +import { FragmentStatistics, Variant } from 'src/app/objects/Variants/variant'; +import { + deserialize, + LeafNode, + ParallelGroup, + SequenceGroup, + VariantElement, +} from 'src/app/objects/Variants/variant_element'; +import { collapsingText, fadeInText } from 'src/app/animations/text-animations'; +import { findPathToSelectedNode } from 'src/app/objects/Variants/utility_functions'; +import { applyInverseStrokeToPoly } from 'src/app/utils/render-utils'; +import { Observable, of, Subject } from 'rxjs'; +import { first, takeUntil, tap } from 'rxjs/operators'; + +@Component({ + selector: 'app-variant-modeler', + templateUrl: './variant-modeler.component.html', + styleUrls: ['./variant-modeler.component.css'], + animations: [fadeInText, collapsingText], +}) +export class VariantModelerComponent + extends LayoutChangeDirective + implements OnInit, OnDestroy +{ + activityNames: Array<String> = []; + + public colorMap: Map<string, string>; + + VariantModelerComponent = VariantModelerComponent; + + @ViewChild('VariantMainGroup') + variantElement: ElementRef; + + @ViewChild(ZoomFieldComponent) + editor: ZoomFieldComponent; + + @ViewChild(VariantDrawerDirective) + variantDrawer: VariantDrawerDirective; + + currentVariant: VariantElement = null; + + cachedVariants: VariantElement[] = [null]; // edited + cacheSize: number = 100; + cacheIdx: number = 0; + + emptyVariant: boolean = true; + + selectedElement = false; + multiSelect = false; + multipleSelected = false; + + infixType = InfixType; + curInfixType = InfixType.NOT_AN_INFIX; + + newLeaf; + + collapse: boolean = false; + + insertionStrategy = activityInsertionStrategy; + selectedStrategy = this.insertionStrategy.behind; + + variantEnrichedSelection: Selection<any, any, any, any>; + zoom: any; + + redundancyWarning = false; + + private _destroy$ = new Subject(); + + constructor( + private sharedDataService: SharedDataService, + private logService: LogService, + private variantService: VariantService, + private backendService: BackendService, + private colorMapService: ColorMapService, + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + private goldenLayoutComponentService: GoldenLayoutComponentService, + elRef: ElementRef, + renderer: Renderer2 + ) { + super(elRef.nativeElement, renderer); + } + + ngOnInit(): void { + this.logService.activitiesInEventLog$ + .pipe(takeUntil(this._destroy$)) + .subscribe((activities) => { + this.activityNames = []; + for (const activity in activities) { + this.activityNames.push(activity); + this.activityNames.sort(); + } + }); + + this.logService.loadedEventLog$ + .pipe(takeUntil(this._destroy$)) + .subscribe((newLog) => { + if (newLog) { + this.emptyVariant = true; + } + }); + + this.colorMapService.colorMap$ + .pipe(takeUntil(this._destroy$)) + .subscribe((map) => { + this.colorMap = map; + if (this.variantDrawer) { + this.variantDrawer.redraw(); + } + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void { + this.collapse = width < 1150; + } + + handleVisibilityChange(visibility: boolean): void {} + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} + + handleRedraw(selection: Selection<any, any, any, any>) { + selection.selectAll('g').on('click', function (event, _) { + event.stopPropagation(); + const select = d3.select(this as SVGElement); + toogleSelect(select); + }); + const toogleSelect = function (svgSelection) { + if (!this.multiSelect) { + d3.select('#VariantMainGroup') + .selectAll('.selected-polygon') + .classed('selected-polygon', false) + .attr('stroke', false); + + d3.select('#VariantMainGroup') + .selectAll('.chevron-group') + .style('fill-opacity', 0.5); + + d3.select('#VariantMainGroup') + .selectAll('.selected-variant-g') + .classed('selected-variant-g', false); + + svgSelection.classed('selected-variant-g', true); + + const poly = svgSelection.select('polygon'); + poly.classed('selected-polygon', true); + + this.multipleSelected = false; + } else { + this.multipleSelected = true; + + svgSelection.classed( + 'selected-variant-g', + !svgSelection.classed('selected-variant-g') + ); + + const poly = svgSelection.select('polygon'); + + poly.classed('selected-polygon', !poly.classed('selected-polygon')); + + // If one is selected reactivate insert + if ( + d3 + .select('#VariantMainGroup') + .selectAll('.selected-variant-g') + .nodes().length == 1 + ) { + this.multipleSelected = false; + } + } + this.selectedElement = true; + }.bind(this); + + selection.selectAll('g').classed('selected-variant-g', (d) => { + return d === this.newLeaf; + }); + + if (!(selection.selectAll('.selected-variant-g').nodes().length > 0)) { + this.selectedElement = false; + } + + this.variantEnrichedSelection = selection; + } + + handleActivityButtonClick(event) { + if (this.selectedElement || this.emptyVariant) { + const leaf = new LeafNode([event.activityName]); + this.newLeaf = leaf; + + // hide tooltip + if (this.variantService.activityTooltipReference) { + this.variantService.activityTooltipReference.tooltip('hide'); + } + + if (this.emptyVariant) { + const variantGroup = new SequenceGroup([leaf]); + variantGroup.setExpanded(true); + this.currentVariant = variantGroup; + this.emptyVariant = false; + this.selectedElement = true; + } else { + leaf.setExpanded(true); + const selectedElement = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data()[0]; + + switch (this.selectedStrategy) { + case this.insertionStrategy.infront: + if (!this.multipleSelected) { + this.handleInfrontInsert( + this.currentVariant, + leaf, + selectedElement + ); + const grandParent = this.findParent( + this.currentVariant, + this.findParent(this.currentVariant, leaf) + ); + if (grandParent instanceof ParallelGroup) { + this.sortParallel(grandParent); + } + } + break; + case this.insertionStrategy.behind: + if (!this.multipleSelected) { + this.handleBehindInsert( + this.currentVariant, + leaf, + selectedElement + ); + const grandParent = this.findParent( + this.currentVariant, + this.findParent(this.currentVariant, leaf) + ); + if (grandParent instanceof ParallelGroup) { + this.sortParallel(grandParent); + } + } + break; + case this.insertionStrategy.parallel: + if (!this.multipleSelected) { + this.handleParallelInsert( + this.currentVariant, + leaf, + selectedElement + ); + } else { + const selectedElements = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data(); + this.handleMultiParallelInsert( + this.currentVariant, + leaf, + selectedElements + ); + } + this.sortParallel(this.findParent(this.currentVariant, leaf)); + break; + case this.insertionStrategy.replace: + if (!this.multipleSelected) { + this.handleReplace(this.currentVariant, leaf, selectedElement); + } + break; + } + this.triggerRedraw(); + } + this.cacheCurrentVariant(); + } + } + + copyVariant(variant: VariantElement) { + const children = variant.getElements(); + if (variant instanceof LeafNode) { + return new LeafNode([variant.asLeafNode().activity[0]]); + } else { + const newChildren = []; + for (const child of children) { + newChildren.push(this.copyVariant(child)); + } + variant.setElements(newChildren); + return variant; + } + } + + handleMultiParallelInsert( + variant: VariantElement, + leaf: LeafNode, + selectedElement + ) { + const parent = this.findParent(variant, selectedElement[0]); + const grandParent = this.findParent(variant, parent); // if parent is root, grandParent is null + const children = parent.getElements(); + if ( + children.length === selectedElement.length && + grandParent && + grandParent instanceof ParallelGroup + ) { + const parentSiblings = grandParent.getElements(); + parentSiblings.splice(0, 0, leaf); + grandParent.setElements(parentSiblings); + } else { + const index = children.indexOf(selectedElement[0]); + const newParent = new ParallelGroup([ + leaf, + new SequenceGroup(selectedElement), + ]); + children.splice(index, selectedElement.length); + children.splice(index, 0, newParent); + parent.setElements(children); + } + } + + handleParallelInsert( + variant: VariantElement, + leaf: LeafNode, + selectedElement + ) { + const children = variant.getElements(); + + if (children) { + const index = children.indexOf(selectedElement); + if (variant && variant === selectedElement) { + variant.setElements([ + new ParallelGroup([leaf, new SequenceGroup(children)]), + ]); + } else if (index > -1) { + // Handle parent ParallelGroup + if (variant instanceof ParallelGroup) { + children.splice(index, 0, leaf); + } else { + // If the selected element is a parallel group, insert into its children + if (selectedElement instanceof ParallelGroup) { + selectedElement.getElements().push(leaf); + + // Else create a new parallel group for leaf and selected + } else { + children.splice( + index, + 1, + new ParallelGroup([leaf, selectedElement]) + ); + } + } + } else { + for (const child of children) { + this.handleParallelInsert(child, leaf, selectedElement); + } + } + } + } + + handleInfixButtonClick(infixtype: InfixType) { + this.curInfixType = infixtype; + } + + handleBehindInsert(variant: VariantElement, leaf: LeafNode, selectedElement) { + const children = variant.getElements(); + + if (children) { + const index = children.indexOf(selectedElement); + if (variant && variant === selectedElement) { + children.splice(children.length, 0, leaf); + } else if (index > -1) { + // Handling Parent Parallel Group Cases + if (variant instanceof ParallelGroup) { + // Inserting behind a leafNode inside a ParallelGroup + if (selectedElement instanceof LeafNode) { + children.splice( + index, + 1, + new SequenceGroup([selectedElement, leaf]) + ); + } else { + // Inserting behind a ParallelGroup inside a ParallelGroup + if (selectedElement instanceof ParallelGroup) { + children.splice( + children.indexOf(selectedElement), + 1, + new SequenceGroup([selectedElement, leaf]) + ); + + // Inserting behind a SequeneGroup inside a ParallelGroup + } else { + const selectedChildren = selectedElement.getElements(); + selectedChildren.push(leaf); + } + } + + // Else the variant is a SequenceGroup and we can simply insert after the selected Element + } else { + children.splice(index + 1, 0, leaf); + } + + // Recursing into the Children + } else { + for (const child of children) { + this.handleBehindInsert(child, leaf, selectedElement); + } + } + } + } + + handleInfrontInsert( + variant: VariantElement, + leaf: LeafNode, + selectedElement + ) { + const children = variant.getElements(); + + if (children) { + const index = children.indexOf(selectedElement); + if (variant && variant === selectedElement) { + children.splice(0, 0, leaf); + } else if (index > -1) { + if (variant instanceof ParallelGroup) { + // Inserting infront a leafNode inside a ParallelGroup + if (selectedElement instanceof LeafNode) { + children.splice( + index, + 1, + new SequenceGroup([leaf, selectedElement]) + ); + } else { + // Inserting infront a ParallelGroup inside a ParallelGroup + if (selectedElement instanceof ParallelGroup) { + children.splice( + children.indexOf(selectedElement), + 1, + new SequenceGroup([leaf, selectedElement]) + ); + + // Inserting infront a SequeneGroup inside a ParallelGroup + } else { + const selectedChildren = selectedElement.getElements(); + selectedChildren.unshift(leaf); + } + } + } else { + children.splice(index, 0, leaf); + } + } else { + for (const child of children) { + this.handleInfrontInsert(child, leaf, selectedElement); + } + } + } + } + + handleReplace(variant: VariantElement, leaf: LeafNode, selectedElement) { + const children = variant.getElements(); + + if (children) { + const index = children.indexOf(selectedElement); + if (variant && variant === selectedElement) { + variant.setElements([leaf]); + } + if (index > -1) { + children.splice(index, 1, leaf); + } else { + for (const child of children) { + this.handleReplace(child, leaf, selectedElement); + } + } + } + } + + @HostListener('window:keydown.control', ['$event']) + onMultiSelectStart() { + this.multiSelect = true; + } + + @HostListener('window:keyup.control', ['$event']) + onMultiSelectStop() { + this.multiSelect = false; + } + + onDeleteSelected() { + const ElementsToDelete = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data(); + + if ( + ElementsToDelete.length === 1 && + ElementsToDelete[0] instanceof SequenceGroup && + this.currentVariant === ElementsToDelete[0] + ) { + this.onDeleteVariant(); + } // need further check. Is this nested function allowed? + else { + this.deleteElementFromVariant( + this.currentVariant, + this.currentVariant, + ElementsToDelete + ); + + this.multiSelect = false; + this.multipleSelected = false; + + this.cacheCurrentVariant(); + + this.triggerRedraw(); + } + } + + computeActivityColor = ( + self: VariantDrawerDirective, + element: VariantElement + ) => { + let color; + color = this.colorMap.get(element.asLeafNode().activity[0]); + + if (!color) { + color = '#d3d3d3'; // lightgrey + } + + return color; + }; + + deleteElementFromVariant( + variant: VariantElement, + parent: VariantElement, + elementsToDelete + ) { + const children = variant.getElements(); + + if (children) { + for (const elementToDelete of elementsToDelete) { + const index = children.indexOf(elementToDelete); + if (index > -1) { + this.newLeaf = children[index - 1]; + + children.splice(index, 1); + } + } + + if ( + children.length === 1 && + variant instanceof SequenceGroup && + parent instanceof ParallelGroup && + (children[0] instanceof ParallelGroup || + children[0] instanceof LeafNode) + ) { + const childrenParent = parent.getElements(); + const aloneChild = children[0]; + if (aloneChild instanceof LeafNode) { + childrenParent.splice(childrenParent.indexOf(variant), 1, aloneChild); + } else { + const parallelChildren = children[0].getElements(); + const deleteIndex = childrenParent.indexOf(variant); + childrenParent.splice(deleteIndex, 1); + for (const newNode of parallelChildren.reverse()) { + childrenParent.splice(deleteIndex, 0, newNode); + } + } + parent.setElements(childrenParent); + } else if ( + children.length === 1 && + variant instanceof ParallelGroup && + parent instanceof SequenceGroup && + (children[0] instanceof SequenceGroup || + children[0] instanceof LeafNode) + ) { + const childrenParent = parent.getElements(); + const aloneChild = children[0]; + if (aloneChild instanceof LeafNode) { + childrenParent.splice(childrenParent.indexOf(variant), 1, aloneChild); + } else { + const sequenceChildren = children[0].getElements(); + const deleteIndex = childrenParent.indexOf(variant); + childrenParent.splice(deleteIndex, 1); + for (const newNode of sequenceChildren.reverse()) { + childrenParent.splice(deleteIndex, 0, newNode); + } + } + parent.setElements(childrenParent); + } + + // edited + if (children.length === 0) { + const childrenParent = parent.getElements(); + if (!(variant === this.currentVariant)) { + childrenParent.splice(childrenParent.indexOf(variant), 1); + parent.setElements(childrenParent); + } else { + this.currentVariant = null; + this.emptyVariant = true; + } + } else { + variant.setElements(children); + for (const child of children) { + this.deleteElementFromVariant(child, variant, elementsToDelete); + } + } + } + } + + onDeleteVariant() { + this.currentVariant = null; + this.emptyVariant = true; + + this.multiSelect = false; + this.multipleSelected = false; + + this.cacheCurrentVariant(); + + this.triggerRedraw(); + } + + cacheCurrentVariant() { + if (this.cacheIdx < this.cachedVariants.length - 1) { + this.cachedVariants = this.cachedVariants.slice(0, this.cacheIdx + 1); + } + + if (this.currentVariant) { + this.cachedVariants.push(this.currentVariant.copy()); + } else { + this.cachedVariants.push(null); + } + if (this.cachedVariants.length > this.cacheSize) { + this.cachedVariants.shift(); + } else { + if (!(this.cacheIdx == null)) { + this.cacheIdx += 1; + } else { + this.cacheIdx = this.cachedVariants.length - 1; + } + } + } + + compareNode(node1, node2) { + if (node1 instanceof SequenceGroup) { + return false; + } else if (node2 instanceof SequenceGroup) { + return true; + } else { + return node1.asLeafNode().activity[0] > node2.asLeafNode().activity[0]; + } + } + + /* + sortParallel(variant) { + let children = variant.getElements(); + console.log(children); + //children.sort((node1, node2) => this.compareNode(node1, node2)); + children = children.sort((a, b) => true); + console.log(children); + variant.setElements(children); + }*/ + sortParallel(variant) { + const children = variant.getElements(); + for (let i = 1; i < children.length; i++) { + const temp = children[i]; + let j = i - 1; + while (j >= 0 && this.compareNode(children[j], temp)) { + children[j + 1] = children[j]; + j--; + } + children[j + 1] = temp; + } + return children; + } + + findParent(parent, node) { + const children = parent.getElements(); + if (!children) { + return null; + } else { + const index = children.indexOf(node); + if (index > -1) { + return parent; + } else { + for (const child of children) { + if (this.findParent(child, node) != null) { + return this.findParent(child, node); + } + } + return null; + } + } + } // check is node is a child of parent + + checkOverlapInsert() { + if (this.emptyVariant || !this.variantEnrichedSelection) { + return false; + } else { + const selectedElement = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data()[0]; + const parent = this.findParent(this.currentVariant, selectedElement); + if (parent && !(parent instanceof ParallelGroup)) { + return false; + } else { + if (!parent) { + return false; + } else { + const siblings = parent.getElements(); + for (const s of siblings) { + if (s instanceof SequenceGroup && s.getElements().length > 1) { + return true; + } + } + return false; + } + } + } + } + + checkNeighborSelection() { + const selectedElements = this.variantEnrichedSelection + .selectAll('.selected-variant-g') + .data(); + + if ( + !( + this.findParent(this.currentVariant, selectedElements[0]) instanceof + SequenceGroup + ) + ) { + return false; + } + + for (let i = 0; i < selectedElements.length - 1; i++) { + const firstParent = this.findParent( + this.currentVariant, + selectedElements[i] + ); + const secondParent = this.findParent( + this.currentVariant, + selectedElements[i + 1] + ); + if ( + firstParent != secondParent || + firstParent.getElements().indexOf(selectedElements[i + 1]) != + firstParent.getElements().indexOf(selectedElements[i]) + 1 + ) { + return false; + } + } + return true; + } + + removeSelection() { + this.selectedElement = false; + this.multiSelect = false; + this.multipleSelected = false; + + this.triggerRedraw(); + this.newLeaf = null; + } + + redo() { + this.selectedElement = false; + this.emptyVariant = false; + + this.cacheIdx++; + if (this.cachedVariants[this.cacheIdx] === null) { + this.currentVariant = null; + this.emptyVariant = true; + } else { + this.currentVariant = this.cachedVariants[this.cacheIdx].copy(); + } + this.newLeaf = null; + } + + undo() { + this.selectedElement = false; + this.emptyVariant = false; + + this.cacheIdx--; + if (this.cachedVariants[this.cacheIdx] === null) { + this.currentVariant = null; + this.emptyVariant = true; + } // edited + else { + this.currentVariant = this.cachedVariants[this.cacheIdx].copy(); + } + this.newLeaf = null; + } + + // This is a work-around that we should address in a more unified manner + // The underlying challenge is causing a redraw by triggering change detection, + // something that in its current state due to only a shallow check of the VariantElement + triggerRedraw() { + setTimeout(() => this.variantDrawer.redraw(), 1); + } + + focusSelected() { + this.editor.focusSelected(250); + } + + centerVariant() { + this.editor.centerContent(250); + } + + computeFocusOffset = (svg) => { + const path = findPathToSelectedNode( + this.currentVariant, + svg.select('.selected-variant-g').data()[0] + ).slice(1); + let translateX = 0; + + for (const element of svg + .selectAll('g') + .filter((d: VariantElement) => { + return path.indexOf(d) > -1; + }) + .nodes()) { + const transform = d3 + .select(element) + .attr('transform') + .match(/[\d.]+/g); + translateX += parseFloat(transform[0]); + } + + return [-translateX, 0]; + }; + + addCurrentVariantToVariantList() { + const copyCurrent = cloneDeep(this.currentVariant); + + setParent(copyCurrent); + copyCurrent.setExpanded(false); + + const newVariant = new Variant( + 0, + copyCurrent, + false, + true, + false, + 0, + undefined, + true, + false, + true, + 0, + this.curInfixType + ); + + newVariant.alignment = undefined; + newVariant.deviations = undefined; + newVariant.id = objectHash(newVariant); + + this.variantService.nUserVariants += 1; + newVariant.bid = -this.variantService.nUserVariants; + + const duplicate = this.variantService.variants.some((v: Variant) => { + return newVariant.equals(v) || v.id === newVariant.id; + }); + + if (!duplicate) { + this.variantService.variants.push(newVariant); + this.addStatistics(newVariant).subscribe(); + + if (newVariant.infixType === InfixType.NOT_AN_INFIX) { + this.variantService.addUserDefinedVariant(newVariant).subscribe(() => { + if (this.variantService.clusteringConfig) { + // trigger new clustering + this.variantService.clusteringConfig = + this.variantService.clusteringConfig; + } else { + this.variantService.variants = this.variantService.variants; + } + }); + } else { + this.variantService.addInfixToBackend(newVariant).subscribe(() => { + if (this.variantService.clusteringConfig) { + // trigger new clustering + this.variantService.clusteringConfig = + this.variantService.clusteringConfig; + } else { + this.variantService.variants = this.variantService.variants; + } + }); + } + } else { + this.redundancyWarning = true; + setTimeout(() => (this.redundancyWarning = false), 500); + } + } + + private addStatistics(newVariant: Variant): Observable<any> { + if (newVariant.infixType !== InfixType.NOT_AN_INFIX) { + return this.backendService.countFragmentOccurrences(newVariant).pipe( + tap((statistics: FragmentStatistics) => { + newVariant.count = statistics.traceOccurrences; + newVariant.fragmentStatistics = statistics; + }) + ); + } + return of(); + } + + applySortOnVariantModeler() { + const variantExplorerRef = + this.goldenLayoutComponentService.goldenLayout.findFirstComponentItemById( + VariantExplorerComponent.componentName + ); + const variantExplorer = + variantExplorerRef.component as VariantExplorerComponent; + variantExplorer.sortingFeature = 'userDefined'; + variantExplorer.onSortOrderChanged(false); + } + + sortVariant(variant) { + this.backendService.sortInVariantModeler(variant).subscribe((res) => { + this.currentVariant = deserialize(res['variants']); + }); + } +} + +export namespace VariantModelerComponent { + export const componentName = 'VariantModelerComponent'; +} + +export enum activityInsertionStrategy { + infront = 'infront', + behind = 'behind', + parallel = 'parallel', + replace = 'replace', +} diff --git a/src/frontend/src/app/components/variant-performance/variant-color-map/variant-color-map.component.html b/src/frontend/src/app/components/variant-performance/variant-color-map/variant-color-map.component.html new file mode 100644 index 0000000000000000000000000000000000000000..6037b7135153470b88cd022d6fd1bc8f68dc25ab --- /dev/null +++ b/src/frontend/src/app/components/variant-performance/variant-color-map/variant-color-map.component.html @@ -0,0 +1,57 @@ +<div class="card text-white mb-3" *ngIf="serviceTimeValues"> + <div class="card-body"> + <h5 class="card-title">Service Time</h5> + + <div class="mb-3"> + <select + class="form-select form-select-sm" + aria-label="variance service time aggregation statistic" + (change)="serviceTimeColorScaleChange($event)" + name="performanceValue" + > + <option + *ngFor="let pValue of availablePerformanceValues" + [value]="pValue[1]" + > + {{ pValue[0] }} + </option> + </select> + <!--<div class="form-text">Service time aggregation method</div>--> + </div> + + <app-color-map + [colorMapValues]="serviceTimeValues" + [firstColorStriped]="true" + [firstColorDetached]="true" + ></app-color-map> + </div> +</div> + +<div class="card text-white mb-3" *ngIf="waitingTimeValues"> + <div class="card-body"> + <h5 class="card-title">Waiting Time</h5> + + <div class="mb-3"> + <select + class="form-select form-select-sm" + aria-label="variance service time aggregation statistic" + (change)="waitingTimeColorScaleChange($event)" + name="performanceValue" + > + <option + *ngFor="let pValue of availablePerformanceValues" + [value]="pValue[1]" + > + {{ pValue[0] }} + </option> + </select> + <!--<div class="form-text">Waiting time aggregation method</div>--> + </div> + + <app-color-map + [colorMapValues]="waitingTimeValues" + [firstColorStriped]="true" + [firstColorDetached]="true" + ></app-color-map> + </div> +</div> diff --git a/src/frontend/src/app/components/variant-performance/variant-color-map/variant-color-map.component.scss b/src/frontend/src/app/components/variant-performance/variant-color-map/variant-color-map.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..15debadc14fe6573fa7d16d9cb0259b7ced2957b --- /dev/null +++ b/src/frontend/src/app/components/variant-performance/variant-color-map/variant-color-map.component.scss @@ -0,0 +1,10 @@ +:host { + padding: 10px; + display: flex; +} + +.card { + flex: 1; + background-color: transparent; + border: 0; +} diff --git a/src/frontend/src/app/components/variant-performance/variant-color-map/variant-color-map.component.spec.ts b/src/frontend/src/app/components/variant-performance/variant-color-map/variant-color-map.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..c3da7343d96026556611a811746a86fc71b5c0df --- /dev/null +++ b/src/frontend/src/app/components/variant-performance/variant-color-map/variant-color-map.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantColorMapComponent } from './variant-color-map.component'; + +describe('VariantColorMapComponent', () => { + let component: VariantColorMapComponent; + let fixture: ComponentFixture<VariantColorMapComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantColorMapComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantColorMapComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-performance/variant-color-map/variant-color-map.component.ts b/src/frontend/src/app/components/variant-performance/variant-color-map/variant-color-map.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..abf7890ab445f5f089dcefaaca98aada714ba6de --- /dev/null +++ b/src/frontend/src/app/components/variant-performance/variant-color-map/variant-color-map.component.ts @@ -0,0 +1,87 @@ +import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { VariantPerformanceService } from 'src/app/services/variant-performance.service'; +import { + buildColorValues, + ColorMapValue, +} from '../../performance/color-map/color-map.component'; + +@Component({ + selector: 'app-variant-color-map', + templateUrl: './variant-color-map.component.html', + styleUrls: ['./variant-color-map.component.scss'], +}) +export class VariantColorMapComponent implements OnDestroy { + availablePerformanceValues = [ + ['Mean', 'mean'], + ['Minimum', 'min'], + ['Maximum', 'max'], + ['Standard Deviation', 'stdev'], + ]; + + public serviceTimeValues: ColorMapValue[]; + public waitingTimeValues: ColorMapValue[]; + + private _destroy$ = new Subject(); + + constructor( + public variantPerformanceService: VariantPerformanceService, + private changeDetectorRef: ChangeDetectorRef + ) { + this.variantPerformanceService.serviceTimeColorMap + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + this.updateServiceTimeValues(colorMap); + changeDetectorRef.markForCheck(); + }); + + this.variantPerformanceService.waitingTimeColorMap + .pipe(takeUntil(this._destroy$)) + .subscribe((colorMap) => { + this.updateWaitingTimeValues(colorMap); + changeDetectorRef.markForCheck(); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + private updateServiceTimeValues(colorMap) { + this.serviceTimeValues = this.getColorValues( + colorMap, + 'serviceTime', + this.variantPerformanceService.serviceTimeStatistic + ); + } + + private updateWaitingTimeValues(colorMap) { + this.waitingTimeValues = this.getColorValues( + colorMap, + 'waitingTime', + this.variantPerformanceService.waitingTimeStatistic + ); + } + + private getColorValues( + colorScale, + performanceIndicator, + value + ): ColorMapValue[] { + return buildColorValues(colorScale, [ + this.variantPerformanceService.minValues[performanceIndicator], + this.variantPerformanceService.maxValues[performanceIndicator], + ]); + } + + public serviceTimeColorScaleChange(event): void { + const value = event.target.value; + this.variantPerformanceService.serviceTimeStatistic = value; + } + + public waitingTimeColorScaleChange(event): void { + const value = event.target.value; + this.variantPerformanceService.waitingTimeStatistic = value; + } +} diff --git a/src/frontend/src/app/components/variant-performance/variant-performance.component.html b/src/frontend/src/app/components/variant-performance/variant-performance.component.html new file mode 100644 index 0000000000000000000000000000000000000000..2570c0d201c773076b678ca652b1f723a6a030d5 --- /dev/null +++ b/src/frontend/src/app/components/variant-performance/variant-performance.component.html @@ -0,0 +1,120 @@ +<ul class="nav nav-tabs bg-dark" role="tablist"> + <li class="nav-item" role="presentation"> + <button + class="nav-link active button" + id="variant-selection-tab" + data-bs-toggle="tab" + data-bs-target="#variantSelection" + role="tab" + aria-controls="variantSelection" + aria-selected="true" + > + Selection + </button> + </li> + <li class="nav-item" role="presentation"> + <button + class="nav-link button" + id="variant-colormap-tab" + data-bs-toggle="tab" + data-bs-target="#variantColormap" + type="button" + role="tab" + aria-controls="variantColormap" + aria-selected="false" + #colorMapTab + > + Color Map + </button> + </li> +</ul> + +<div class="tab-content" id="myTabContent"> + <div + class="tab-pane fade show active" + id="variantSelection" + role="tabpanel" + aria-labelledby="variant-selection-tab" + > + <ng-container *ngTemplateOutlet="selectionPerformance"> </ng-container> + </div> + <div + class="tab-pane fade color-map-tab" + id="variantColormap" + role="tabpanel" + aria-labelledby="variant-color-map" + > + <app-variant-color-map + *ngIf=" + variantPerformanceService.performanceInformationLoaded; + else unavailableInfoColorMap + " + ></app-variant-color-map> + <ng-template #unavailableInfoColorMap> + <app-unavailable-info> + No performance values available. + <br /> + To load performance values change into Performance View in the Variant + Explorer. + </app-unavailable-info> + </ng-template> + </div> +</div> + +<ng-template #selectionPerformance> + <app-unavailable-info *ngIf="!performanceStats"> + To show variant performance, change into Performance View and click on the + variant chevron in the Variant Explorer. + </app-unavailable-info> + + <div *ngIf="performanceStats"> + <table + class="table table-sm table-striped table-dark table-hover table-bordered mb-0" + style="font-size: small" + > + <thead> + <tr> + <th colspan="2" class="variant-performance-th">{{ title }}</th> + </tr> + </thead> + <tbody class="no-top-border"> + <tr> + <td>Mean:</td> + <td> + {{ performanceStats.mean | humanizeDuration }} + </td> + </tr> + <tr> + <td>Stdev:</td> + <td> + {{ performanceStats.stdev | humanizeDuration }} + </td> + </tr> + <tr> + <td>Min:</td> + <td> + {{ performanceStats.min | humanizeDuration }} + </td> + </tr> + <tr> + <td>Max:</td> + <td> + {{ performanceStats.max | humanizeDuration }} + </td> + </tr> + <tr> + <td>95th Percentile:</td> + <td> + {{ performanceStats["95th"] | humanizeDuration }} + </td> + </tr> + <tr> + <td>50th Percentile:</td> + <td> + {{ performanceStats["50th"] | humanizeDuration }} + </td> + </tr> + </tbody> + </table> + </div> +</ng-template> diff --git a/src/frontend/src/app/components/variant-performance/variant-performance.component.scss b/src/frontend/src/app/components/variant-performance/variant-performance.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..1efb170feddedf84ede48a701dac976e89d00404 --- /dev/null +++ b/src/frontend/src/app/components/variant-performance/variant-performance.component.scss @@ -0,0 +1,17 @@ +:host { + display: flex; + flex-direction: column; + overflow: auto; + position: absolute; + background-color: var(--box-background-color); +} + +.variant-performance-th { + font-size: medium; + font-weight: normal; + color: white; +} + +.no-top-border { + border-top: none; +} diff --git a/src/frontend/src/app/components/variant-performance/variant-performance.component.spec.ts b/src/frontend/src/app/components/variant-performance/variant-performance.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..14273a18f15eafc8747574909d83df9f1100664b --- /dev/null +++ b/src/frontend/src/app/components/variant-performance/variant-performance.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VariantPerformanceComponent } from './variant-performance.component'; + +describe('VariantPerformanceComponent', () => { + let component: VariantPerformanceComponent; + let fixture: ComponentFixture<VariantPerformanceComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VariantPerformanceComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VariantPerformanceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/variant-performance/variant-performance.component.ts b/src/frontend/src/app/components/variant-performance/variant-performance.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..ab20f2389d18c8e555aa9b2a42526f882ad18cc6 --- /dev/null +++ b/src/frontend/src/app/components/variant-performance/variant-performance.component.ts @@ -0,0 +1,98 @@ +import { + AfterViewInit, + ChangeDetectorRef, + Component, + ElementRef, + Inject, + OnDestroy, + OnInit, + Renderer2, + ViewChild, +} from '@angular/core'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { VariantPerformanceService } from 'src/app/services/variant-performance.service'; +import { VariantViewModeService } from 'src/app/services/viewModeServices/variant-view-mode.service'; + +@Component({ + selector: 'app-variant-performance', + templateUrl: './variant-performance.component.html', + styleUrls: ['./variant-performance.component.scss'], +}) +export class VariantPerformanceComponent + extends LayoutChangeDirective + implements OnInit, AfterViewInit, OnDestroy +{ + @ViewChild('colorMapTab') colorMapTab: ElementRef; + + constructor( + public variantPerformanceService: VariantPerformanceService, + private changeDetectorRef: ChangeDetectorRef, + renderer: Renderer2, + @Inject(LayoutChangeDirective.GoldenLayoutContainerInjectionToken) + private container: ComponentContainer, + elRef: ElementRef, + private variantViewModeService: VariantViewModeService + ) { + super(elRef.nativeElement, renderer); + } + + handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void {} + + handleVisibilityChange(visibility: boolean): void {} + + handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void {} + + public performanceStats: any; + public title: string; + + public colorScale; + + private _destroy$ = new Subject(); + + ngOnInit(): void { + this.variantPerformanceService.performanceStatsForSelectedVariantElement$ + .pipe(takeUntil(this._destroy$)) + .subscribe((data) => { + if (data == undefined) { + this.performanceStats = null; + return; + } + this.performanceStats = data[0]; + const isServiceTime: boolean = data[1]; + this.title = 'Service Time'; + if (!isServiceTime) { + this.title = 'Waiting Time'; + } + this.changeDetectorRef.markForCheck(); + }); + } + + ngAfterViewInit(): void { + this.variantViewModeService.viewMode$ + .pipe(takeUntil(this._destroy$)) + .subscribe((viewMode) => { + if (viewMode === ViewMode.PERFORMANCE) + this.colorMapTab.nativeElement.click(); + }); + } + + ngOnDestroy(): void { + this._destroy$.next(); + } +} + +export namespace VariantPerformanceComponent { + export const componentName = 'VariantPerformanceComponent'; +} diff --git a/src/frontend/src/app/components/zoom-field/zoom-field.component.css b/src/frontend/src/app/components/zoom-field/zoom-field.component.css new file mode 100644 index 0000000000000000000000000000000000000000..66b978a9f85950fb322f6e812811805dadabc1fd --- /dev/null +++ b/src/frontend/src/app/components/zoom-field/zoom-field.component.css @@ -0,0 +1,8 @@ +:host{ + color: var(--text-secondary); + width: 100%; + height: 100%; + background-image: radial-gradient(var(--line-color) 1px, transparent 0); + background-size: 20px 20px; + cursor : pointer; +} diff --git a/src/frontend/src/app/components/zoom-field/zoom-field.component.html b/src/frontend/src/app/components/zoom-field/zoom-field.component.html new file mode 100644 index 0000000000000000000000000000000000000000..66325f88fbb07f8c099c236542a35f1294792bf8 --- /dev/null +++ b/src/frontend/src/app/components/zoom-field/zoom-field.component.html @@ -0,0 +1 @@ +<ng-content #content></ng-content> diff --git a/src/frontend/src/app/components/zoom-field/zoom-field.component.spec.ts b/src/frontend/src/app/components/zoom-field/zoom-field.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..9e289e4480d830af1dc7e0c218fc42f294383488 --- /dev/null +++ b/src/frontend/src/app/components/zoom-field/zoom-field.component.spec.ts @@ -0,0 +1,27 @@ +/* tslint:disable:no-unused-variable */ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { DebugElement } from '@angular/core'; + +import { ZoomFieldComponent } from './zoom-field.component'; + +describe('ZoomFieldComponent', () => { + let component: ZoomFieldComponent; + let fixture: ComponentFixture<ZoomFieldComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ZoomFieldComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ZoomFieldComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/components/zoom-field/zoom-field.component.ts b/src/frontend/src/app/components/zoom-field/zoom-field.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..c90bc6415c44d96e5c9faaaa954ea220623aa284 --- /dev/null +++ b/src/frontend/src/app/components/zoom-field/zoom-field.component.ts @@ -0,0 +1,117 @@ +import { + Component, + ElementRef, + Input, + AfterViewInit, + ContentChild, +} from '@angular/core'; +import * as d3 from 'd3'; +import { COLORS_BLUE } from 'src/app/objects/Colors'; + +@Component({ + selector: 'app-zoom-field', + templateUrl: './zoom-field.component.html', + styleUrls: ['./zoom-field.component.css'], +}) +export class ZoomFieldComponent implements AfterViewInit { + constructor(private editorWindow: ElementRef) {} + + @ContentChild('content') + content: ElementRef; + + @Input() + computeFocusOffsets: (any) => [number, number]; + + @Input() + computeCenterOffsets: (any) => [number, number]; + + @Input() + clkCallback; + + @Input() + rghtClkCallback; + + @Input() + dblClkCallback; + + @Input() + shortCutCallbacks: Map<string, (any) => [number, number]>; + + @Input() + zoomScale: [number, number]; + + private zoom: any; + + ngAfterViewInit(): void { + this.initalCenterContent(); + this.addZoomFunctionality(); + } + + private initalCenterContent() { + const boundingRect = ( + this.editorWindow.nativeElement as HTMLElement + ).getBoundingClientRect(); + d3.select(this.content.nativeElement) + .select('g') + .attr( + 'transform', + `translate(${boundingRect.width / 2}, ${boundingRect.height / 2})` + ); + } + + private addZoomFunctionality(): void { + const zoomGroup = d3.select(this.content.nativeElement); + + const zooming = function (event) { + d3.select(this.content.nativeElement) + .select('g') + .attr( + 'transform', + event.transform.translate( + this.editorWindow.nativeElement.offsetWidth / 2, + this.editorWindow.nativeElement.offsetHeight / 2 + ) + ); + }.bind(this); + + this.zoom = d3.zoom().scaleExtent(this.zoomScale).on('zoom', zooming); + + zoomGroup.call(this.zoom).on('dblclick.zoom', null); + } + + centerContent(animationDuration: number) { + const svg = d3.select(this.content.nativeElement); + const variantElement = d3.select(this.content.nativeElement).select('g'); + const [translateX, translateY] = this.computeCenterOffsets + ? this.computeCenterOffsets(svg) + : [0, 0]; + d3.select(this.content.nativeElement) + .transition() + .duration(animationDuration) + .ease(d3.easeExpInOut) + .call( + this.zoom.transform, + d3.zoomIdentity.translate( + translateX - +variantElement.attr('width') / 2, + translateY + ) + ); + } + + focusSelected(animationDuration: number) { + const svg = d3.select(this.content.nativeElement); + const [translateX, translateY] = this.computeFocusOffsets + ? this.computeFocusOffsets(svg) + : [0, 0]; + console.log('offset'); + console.log(translateX, translateY); + svg + .transition() + .duration(animationDuration) + .ease(d3.easeExpInOut) + .call( + this.zoom.transform, + d3.zoomIdentity.translate(translateX, translateY) + ); + } +} diff --git a/src/frontend/src/app/constants/backend_route_constants.ts b/src/frontend/src/app/constants/backend_route_constants.ts new file mode 100644 index 0000000000000000000000000000000000000000..8ae7b3e4247c691a8fdfe047eb849f6efc8acd7f --- /dev/null +++ b/src/frontend/src/app/constants/backend_route_constants.ts @@ -0,0 +1,25 @@ +export class ROUTES { + public static BASE_URL = '127.0.0.1:40000/'; + public static HTTP_BASE_URL = 'http://' + this.BASE_URL; + public static WS_HTTP_BASE_URL = 'ws://' + this.BASE_URL; + + public static LOG = 'log/'; + public static DISCOVER = 'discoverTree/'; + public static MODIFY_LOG = 'modifylog/'; + public static MODIFY_TREE = 'modifyTree/'; + public static PT_STRING = 'treeSting/'; + public static TREE_PERFORMANCE = 'treePerformance/'; + public static VARIANT = 'variant/'; + public static VARIANT_PERFORMANCE = 'variantPerformance/'; + public static SUBVARIANT_PERFORMANCE = 'subvariantPerformance/'; + public static TREE_CONFORMANCE = 'treeConformance/'; + public static VARIANT_CONFORMANCE = 'ws/conformance'; + public static QUERY = 'variantQuery/'; + public static CONFIG = 'config/'; + public static EXPORT = 'exporting/'; + public static IMPORT = 'importing/'; + public static VARIANTMINING = 'subvariantMining/'; + public static SEQUENTIALIZER = 'sequentializer/'; + public static LPMMINER = 'lpmMining/'; + public static REPETITIONS_MINING = 'ws/repetitionsMining'; +} diff --git a/src/frontend/src/app/constants/bpmn_model_drawer_constants.ts b/src/frontend/src/app/constants/bpmn_model_drawer_constants.ts new file mode 100644 index 0000000000000000000000000000000000000000..b87d0b85f807690284253fe3aa2614a76e4bfd81 --- /dev/null +++ b/src/frontend/src/app/constants/bpmn_model_drawer_constants.ts @@ -0,0 +1,39 @@ +export class BPMN_Constant { + public static EVENT_HEIGHT = 40; + public static EVENT_WIDTH = 120; + public static START_END_RADIUS = 20; + + public static LINE_COLOR = 'black'; + + public static BASE_HEIGHT_WIDTH = 30; + public static STROKE_WIDTH = 1; + public static STROKE_COLOR = 'gray'; + public static ARROW_LENGTH = 10; + public static ARROW_LENGTH_WITHOUT_WINGS = 0.75 * this.ARROW_LENGTH; + public static CORNER_RADIUS = '3'; + public static INVISIBLE_FONT_SIZE = '2em'; + public static OPERATOR_FONT_SIZE = '1.5em'; + public static VISIBLE_FONT_SIZE = '12px'; + + // ensure with maximum that arrows don't get flipped + public static HORIZONTALSPACING = Math.max(15, this.ARROW_LENGTH); + public static VERTICALSPACING = Math.max( + 15, + this.ARROW_LENGTH - (this.EVENT_HEIGHT / 2 - this.STROKE_WIDTH) + ); + + public static OPERATOR_NODE_WIDTH = + this.BASE_HEIGHT_WIDTH + this.STROKE_WIDTH; + public static OPERATOR_CENTER = this.OPERATOR_NODE_WIDTH / 2; + public static OPERATOR_DIAGONAL_LENGTH = + Math.sqrt(2 * Math.pow(this.OPERATOR_NODE_WIDTH, 2)) / 2; + + public static OPERATOR_COLOR = '#404040'; + public static VISIBLE_ACTIVITIY_DEFAULT_COLOR = '#8f8f8f'; + public static INVISIBLE_ACTIVITIY_DEFAULT_COLOR = '#181818'; + + public static PADDING = 5; + public static MAX_ZOOM = 3; + public static MIN_ZOOM = 0.1; + public static DEFAULT_ZOOM = 1; +} diff --git a/src/frontend/src/app/constants/process_tree_drawer_constants.ts b/src/frontend/src/app/constants/process_tree_drawer_constants.ts new file mode 100644 index 0000000000000000000000000000000000000000..42dba7b2fdb6ae43e987535f532806f3a3174202 --- /dev/null +++ b/src/frontend/src/app/constants/process_tree_drawer_constants.ts @@ -0,0 +1,23 @@ +/* + Defines tree constants that should be directly applied to each SVG element + and that form the basic visualization of the tree. + This allows for us to export the styled tree +*/ + +export class PT_Constant { + public static BASE_HEIGHT_WIDTH = 30; + public static EXPORT_OFFSET = 20; + public static NODE_SPACING = 20; + + public static STROKE_WIDTH = '2'; + public static STROKE_COLOR = 'gray'; + public static CORNER_RADIUS = '3'; + public static INVISIBLE_FONT_SIZE = '2em'; + public static OPERATOR_FONT_SIZE = '1.5em'; + public static VISIBLE_FONT_SIZE = '12px'; + + public static DEFAULT_STROKE_COLOR = 'gray'; + public static OPERATOR_COLOR = '#404040'; + public static VISIBILE_ACTIVITY_DEFAULT_COLOR = '#8f8f8f'; + public static INVISIBLE_ACTIVTIY_COLOR = '#181818'; +} diff --git a/src/frontend/src/app/constants/variant_element_drawer_constants.ts b/src/frontend/src/app/constants/variant_element_drawer_constants.ts new file mode 100644 index 0000000000000000000000000000000000000000..09e838f37fb9078367add2c2040c20835b6ded56 --- /dev/null +++ b/src/frontend/src/app/constants/variant_element_drawer_constants.ts @@ -0,0 +1,24 @@ +export class VARIANT_Constants { + public static LEAF_WIDTH = 40; + public static LEAF_WIDTH_EXPANDED = 120; + public static LEAF_HEIGHT = 23; + public static MARGIN_X = 8; + public static MARGIN_Y = 5; + public static SEQUENCEGROUP_Margin = 15; + public static ARROW_FEATHER_LENGTH = 10; + public static ARROW_HEAD_LENGTH = 12; + public static ARROW_HEAD_ANGLE = 20; + public static FONT_SIZE = 15; + public static WAITING_WIDTH = 5; + public static CHAR_WIDTH = 12; + public static MAX_OFFSETWIDTH = 800; + public static LEGEND_MARGIN_X = 10; + public static LEGEND_MARGIN_Y = 5; + public static POINT_RADIUS = 7; + public static INTERVAL_LENGTH = 60; + public static SELECTION_STROKE_WIDTH = 2; + public static SKIP_WIDTH = 25; + public static SKIP_MARGIN = 10; + public static CHOICE_BRACKET_FONT_SIZE = 10; + public static CHAR_LENGTH = 7.5; +} diff --git a/src/frontend/src/app/dependency-factories.ts b/src/frontend/src/app/dependency-factories.ts new file mode 100644 index 0000000000000000000000000000000000000000..8dd692ca151b9f9d381add4eca07e7e039194bce --- /dev/null +++ b/src/frontend/src/app/dependency-factories.ts @@ -0,0 +1,16 @@ +import { environment } from 'src/environments/environment'; +import { ElectronService } from './services/electronService/electron.service'; +import { ElectronDummyService } from './services/electronService/electron-dummy.service'; +import { ElectronInterface } from './services/electronService/electron-interface'; + +export function electronServiceFactory(): ElectronInterface { + // Provide the ElectronService if the environment is Electron + if (environment.electron) { + return new ElectronService(); + } else { + console.error( + 'Cannot provide normal ElectronService when running in browser. Instead providing dummy with limited functionallity' + ); + return new ElectronDummyService(); + } +} diff --git a/src/frontend/src/app/directives/arc-diagram/arc-diagram.directive.ts b/src/frontend/src/app/directives/arc-diagram/arc-diagram.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..d5fc108492a861f6bf6cbc6d86b78a7cd92ba99c --- /dev/null +++ b/src/frontend/src/app/directives/arc-diagram/arc-diagram.directive.ts @@ -0,0 +1,309 @@ +import { Directive, ElementRef, Input, Renderer2 } from '@angular/core'; +import { Arc, Level, Pair } from './data'; +import * as d3 from 'd3'; +import { IVariant } from '../../objects/Variants/variant_interface'; +import { VariantDrawerDirective } from '../variant-drawer/variant-drawer.directive'; +import { FilterConfig } from './filter-config'; +import { setChevronIdsForArcDiagrams } from '../../utils/render-utils'; + +@Directive({ + selector: '[appArcDiagram]', + exportAs: 'arcDiagram', +}) +export class ArcDiagramDirective { + constructor(elRef: ElementRef, renderer: Renderer2) { + this.svgHtmlElement = elRef; + renderer.setStyle(this.svgHtmlElement.nativeElement, 'display', 'none'); + } + + svgHtmlElement: ElementRef; + + arcs: Arc[]; + + @Input() + variant: IVariant; + + @Input() + filterConfig: FilterConfig; + + private config = { + width: 800, + transparency: 0.4, + hoverTransparency: 1, + hoverColor: 'red', + LoD: 1, + arcColor: 'lightgrey', + strokeWidth: '1', + baseHeight: 50, + step: 30, + barHeight: 10, + barRoundness: 4, + }; + + // private containsDisallowedActivities(activities: Set<string>, filterParams: FilterParams) { + // let activitiesToInclude = filterParams.activitiesSelection.selectedItems; + // for( let act of activities) { + // if(!activitiesToInclude.has(act)) return true; + // } + // return false; + // } + + /** Method to parse the input of the textfield or the file + * @param pairs The array of pairs to be parsed and visualized as arcs + * @return Struct of characters and essential matching pair arcs to draw + */ + public parseInput = (pairs: Pair[]) => { + let arcs: Arc[] = []; + let maxDistance = -1; + for (let i = 0; i < pairs.length; i++) { + let pair = pairs[i]; + const arc = new Arc( + pair.positions.bfs[0], + pair.length, + pair.positions.bfs[1], + pair.matches, + JSON.stringify(pair.pattern), + pair.activities, + pair.size + ); + arcs.push(arc); + if (arc.distanceBetweenPairs > maxDistance) { + maxDistance = arc.distanceBetweenPairs; + } + } + return { arcs, maxDistance }; + }; + + /** Draw the arc diagram + */ + public draw = (variantDrawer: VariantDrawerDirective, arcsToDraw?: Arc[]) => { + setChevronIdsForArcDiagrams(this.variant.variant, variantDrawer); + + if (!arcsToDraw) { + arcsToDraw = this.arcs; + } + // clear the chart and redraw everything + // $('#chart').empty(); + let arcs: Arc[] = []; + + //filter the data for LoD + for (let j = 0; j < arcsToDraw.length; j++) { + if (arcsToDraw[j].numberEle >= this.config.LoD) arcs.push(arcsToDraw[j]); + } + + this.config.width = this.variant.variant.width; + + const levels: Level[] = []; + let idx = 0; + for (let i = arcs.length - 1; i >= 0; i--) { + const arc = arcs[i]; + if ( + !levels.some( + (lvl) => lvl.distanceBetweenPairs === arc.distanceBetweenPairs + ) + ) { + levels.push(new Level(arc.distanceBetweenPairs, idx++)); + } + } + + const height = this.config.baseHeight + this.config.step * (idx - 1); + + const variantEl = d3.select(variantDrawer.svgHtmlElement.nativeElement); + + const chart = d3 + .select(this.svgHtmlElement.nativeElement) + .attr('width', this.config.width) + .attr('height', height) + .style('display', 'block'); + + chart.select('#arcGroup').selectAll('*').remove(); + + //plot the arcs like defined in the arcs array of the parsed data + const arcSvg = chart.select('#arcGroup'); + + // source base bar + const arcGroups = arcSvg.selectAll('path').data(arcs).enter().append('g'); + + const config = this.config; + + function appendBarBasedOn(dest: string) { + arcGroups + .append('rect') + .attr('x', function (d: Arc) { + const startLeafCoords = variantEl + .select(`g.bfs-group-${d[`${dest}Pos`]}`) + .attr('transform') + .split(/[\s,()]+/); + return parseFloat(startLeafCoords[1]); + }) + .attr('y', function (d: Arc) { + const level = levels.find( + (lvl) => + lvl.distanceBetweenPairs === + d.targetPos - d.sourcePos - d.numberEle + ); + return height - level.fromBottom * config.step - config.barHeight; + }) + .attr('width', function (d: Arc) { + const width = variantEl + .select(`g.bfs-group-${d[`${dest}Pos`] + d.numberEle - 1}>polygon`) + .attr('points') + .split(' ')[1] + .split(',')[0]; + const endLeafCoords = variantEl + .select(`g.bfs-group-${d[`${dest}Pos`] + d.numberEle - 1}`) + .attr('transform') + .split(/[\s,()]+/); + const startLeafCoords = variantEl + .select(`g.bfs-group-${d[`${dest}Pos`]}`) + .attr('transform') + .split(/[\s,()]+/); + return ( + parseFloat(endLeafCoords[1]) + + parseFloat(width) - + parseFloat(startLeafCoords[1]) + ); + }) + .attr('height', config.barHeight) + .attr('rx', config.barRoundness) + .attr('ry', config.barRoundness) + .attr('class', `${dest}-rect`) + .style('fill', config.arcColor) + .style('fill-opacity', config.transparency) + .style('cursor', 'pointer'); + } + + appendBarBasedOn('source'); + appendBarBasedOn('target'); + + let areOtherArcsHidden = false; + + // arc between the source and target bar + arcGroups + .each(function () { + const sbbox = (this.firstElementChild as SVGGraphicsElement).getBBox(); + let scx = sbbox.width / 2 + sbbox.x; + const tbbox = (this.lastElementChild as SVGGraphicsElement).getBBox(); + let tcx = tbbox.width / 2 + tbbox.x; + + d3.select(this) + .append('path') + .attr('d', function (d: Arc) { + const path = d3.path(); + + const baseHeight = levels.find( + (lvl) => + lvl.distanceBetweenPairs === + d.targetPos - d.sourcePos - d.numberEle + )?.fromBottom; + const levelHeight = + height - baseHeight * config.step - config.barHeight; + + path.moveTo(scx, levelHeight); + + path.quadraticCurveTo( + (scx + tcx) / 2, + levelHeight - config.step, + tcx, + levelHeight + ); + + return path.toString(); + }) + .style('stroke', config.arcColor) + .style('fill', 'none') + .style('stroke-linecap', 'round') + .style('stroke-opacity', config.transparency) + .style('cursor', 'pointer'); + }) + .on('mouseover', function (_, i) { + // highlight all corresponding bars and arcs + arcGroups.selectAll('rect,path').each(highlightArcComponents); + + function highlightArcComponents(x: Arc) { + if (i.text == x.text) { + d3.select(this) + .style('fill', function () { + return this.tagName == 'rect' ? config.hoverColor : 'none'; + }) + .style('stroke', function () { + return this.tagName == 'path' ? config.hoverColor : 'none'; + }); + } + let highlightTransparency = + i == x ? config.hoverTransparency : config.transparency; + d3.select(this) + .style('fill-opacity', highlightTransparency) + .style('stroke-opacity', highlightTransparency); + } + + // blur out all the chevrons + variantEl + .selectAll('g.variant-element-group') + .style('fill-opacity', config.transparency); + + arcs.forEach(highlightMatchingChevrons); + + function highlightMatchingChevrons(x: Arc) { + if (i.text == x.text) { + x.matches.forEach((dfsId: number) => { + if (dfsId == 0) { + return; + } + let el = variantEl.select(`g.dfs-group-${dfsId}`); + if (i == x) { + el.style('fill-opacity', config.hoverTransparency); + } + el.select('polygon') + .style('stroke', config.hoverColor) + .style('stroke-width', config.strokeWidth); + }); + } + } + }) + .on('mouseout', function () { + arcGroups + .selectAll('rect') + .style('fill-opacity', config.transparency) + .style('fill', config.arcColor); + arcGroups + .selectAll('path') + .style('stroke-opacity', config.transparency) + .style('stroke', config.arcColor); + variantEl + .selectAll('g') + .style('fill-opacity', config.hoverTransparency) + .selectAll('polygon') + .style('stroke', 'none'); + }) + .on('click', function (d, i) { + // move all patterns to the same level as that of the clicked one + arcGroups.selectAll('rect,path').each(function (x: Arc) { + moveArcComponents(this, x, areOtherArcsHidden); + }); + areOtherArcsHidden = !areOtherArcsHidden; + + function moveArcComponents(el, x: Arc, reset: boolean) { + if (i.text == x.text && i != x && !reset) { + d3.select(el.parentNode) + .transition() + .duration(500) + .attr('transform', function () { + return `translate(0, ${ + d.target.getAttribute('y') - this.firstChild.getAttribute('y') + })`; + }); + } + if (reset) { + d3.select(el.parentNode) + .transition() + .duration(500) + .attr('transform', null); + } + if (i.text != x.text) { + d3.select(el).style('visibility', reset ? 'visible' : 'hidden'); + } + } + }); + }; +} diff --git a/src/frontend/src/app/directives/arc-diagram/data.ts b/src/frontend/src/app/directives/arc-diagram/data.ts new file mode 100644 index 0000000000000000000000000000000000000000..b04e2e6b3f4c0452903e506a635efd88038c1406 --- /dev/null +++ b/src/frontend/src/app/directives/arc-diagram/data.ts @@ -0,0 +1,73 @@ +class Arc { + sourcePos: number; + numberEle: number; + targetPos: number; + matches: Set<number>; + text: string; + activities: Array<string>; + size: number; + distanceBetweenPairs: number; + + constructor( + sourcePos, + numberEle, + targetPos, + matches, + text, + activities, + size + ) { + this.sourcePos = sourcePos; + /** First starting position of the arc */ + this.numberEle = numberEle; + /** Length of the arc in characters */ + this.targetPos = targetPos; + /** Second starting position of the arc */ + this.matches = matches; + /** DFS ids of all matching chevrons in the arc */ + this.text = text; /** String value of the arc */ + this.activities = activities; + this.size = size; + this.distanceBetweenPairs = targetPos - sourcePos - numberEle; + } +} + +class Positions { + dfs: number[]; + bfs: number[]; + + constructor(dfs, bfs) { + this.dfs = dfs; + this.bfs = bfs; + } +} + +class Pair { + positions: Positions; + pattern: string[]; + length: number; + matches: Set<number>; + activities: Array<string>; + size: number; + + constructor(positions, pattern, matches, activities, size) { + this.positions = positions; // starting positions in concurrency tree + this.pattern = pattern; // activities in repetition + this.matches = matches; // DFS ids of all matching tree nodes in the pair + this.length = pattern.length; // number of activities in repetition + this.activities = activities; // list of activities in the pattern ( = leaf nodes, not a set ) + this.size = size; + } +} + +class Level { + distanceBetweenPairs: number; // number of chevrons between them + fromBottom: number; // which level the arcs are drawn on + + constructor(distanceBetweenPairs: number, fromBottom: number) { + this.distanceBetweenPairs = distanceBetweenPairs; + this.fromBottom = fromBottom; + } +} + +export { Arc, Pair, Level }; diff --git a/src/frontend/src/app/directives/arc-diagram/filter-config.ts b/src/frontend/src/app/directives/arc-diagram/filter-config.ts new file mode 100644 index 0000000000000000000000000000000000000000..e6c1fc603d027decdc5f830725147ce93650dfd4 --- /dev/null +++ b/src/frontend/src/app/directives/arc-diagram/filter-config.ts @@ -0,0 +1,3 @@ +export class FilterConfig { + minPatternSize: number; +} diff --git a/src/frontend/src/app/directives/bpmn-drawer/bpmn-drawer.directive.spec.ts b/src/frontend/src/app/directives/bpmn-drawer/bpmn-drawer.directive.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..3b96b3f3d81c188e2bf6da50ce55087338696481 --- /dev/null +++ b/src/frontend/src/app/directives/bpmn-drawer/bpmn-drawer.directive.spec.ts @@ -0,0 +1,11 @@ +/* tslint:disable:no-unused-variable */ + +import { TestBed, async } from '@angular/core/testing'; +import { BpmnDrawerDirective } from './bpmn-drawer.directive'; + +describe('Directive: BpmnDrawer', () => { + it('should create an instance', () => { + const directive = new BpmnDrawerDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/directives/bpmn-drawer/bpmn-drawer.directive.ts b/src/frontend/src/app/directives/bpmn-drawer/bpmn-drawer.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..37a942d5a89a442777322ffd2967298302fc7b22 --- /dev/null +++ b/src/frontend/src/app/directives/bpmn-drawer/bpmn-drawer.directive.ts @@ -0,0 +1,868 @@ +import { Directive, ElementRef, Input } from '@angular/core'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import * as d3 from 'd3'; +import { + Block_Structured_BPMN, + ChoiceBlock, + convertPTtoBlockstructuredBPMN, + Event, + LoopBlock, + ParallelBlock, + SequenceBlock, +} from 'src/app/objects/BPMN/block-structured-bpmn'; +import { BPMN_Constant } from 'src/app/constants/bpmn_model_drawer_constants'; +import { ProcessTreeOperator } from 'src/app/objects/ProcessTree/ProcessTree'; +import { VariantService } from '../../services/variantService/variant.service'; +import { getBootstrapTooltipsAllowList } from '../../components/process-tree-editor/utils'; +import { ViewMode } from '../../objects/ViewMode'; +import { ModelViewModeService } from '../../services/viewModeServices/model-view-mode.service'; + +@Directive({ + selector: '[appBpmnDrawer]', +}) +export class BpmnDrawerDirective { + @Input() + computeNodeColor; + + @Input() + computeTextColor; + + @Input() + computeFillColor; + + @Input() + tooltipText; + + @Input() + onClickCallBack; + + mainGroup; + root; + + constructor( + elRef: ElementRef, + private processTreeService: ProcessTreeService, + private variantService: VariantService, + private modelViewModeService: ModelViewModeService + ) { + this.mainGroup = d3.select(elRef.nativeElement); + } + + redraw(tree) { + this.mainGroup.selectChildren().remove(); + + this.root = tree; + + if (tree) { + const model = convertPTtoBlockstructuredBPMN( + tree, + this.processTreeService.nodeWidthCache + ); + + const start = this.mainGroup + .append('g') + .attr( + 'transform', + `translate(${-( + BPMN_Constant.HORIZONTALSPACING + + BPMN_Constant.START_END_RADIUS - + BPMN_Constant.STROKE_WIDTH + )},${BPMN_Constant.BASE_HEIGHT_WIDTH / 2})` + ); + + this.drawStart(start, tree, model._pt.frozen); + + this.drawLine( + start, + BPMN_Constant.START_END_RADIUS, + 0, + BPMN_Constant.START_END_RADIUS + BPMN_Constant.HORIZONTALSPACING, + 0, + model._pt.frozen + ); + + const bpmn = this.mainGroup.append('g'); + + this.drawBlock(model, bpmn); + + const end = this.mainGroup + .append('g') + .attr( + 'transform', + `translate(${ + model.width + + BPMN_Constant.HORIZONTALSPACING + + BPMN_Constant.START_END_RADIUS + }, ${BPMN_Constant.BASE_HEIGHT_WIDTH / 2})` + ); + + this.drawEnd(end, tree, model._pt.frozen); + + this.drawLine( + end, + -(BPMN_Constant.START_END_RADIUS + BPMN_Constant.HORIZONTALSPACING), + 0, + -BPMN_Constant.START_END_RADIUS, + 0, + model._pt.frozen + ); + + // translate diagram to fit into positive x and positive y quadrant + this.mainGroup.attr( + 'transform', + `translate(${ + 2 * BPMN_Constant.START_END_RADIUS + BPMN_Constant.HORIZONTALSPACING + }, ${ + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH - + BPMN_Constant.OPERATOR_NODE_WIDTH / 2 + })` + ); + } + } + + drawBlock(model: Block_Structured_BPMN, selection, reversed = false) { + selection.datum(model._pt); + selection.attr('id', model._pt.id); + + if (model instanceof SequenceBlock) { + this.drawSequenceBlock(model, selection, reversed); + } else if (model instanceof Event) { + this.drawEvent(model, selection); + } else if (model instanceof ParallelBlock) { + this.drawParallelBlock(model, selection, reversed); + } else if (model instanceof ChoiceBlock) { + this.drawChoiceBlock(model, selection, reversed); + } else if (model instanceof LoopBlock) { + this.drawLoopBlock(model, selection, reversed); + } + } + + drawParallelBlock( + model: ParallelBlock, + selection: d3.Selection<any, any, any, any>, + reversed = false + ) { + const parallel_block = selection; + + const enter_operator = parallel_block.append('g'); + this.drawOperatorNode(enter_operator, model); + + let offset_x = + BPMN_Constant.HORIZONTALSPACING + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH; + + let offset_y = 0; + + let interpolate_along_diag; + + if (model.members.length > 1) { + interpolate_along_diag = [...model.members.keys()].map((i) => { + return { + y: + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH - + (BPMN_Constant.OPERATOR_DIAGONAL_LENGTH / + (model.members.length - 1)) * + i, + x: + (BPMN_Constant.OPERATOR_DIAGONAL_LENGTH / + (model.members.length - 1)) * + i, + }; + }); + } else { + interpolate_along_diag = [ + { y: 0, x: BPMN_Constant.OPERATOR_DIAGONAL_LENGTH }, + ]; + } + + for (let block of model.members) { + const interpolate = interpolate_along_diag.pop(); + + const center = (model.core_width - block.width) / 2; + + // General Case + if ( + !(block instanceof Event && block.eventName === ProcessTreeOperator.tau) + ) { + const g = parallel_block + .append('g') + .attr('transform', `translate(${offset_x + center}, ${offset_y})`); + + this.drawBlock(block, g, reversed); + + // draw line from entry block to member block + this.drawLine( + parallel_block, + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH + interpolate.x, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + interpolate.y, + offset_x + center, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + offset_y, + model._pt.frozen, + reversed + ); + + // draw line from member block to leave block + this.drawLine( + parallel_block, + offset_x + center + block.width, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + offset_y, + model.core_width + + 2 * BPMN_Constant.HORIZONTALSPACING + + interpolate.y, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + interpolate.y, + model._pt.frozen, + reversed + ); + + // Draw a skip-line in the tau case + } else { + this.drawSkipLine( + parallel_block, + block, + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH + interpolate.x, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + interpolate.y, + model.core_width + + 2 * BPMN_Constant.HORIZONTALSPACING + + interpolate.y, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + offset_y, + model._pt.frozen, + reversed + ); + } + + offset_y += block.height + BPMN_Constant.VERTICALSPACING; + } + + if (model.members.length === 0) { + const interpolate = interpolate_along_diag.pop(); + + this.drawLine( + parallel_block, + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH + interpolate.x, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2, + model.core_width + 2 * BPMN_Constant.HORIZONTALSPACING + interpolate.y, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2, + model._pt.frozen, + reversed + ); + } + + const leave_operator = parallel_block + .append('g') + .attr( + 'transform', + `translate(${ + model.core_width + 2 * BPMN_Constant.HORIZONTALSPACING + }, 0)` + ); + + this.drawOperatorNode(leave_operator, model); + } + + drawChoiceBlock( + model: ChoiceBlock, + selection: d3.Selection<any, any, any, any>, + reversed = false + ) { + const choiceblock = selection; + + const enter_operator = choiceblock.append('g'); + this.drawOperatorNode(enter_operator, model); + + let offset_x = + BPMN_Constant.HORIZONTALSPACING + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH; + + let offset_y = 0; + let interpolate_along_diag; + + if (model.members.length > 1) { + interpolate_along_diag = [...model.members.keys()].map((i) => { + return { + y: + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH - + (BPMN_Constant.OPERATOR_DIAGONAL_LENGTH / + (model.members.length - 1)) * + i, + x: + (BPMN_Constant.OPERATOR_DIAGONAL_LENGTH / + (model.members.length - 1)) * + i, + }; + }); + } else { + interpolate_along_diag = [ + { y: 0, x: BPMN_Constant.OPERATOR_DIAGONAL_LENGTH }, + ]; + } + + for (let block of model.members) { + const interpolate = interpolate_along_diag.pop(); + + const center = (model.core_width - block.width) / 2; + + if ( + !(block instanceof Event && block.eventName === ProcessTreeOperator.tau) + ) { + const g = choiceblock + .append('g') + .attr('transform', `translate(${offset_x + center}, ${offset_y})`); + + this.drawBlock(block, g, reversed); + + // draw line from entry block to member block + this.drawLine( + choiceblock, + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH + interpolate.x, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + interpolate.y, + offset_x + center, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + offset_y, + model._pt.frozen, + reversed + ); + + // draw line from member block to leave block + this.drawLine( + choiceblock, + offset_x + center + block.width, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + offset_y, + model.core_width + + 2 * BPMN_Constant.HORIZONTALSPACING + + interpolate.y, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + interpolate.y, + model._pt.frozen, + reversed + ); + + // Draw a skip-line in the tau case + } else { + this.drawSkipLine( + choiceblock, + block, + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH + interpolate.x, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + interpolate.y, + model.core_width + + 2 * BPMN_Constant.HORIZONTALSPACING + + interpolate.y, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + offset_y, + model._pt.frozen, + reversed + ); + } + + offset_y += block.height + BPMN_Constant.VERTICALSPACING; + } + + if (model.members.length === 0) { + const interpolate = interpolate_along_diag.pop(); + + this.drawLine( + choiceblock, + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH + interpolate.x, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2, + model.core_width + 2 * BPMN_Constant.HORIZONTALSPACING + interpolate.y, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2, + model._pt.frozen, + reversed + ); + } + + const leave_operator = choiceblock + .append('g') + .attr( + 'transform', + `translate(${ + model.core_width + 2 * BPMN_Constant.HORIZONTALSPACING + }, 0)` + ); + + this.drawOperatorNode(leave_operator, model); + } + + drawLoopBlock( + model: LoopBlock, + selection: d3.Selection<any, any, any, any>, + reversed = false + ) { + const loop_block = selection; + + const enter_operator = loop_block.append('g'); + this.drawOperatorNode(enter_operator, model); + + let offset_x = + BPMN_Constant.HORIZONTALSPACING + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH; + + let offset_y = 0; + + if (model.members.length > 0) { + const do_block = model.members[0]; + + let center = (model.core_width - do_block.width) / 2; + + let g = loop_block + .append('g') + .attr('transform', `translate(${offset_x + center}, ${offset_y})`); + + if ( + !( + do_block instanceof Event && + do_block.eventName === ProcessTreeOperator.tau + ) + ) { + this.drawBlock(do_block, g, reversed); + + // Draw line from do block to member block + this.drawLine( + loop_block, + 2 * BPMN_Constant.OPERATOR_DIAGONAL_LENGTH, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2, + offset_x + center, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + offset_y, + model._pt.frozen, + reversed + ); + + // Draw line from do block to leave block + this.drawLine( + loop_block, + offset_x + center + do_block.width, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + offset_y, + model.core_width + 2 * BPMN_Constant.HORIZONTALSPACING, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2, + model._pt.frozen, + reversed + ); + + // Draw a skip-line in the tau case + } else { + this.drawSkipLine( + loop_block, + do_block, + 2 * BPMN_Constant.OPERATOR_DIAGONAL_LENGTH, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2, + model.core_width + 2 * BPMN_Constant.HORIZONTALSPACING, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2, + model._pt.frozen, + reversed + ); + } + + offset_y += do_block.height + BPMN_Constant.VERTICALSPACING; + + if (model.members.length > 1) { + const redo_block = model.members[1]; + + center = (model.core_width - redo_block.width) / 2; + + if ( + !( + redo_block instanceof Event && + redo_block.eventName === ProcessTreeOperator.tau + ) + ) { + g = loop_block + .append('g') + .attr('transform', `translate(${offset_x + center}, ${offset_y})`); + + this.drawBlock(redo_block, g, !reversed); + + // Draw line from redo block to entry block + this.drawLine( + loop_block, + offset_x + center, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + offset_y, + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH, + model._pt.frozen, + reversed + ); + + // Draw line from redo block to leave block + this.drawLine( + loop_block, + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH + + model.core_width + + 2 * BPMN_Constant.HORIZONTALSPACING, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH, + offset_x + center + redo_block.width, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + offset_y, + model._pt.frozen, + reversed + ); + + // Draw a skip-line in the tau case + } else { + this.drawSkipLine( + loop_block, + redo_block, + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH + + model.core_width + + 2 * BPMN_Constant.HORIZONTALSPACING, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH, + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2 + offset_y, + model._pt.frozen, + reversed + ); + } + } + } + + if (model.members.length === 0) { + this.drawLine( + loop_block, + 2 * BPMN_Constant.OPERATOR_DIAGONAL_LENGTH, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2, + model.core_width + 2 * BPMN_Constant.HORIZONTALSPACING, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2, + model._pt.frozen, + reversed + ); + } + + const leave_operator = loop_block + .append('g') + .attr( + 'transform', + `translate(${ + model.core_width + 2 * BPMN_Constant.HORIZONTALSPACING + }, 0)` + ); + + this.drawOperatorNode(leave_operator, model); + } + + drawOperatorNode(parent, model: Block_Structured_BPMN) { + // Determine operator Label: + + const label = model instanceof ParallelBlock ? '\u002b' : '\u2613'; + + parent.datum(model._pt).classed('cursor-pointer', true); + + let color; + + color = BPMN_Constant.OPERATOR_COLOR; + + const transforms = [ + `translate(${ + BPMN_Constant.OPERATOR_DIAGONAL_LENGTH - BPMN_Constant.OPERATOR_CENTER + }, 0)`, + //translate to origin to avoid transform-origin which is not widely supported + `translate(${BPMN_Constant.OPERATOR_CENTER}, ${BPMN_Constant.OPERATOR_CENTER})`, + 'rotate(45)', + //translate back + `translate(-${BPMN_Constant.OPERATOR_CENTER}, -${BPMN_Constant.OPERATOR_CENTER})`, + ]; + + const op = parent + .append('rect') + .classed('BPMNOperatorNode', true) + .attr('width', BPMN_Constant.BASE_HEIGHT_WIDTH) + .attr('height', BPMN_Constant.BASE_HEIGHT_WIDTH) + .attr('fill', color) + .attr('stroke', BPMN_Constant.STROKE_COLOR) + .attr('stroke-width', BPMN_Constant.STROKE_WIDTH) + .attr('transform', transforms.join(', ')) + .classed('frozen-node-operator', model._pt.frozen); + + parent.on('click', (e: PointerEvent, data) => { + this.onClickCallBack(this, e, data); + }); + + parent + .append('text') + .classed('user-select-none', true) + .classed('BPMNOperatorText', true) + .attr( + 'transform', + `translate(${BPMN_Constant.OPERATOR_DIAGONAL_LENGTH}, ${BPMN_Constant.OPERATOR_CENTER})` + ) + .attr('text-anchor', 'middle') + .attr('dominant-baseline', 'middle') + .attr('font-size', BPMN_Constant.OPERATOR_FONT_SIZE) + .attr('fill', 'white') + .text(label); + } + + addToolTip(node) { + const myDefaultAllowList = getBootstrapTooltipsAllowList(); + + node + .classed('cursor-pointer', true) + .attr('data-bs-toggle', 'tooltip') + .attr('data-bs-placement', 'top') + .attr('whiteList', myDefaultAllowList) + .attr('data-bs-title', (d) => this.tooltipText(d)) + .attr('data-bs-template', (d) => { + if ( + (this.modelViewModeService.viewMode === ViewMode.PERFORMANCE && + d.hasPerformance() && + d.label !== ProcessTreeOperator.tau) || + (this.modelViewModeService.viewMode === ViewMode.CONFORMANCE && + d.conformance !== null) + ) { + return `<div class="tooltip performance-tooltip" role="tooltip"> + <div class="tooltip-arrow"></div> + <div class="tooltip-inner p-0" style="max-width: none; border-radius: 15px;"></div> + </div>`; + } + + return `<div class="tooltip" role="tooltip"> + <div class="tooltip-arrow"></div> + <div class="tooltip-inner"></div> + </div>`; + }) + .attr('data-bs-html', true); + + // manually trigger tooltip through jquery + node.on('mouseenter', (e: PointerEvent, data) => { + // @ts-ignore + this.variantService.activityTooltipReference = $(e.target); + this.variantService.activityTooltipReference.tooltip('show'); + }); + } + + drawSequenceBlock( + model: SequenceBlock, + selection: d3.Selection<any, any, any, any>, + reversed = false + ) { + const seq_block = selection; + + let offset_x = 0; + + const children = reversed ? model.members.slice().reverse() : model.members; + + children.forEach((block, index, array) => { + const g = seq_block + .append('g') + .attr('transform', `translate(${offset_x}, 0)`); + + this.drawBlock(block, g, reversed); + offset_x += block.width; + + if (index < array.length - 1) { + this.drawLine( + seq_block, + offset_x, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2, + offset_x + BPMN_Constant.HORIZONTALSPACING, + BPMN_Constant.BASE_HEIGHT_WIDTH / 2, + model._pt.frozen, + reversed + ); + offset_x += BPMN_Constant.HORIZONTALSPACING; + } + }); + } + + drawLine( + selection, + x1: number, + y1: number, + x2: number, + y2: number, + frozen = false, + reversed = false + ) { + if (reversed) { + [x1, x2] = [x2, x1]; + [y1, y2] = [y2, y1]; + } + + const lineData: Array<[number, number]> = [[x1, y1]]; + const d = BPMN_Constant.ARROW_LENGTH_WITHOUT_WINGS; + + // forwards arrow + if (x2 > x1) { + // downwards + if (y2 >= y1) { + lineData.push([x1, y2]); + lineData.push([x2 - d, y2]); + // upwards + } else { + lineData.push([x2, y1]); + lineData.push([x2, y2 + d]); + } + } + // backwards arrow + else { + // downwards + if (y2 >= y1) { + lineData.push([x1, y2]); + lineData.push([x2 + d, y2]); + // upwards + } else { + lineData.push([x2, y1]); + lineData.push([x2, y2 + d]); + } + } + + const line = selection + .append('path') + .attr('d', d3.line()(lineData)) + .attr('fill', 'none') + .attr('stroke-width', '1') + .attr('stroke', BPMN_Constant.STROKE_COLOR) + .style('stroke-linejoin', 'round') + .attr('marker-end', frozen ? 'url(#arrow-frozen)' : 'url(#arrow-grey)') + .classed('frozen-edge', frozen); + } + + drawSkipLine( + selection, + model, + x1: number, + y1: number, + x2: number, + y2: number, + frozen = false, + reversed = false + ) { + if (reversed) { + [x1, x2] = [x2, x1]; + } + + const lineData: Array<[number, number]> = [[x1, y1]]; + const d = BPMN_Constant.ARROW_LENGTH_WITHOUT_WINGS; + + // forwards arrow + if (x2 > x1) { + if (y1 == y2) { + lineData.push([x2 - d, y2]); + } else { + lineData.push([x1, y2]); + lineData.push([x2, y2]); + lineData.push([x2, y1 + d]); + } + } + // backwards arrow + else { + if (y1 == y2) { + lineData.push([x2 + d, y2]); + } else { + lineData.push([x1, y2]); + lineData.push([x2, y2]); + lineData.push([x2, y1 + d]); + } + } + + const line = selection + .append('path') + .attr('d', d3.line()(lineData)) + .attr('fill', 'none') + .attr('stroke-width', '1') + .attr('stroke', BPMN_Constant.STROKE_COLOR) + .style('stroke-linejoin', 'round') + .attr('marker-end', frozen ? 'url(#arrow-frozen)' : 'url(#arrow-grey)') + .classed('frozen-edge', frozen); + + line.datum(model._pt); + line.attr('id', model._pt.id); + } + + drawEvent(model: Event, selection) { + const node = selection + .append('rect') + .attr('stroke-width', 1) + .attr('stroke', BPMN_Constant.STROKE_COLOR) + .attr('rx', 3) + .attr('ry', 3); + + node.datum(model._pt); + + node.classed('frozen-node-visible-activity', model._pt.frozen); + selection.classed('cursor-pointer', true); + + const color = this.computeNodeColor(model._pt); + const text_color = this.computeTextColor(model._pt); + + const width = model.width; + + if (model.eventName === ProcessTreeOperator.tau) { + node + .attr('width', width) + .attr('height', BPMN_Constant.BASE_HEIGHT_WIDTH) + .attr('fill', color); + } else { + node + .attr('width', width) + .attr('height', BPMN_Constant.BASE_HEIGHT_WIDTH) + .attr('fill', color); + } + + selection.on('click', (e: PointerEvent, data) => { + this.onClickCallBack(this, e, data); + }); + + const activityText = selection + .append('text') + .attr('x', width / 2) + .attr('y', BPMN_Constant.BASE_HEIGHT_WIDTH / 2) + .attr('text-anchor', 'middle') + .attr('dominant-baseline', 'middle') + .attr('font-size', 12) + .attr('fill', text_color) + .classed('user-select-none', true); + + const tspan = activityText + .append('tspan') + .attr('x', width / 2) + .attr('y', BPMN_Constant.BASE_HEIGHT_WIDTH / 2); + + if (model.eventName) { + // shorten text if it is too long + if (model.eventName.length <= 20) { + tspan.text(model.eventName); + } else { + tspan.text(model.eventName.substring(0, 20) + '...'); + } + } + + this.addToolTip(selection); + } + + drawStart(parent, tree, frozen) { + parent.classed('cursor-pointer', true).attr('id', tree.id).datum(tree); + + parent + .append('circle') + .classed('BPMNOperatorNode', true) + .attr('r', BPMN_Constant.START_END_RADIUS) + .attr('fill', BPMN_Constant.OPERATOR_COLOR) + .attr('stroke', BPMN_Constant.STROKE_COLOR) + .attr('stroke-width', BPMN_Constant.STROKE_WIDTH) + .classed('frozen-node-operator', frozen); + + parent.on('click', (e: PointerEvent, data) => { + this.onClickCallBack(this, e, data); + }); + } + + drawEnd(parent, tree, frozen) { + parent.classed('cursor-pointer', true).attr('id', tree.id).datum(tree); + + parent + .append('circle') + .classed('BPMNOperatorNode', true) + .attr('r', BPMN_Constant.START_END_RADIUS) + .attr('fill', BPMN_Constant.OPERATOR_COLOR) + .attr('stroke', BPMN_Constant.STROKE_COLOR) + .attr('stroke-width', BPMN_Constant.STROKE_WIDTH) + .classed('frozen-node-operator', frozen); + + parent + .append('circle') + .classed('BPMNOperatorNode', true) + .attr('r', BPMN_Constant.START_END_RADIUS - 2) + .attr('fill', BPMN_Constant.OPERATOR_COLOR) + .attr('stroke', BPMN_Constant.STROKE_COLOR) + .attr('stroke-width', BPMN_Constant.STROKE_WIDTH) + .classed('frozen-node-operator', frozen); + + parent.on('click', (e: PointerEvent, data) => { + this.onClickCallBack(this, e, data); + }); + } +} diff --git a/src/frontend/src/app/directives/drop-zone/drop-zone.directive.spec.ts b/src/frontend/src/app/directives/drop-zone/drop-zone.directive.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..8213223e0d53c01e1b99e14092070697898f1d25 --- /dev/null +++ b/src/frontend/src/app/directives/drop-zone/drop-zone.directive.spec.ts @@ -0,0 +1,8 @@ +import { DropZoneDirective } from './drop-zone.directive'; + +describe('DropZoneDirective', () => { + it('should create an instance', () => { + const directive = new DropZoneDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/directives/drop-zone/drop-zone.directive.ts b/src/frontend/src/app/directives/drop-zone/drop-zone.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..2419adb7c2cd9c679302296d71c490ebb032b9be --- /dev/null +++ b/src/frontend/src/app/directives/drop-zone/drop-zone.directive.ts @@ -0,0 +1,17 @@ +import { Directive, HostListener } from '@angular/core'; + +@Directive({ + selector: '[appDropZone]', +}) +export class DropZoneDirective { + private static _windowDrag: boolean = false; + constructor() {} + + static get windowDrag(): boolean { + return DropZoneDirective._windowDrag; + } + + static set windowDrag(state: boolean) { + DropZoneDirective._windowDrag = state; + } +} diff --git a/src/frontend/src/app/directives/layout-change/layout-change.directive.spec.ts b/src/frontend/src/app/directives/layout-change/layout-change.directive.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..27ec09605176daabc70f0e62a25d586d46771ac4 --- /dev/null +++ b/src/frontend/src/app/directives/layout-change/layout-change.directive.spec.ts @@ -0,0 +1 @@ +import { LayoutChangeDirective } from './layout-change.directive'; diff --git a/src/frontend/src/app/directives/layout-change/layout-change.directive.ts b/src/frontend/src/app/directives/layout-change/layout-change.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..536354abb43526545d827d0b838fb9cc046a9910 --- /dev/null +++ b/src/frontend/src/app/directives/layout-change/layout-change.directive.ts @@ -0,0 +1,70 @@ +import { Directive, InjectionToken, Renderer2 } from '@angular/core'; +import { ComponentContainer, LogicalZIndex } from 'golden-layout'; + +@Directive() +export abstract class LayoutChangeDirective { + constructor( + public rootHtmlElement: HTMLElement, + private renderer2: Renderer2 + ) {} + + setPositionAndSize(left: number, top: number, width: number, height: number) { + this.renderer2.setStyle( + this.rootHtmlElement, + 'left', + this.numberToPixels(left) + ); + this.renderer2.setStyle( + this.rootHtmlElement, + 'top', + this.numberToPixels(top) + ); + this.renderer2.setStyle( + this.rootHtmlElement, + 'width', + this.numberToPixels(width) + ); + this.renderer2.setStyle( + this.rootHtmlElement, + 'height', + this.numberToPixels(height) + ); + } + + setVisibility(visible: boolean) { + if (visible) { + this.renderer2.setStyle(this.rootHtmlElement, 'display', ''); + } else { + this.renderer2.setStyle(this.rootHtmlElement, 'display', 'none'); + } + } + + setZIndex(value: string) { + this.renderer2.setStyle(this.rootHtmlElement, 'zIndex', value); + } + + private numberToPixels(value: number): string { + return value.toString(10) + 'px'; + } + + // Abstract method that gets called after each virtual recting event to allow the component to change its layout + abstract handleResponsiveChange( + left: number, + top: number, + width: number, + height: number + ): void; + + abstract handleVisibilityChange(visibility: boolean): void; + + abstract handleZIndexChange( + logicalZIndex: LogicalZIndex, + defaultZIndex: string + ): void; +} + +export namespace LayoutChangeDirective { + const GoldenLayoutContainerTokenName = 'GoldenLayoutContainer'; + export const GoldenLayoutContainerInjectionToken = + new InjectionToken<ComponentContainer>(GoldenLayoutContainerTokenName); +} diff --git a/src/frontend/src/app/directives/process-tree-drawer/process-tree-drawer.directive.spec.ts b/src/frontend/src/app/directives/process-tree-drawer/process-tree-drawer.directive.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..3b2dd5c2d80ea62fdf7a29a0c4faa37ca1ab3b59 --- /dev/null +++ b/src/frontend/src/app/directives/process-tree-drawer/process-tree-drawer.directive.spec.ts @@ -0,0 +1,11 @@ +/* tslint:disable:no-unused-variable */ + +import { TestBed, async } from '@angular/core/testing'; +import { ProcessTreeDrawerDirective } from './process-tree-drawer.directive'; + +describe('Directive: ProcessTreeDrawer', () => { + it('should create an instance', () => { + const directive = new ProcessTreeDrawerDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/directives/process-tree-drawer/process-tree-drawer.directive.ts b/src/frontend/src/app/directives/process-tree-drawer/process-tree-drawer.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..8143eae584b5721dc368c45ed335b779106bdd85 --- /dev/null +++ b/src/frontend/src/app/directives/process-tree-drawer/process-tree-drawer.directive.ts @@ -0,0 +1,340 @@ +import { PT_Constant } from './../../constants/process_tree_drawer_constants'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { Directive, ElementRef, Input } from '@angular/core'; +import { + ProcessTree, + ProcessTreeOperator, +} from 'src/app/objects/ProcessTree/ProcessTree'; +import { flextree } from 'd3-flextree'; +import { ContextMenuService } from '@perfectmemory/ngx-contextmenu'; + +import * as d3 from 'd3'; +import { ModelViewModeService } from 'src/app/services/viewModeServices/model-view-mode.service'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { VariantService } from '../../services/variantService/variant.service'; +import { getBootstrapTooltipsAllowList } from '../../components/process-tree-editor/utils'; +import { ProcessTreeEditorContextMenuComponent } from 'src/app/components/process-tree-editor/process-tree-editor-context-menu/process-tree-editor-context-menu.component'; + +@Directive({ + selector: '[appProcessTreeDrawer]', +}) +export class ProcessTreeDrawerDirective { + nodeEnter: any; + + root: d3.HierarchyNode<any>; + mainSvgGroup: any; + + processTreeSyntaxInfo: any; + selectedRootNode: any; + + constructor( + elRef: ElementRef, + private processTreeService: ProcessTreeService, + private modelViewModeService: ModelViewModeService, + private variantService: VariantService, + private contextMenuService: ContextMenuService<any> + ) { + this.mainSvgGroup = d3.select(elRef.nativeElement); + } + + @Input() + contextMenuComponent: ProcessTreeEditorContextMenuComponent; + + @Input() + computeNodeColor; + + @Input() + computeTextColor; + + @Input() + tooltipText; + + @Input() + onClickCallBack; + + redraw(tree: ProcessTree) { + if (tree) { + this.root = d3.hierarchy(tree, (d) => { + // @ts-ignore + return d.children; + }); + } else { + this.root = null; + } + + // synchronization between update of node width cache and process tree rendering + setTimeout(() => this.update(this.root), 0); + } + + drawNodes(node: d3.Selection<any, any, any, any>) { + const myDefaultAllowList = getBootstrapTooltipsAllowList(); + + // add node groups + this.nodeEnter = node + .enter() + .append('g') + .attr('id', (d) => { + return d.data.id; + }) + .classed('cursor-pointer', true) + .attr('data-bs-toggle', 'tooltip') + .attr('data-bs-placement', 'top') + .attr('whiteList', myDefaultAllowList) + .attr('data-bs-title', (d) => this.tooltipText(d)) + .attr('data-bs-template', (d) => { + if ( + (this.modelViewModeService.viewMode === ViewMode.PERFORMANCE && + d.data.hasPerformance() && + d.data.label !== ProcessTreeOperator.tau) || + (this.modelViewModeService.viewMode === ViewMode.CONFORMANCE && + d.data.conformance !== null) + ) { + return `<div class="tooltip performance-tooltip" role="tooltip"> + <div class="tooltip-arrow"></div> + <div class="tooltip-inner p-0" style="max-width: none; border-radius: 15px;"></div> + </div>`; + } + + return `<div class="tooltip" role="tooltip"> + <div class="tooltip-arrow"></div> + <div class="tooltip-inner"></div> + </div>`; + }) + .attr('data-bs-html', true); + + // manually trigger tooltip through jquery + this.nodeEnter.on('mouseenter', (e: PointerEvent, data) => { + // @ts-ignore + this.variantService.activityTooltipReference = $(e.target); + this.variantService.activityTooltipReference.tooltip('show'); + }); + + this.nodeEnter.on('contextmenu', (e: PointerEvent, data) => { + e.preventDefault(); + e.stopPropagation(); + this.contextMenuService.show(this.contextMenuComponent?.contextMenu, { + value: data.data, + x: e.x, + y: e.y, + }); + }); + + // add nodes + this.nodeEnter + .append('rect') + .classed('node', true) + .attr('rx', PT_Constant.CORNER_RADIUS) + .attr('ry', PT_Constant.CORNER_RADIUS) + .attr('stroke', PT_Constant.STROKE_COLOR) + .attr('stroke-width', PT_Constant.STROKE_WIDTH) + .merge(node.select('.node')) + .style('fill', (d) => this.computeNodeColor(d)) + .classed('node-operator', function (d: any) { + return d.data.operator !== null; + }) + .classed('frozen-node-operator', function (d: any) { + return d.data.operator !== null && d.data.frozen === true; + }) + .classed('node-visible-activity', function (d: any) { + return ( + d.data.label !== null && d.data.label !== ProcessTreeOperator.tau + ); + }) + .classed('selected-node', function (d: any) { + return d.data.selected; + }) + .classed('frozen-node-visible-activity', function (d: any) { + return ( + d.data.label !== null && + d.data.label !== ProcessTreeOperator.tau && + d.data.frozen === true + ); + }) + .classed('node-invisible-activity', (d: any) => { + return d.data.label === ProcessTreeOperator.tau; + }) + .classed('frozen-node-invisible-activity', (d: any) => { + return ( + d.data.label === ProcessTreeOperator.tau && d.data.frozen === true + ); + }) + .attr('width', PT_Constant.BASE_HEIGHT_WIDTH) + .attr('height', PT_Constant.BASE_HEIGHT_WIDTH) + .attr('font-size', (d: any) => { + if (d.data.label === ProcessTreeOperator.tau) + return PT_Constant.INVISIBLE_FONT_SIZE; + return ''; + }) + .attr('x', function (d: any) { + return d.x - PT_Constant.BASE_HEIGHT_WIDTH / 2; + }) + .attr('y', function (d: any) { + return d.y; + }); + + // add node text + this.nodeEnter + .append('text') + .classed('user-select-none', true) + .classed('node-text', true) + .attr('text-anchor', 'middle') + .attr('dominant-baseline', 'middle') + .merge(node.select('text')) + .attr('fill', (d) => this.computeTextColor(d)) + .attr('font-size', (d: any) => { + if (d.data.operator) { + return PT_Constant.OPERATOR_FONT_SIZE; + } + return PT_Constant.VISIBLE_FONT_SIZE; + }) + .attr('x', function (d: any) { + return d.x; + }) + .attr('y', function (d: any) { + return d.y + PT_Constant.BASE_HEIGHT_WIDTH / 2 + 3; + }) + .text(function (d: any) { + if (d.data.operator) { + return d.data.operator; + } + if (d.data.label) { + // shorten text if it is too long + if (d.data.label.length <= 20) { + return d.data.label; + } else { + return d.data.label.substring(0, 20) + '...'; + } + } + }); + + // resize leaf nodes if text is too long + this.nodeEnter + .merge(node) + .select('.node-visible-activity') + .attr('x', function (d) { + return ( + d.x - + Math.max( + PT_Constant.BASE_HEIGHT_WIDTH, + this.nextSibling.getComputedTextLength() + 10 + ) / + 2 + ); + }) + .attr('width', function () { + return Math.max( + PT_Constant.BASE_HEIGHT_WIDTH, + this.nextSibling.getComputedTextLength() + 10 + ); + }); + + // remove nodes + node.exit().transition().duration(50).remove(); + } + + drawEdges(root) { + const edges = this.mainSvgGroup.selectAll('line').data(root.links()); + + edges.classed('selected-edge', false); + + // remove old edges + edges.exit().remove(); + + // add edges + edges + .enter() + .append('line') + .attr('class', 'link') + .merge(edges) + // .transition() + .attr('x1', function (d: any) { + return d.source.x; + }) + .attr('y1', function (d: any) { + return d.source.y + PT_Constant.BASE_HEIGHT_WIDTH; + }) + .attr('x2', function (d: any) { + return d.target.x; + }) + .attr('y2', function (d: any) { + return d.target.y; + }) + .attr('stroke', PT_Constant.STROKE_COLOR) + .classed('frozen-edge', (d) => { + return d.source.data.frozen; + }); + } + + update(root): void { + this.mainSvgGroup.selectAll('g').remove(); + + if (root) { + // add node groups that contain a rectangle and text + this.calculateTreeLayout(root); + + const node = this.mainSvgGroup + .selectAll('g') + .data(root.descendants(), function (d) { + return d.data.id; + }); + + // Draw Nodes + this.drawNodes(node); + + // Draw Edges + this.drawEdges(root); + + this.addSelectionFunctionality(); + } else { + this.selectedRootNode = null; + this.mainSvgGroup.selectAll('*').remove(); + } + } + + createNode(operator, label): d3.HierarchyNode<any> { + // TODO make sure that IDs are unique!!! + const nodeData = { + operator, + label, + id: Math.floor(1000000000 + Math.random() * 900000000), + children: [], + }; + return d3.hierarchy(nodeData); + } + + calculateTreeLayout(root): void { + if (root) { + const flextreeLayout = flextree(); + flextreeLayout.nodeSize((node) => { + if (node.data.operator || node.data.label === ProcessTreeOperator.tau) { + return [ + PT_Constant.BASE_HEIGHT_WIDTH, + 2 * PT_Constant.BASE_HEIGHT_WIDTH, + ]; + } + + return [ + this.processTreeService.nodeWidthCache[node.data.label], + 2 * PT_Constant.BASE_HEIGHT_WIDTH, + ]; + }); + + // Specifies the spacing between two nodes + flextreeLayout.spacing((nodeA, nodeB) => { + return nodeA.parent === nodeB.parent + ? PT_Constant.NODE_SPACING + : 2 * PT_Constant.NODE_SPACING; + }); + + // calculate layout + flextreeLayout(root); + } + } + + addSelectionFunctionality(): void { + this.nodeEnter.on('click', (e: PointerEvent, data) => { + this.onClickCallBack(this, e, data); + e.stopPropagation(); + }); + } +} diff --git a/src/frontend/src/app/directives/resize-column.directive.spec.ts b/src/frontend/src/app/directives/resize-column.directive.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..5e998825ac3a8295d763eb42f7b03fb13e7dd080 --- /dev/null +++ b/src/frontend/src/app/directives/resize-column.directive.spec.ts @@ -0,0 +1,11 @@ +/* tslint:disable:no-unused-variable */ + +import { TestBed, async } from '@angular/core/testing'; +import { ResizeColumnDirective } from './resize-column.directive'; + +describe('Directive: ResizeColumn', () => { + it('should create an instance', () => { + const directive = new ResizeColumnDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/directives/resize-column.directive.ts b/src/frontend/src/app/directives/resize-column.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..25ebf8bb98bc68b2efda618d87e201139c47c153 --- /dev/null +++ b/src/frontend/src/app/directives/resize-column.directive.ts @@ -0,0 +1,40 @@ +import { DOCUMENT } from '@angular/common'; +import { Directive, ElementRef, Inject, Output } from '@angular/core'; +import { + distinctUntilChanged, + map, + switchMap, + takeUntil, + tap, +} from 'rxjs/operators'; +import { fromEvent } from 'rxjs'; + +@Directive({ + selector: '[resizeable]', // eslint-disable-line @angular-eslint/directive-selector +}) +export class ResizeColumnDirective { + @Output() + readonly resizeable = fromEvent<MouseEvent>( + this.elementRef.nativeElement, + 'mousedown' + ).pipe( + tap((e) => e.preventDefault()), + switchMap(() => { + const { width, right } = this.elementRef.nativeElement + .closest('th')! + .getBoundingClientRect(); + + return fromEvent<MouseEvent>(this.documentRef, 'mousemove').pipe( + map(({ clientX }) => width + clientX - right), + distinctUntilChanged(), + takeUntil(fromEvent(this.documentRef, 'mouseup')) + ); + }) + ); + + constructor( + @Inject(DOCUMENT) private readonly documentRef: Document, + @Inject(ElementRef) + private readonly elementRef: ElementRef<HTMLElement> + ) {} +} diff --git a/src/frontend/src/app/directives/shared-directives/shared-directives.module.ts b/src/frontend/src/app/directives/shared-directives/shared-directives.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..788b978e8fd5217b6ac9014002bd6667dcae9840 --- /dev/null +++ b/src/frontend/src/app/directives/shared-directives/shared-directives.module.ts @@ -0,0 +1,9 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { StopEventPropagationDirective } from './stop-event-propagation.directive'; +@NgModule({ + declarations: [StopEventPropagationDirective], + imports: [CommonModule], + exports: [StopEventPropagationDirective], +}) +export class SharedDirectivesModule {} diff --git a/src/frontend/src/app/directives/shared-directives/stop-event-propagation.directive.spec.ts b/src/frontend/src/app/directives/shared-directives/stop-event-propagation.directive.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..4d4856045684254bcda6e16547f74b1d3e76b6c6 --- /dev/null +++ b/src/frontend/src/app/directives/shared-directives/stop-event-propagation.directive.spec.ts @@ -0,0 +1,8 @@ +import { StopEventPropagationDirective } from './stop-event-propagation.directive'; + +describe('StopEventPropagationDirective', () => { + it('should create an instance', () => { + const directive = new StopEventPropagationDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/directives/shared-directives/stop-event-propagation.directive.ts b/src/frontend/src/app/directives/shared-directives/stop-event-propagation.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..d27c6c416a965c82dfc77489052557da542789e6 --- /dev/null +++ b/src/frontend/src/app/directives/shared-directives/stop-event-propagation.directive.ts @@ -0,0 +1,11 @@ +import { Directive, HostListener } from '@angular/core'; + +@Directive({ + selector: '[appStopClickEventPropagation]', +}) +export class StopEventPropagationDirective { + @HostListener('click', ['$event']) + public onClick(event: any): void { + event.stopPropagation(); + } +} diff --git a/src/frontend/src/app/directives/syntax-highlighted-textarea/syntax-highlighted-textarea.directive.spec.ts b/src/frontend/src/app/directives/syntax-highlighted-textarea/syntax-highlighted-textarea.directive.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..cac7a264cac3760444219eb3f890822432ef88f4 --- /dev/null +++ b/src/frontend/src/app/directives/syntax-highlighted-textarea/syntax-highlighted-textarea.directive.spec.ts @@ -0,0 +1,11 @@ +/* tslint:disable:no-unused-variable */ + +import { TestBed, async } from '@angular/core/testing'; +import { SyntaxHighlightedTextareaDirective } from './syntax-highlighted-textarea.directive'; + +describe('Directive: SyntaxHighlightedTextarea', () => { + it('should create an instance', () => { + const directive = new SyntaxHighlightedTextareaDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/directives/syntax-highlighted-textarea/syntax-highlighted-textarea.directive.ts b/src/frontend/src/app/directives/syntax-highlighted-textarea/syntax-highlighted-textarea.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..a08ea53802e97129d6c0f4cbe76b4a4d53c1e3f1 --- /dev/null +++ b/src/frontend/src/app/directives/syntax-highlighted-textarea/syntax-highlighted-textarea.directive.ts @@ -0,0 +1,56 @@ +import { + AfterViewInit, + Directive, + ElementRef, + Input, + Renderer2, + ViewChild, +} from '@angular/core'; + +@Directive({ + selector: '[appSyntaxHighlightedTextarea]', +}) +export class SyntaxHighlightedTextareaDirective implements AfterViewInit { + @ViewChild('queryEditor') queryEditor: ElementRef<HTMLTextAreaElement>; + @ViewChild('queryEditorBackdrop') + queryEditorBackdrop: ElementRef<HTMLDivElement>; + @ViewChild('highlightText') highlightText: ElementRef<HTMLDivElement>; + + @Input() + applyHighlights: (text: string) => string; + + constructor(private renderer: Renderer2, private textarea: ElementRef) {} + + ngAfterViewInit(): void { + this.renderer.listen(this.textarea.nativeElement, 'input', (input) => { + this.handleInput(); + }); + + this.renderer.listen(this.textarea.nativeElement, 'scroll', (input) => { + this.handleScroll(); + }); + } + + handleInput() { + const text = this.applyHighlights(this.textarea.nativeElement.value); + + this.renderer.setProperty( + this.highlightText.nativeElement, + 'innerHTML', + text + ); + } + + handleScroll() { + this.renderer.setProperty( + this.queryEditorBackdrop.nativeElement, + 'scrollTop', + this.queryEditor.nativeElement.scrollTop + ); + this.renderer.setProperty( + this.queryEditorBackdrop.nativeElement, + 'scrollLeft', + this.queryEditor.nativeElement.scrollLeft + ); + } +} diff --git a/src/frontend/src/app/directives/variant-drawer/variant-drawer.directive.spec.ts b/src/frontend/src/app/directives/variant-drawer/variant-drawer.directive.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..6e971d9d6d9f77843caa25f8786cf3965d8134ed --- /dev/null +++ b/src/frontend/src/app/directives/variant-drawer/variant-drawer.directive.spec.ts @@ -0,0 +1,11 @@ +/* tslint:disable:no-unused-variable */ + +import { TestBed, async } from '@angular/core/testing'; +import { VariantDrawerDirective } from './variant-drawer.directive'; + +describe('Directive: VariantDrawer', () => { + it('should create an instance', () => { + const directive = new VariantDrawerDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/directives/variant-drawer/variant-drawer.directive.ts b/src/frontend/src/app/directives/variant-drawer/variant-drawer.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..5f56358cb88a38f655308bc4be0af3637c53f547 --- /dev/null +++ b/src/frontend/src/app/directives/variant-drawer/variant-drawer.directive.ts @@ -0,0 +1,1155 @@ +import { VARIANT_Constants } from './../../constants/variant_element_drawer_constants'; + +import { + AfterViewInit, + Directive, + ElementRef, + EventEmitter, + Input, + OnChanges, + OnDestroy, + Output, + SimpleChanges, +} from '@angular/core'; +import * as d3 from 'd3'; +import { Selection } from 'd3'; +import { PolygonGeneratorService } from 'src/app/services/polygon-generator.service'; +import { SharedDataService } from 'src/app/services/sharedDataService/shared-data.service'; +import { + getLowestSelectionActionableElement, + InfixType, + SelectableState, +} from 'src/app/objects/Variants/infix_selection'; +import { + ChoiceGroup, + FallthroughGroup, + InvisibleSequenceGroup, + LeafNode, + LoopGroup, + ParallelGroup, + SequenceGroup, + SkipGroup, + VariantElement, + WaitingTimeNode, +} from 'src/app/objects/Variants/variant_element'; +import { textColorForBackgroundColor } from 'src/app/utils/render-utils'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { VariantViewModeService } from 'src/app/services/viewModeServices/variant-view-mode.service'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { IVariant } from 'src/app/objects/Variants/variant_interface'; +import { ConformanceCheckingService } from 'src/app/services/conformanceChecking/conformance-checking.service'; +import { VariantService } from '../../services/variantService/variant.service'; + +@Directive({ + selector: '[appVariantDrawer]', + exportAs: 'variantDrawer', +}) +export class VariantDrawerDirective + implements AfterViewInit, OnChanges, OnDestroy +{ + setExpanded(expanded: boolean) { + this.variant.variant.setExpanded(expanded); + this.variant.alignment?.setExpanded(expanded); + this.redraw(); + } + + constructor( + elRef: ElementRef<HTMLElement>, + private polygonService: PolygonGeneratorService, + private sharedDataService: SharedDataService, //edited + private variantViewModeService: VariantViewModeService, + private conformanceCheckingService: ConformanceCheckingService, + private variantService: VariantService + ) { + this.svgHtmlElement = elRef; + } + + svgHtmlElement: ElementRef; + + @Input() + variant: IVariant; + + @Input() + traceInfixSelectionMode: boolean = false; + + @Input() + infixType: InfixType; + + @Input() + computeActivityColor: ( + drawerDirective: VariantDrawerDirective, + element: VariantElement, + variant: IVariant + ) => string; + + @Input() + onClickCbFc: ( + drawerDirective: VariantDrawerDirective, + element: VariantElement, + variant: IVariant + ) => void; + + @Input() + onMouseOverCbFc: ( + drawerDirective: VariantDrawerDirective, + element: VariantElement, + variant: IVariant, + selection + ) => void; + + @Input() + onRightMouseClickCbFc: ( + drawerDirective: VariantDrawerDirective, + element: VariantElement, + variant: IVariant, + event: Event + ) => void; + + @Input() + keepStandardView: boolean = false; + + @Input() + addCursorPointer: boolean = true; + + @Output() + selection = new EventEmitter<Selection<any, any, any, any>>(); + + @Output() redrawArcsIfComputed = new EventEmitter(); + + svgSelection!: Selection<any, any, any, any>; + + private _destroy$ = new Subject(); + + ngAfterViewInit(): void { + this.svgSelection = d3.select(this.svgHtmlElement.nativeElement); + + this.svgSelection = this.svgSelection + .append('g') + .style('padding-top', '5px'); + + this.redraw(); + + this.variantViewModeService.viewMode$ + .pipe(takeUntil(this._destroy$)) + .subscribe((viewMode: ViewMode) => { + this.redraw(); + this.setInspectVariant(); + }); + + this.redrawArcsIfComputed.emit(); + } + + ngOnChanges(changes: SimpleChanges): void { + if ( + changes.variant && + !changes.variant.firstChange && + changes.variant.currentValue + ) { + this.redraw(); + } else if ( + changes.infixType && + !changes.infixType.firstChange && + changes.infixType.currentValue + ) { + this.redraw(); + } else if ( + changes.traceInfixSelectionMode && + (!changes.variant || !changes.variant.firstChange) + ) { + this.redraw(); + } + } + + ngOnDestroy(): void { + this._destroy$.next(); + } + + redraw(): void { + this.svgSelection.selectAll('*').remove(); + if (this.variant.variant) { + const height = this.variant.variant.recalculateHeight( + !this.keepStandardView && + this.variantViewModeService.viewMode === ViewMode.PERFORMANCE + ); + const width = this.variant.variant.recalculateWidth( + !this.keepStandardView && + this.variantViewModeService.viewMode === ViewMode.PERFORMANCE + ); + + if ( + !this.keepStandardView && + this.variantViewModeService.viewMode === ViewMode.CONFORMANCE && + this.variant.alignment + ) { + const height = this.variant.alignment.recalculateHeight(false); + const width = this.variant.alignment.recalculateWidth(false); + } + + const svg_container = d3.select(this.svgHtmlElement.nativeElement); + this.variant.variant.updateWidth( + !this.keepStandardView && + this.variantViewModeService.viewMode === ViewMode.PERFORMANCE + ); + + const [svg, width_offset] = this.handleInfix( + this.infixType, + height, + width + ); + + svg_container + .attr('width', width + width_offset) + .attr('height', height + 2 * VARIANT_Constants.SELECTION_STROKE_WIDTH); + + if ( + !this.keepStandardView && + this.variantViewModeService.viewMode === ViewMode.CONFORMANCE && + this.variant.alignment + ) + this.draw(this.variant.alignment, svg, true); + else this.draw(this.variant.variant, svg, true); + + if ( + this.variant.variant instanceof SequenceGroup && + (this.keepStandardView || + this.variantViewModeService.viewMode !== ViewMode.PERFORMANCE) + ) { + this.svgSelection.select('polygon').style('fill', 'transparent'); + } + + this.selection.emit(this.svgSelection); + } + } + + private handleInfix(infixType, height: number, width: number): [any, number] { + let width_offset = 0; + + const PREFIX_OFFSET = 35; + const POSTFIX_OFFSET = 25; + + const svg = this.svgSelection; + const variant_svg = svg + .append('g') + .attr('width', width) + .attr('height', height); + + const height_offset = (height - 2 * VARIANT_Constants.MARGIN_Y) / 2 - 7.65; + switch (infixType) { + case InfixType.NOT_AN_INFIX: + break; + + case InfixType.POSTFIX: + width_offset = POSTFIX_OFFSET; + break; + + case InfixType.PREFIX: + width_offset = PREFIX_OFFSET; + break; + + case InfixType.PROPER_INFIX: + width_offset = PREFIX_OFFSET + POSTFIX_OFFSET; + break; + } + + svg.attr('width', width + width_offset).attr('height', height); + + if ( + infixType === InfixType.POSTFIX || + infixType === InfixType.PROPER_INFIX + ) { + variant_svg.attr( + 'transform', + `translate(${PREFIX_OFFSET}, ${VARIANT_Constants.SELECTION_STROKE_WIDTH})` + ); + + svg + .append('g') + .attr('transform', `translate(0, ${height_offset})`) + .append('use') + .attr('href', '#infixDots') + .attr('transform', 'scale(1.7)'); + } else { + variant_svg.attr( + 'transform', + `translate(0, ${VARIANT_Constants.SELECTION_STROKE_WIDTH})` + ); + } + + if ( + infixType === InfixType.PREFIX || + infixType === InfixType.PROPER_INFIX + ) { + svg + .append('g') + .attr( + 'transform', + `translate(${ + width + (infixType === InfixType.PROPER_INFIX ? PREFIX_OFFSET : 0) + }, ${height_offset})` + ) + .append('use') + .attr('href', '#infixDots') + .attr('transform', 'scale(1.7)'); + } + + return [variant_svg, width_offset]; + } + + draw( + element: VariantElement, + svgElement: Selection<any, any, any, any>, + outerElement: boolean = false + ): void { + svgElement.datum(element).classed('variant-element-group', true); + + if (element instanceof ParallelGroup) { + this.drawParallelGroup(element.asParallelGroup(), svgElement); + } else if (element instanceof ChoiceGroup) { + this.drawChoiceGroup(element.asChoiceGroup(), svgElement); + } else if (element instanceof FallthroughGroup) { + this.drawFallthroughGroup(element.asFallthroughGroup(), svgElement); + } else if (element instanceof SequenceGroup) { + this.drawSequenceGroup( + element.asSequenceGroup(), + svgElement, + outerElement + ); + } else if (element instanceof LeafNode) { + this.drawLeafNode(element.asLeafNode(), svgElement); + } else if (element instanceof WaitingTimeNode) { + this.drawWaitingNode(element.asLeafNode(), svgElement); + } else if (element instanceof LoopGroup) { + this.drawLoopGroup(element.asLoopGroup(), svgElement); + } else if (element instanceof SkipGroup) { + this.drawSkipGroup(element.asSkipGroup(), svgElement); + } + } + + public drawLoopGroup( + loopGroup: LoopGroup, + parent: Selection<any, any, any, any> + ): void { + const width = loopGroup.getWidth(); + const height = loopGroup.getHeight(); + + let leafNode = loopGroup.elements[0].asLeafNode(); + + const polygonPoints = this.polygonService.getPolygonPoints(width, height); + + const color = this.computeActivityColor(this, leafNode, this.variant); + + let laElement = getLowestSelectionActionableElement(loopGroup); + let actionable = + laElement.parent !== null && + laElement.infixSelectableState !== SelectableState.None; + + let polygon = this.createPolygon(parent, polygonPoints, color, actionable); + + if (this.traceInfixSelectionMode) { + this.addInfixSelectionAttributes(loopGroup, polygon, true); + } + + if (this.onClickCbFc) { + parent.on('click', (e: PointerEvent) => { + this.onVariantClick(loopGroup); + e.stopPropagation(); + }); + } + + const textcolor = textColorForBackgroundColor( + color, + this.traceInfixSelectionMode && !loopGroup.selected + ); + + const activityText = parent + .append('text') + .attr('x', width / 2) + .attr('y', height / 2) + .classed('user-select-none', true) + .attr('text-anchor', 'middle') + .attr('dominant-baseline', 'middle') + .attr('font-size', VARIANT_Constants.FONT_SIZE) + .attr('fill', textcolor) + .classed('activity-text', true); + + let y = height / 2; + if (leafNode.activity.length > 1) { + y = + height / 2 - + ((leafNode.activity.length - 1) / 2) * + (VARIANT_Constants.FONT_SIZE + VARIANT_Constants.MARGIN_Y); + } + + parent + .append('path') + .attr('fill', textcolor) + .attr( + 'd', + 'M11 5.466V4H5a4 4 0 0 0-3.584 5.777.5.5 0 1 1-.896.446A5 5 0 0 1 5 3h6V1.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384l-2.36 1.966a.25.25 0 0 1-.41-.192Zm3.81.086a.5.5 0 0 1 .67.225A5 5 0 0 1 11 13H5v1.466a.25.25 0 0 1-.41.192l-2.36-1.966a.25.25 0 0 1 0-.384l2.36-1.966a.25.25 0 0 1 .41.192V12h6a4 4 0 0 0 3.585-5.777.5.5 0 0 1 .225-.67Z' + ) + .attr( + 'transform', + `translate(${width / 2 - 8}, ${VARIANT_Constants.MARGIN_Y})` + ); + + let label = leafNode.activity[0]; + const tspan = activityText + .append('tspan') + .attr('x', width / 2) + .attr('y', y + VARIANT_Constants.FONT_SIZE - VARIANT_Constants.MARGIN_Y) + .classed( + 'cursor-pointer', + (!this.traceInfixSelectionMode || actionable) && this.addCursorPointer + ) + .text(label); + + const maxWidth = + loopGroup.getWidth() - + loopGroup.getHeadLength() * 2 - + VARIANT_Constants.MARGIN_X; + const truncated = this.wrapInnerLabelText(tspan, label, maxWidth); + + if (truncated) { + activityText + .attr('title', leafNode.activity[0]) + .attr('data-bs-toggle', 'tooltip'); + } + + if (this.onMouseOverCbFc) { + this.onMouseOverCbFc(this, loopGroup, this.variant, parent); + } + } + + drawSequenceGroup( + element: SequenceGroup, + parent: Selection<any, any, any, any>, + outerElement: boolean + ): void { + const width = element.getWidth(); + const height = element.getHeight(); + + const polygonPoints = this.polygonService.getPolygonPoints(width, height); + + const color = 'lightgrey'; + + let laElement = getLowestSelectionActionableElement(element); + let actionable = + laElement.parent !== null && + laElement.infixSelectableState !== SelectableState.None; + + let polygon = this.createPolygon( + parent, + polygonPoints, + color, + actionable, + true + ); + + if ( + this.traceInfixSelectionMode && + element.parent && + !(element instanceof InvisibleSequenceGroup) + ) { + this.addInfixSelectionAttributes(element, polygon, false); + } + + if ( + element instanceof InvisibleSequenceGroup || + element.parent instanceof SkipGroup + ) { + polygon.style('fill', 'transparent'); + } else { + if (this.onClickCbFc) { + parent.on('click', (e: PointerEvent) => { + this.onVariantClick(element); + e.stopPropagation(); + }); + } + } + + let xOffset = 0; + + const inEditor = + d3 + .select(this.svgHtmlElement.nativeElement) + .classed('in-variant-modeler') || + d3.select(this.svgHtmlElement.nativeElement).classed('pattern-variant'); + + if ( + (!outerElement || + inEditor || + (!this.keepStandardView && + this.variantViewModeService.viewMode === ViewMode.PERFORMANCE)) && + !(element.parent instanceof SkipGroup) + ) { + xOffset += + element.getHeadLength() + + element.getMarginX() - + element.elements[0].getHeadLength(); + } + + for (const child of element.elements) { + if ( + child instanceof WaitingTimeNode && + (this.keepStandardView || + this.variantViewModeService.viewMode !== ViewMode.PERFORMANCE) + ) { + continue; + } + + const childWidth = child.getWidth( + !this.keepStandardView && + this.variantViewModeService.viewMode === ViewMode.PERFORMANCE + ); + const childHeight = child.getHeight(); + const yOffset = height / 2 - childHeight / 2; + const g = parent + .append('g') + .attr('transform', `translate(${xOffset}, ${yOffset})`); + + this.draw(child, g, false); + xOffset += childWidth; + } + + if (this.onMouseOverCbFc) { + this.onMouseOverCbFc(this, element, this.variant, parent); + } + + if (this.onRightMouseClickCbFc) { + parent.on('contextmenu', (e: PointerEvent) => { + this.onRightMouseClickCbFc(this, element, this.variant, e); + e.stopPropagation(); + }); + } + } + + drawParallelGroup( + element: ParallelGroup, + parent: Selection<any, any, any, any> + ): void { + const width = element.getWidth(); + const height = element.getHeight(); + + const polygonPoints = this.polygonService.getPolygonPoints(width, height); + + let laElement = getLowestSelectionActionableElement(element); + let actionable = + laElement.parent !== null && + laElement.infixSelectableState !== SelectableState.None; + + const color = 'lightgrey'; + let polygon = this.createPolygon( + parent, + polygonPoints, + color, + actionable, + true + ); + + if ( + this.traceInfixSelectionMode && + !(element instanceof InvisibleSequenceGroup) + ) { + this.addInfixSelectionAttributes(element, polygon, false); + } + + if (this.onClickCbFc) { + parent.on('click', (e: PointerEvent) => { + this.onVariantClick(element); + e.stopPropagation(); + }); + } + + if (this.onRightMouseClickCbFc) { + parent.on('contextmenu', (e: PointerEvent) => { + this.onRightMouseClickCbFc(this, element, this.variant, e); + e.stopPropagation(); + }); + } + + let y = VARIANT_Constants.MARGIN_Y; + + for (const child of element.elements) { + if ( + child instanceof WaitingTimeNode && + (this.keepStandardView || + this.variantViewModeService.viewMode !== ViewMode.PERFORMANCE) + ) { + continue; + } + + const height = child.getHeight(); + const x = element.getHeadLength() + 0.5 * VARIANT_Constants.MARGIN_X; + const g = parent.append('g').attr('transform', `translate(${x}, ${y})`); + this.draw(child, g, false); + y += height + VARIANT_Constants.MARGIN_Y; + } + + if (this.onMouseOverCbFc) { + this.onMouseOverCbFc(this, element, this.variant, parent); + } + } + + drawChoiceGroup( + element: ChoiceGroup, + parent: Selection<any, any, any, any> + ): void { + const width = element.getWidth(); + const height = element.getHeight(); + + const polygonPoints = this.polygonService.getPolygonPoints(width, height); + + let laElement = getLowestSelectionActionableElement(element); + let actionable = + laElement.parent !== null && + laElement.infixSelectableState !== SelectableState.None; + + const color = 'lightgrey'; + let polygon = this.createPolygon( + parent, + polygonPoints, + color, + actionable, + true + ); + + if ( + this.traceInfixSelectionMode && + !(element instanceof InvisibleSequenceGroup) + ) { + this.addInfixSelectionAttributes(element, polygon, false); + } + + if (this.onClickCbFc) { + parent.on('click', (e: PointerEvent) => { + this.onVariantClick(element); + e.stopPropagation(); + }); + } + + if (this.onRightMouseClickCbFc) { + parent.on('contextmenu', (e: PointerEvent) => { + this.onRightMouseClickCbFc(this, element, this.variant, e); + e.stopPropagation(); + }); + } + + let y = VARIANT_Constants.MARGIN_Y; + + //edited + const textcolor = textColorForBackgroundColor( + color, + this.traceInfixSelectionMode && !element.selected + ); + + const v_height = element.getHeight(); + const v_width = element.getWidth(); + + const activityText = parent + .append('text') + .attr('x', v_width / 2) + .attr('y', v_height / 2) + .classed('user-select-none', true) + .attr('text-anchor', 'middle') + .attr('dominant-baseline', 'middle') + .attr( + 'font-size', + (VARIANT_Constants.LEAF_HEIGHT + VARIANT_Constants.MARGIN_Y) * + element.elements.length + + VARIANT_Constants.MARGIN_Y + ) + .attr('font-weight', 300) + .attr('fill', textcolor) + .classed('activity-text', true); + + const tspan_infront = activityText + .append('tspan') + .attr( + 'x', + element.getHeadLength() + + 0.5 * + (((VARIANT_Constants.LEAF_HEIGHT + VARIANT_Constants.MARGIN_Y) * + element.elements.length + + VARIANT_Constants.MARGIN_Y) / + 2.8) + + 0.5 * VARIANT_Constants.MARGIN_X + ) + .attr('y', v_height / 2) + .classed( + 'cursor-pointer', + (!this.traceInfixSelectionMode || actionable) && this.addCursorPointer + ) + .text('{'); + + for (const child of element.elements) { + if ( + child instanceof WaitingTimeNode && + (this.keepStandardView || + this.variantViewModeService.viewMode !== ViewMode.PERFORMANCE) + ) { + continue; + } + + const height = child.getHeight(); + const x = + element.getHeadLength() + + 0.5 * VARIANT_Constants.MARGIN_X + + ((VARIANT_Constants.LEAF_HEIGHT + VARIANT_Constants.MARGIN_Y) * + element.elements.length + + VARIANT_Constants.MARGIN_Y) / + 2.8; + const g = parent.append('g').attr('transform', `translate(${x}, ${y})`); + this.draw(child, g, false); + y += height + VARIANT_Constants.MARGIN_Y; + } + + const tspan_behind = activityText + .append('tspan') + .attr( + 'x', + element.getWidth() - + element.getHeadLength() - + 0.5 * VARIANT_Constants.MARGIN_X - + 0.5 * + (((VARIANT_Constants.LEAF_HEIGHT + VARIANT_Constants.MARGIN_Y) * + element.elements.length + + VARIANT_Constants.MARGIN_Y) / + 2.8) + ) + .attr('y', v_height / 2) + .classed( + 'cursor-pointer', + (!this.traceInfixSelectionMode || actionable) && this.addCursorPointer + ) + .text('}'); + + if (this.onMouseOverCbFc) { + this.onMouseOverCbFc(this, element, this.variant, parent); + } + } + + drawFallthroughGroup( + element: FallthroughGroup, + parent: Selection<any, any, any, any> + ): void { + const width = element.getWidth(); + const height = element.getHeight(); + + const polygonPoints = this.polygonService.getPolygonPoints(width, height); + + let laElement = getLowestSelectionActionableElement(element); + let actionable = + laElement.parent !== null && + laElement.infixSelectableState !== SelectableState.None; + + const color = 'lightgrey'; + let polygon = this.createFallthroughPolygon( + parent, + polygonPoints, + color, + actionable, + true + ); + + if ( + this.traceInfixSelectionMode && + !(element instanceof InvisibleSequenceGroup) + ) { + this.addInfixSelectionAttributes(element, polygon, false); + } + + if (this.onClickCbFc) { + parent.on('click', (e: PointerEvent) => { + this.onVariantClick(element); + e.stopPropagation(); + }); + } + + if (this.onRightMouseClickCbFc) { + parent.on('contextmenu', (e: PointerEvent) => { + this.onRightMouseClickCbFc(this, element, this.variant, e); + e.stopPropagation(); + }); + } + + let y = VARIANT_Constants.MARGIN_Y; + + for (const child of element.elements) { + if ( + child instanceof WaitingTimeNode && + (this.keepStandardView || + this.variantViewModeService.viewMode !== ViewMode.PERFORMANCE) + ) { + continue; + } + + const height = child.getHeight(); + const x = element.getHeadLength() + 0.5 * VARIANT_Constants.MARGIN_X; + const g = parent.append('g').attr('transform', `translate(${x}, ${y})`); + this.draw(child, g, false); + y += height + VARIANT_Constants.MARGIN_Y; + } + + if (this.onMouseOverCbFc) { + this.onMouseOverCbFc(this, element, this.variant, parent); + } + } + + private createPolygon( + parent: d3.Selection<any, any, any, any>, + polygonPoints: string, + color: string, + actionable: boolean, + group = false + ) { + const poly = parent + .append('polygon') + .attr('points', polygonPoints) + .style('fill', color) + .classed( + 'cursor-pointer', + (!this.traceInfixSelectionMode || actionable) && this.addCursorPointer + ); + + if (group) { + poly.classed('chevron-group', true); + poly.style('fill-opacity', 0.5).style('stroke-width', 2); + } + + return poly; + } + + private createFallthroughPolygon( + parent: d3.Selection<any, any, any, any>, + polygonPoints: string, + color: string, + actionable: boolean, + group = false + ) { + const poly = parent + .append('polygon') + .attr('points', polygonPoints) + .style('fill', color) + .classed('cursor-pointer', !this.traceInfixSelectionMode || actionable); + poly.classed('chevron-group', true); + poly.style('stroke-width', 2); + return poly; + } + + public drawLeafNode( + element: LeafNode, + parent: Selection<any, any, any, any> + ): void { + const width = element.getWidth(); + let height = element.getHeight(); + const polygonPoints = this.polygonService.getPolygonPoints(width, height); + + const color = this.computeActivityColor(this, element, this.variant); + + let laElement = getLowestSelectionActionableElement(element); + + let actionable = + laElement.parent !== null && + laElement.infixSelectableState !== SelectableState.None; + + let polygon = this.createPolygon( + parent, + polygonPoints, + color, + actionable, + false + ); + + if (this.traceInfixSelectionMode) { + this.addInfixSelectionAttributes(element, polygon, true); + } + + const textcolor = textColorForBackgroundColor( + color, + this.traceInfixSelectionMode && !element.selected + ); + + const activityText = parent + .append('text') + .attr('x', width / 2) + .attr('y', height / 2) + .classed('user-select-none', true) + .attr('text-anchor', 'middle') + .attr('dominant-baseline', 'middle') + .attr('font-size', VARIANT_Constants.FONT_SIZE) + .attr('fill', textcolor) + .classed('activity-text', true); + + let y = height / 2; + if (element.activity.length > 1) { + y = + height / 2 - + ((element.activity.length - 1) / 2) * + (VARIANT_Constants.FONT_SIZE + VARIANT_Constants.MARGIN_Y); + } + + let truncated = false; + let dy = 0; + + element.activity.forEach((a, _i) => { + const tspan = activityText + .append('tspan') + .attr('x', width / 2) + .attr('y', y + dy) + .classed( + 'cursor-pointer', + (!this.traceInfixSelectionMode || actionable) && this.addCursorPointer + ) + .text(a); + + dy += VARIANT_Constants.FONT_SIZE + VARIANT_Constants.MARGIN_Y; + tspan.attr( + 'height', + VARIANT_Constants.FONT_SIZE + VARIANT_Constants.MARGIN_Y + ); + + const maxWidth = + element.getWidth() - + element.getHeadLength() * 2 - + VARIANT_Constants.MARGIN_X; + const tr = this.wrapInnerLabelText(tspan, a, maxWidth); + truncated ||= tr; + + if (a === 'W_Nabellen incomplete dossiers' && !tr) { + console.log('Did not wrap', a, tspan, maxWidth); + } + }); + + if (truncated) { + activityText + .attr('title', element.activity.join(';')) + .attr('data-bs-toggle', 'tooltip'); + // manually trigger tooltip through jquery + activityText.on('mouseenter', (e: PointerEvent, data) => { + // @ts-ignore + this.variantService.activityTooltipReference = $(e.target); + this.variantService.activityTooltipReference.tooltip('show'); + }); + } + + if (this.onClickCbFc) { + parent.on('click', (e: PointerEvent) => { + this.onVariantClick(element); + // hide the tooltip + if (this.variantService.activityTooltipReference) { + this.variantService.activityTooltipReference.tooltip('hide'); + } + e.stopPropagation(); + }); + } + + if (this.onMouseOverCbFc) { + this.onMouseOverCbFc(this, element, this.variant, parent); + } + } + + onVariantClick(element: VariantElement) { + this.onClickCbFc(this, element, this.variant); + this.redrawArcsIfComputed.emit(); + } + + private addInfixSelectionAttributes( + element: VariantElement, + polygon: any, + isLeafNode: boolean + ) { + if ( + !this.keepStandardView && + this.variantViewModeService.viewMode === ViewMode.PERFORMANCE + ) + return; + + if (element.selected) { + polygon.attr('stroke-opacity', '0.5'); + if (!element.isVisibleParentSelected()) + polygon.attr('stroke', '#ff0000').attr('stroke-width', '4px'); + return; + } + + if (element.infixSelectableState !== SelectableState.Selectable) { + polygon.style('fill-opacity', '0.1'); + return; + } + + // element is selectable + polygon + .attr('stroke', '#ff0000') + .attr('stroke-width', '1px') + .attr('stroke-dasharray', 4); + + if (isLeafNode) { + polygon.style('fill-opacity', '0.2'); + } else { + polygon.style('fill', '#999999'); + } + } + + private drawWaitingNode( + element: LeafNode, + parent: Selection<any, any, any, any> + ) { + const width = element.getWidth(); + const height = element.getHeight(); + + const polygonPoints = this.polygonService.getPolygonPoints(width, height); + + const color = this.computeActivityColor(this, element, this.variant); + + this.createPolygon(parent, polygonPoints, color, false); + + if (this.onClickCbFc) { + parent.on('click', (e: PointerEvent) => { + this.onVariantClick(element); + e.stopPropagation(); + }); + } + + if (this.onRightMouseClickCbFc) { + parent.on('contextmenu', (e: PointerEvent) => { + this.onRightMouseClickCbFc(this, element, this.variant, e); + e.stopPropagation(); + }); + } + + if (this.onMouseOverCbFc) { + this.onMouseOverCbFc(this, element, this.variant, parent); + } + } + + drawSkipGroup( + element: SequenceGroup, + parent: Selection<any, any, any, any> + ): void { + const height = element.getHeight(); + + let xOffset = 0; + + element.elements.forEach((child, idx) => { + const childWidth = child.getWidth( + !this.keepStandardView && + this.variantViewModeService.viewMode === ViewMode.PERFORMANCE + ); + const childHeight = child.getHeight(); + const yOffset = height / 2 - childHeight / 2; + const g = parent + .append('g') + .attr('transform', `translate(${xOffset}, ${yOffset})`); + + this.draw(child, g, false); + xOffset += childWidth; + + if (idx >= element.elements.length - 1) return; + + const heightOffset = + (element.getHeight() - 2 * VARIANT_Constants.MARGIN_Y) / 2 - 7.65; + xOffset += VARIANT_Constants.SKIP_MARGIN; + parent + .append('g') + .attr('transform', `translate(${xOffset}, ${heightOffset})`) + .append('use') + .attr('href', '#infixDots') + .attr('transform', 'scale(1.7)'); + xOffset += VARIANT_Constants.SKIP_WIDTH + VARIANT_Constants.SKIP_MARGIN; + }); + + if (this.onMouseOverCbFc) { + this.onMouseOverCbFc(this, element, this.variant, parent); + } + } + + private wrapInnerLabelText( + textSelection: Selection<any, any, any, any>, + text: string, + maxWidth: number + ): boolean { + let textLength = this.getComputedTextLength(textSelection); + //let textLength = textSelection.node().getBoundingClientRect().width; + + let truncated = false; + while (textLength > maxWidth && text.length > 1) { + text = text.slice(0, -1); + if (text[text.length - 1] == ' ') { + text = text.slice(0, -1); + } + textSelection.text(text + '..'); + textLength = this.getComputedTextLength(textSelection); + //textLength = textSelection.node().getBoundingClientRect().width; + truncated = true; + } + + if (text === 'W_Nabellen incomplete dossiers' && !truncated) { + console.log('Inner Text length after Wrap', text, textLength, maxWidth); + } + + return truncated; + } + + private getComputedTextLength( + textSelection: Selection<any, any, any, any> + ): number { + let textLength; + if ( + this.sharedDataService.computedTextLengthCache.has(textSelection.text()) + ) { + textLength = this.sharedDataService.computedTextLengthCache.get( + textSelection.text() + ); + } else { + textLength = textSelection.node().getBoundingClientRect().width; + if (textLength == 0) { + textLength = + textSelection.text().length * VARIANT_Constants.CHAR_LENGTH; + } + } + if (textLength > 0) { + this.sharedDataService.computedTextLengthCache.set( + textSelection.text(), + textLength + ); + } + + return textLength; + } + + /* + public resetCachedTextLength() { + this.sharedDataService.computedTextLengthCache = new Map<string, number>(); + console.log('reset'); + }*/ + + getSVGGraphicElement(): SVGGraphicsElement { + return this.svgHtmlElement.nativeElement; + } + + isExpanded(): boolean { + return this.variant.variant.expanded; + } + + setInspectVariant() { + d3.select('.selected-polygon').classed('selected-polygon', false); + d3.selectAll('.variant-polygon').classed( + 'cursor-pointer', + !this.keepStandardView && + this.variantViewModeService.viewMode === ViewMode.PERFORMANCE && + this.addCursorPointer + ); + d3.selectAll('.activity-text').classed( + 'cursor-pointer', + !this.keepStandardView && + this.variantViewModeService.viewMode === ViewMode.PERFORMANCE && + this.addCursorPointer + ); + } + + changeSelected(group: VariantElement) { + d3.selectAll('.variant-element-group') + .selectAll('polygon') + .classed('selected-polygon', (d) => group === d); + } +} diff --git a/src/frontend/src/app/interceptors/http-request.interceptor.spec.ts b/src/frontend/src/app/interceptors/http-request.interceptor.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..7dbff574e8c115f40bcb769c5845f255515fe16b --- /dev/null +++ b/src/frontend/src/app/interceptors/http-request.interceptor.spec.ts @@ -0,0 +1,18 @@ +import { TestBed } from '@angular/core/testing'; + +import { HttpRequestInterceptor } from './http-request.interceptor'; + +describe('HttpRequestInterceptor', () => { + beforeEach(() => + TestBed.configureTestingModule({ + providers: [HttpRequestInterceptor], + }) + ); + + it('should be created', () => { + const interceptor: HttpRequestInterceptor = TestBed.inject( + HttpRequestInterceptor + ); + expect(interceptor).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/interceptors/http-request.interceptor.ts b/src/frontend/src/app/interceptors/http-request.interceptor.ts new file mode 100644 index 0000000000000000000000000000000000000000..d2c411798f0ea1fe2b7d30ba1071cd34525f87b1 --- /dev/null +++ b/src/frontend/src/app/interceptors/http-request.interceptor.ts @@ -0,0 +1,104 @@ +import { Injectable } from '@angular/core'; +import { + HttpErrorResponse, + HttpEvent, + HttpHandler, + HttpInterceptor, + HttpRequest, +} from '@angular/common/http'; +import { Observable, throwError } from 'rxjs'; +import { catchError, finalize } from 'rxjs/operators'; +import { BackgroundTaskInfoService } from '../services/backgroundTaskInfoService/background-task-info.service'; +import { BackendService } from '../services/backendService/backend.service'; +import { ErrorService } from '../services/errorService/error.service'; +import { BackendInfoService } from '../services/backendInfoService/backend-info.service'; +import { ROUTES } from '../constants/backend_route_constants'; + +@Injectable() +export class HttpRequestInterceptor implements HttpInterceptor { + private excludedEndpointsForTaskCounter = ['info', 'log/reset Log Cache']; + private endpointsToCancelBeforeInterception = [ + 'subvariant Mining/repetitions Mining', + ]; + + constructor( + private backgroundTaskInfoService: BackgroundTaskInfoService, + private backendService: BackendService, + private errorService: ErrorService, + private backendInfoService: BackendInfoService + ) {} + + intercept( + request: HttpRequest<unknown>, + next: HttpHandler + ): Observable<HttpEvent<unknown>> { + const calledEndpoint = request.url + .slice(ROUTES.HTTP_BASE_URL.length) + .replace(/([a-z0-9])([A-Z])/g, '$1 $2'); + + if (this.shouldCancelEndpoints(calledEndpoint)) { + this.backendService.cancelOtherBgTasks.next(); + } + + let id; + if (!this.shouldIgnoreRequestForTaskCounter(calledEndpoint)) { + id = this.backgroundTaskInfoService.setRequest(String(calledEndpoint)); + } + + return next.handle(request).pipe( + catchError((error: HttpErrorResponse) => { + this.setBackendRunningState(error); + if (this.shouldIgnoreError(error)) { + return next.handle(request); + } + + this.errorService.addApiError(error); + return throwError(error); + }), + finalize(() => { + if (id) { + this.backgroundTaskInfoService.removeRequest(id); + } + }) + ); + } + + shouldIgnoreError(error: HttpErrorResponse): boolean { + return ( + // ignore timeouts for alignment computations because they are handled in the variant explorer + (error.status == 504 && + error.url?.endsWith('calculateAlignmentsCVariant')) || + // info requests are made to show the backend state in the footer; therefore, we do not want to show the error dialog + error.url?.endsWith('/info') || + error.url?.endsWith('resetLogCache') || + // ignore FileNotFoundError while loading EventLog because of handling in caller + (error.status == 404 && error.url?.endsWith('/loadEventLogFromFilePath')) + ); + } + + shouldIgnoreRequestForTaskCounter(endpoint: string): boolean { + return this.excludedEndpointsForTaskCounter.includes(endpoint); + } + + shouldCancelEndpoints(endpoint: string): boolean { + const activeRequestToBeCancelledExists = + Array.from(this.backgroundTaskInfoService.activeRequests.values())?.find( + (task) => + this.endpointsToCancelBeforeInterception.includes(task.Description) + ) !== undefined; + return ( + activeRequestToBeCancelledExists && + !this.endpointsToCancelBeforeInterception.includes(endpoint) && + !this.shouldIgnoreRequestForTaskCounter(endpoint) + ); + } + + setBackendRunningState(error: HttpErrorResponse): void { + let isRunning = true; + if (error.status === 0) { + isRunning = false; + } + + this.backendInfoService.setRunning(isRunning); + } +} diff --git a/src/frontend/src/app/objects/ApiError.ts b/src/frontend/src/app/objects/ApiError.ts new file mode 100644 index 0000000000000000000000000000000000000000..224bb83a6b201aeaba57b54fb5d7d847c49dd7e8 --- /dev/null +++ b/src/frontend/src/app/objects/ApiError.ts @@ -0,0 +1,4 @@ +export interface ApiError { + stack_trace: string; + detail: any; +} diff --git a/src/frontend/src/app/objects/BPMN/block-structured-bpmn.ts b/src/frontend/src/app/objects/BPMN/block-structured-bpmn.ts new file mode 100644 index 0000000000000000000000000000000000000000..54ceaeb0f3c4855c50c6372294782a79f6aecc48 --- /dev/null +++ b/src/frontend/src/app/objects/BPMN/block-structured-bpmn.ts @@ -0,0 +1,267 @@ +import { BPMN_Constant } from 'src/app/constants/bpmn_model_drawer_constants'; +import { ProcessTree, ProcessTreeOperator } from '../ProcessTree/ProcessTree'; + +export abstract class Block_Structured_BPMN { + private _members: Array<Block_Structured_BPMN>; + private _width: number; + private _height: number; + + _pt: ProcessTree; + + constructor(members: Array<Block_Structured_BPMN> = null, pt: ProcessTree) { + this._members = members; + this._pt = pt; + } + + public get members(): Array<Block_Structured_BPMN> { + return this._members; + } + public set members(value: Array<Block_Structured_BPMN>) { + this._members = value; + } + + public get width(): number { + return this._width; + } + public set width(value: number) { + this._width = value; + } + + public get height(): number { + return this._height; + } + public set height(value: number) { + this._height = value; + } + + abstract recalculateHeight(); + abstract recalculateWidth(); +} + +export class LoopBlock extends Block_Structured_BPMN { + core_width; + + constructor(members: Array<Block_Structured_BPMN>, pt: ProcessTree) { + super(members, pt); + this.width = this.recalculateWidth(); + this.height = this.recalculateHeight(); + } + + public recalculateHeight(): number { + return compute_height_vertical_group(this); + } + + public recalculateWidth(): number { + return compute_width_vertical_group(this); + } +} + +export class ChoiceBlock extends Block_Structured_BPMN { + core_width; + + constructor(members: Array<Block_Structured_BPMN>, pt: ProcessTree) { + super(members, pt); + this.width = this.recalculateWidth(); + this.height = this.recalculateHeight(); + } + + public recalculateHeight(): number { + return compute_height_vertical_group(this); + } + + public recalculateWidth(): number { + return compute_width_vertical_group(this); + } +} + +export class ParallelBlock extends Block_Structured_BPMN { + core_width; + + constructor(members: Array<Block_Structured_BPMN>, pt: ProcessTree) { + super(members, pt); + this.width = this.recalculateWidth(); + this.height = this.recalculateHeight(); + } + + public recalculateHeight(): number { + return compute_height_vertical_group(this); + } + + public recalculateWidth(): number { + return compute_width_vertical_group(this); + } +} + +export class SequenceBlock extends Block_Structured_BPMN { + constructor(members: Array<Block_Structured_BPMN>, pt: ProcessTree) { + super(members, pt); + this.width = this.recalculateWidth(); + this.height = this.recalculateHeight(); + } + + public recalculateHeight(): number { + if (this.members.length > 0) { + this.height = Math.max( + ...this.members.map((block: Block_Structured_BPMN) => block.height) + ); + } else { + this.height = BPMN_Constant.EVENT_HEIGHT; + } + + return this.height; + } + + public recalculateWidth(): number { + if (this.members.length > 0) { + this.width = this.members + .map((block: Block_Structured_BPMN) => block.width) + .reduce((a: number, b: number) => a + b); + + if (this.members.length > 1) { + this.width += + (this.members.length - 1) * BPMN_Constant.HORIZONTALSPACING; + } + } else { + this.width = 2 * BPMN_Constant.HORIZONTALSPACING; + } + + return this.width; + } +} + +export class Event extends Block_Structured_BPMN { + private _eventName: string; + + constructor( + eventName: string, + pt: ProcessTree, + blockWidthCache: Map<string, number> + ) { + super(null, pt); + this._eventName = eventName; + this.width = this.recalculateWidth(blockWidthCache); + this.height = this.recalculateHeight(); + } + + public get eventName(): string { + return this._eventName; + } + + public set eventName(value: string) { + this._eventName = value; + } + + recalculateHeight() { + this.height = BPMN_Constant.EVENT_HEIGHT; + return this.height; + } + + recalculateWidth(blockWidthCache: Map<string, number> = null) { + if (this.eventName === ProcessTreeOperator.tau) { + this.width = BPMN_Constant.BASE_HEIGHT_WIDTH; + } else { + const width = blockWidthCache[this.eventName]; + + this.width = width ? width : BPMN_Constant.EVENT_WIDTH; + } + + return this.width; + } +} + +export function convertPTtoBlockstructuredBPMN( + pt: ProcessTree, + blockWidthCache: Map<string, number> = null +): Block_Structured_BPMN { + let block: Block_Structured_BPMN; + + if (!pt) { + return new Event(ProcessTreeOperator.tau, pt, blockWidthCache); + } + + if (pt.operator) { + let members = pt.children.map((c) => + convertPTtoBlockstructuredBPMN(c, blockWidthCache) + ); + + if ( + pt.operator == ProcessTreeOperator.choice || + pt.operator == ProcessTreeOperator.parallelism + ) { + members.sort((m1, m2) => m1.width - m2.width); + } + + switch (pt.operator) { + case ProcessTreeOperator.choice: { + block = new ChoiceBlock(members, pt); + break; + } + case ProcessTreeOperator.loop: { + block = new LoopBlock(members, pt); + break; + } + case ProcessTreeOperator.sequence: { + block = new SequenceBlock(members, pt); + break; + } + case ProcessTreeOperator.parallelism: { + block = new ParallelBlock(members, pt); + break; + } + default: { + console.warn('ERROR NOT A KNOWN OPERATOR'); + } + } + } else { + block = pt.label + ? new Event(pt.label, pt, blockWidthCache) + : new Event(ProcessTreeOperator.tau, pt, blockWidthCache); + } + + return block; +} + +function compute_height_vertical_group(model: any): number { + if (model.members.length > 0) { + model.height = model.members + .map((block: Block_Structured_BPMN) => block.height) + .reduce((a: number, b: number) => a + b); + + if (model.members.length > 1) { + model.height += + (model.members.length - 1) * BPMN_Constant.VERTICALSPACING; + } + } else { + model.height = BPMN_Constant.EVENT_HEIGHT; + } + + return model.height; +} + +function compute_width_vertical_group(model: any): number { + if (model.members.length === 0) + model.width = 2 * BPMN_Constant.OPERATOR_DIAGONAL_LENGTH; + else if (model.members.length === 1) + model.width = + 2 * BPMN_Constant.OPERATOR_DIAGONAL_LENGTH + model.members[0].width; + else { + const widths_after_interpolation = [...model.members.entries()].map( + ([index, block]) => + block.width + + 2 * + (BPMN_Constant.OPERATOR_DIAGONAL_LENGTH / + (model.members.length - 1)) * + (model.members.length - 1 - index) + ); + + model.width = Math.max(...widths_after_interpolation); + } + + model.core_width = model.width; + + model.width += 2 * BPMN_Constant.HORIZONTALSPACING; + + model.width += 2 * BPMN_Constant.OPERATOR_DIAGONAL_LENGTH; + + return model.width; +} diff --git a/src/frontend/src/app/objects/ClusteringAlgorithm.ts b/src/frontend/src/app/objects/ClusteringAlgorithm.ts new file mode 100644 index 0000000000000000000000000000000000000000..2b54cf217a409d011f09f8760657bf4ab0d86217 --- /dev/null +++ b/src/frontend/src/app/objects/ClusteringAlgorithm.ts @@ -0,0 +1,4 @@ +export enum ClusteringAlgorithm { + LABEL_VECTOR_CLUSTERING = 'LABEL_VECTOR_CLUSTERING', + AGGLOMERATIVE_EDIT_DISTANCE_CLUSTERING = 'AGGLOMERATIVE_EDIT_DISTANCE_CLUSTERING', +} diff --git a/src/frontend/src/app/objects/ClusteringConfig.ts b/src/frontend/src/app/objects/ClusteringConfig.ts new file mode 100644 index 0000000000000000000000000000000000000000..6d0567d281408fbbd421bf00137296c250627f1d --- /dev/null +++ b/src/frontend/src/app/objects/ClusteringConfig.ts @@ -0,0 +1,6 @@ +import { ClusteringAlgorithm } from './ClusteringAlgorithm'; + +export type ClusteringConfig = { + algorithm: ClusteringAlgorithm; + params: any; +}; diff --git a/src/frontend/src/app/objects/ColorMap.ts b/src/frontend/src/app/objects/ColorMap.ts new file mode 100644 index 0000000000000000000000000000000000000000..283fe4c0f785817377c6c625a2396f65437587fa --- /dev/null +++ b/src/frontend/src/app/objects/ColorMap.ts @@ -0,0 +1,21 @@ +export const ZERO_VALUE_COLOR = '#FFFFFF'; + +export class ColorMap { + scale: d3.ScaleThreshold<any, any, any>; + + constructor(scale: d3.ScaleThreshold<any, any, any>) { + this.scale = scale; + } + + getColor(value: number) { + return this.scale(value); + } + + domain() { + return this.scale.domain(); + } + + range() { + return this.scale.range(); + } +} diff --git a/src/frontend/src/app/objects/Colors.ts b/src/frontend/src/app/objects/Colors.ts new file mode 100644 index 0000000000000000000000000000000000000000..3102d3e4317f787341e77544798910f2f1cbcf06 --- /dev/null +++ b/src/frontend/src/app/objects/Colors.ts @@ -0,0 +1,67 @@ +// https://observablehq.com/@philippkoytek/celonis-data-visualization-colors +export const COLORS_CYAN = [ + '#3ad7f7', + '#15bfdf', + '#03a6c6', + '#028eac', + '#027694', + '#025f7c', + '#024965', + '#01344f', + '#012138', +]; + +export const COLORS_PINK = [ + '#ffeaff', + '#ffcaf5', + '#ffabde', + '#fd8ac8', + '#fc63b0', + '#f4378f', + '#d62578', + '#b91260', + '#9b0048', +]; + +export const COLORS_TEAL = [ + '#00e8c0', + '#04d1b3', + '#06baa5', + '#06a496', + '#068f87', + '#067a76', + '#046665', + '#025254', + '#024042', +]; + +export const COLORS_PURPLE = [ + '#ffebff', + '#f5c4f7', + '#e1a0f1', + '#c97cec', + '#b251ef', + '#942edc', + // '#6f1cb7', + '#4a0297', +]; + +export const COLORS_BLUE = [ + '#e9edff', + '#c2ccff', + '#9aacff', + '#738aff', + '#4c68fa', + '#2743ec', + // '#1123c7', + '#020297', +]; + +export const COLORS_RED_GREEN = [ + '#f01523', + '#f3431c', + '#f77116', + '#fa9f0f', + '#fdcd08', + '#198754', +]; diff --git a/src/frontend/src/app/objects/ContextMenuAction.ts b/src/frontend/src/app/objects/ContextMenuAction.ts new file mode 100644 index 0000000000000000000000000000000000000000..c435af68e149713051b009a675ff5e37dd906ace --- /dev/null +++ b/src/frontend/src/app/objects/ContextMenuAction.ts @@ -0,0 +1,4 @@ +export type ContextMenuAction<T> = { + event: MouseEvent | KeyboardEvent; + value?: T; +}; diff --git a/src/frontend/src/app/objects/LocalProcessModelWithPatterns.ts b/src/frontend/src/app/objects/LocalProcessModelWithPatterns.ts new file mode 100644 index 0000000000000000000000000000000000000000..847ab4fe0cb0b69502f719a5dcabca537e95664e --- /dev/null +++ b/src/frontend/src/app/objects/LocalProcessModelWithPatterns.ts @@ -0,0 +1,12 @@ +import { ProcessTree } from './ProcessTree/ProcessTree'; +import { VariantElement } from './Variants/variant_element'; + +export class LocalProcessModelWithPatterns { + lpm: ProcessTree; + patterns: VariantElement[]; + + constructor(lpm, patterns) { + this.lpm = lpm; + this.patterns = patterns; + } +} diff --git a/src/frontend/src/app/objects/LogExportConfig/LogExportConfig.ts b/src/frontend/src/app/objects/LogExportConfig/LogExportConfig.ts new file mode 100644 index 0000000000000000000000000000000000000000..3579aaf60bbcf2222e60b3880883faa6fe77fb64 --- /dev/null +++ b/src/frontend/src/app/objects/LogExportConfig/LogExportConfig.ts @@ -0,0 +1,10 @@ +import { VariantSelectionMethod } from '../VariantSelectionMethod'; + +export type LogExportConfig = { + variantSelectionMethod: VariantSelectionMethod; + includeTraceFragments: boolean; + includeUserCreatedVariants: boolean; + sequentializeVariants: boolean; + exportAsIntervalLog: boolean; + includeOriginalLogInfo: boolean; +}; diff --git a/src/frontend/src/app/objects/LogModification.ts b/src/frontend/src/app/objects/LogModification.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3dc5dbd9374ad99f38b4e42b1babbd3e1962e09 --- /dev/null +++ b/src/frontend/src/app/objects/LogModification.ts @@ -0,0 +1,63 @@ +import { Type } from 'class-transformer'; +import { Variant } from './Variants/variant'; + +export enum LogModificationType { + ACTIVITY_RENAMING, + ACTIVITY_DELETION, + VARIANT_DELETION, + USER_DEFINED_VARIANT_ADDITION, + USER_DEFINED_INFIX_ADDITION, +} + +export abstract class LogModification { + public abstract readonly type: LogModificationType; + constructor() {} +} + +export class ActivityDeletion extends LogModification { + public readonly type = LogModificationType.ACTIVITY_DELETION; + + constructor(public activityName: string) { + super(); + } +} + +export class ActivityRenaming extends LogModification { + public readonly type = LogModificationType.ACTIVITY_RENAMING; + + constructor(public activityName: string, public newActivityName: string) { + super(); + } +} + +export class VariantsDeletion extends LogModification { + public readonly type = LogModificationType.VARIANT_DELETION; + + constructor(public variantsBids: number[]) { + super(); + } +} + +export class UserDefinedVariantAddition extends LogModification { + public readonly type = LogModificationType.USER_DEFINED_VARIANT_ADDITION; + + @Type(() => Variant) + public variant: Variant; + + constructor(variant: Variant) { + super(); + this.variant = variant; + } +} + +export class UserDefinedInfixAddition extends LogModification { + public readonly type = LogModificationType.USER_DEFINED_INFIX_ADDITION; + + @Type(() => Variant) + public infix: Variant; + + constructor(infix: Variant) { + super(); + this.infix = infix; + } +} diff --git a/src/frontend/src/app/objects/LpmMetrics.ts b/src/frontend/src/app/objects/LpmMetrics.ts new file mode 100644 index 0000000000000000000000000000000000000000..44c271d1e49b2c63ac1ab3c6f9b31d5f97dcd71c --- /dev/null +++ b/src/frontend/src/app/objects/LpmMetrics.ts @@ -0,0 +1,13 @@ +export class LpmMetrics { + support: number; + supportTrans: number; + supportOcc: number; + confidence: number; + precision: number; + coverage: number; + simplicity: number; + skipPrecision: number; + meanRange: number; + minRange: number; + maxRange: number; +} diff --git a/src/frontend/src/app/objects/ProcessTree/ProcessTree.ts b/src/frontend/src/app/objects/ProcessTree/ProcessTree.ts new file mode 100644 index 0000000000000000000000000000000000000000..7c0daed9a8d1e4572d549bed2995571f5a2444a8 --- /dev/null +++ b/src/frontend/src/app/objects/ProcessTree/ProcessTree.ts @@ -0,0 +1,243 @@ +import { PerformanceStats } from '../Variants/variant_element'; +import { Transform, Type } from 'class-transformer'; +import { TransformationType } from 'class-transformer'; + +export class ProcessTree { + public label: string; + public operator: ProcessTreeOperator; + @Type(() => ProcessTree) + @Transform(({ value, key, obj, type }) => { + if (type === TransformationType.PLAIN_TO_CLASS) + value.forEach((child: ProcessTree) => { + child.parent = obj; + }); + return value; + }) + public children: ProcessTree[]; + public id: number; + public frozen: boolean; + @Type(() => TreePerformance) + public performance: TreePerformance; + public conformance: TreeConformance; + @Type(() => ProcessTree) + public parent: ProcessTree; + //public selected: boolean; + + constructor( + label: string, + operator: ProcessTreeOperator, + children: ProcessTree[], + id: number, + frozen: boolean, + performance: TreePerformance, + conformance: TreeConformance, + parent: ProcessTree + ) { + this.label = label; + this.operator = operator; + this.children = children; + this.id = id; + this.frozen = frozen; + this.performance = performance; + this.conformance = conformance; + this.parent = parent; + //this.selected = false; + } + + public equals(other: ProcessTree) { + if (!other) { + return false; + } + let equals = this.label == other.label && this.operator == other.operator; + equals &&= this.children?.length == other.children?.length; + + if (!equals) { + return false; + } + + for (let i = 0; i < this.children?.length; i++) { + equals &&= this.children[i].equals(other.children[i]); + } + + return equals; + } + + public static fromObj(treeObj) { + const tree = new ProcessTree( + treeObj['label'], + treeObj['operator'], + [], + treeObj['id'], + treeObj['frozen'], + treeObj['performance'], + treeObj['conformance'], + null + ); + if (treeObj['children']) { + treeObj['children'].forEach((c) => { + tree.children.push(ProcessTree.fromObj(c)); + }); + + tree.children.forEach((child) => (child.parent = tree)); + } + return tree; + } + + public copy( + parentRelation: boolean = true, + newId: boolean = false + ): ProcessTree { + const children = this.children.map((child) => + child.copy(parentRelation, newId) + ); + + const treeCopy = new ProcessTree( + this.label, + this.operator, + children, + newId ? Math.floor(1000000000 + Math.random() * 900000000) : this.id, + this.frozen, + this.performance, + this.conformance, + null + ); + + if (parentRelation) + treeCopy.children.forEach((child) => { + child.parent = treeCopy; + }); + return treeCopy; + } + + toString() { + if (this.operator) { + return `${this.operator} ( ${this.children + .map((n) => n.toString()) + .join(' ')} )`; + } else { + return this.label === ProcessTreeOperator.tau + ? this.label + ',' + : "'" + this.label + "'" + ','; + } + } + + public hasPerformance() { + return ( + this.performance?.service_time || + this.performance?.cycle_time || + this.performance?.waiting_time || + this.performance?.idle_time + ); + } + + public isValid() { + return checkSyntax(this).correctSyntax; + } +} + +export class TreePerformance { + @Type(() => PerformanceStats) + service_time: PerformanceStats; + @Type(() => PerformanceStats) + waiting_time: PerformanceStats; + @Type(() => PerformanceStats) + cycle_time: PerformanceStats; + @Type(() => PerformanceStats) + idle_time: PerformanceStats; + + constructor(dict: any = {}) { + this.service_time = new PerformanceStats(dict.service_time); + this.waiting_time = new PerformanceStats(dict.waiting_time); + this.cycle_time = new PerformanceStats(dict.cycle_time); + this.idle_time = new PerformanceStats(dict.idle_time); + } +} + +export interface TreeConformance { + weighted_equally: WeightedConformanceValue; + weighted_by_counts: WeightedConformanceValue; +} + +export interface WeightedConformanceValue { + value: number; + weight: number; +} + +// TODO +export enum ProcessTreeOperator { + sequence = '\u2794', + choice = '\u2715', + loop = '\u21BA', + parallelism = '\u2227', + tau = '\u03C4', +} + +export class ProcessTreeSyntaxInfo { + correctSyntax = true; + warnings: string[] = []; + errors: string[] = []; +} + +export function checkSyntax( + pt: ProcessTree, + res = new ProcessTreeSyntaxInfo() +): ProcessTreeSyntaxInfo { + if (pt.label && pt.children.length > 0) { + res.correctSyntax = false; + res.errors.push('an activity node cannot have child nodes'); + } + if ( + pt.operator && + pt.operator !== ProcessTreeOperator.loop && + pt.children.length === 0 + ) { + res.correctSyntax = false; + res.errors.push( + 'a tree operator (' + + ProcessTreeOperator.sequence + + ',' + + ProcessTreeOperator.choice + + ',' + + ProcessTreeOperator.parallelism + + ',' + + ') must have at least one child node' + ); + } + if ( + pt.children.length !== 2 && + pt.operator && + pt.operator === ProcessTreeOperator.loop + ) { + res.correctSyntax = false; + res.errors.push( + 'a loop operator (' + + ProcessTreeOperator.loop + + ') must have exactly two children' + ); + } + if ( + pt.children.length === 1 && + pt.operator && + pt.operator !== ProcessTreeOperator.loop + ) { + res.warnings.push( + 'a tree operator (' + + ProcessTreeOperator.sequence + + ',' + + ProcessTreeOperator.choice + + ',' + + ProcessTreeOperator.parallelism + + ',' + + ') contains only one child node' + ); + } + if (pt.children) { + pt.children.forEach((subtree) => { + const subtreeRes = checkSyntax(subtree); + res.warnings = res.warnings.concat(subtreeRes.warnings); + res.errors = res.errors.concat(subtreeRes.errors); + res.correctSyntax = res.correctSyntax && subtreeRes.correctSyntax; + }); + } + return res; +} diff --git a/src/frontend/src/app/objects/ProcessTree/utility-functions/process-tree-edit-tree.ts b/src/frontend/src/app/objects/ProcessTree/utility-functions/process-tree-edit-tree.ts new file mode 100644 index 0000000000000000000000000000000000000000..b2d100534389ebb4d785cfbd0fe815d724ccbfad --- /dev/null +++ b/src/frontend/src/app/objects/ProcessTree/utility-functions/process-tree-edit-tree.ts @@ -0,0 +1,91 @@ +import { + ProcessTree, + ProcessTreeOperator, +} from 'src/app/objects/ProcessTree/ProcessTree'; + +export function delete_subtree(tree: ProcessTree, tree_to_delete: ProcessTree) { + if (tree === tree_to_delete) { + return; + } else { + if (tree.children) { + let child_list: Array<ProcessTree> = []; + + for (let child of tree.children) { + let res = delete_subtree(child, tree_to_delete); + + if (res) { + child_list.push(res); + } + } + + tree.children = child_list; + } + } + + return tree; +} + +export function createNewRandomNode( + label: string, + operator: ProcessTreeOperator, + id: number = Math.floor(1000000000 + Math.random() * 900000000) +): ProcessTree { + return new ProcessTree(label, operator, [], id, false, null, null, null); +} + +export function insertNode( + selectedNode: ProcessTree, + newNode: ProcessTree, + strat: NodeInsertionStrategy, + operator: ProcessTreeOperator, + label: string +) { + switch (strat) { + case NodeInsertionStrategy.BELOW: { + selectedNode.children.push(newNode); + newNode.parent = selectedNode; + break; + } + + case NodeInsertionStrategy.ABOVE: { + newNode.children = [selectedNode]; + selectedNode.parent = newNode; + break; + } + + case NodeInsertionStrategy.LEFT: { + const idx: number = selectedNode.parent.children.indexOf(selectedNode); + selectedNode.parent.children.splice(idx, 0, newNode); + newNode.parent = selectedNode.parent; + break; + } + + case NodeInsertionStrategy.RIGHT: { + const idx: number = selectedNode.parent.children.indexOf(selectedNode); + selectedNode.parent.children.splice(idx + 1, 0, newNode); + newNode.parent = selectedNode.parent; + break; + } + + case NodeInsertionStrategy.CHANGE: { + if (selectedNode.parent) { + const idx: number = selectedNode.parent.children.indexOf(selectedNode); + newNode.parent = selectedNode.parent; + selectedNode.parent.children.splice(idx, 1, newNode); + } + if (operator) newNode.children = selectedNode.children; + newNode.children.forEach((child) => { + child.parent = newNode; + }); + break; + } + } +} + +export enum NodeInsertionStrategy { + LEFT = 'Left', + RIGHT = 'Right', + ABOVE = 'Above', + BELOW = 'Below', + CHANGE = 'Change', +} diff --git a/src/frontend/src/app/objects/ProcessTree/utility-functions/process-tree-freeze.ts b/src/frontend/src/app/objects/ProcessTree/utility-functions/process-tree-freeze.ts new file mode 100644 index 0000000000000000000000000000000000000000..af2aef68d386877f884d08209efe0b10d0a6cf98 --- /dev/null +++ b/src/frontend/src/app/objects/ProcessTree/utility-functions/process-tree-freeze.ts @@ -0,0 +1,24 @@ +import { ProcessTree } from 'src/app/objects/ProcessTree/ProcessTree'; + +export function markNodeAsFrozen(node: ProcessTree) { + node.frozen = true; + if (node.children) { + node.children.forEach((child) => { + markNodeAsFrozen(child); + }); + } +} + +export function markNodeAsNonFrozen(node: ProcessTree) { + node.frozen = false; + + if (node.parent && node.parent.frozen) { + markNodeAsNonFrozen(node.parent); + return; + } + if (node.children) { + node.children.forEach((child) => { + markNodeAsNonFrozen(child); + }); + } +} diff --git a/src/frontend/src/app/objects/ProcessTree/utility-functions/process-tree-integrity-check.ts b/src/frontend/src/app/objects/ProcessTree/utility-functions/process-tree-integrity-check.ts new file mode 100644 index 0000000000000000000000000000000000000000..df603031bfd7bd6e9c1ccde914893aa8d3098b21 --- /dev/null +++ b/src/frontend/src/app/objects/ProcessTree/utility-functions/process-tree-integrity-check.ts @@ -0,0 +1,61 @@ +import { + ProcessTree, + ProcessTreeOperator, +} from 'src/app/objects/ProcessTree/ProcessTree'; + +export function checkForLoadedTreeIntegrity( + tree: ProcessTree, + activities: string[] +): Set<string> { + let unknownActivities = new Set<string>(); + + if (tree === null) { + return unknownActivities; + } + + for (let subtree of tree.children) { + // If it is a operator, recurse on the children + if (!subtree.label) { + unknownActivities = new Set<string>([ + ...unknownActivities, + ...checkForLoadedTreeIntegrity(subtree, activities), + ]); + + // If it is a leaf with unkown label add it to the set + } else if ( + !( + activities.indexOf(subtree.label) > -1 || + subtree.label === ProcessTreeOperator.tau + ) + ) { + unknownActivities.add(subtree.label); + + // Else continue + } + } + + return unknownActivities; +} + +export function processTreesEqual(pt1: ProcessTree, pt2: ProcessTree): boolean { + if (!pt1 || !pt2) { + return false; + } + if ( + pt1['operator'] === pt2['operator'] && + pt1['label'] === pt2['label'] && + pt1['children'].length === pt2['children'].length + ) { + if (pt1['children'].length === 0) { + return true; + } else { + let res = true; + for (let i = 0; i < pt1['children'].length; i++) { + res = res && processTreesEqual(pt1['children'][i], pt2['children'][i]); + } + return res; + } + } else { + return false; + } +} diff --git a/src/frontend/src/app/objects/ProcessTree/utility-functions/process-tree-transform.ts b/src/frontend/src/app/objects/ProcessTree/utility-functions/process-tree-transform.ts new file mode 100644 index 0000000000000000000000000000000000000000..348c9485e2d9201ebcce56443c26b98e1b546a49 --- /dev/null +++ b/src/frontend/src/app/objects/ProcessTree/utility-functions/process-tree-transform.ts @@ -0,0 +1,35 @@ +import { ProcessTree } from 'src/app/objects/ProcessTree/ProcessTree'; + +export function renameProcessTreeLeafs( + tree: ProcessTree, + activityName: string, + newActivityName: string +): ProcessTree { + if (tree.label && tree.label === activityName) { + tree.label = newActivityName; + } else { + tree.children.forEach((c) => + renameProcessTreeLeafs(c, activityName, newActivityName) + ); + } + + return tree; +} + +export function getSetOfActivitiesInProcessTree( + tree: ProcessTree +): Set<string> { + if (tree) { + let res: Set<string> = new Set(); + if (tree.children && tree.children.length > 0) { + tree.children.forEach((c) => { + res = new Set([...res, ...getSetOfActivitiesInProcessTree(c)]); + }); + } else if (tree.label) { + res.add(tree.label); + } + return res; + } else { + return new Set(); + } +} diff --git a/src/frontend/src/app/objects/TimeUnit.ts b/src/frontend/src/app/objects/TimeUnit.ts new file mode 100644 index 0000000000000000000000000000000000000000..20a3f4b692a86e1c1b7b2baf97fc71e9f0b79038 --- /dev/null +++ b/src/frontend/src/app/objects/TimeUnit.ts @@ -0,0 +1,8 @@ +export enum TimeUnit { + MS = 'Milliseconds', + SEC = 'Seconds', + MIN = 'Minutes', + HOUR = 'Hours', + DAY = 'Days', + MONTH = 'Month', +} diff --git a/src/frontend/src/app/objects/VariantSelectionMethod.ts b/src/frontend/src/app/objects/VariantSelectionMethod.ts new file mode 100644 index 0000000000000000000000000000000000000000..acdc9bb463a31bfb941632d4b307e3ef6cc40e8b --- /dev/null +++ b/src/frontend/src/app/objects/VariantSelectionMethod.ts @@ -0,0 +1,7 @@ +export enum VariantSelectionMethod { + ALL = 'All', + SELECTED = 'Selected', + FITTING = 'Fitting', + NON_FITTING = 'Non-Fitting', + DISPLAYED = 'Displayed', +} diff --git a/src/frontend/src/app/objects/Variants/infix_selection.ts b/src/frontend/src/app/objects/Variants/infix_selection.ts new file mode 100644 index 0000000000000000000000000000000000000000..d32bdf7e36cdd38c70c2e2585f0e9992d08eeb8c --- /dev/null +++ b/src/frontend/src/app/objects/Variants/infix_selection.ts @@ -0,0 +1,229 @@ +import { Variant } from './variant'; +import { + InvisibleSequenceGroup, + LeafNode, + ParallelGroup, + SequenceGroup, + SkipGroup, + VariantElement, + WaitingTimeNode, +} from './variant_element'; + +export enum SelectableState { + Selectable = 0, + Unselectable = 1, + None = 2, +} + +export enum InfixType { + PROPER_INFIX = 1, + PREFIX = 2, + POSTFIX = 3, + NOT_AN_INFIX = 4, +} + +export const isElementWithActivity = (elem: VariantElement) => { + return ( + elem instanceof ParallelGroup || + elem instanceof SequenceGroup || + elem instanceof LeafNode + ); +}; + +const areAllChildrenSelected = (elem: VariantElement) => { + if (elem instanceof LeafNode) { + return elem.selected; + } + + if (elem instanceof ParallelGroup || elem instanceof SequenceGroup) { + for (let e of elem.elements) { + if (!isElementWithActivity(e)) { + continue; + } + if (!e.selected) { + return false; + } + } + + return true; + } else { + // Waiting Time Node, etc... + return true; + } +}; + +export const someChildrenSelected = (elem: VariantElement) => { + if (elem instanceof LeafNode) { + return elem.selected; + } else if (elem instanceof ParallelGroup || elem instanceof SequenceGroup) { + for (let child of elem.elements) { + if (!isElementWithActivity(child)) { + continue; + } + if (someChildrenSelected(child)) { + return true; + } + } + + return false; + } else { + // Waiting Time Node, etc... + return false; + } +}; + +export const updateSelectionAttributesForGroup = (group: any) => { + updateSelectedAttributesForGroup(group); + updateSelectableAttributesForGroup(group); +}; + +const updateSelectedAttributesForGroup = (group: any) => { + let children = group.elements.filter((c) => isElementWithActivity(c)); + group.isAnyInfixSelected = false; + + for (let child of children) { + if (!(child instanceof LeafNode)) { + updateSelectedAttributesForGroup(child); + } else { + if (child.selected) { + group.setRootAnyInfixSelected(true); + } + } + } + + group.selected = areAllChildrenSelected(group); +}; + +const updateSelectableAttributesForGroup = (group: any) => { + let children = group.elements.filter((c) => isElementWithActivity(c)); + + let nothingIsSelected = !someChildrenSelected(group); + + if (nothingIsSelected) { + group.setInfixSelectableState(SelectableState.Selectable, true); + return; + } + + // initialize all elements with not selectable state + for (let child of children) { + child.setInfixSelectableState(SelectableState.None, true); + } + + // First, check if a child is only partly selected + // If yes, set all other children to be not selectable and call this function on that child + for (let child of children) { + let childIsCompletelySelected: boolean = child.selected; + if (childIsCompletelySelected || !someChildrenSelected(child)) { + continue; + } + + if (someChildrenSelected(child)) { + child.setInfixSelectableState(SelectableState.Selectable); + updateSelectableAttributesForGroup(child); + return; + } + } + + group.updateSurroundingSelectableElements(); +}; + +export const setParent = (root: VariantElement) => { + if ( + root instanceof ParallelGroup || + root instanceof SequenceGroup || + root instanceof SkipGroup + ) { + for (let child of root.elements) { + child['parent'] = root; + setParent(child); + } + } +}; + +export const getLowestSelectionActionableElement = (elem: VariantElement) => { + if ( + elem.infixSelectableState !== SelectableState.None || + elem.parent == null + ) { + // Selectable or unselectable or root + return elem; + } else { + return getLowestSelectionActionableElement(elem.parent); + } +}; + +export const getSelectedChildren = (elem: VariantElement) => { + if (elem instanceof LeafNode && elem.selected) { + let ret = elem.copy(); + ret.selected = false; + ret.infixSelectableState = SelectableState.Selectable; + return ret; + } else if (elem instanceof SequenceGroup || elem instanceof ParallelGroup) { + let copyElem; + if (elem instanceof SequenceGroup) { + copyElem = new SequenceGroup([]); + } else if (elem instanceof ParallelGroup) { + copyElem = new ParallelGroup([]); + } + copyElem.selected = false; + copyElem.infixSelectableState = SelectableState.Selectable; + + for (let child of elem.elements) { + if (!(child instanceof WaitingTimeNode) && someChildrenSelected(child)) { + let newPushedChild; + if (!(child instanceof InvisibleSequenceGroup)) { + newPushedChild = child; + } else { + newPushedChild = child.elements[1]; // InvisibleSequenceGroup has one leaf child at this position + } + copyElem.elements.push(getSelectedChildren(newPushedChild)); + } + } + setParent(copyElem); + return copyElem; + } +}; + +// Sometimes selecting trace infix creates variant elements with only one child on many tree levels +// The following function fixes the problem by reducing tree levels +export const removeIntermediateGroupsWithSingleElements = ( + elem: VariantElement +) => { + if (elem instanceof LeafNode) { + return elem; + } else if (elem instanceof SequenceGroup || elem instanceof ParallelGroup) { + if (elem.elements.length == 1) { + let onlyChild = removeIntermediateGroupsWithSingleElements( + elem.elements[0] + ); + return onlyChild; + } else { + let newChildren = elem.elements.map( + removeIntermediateGroupsWithSingleElements + ); + elem.setElements(newChildren); + return elem; + } + } +}; + +export const getInfixTypeForSelectedInfix = (variant: Variant) => { + let children = variant.variant.getElements(); + if ( + children[0].selected && + (variant.infixType === InfixType.NOT_AN_INFIX || + variant.infixType === InfixType.PREFIX) + ) { + return InfixType.PREFIX; + } + + if ( + children[children.length - 1].selected && + (variant.infixType === InfixType.NOT_AN_INFIX || + variant.infixType === InfixType.POSTFIX) + ) { + return InfixType.POSTFIX; + } + + return InfixType.PROPER_INFIX; +}; diff --git a/src/frontend/src/app/objects/Variants/loop_collapsed_variant.ts b/src/frontend/src/app/objects/Variants/loop_collapsed_variant.ts new file mode 100644 index 0000000000000000000000000000000000000000..b90e71e566c4a0cb47d115105d5efeee3a4c827e --- /dev/null +++ b/src/frontend/src/app/objects/Variants/loop_collapsed_variant.ts @@ -0,0 +1,120 @@ +import { ProcessTree } from '../ProcessTree/ProcessTree'; +import { Variant } from './variant'; +import { VariantElement } from './variant_element'; +import { IVariant } from './variant_interface'; + +export class LoopCollapsedVariant implements IVariant { + id: string; + variants: Variant[]; + variant: VariantElement; + isDisplayed: boolean; + alignment: VariantElement; + usedTreeForConformanceChecking: ProcessTree; + fragmentStatistics: any; + collapsedVariantId: string; + clusterId: number; + + constructor( + id: string, + variants: Variant[], + collapsedVariantElement: VariantElement + ) { + this.id = id; + this.variants = variants; + this.variant = collapsedVariantElement; + } + + /* + * Empty implementation for now + * @param variant + */ + public equals(variant: Variant): boolean { + return true; + } + + get infixType() { + return this.variants[0].infixType; + } + + get bid() { + return -10000; + } + + get length() { + return Math.min(...this.variants.map((v) => v.length)); + } + + get number_of_activities() { + return this.variants[0].number_of_activities; + } + + get count() { + return this.variants.reduce((sum, v) => sum + v.count, 0); + } + + get isSelected() { + return this.variants.some((v) => v.isSelected); + } + + set isSelected(isSelected: boolean) { + this.variants.forEach((v) => (v.isSelected = isSelected)); + } + + get percentage() { + return Number( + this.variants.reduce((sum, v) => sum + v.percentage, 0).toFixed(2) + ); + } + + get userDefined() { + return this.variants.every((v) => v.userDefined); + } + + get nSubVariants() { + return this.variants.reduce((sum, v) => v.nSubVariants + sum, 0); + } + + get isTimeouted() { + return this.variants.some((v) => v.isTimeouted); + } + + set isTimeouted(value) { + this.variants.forEach((v) => (v.isTimeouted = value)); + } + + get isConformanceOutdated() { + return this.variants.some((v) => v.isConformanceOutdated); + } + + set isConformanceOutdated(value) { + this.variants.forEach((v) => (v.isConformanceOutdated = value)); + } + + get isAddedFittingVariant() { + return this.variants.every((v) => v.isAddedFittingVariant); + } + + set isAddedFittingVariant(value) { + this.variants.forEach((v) => (v.isAddedFittingVariant = value)); + } + + get calculationInProgress() { + return this.variants.some((v) => v.calculationInProgress); + } + + set calculationInProgress(value) { + this.variants.forEach((v) => (v.calculationInProgress = value)); + } + + get deviations() { + if (this.variants.some((v) => v.deviations === undefined)) { + return undefined; + } + + return Math.max(...this.variants.map((v) => v.deviations)); + } + + set deviations(value) { + this.variants.forEach((v) => (v.deviations = value)); + } +} diff --git a/src/frontend/src/app/objects/Variants/subvariant.ts b/src/frontend/src/app/objects/Variants/subvariant.ts new file mode 100644 index 0000000000000000000000000000000000000000..c533982b19754102f946351bdc97df9602fbf132 --- /dev/null +++ b/src/frontend/src/app/objects/Variants/subvariant.ts @@ -0,0 +1,8 @@ +export class SubvariantVisualization { + activity: string; + xStart: number; + xEnd: number; + yIndex: number; + performanceStats; + isWaitingTimeNode: boolean = false; +} diff --git a/src/frontend/src/app/objects/Variants/utility_functions.ts b/src/frontend/src/app/objects/Variants/utility_functions.ts new file mode 100644 index 0000000000000000000000000000000000000000..cae7544ee721f9a34c52027d65ee15afba6bdb8f --- /dev/null +++ b/src/frontend/src/app/objects/Variants/utility_functions.ts @@ -0,0 +1,31 @@ +import { + LeafNode, + VariantElement, +} from 'src/app/objects/Variants/variant_element'; + +export function findPathToSelectedNode( + start: VariantElement, + end +): Array<VariantElement> { + const path = searchPath(start, end); + + function searchPath(parent: VariantElement, element): Array<VariantElement> { + if (parent.getElements().indexOf(element) > -1) { + return [parent, element]; + } else if (!(parent instanceof LeafNode)) { + for (let child of parent.getElements()) { + if (!(child instanceof LeafNode)) { + const res = searchPath(child, element); + + if (res.length > 0) { + return [parent].concat(res); + } + } + } + } + + return []; + } + + return path; +} diff --git a/src/frontend/src/app/objects/Variants/variant-miner-types.ts b/src/frontend/src/app/objects/Variants/variant-miner-types.ts new file mode 100644 index 0000000000000000000000000000000000000000..4a82842e8ac1ad5249e61db3958689bbebc850e9 --- /dev/null +++ b/src/frontend/src/app/objects/Variants/variant-miner-types.ts @@ -0,0 +1,134 @@ +import { InfixType } from 'src/app/objects/Variants/infix_selection'; +import { + SkipGroup, + VariantElement, +} from 'src/app/objects/Variants/variant_element'; +import { ProcessTree } from '../ProcessTree/ProcessTree'; + +export class MiningConfig { + size: number; + min_sup: number; + strat: number; + loop: number; + algo: number; + artifical_start: boolean; + + constructor(size, min_sup, strat, loop, algo, art_start) { + this.size = size; + this.min_sup = min_sup; + this.strat = strat; + this.loop = loop; + this.algo = algo; + this.artifical_start = art_start; + } + + serialize() { + return { + size: this.size, + min_sup: this.min_sup, + strat: this.strat, + algo: this.algo, + loop: this.loop, + algo_type: 0, + artifical_start: this.artifical_start, + }; + } +} + +export enum FrequentMiningStrategy { + TraceTransaction = 1, + VariantTransaction = 2, + TraceOccurence = 3, + VariantOccurence = 4, +} + +export enum FrequentMiningCMStrategy { + ClosedMaximal = 1, + OnlyMaximal = 2, +} + +export enum FrequentMiningAlgorithm { + ValidTreeMiner = 1, + ClosedMaximalMiner = 2, + EfPatternMiner = 3, +} + +export enum VariantSortKey { + size = 'size', + id = 'id', + support = 'support', + conformance = 'conformance', + maximal = 'maximal', + closed = 'closed', +} + +export enum VariantFilterKey { + size = 'size', + support = 'support', + id = 'id', + deviation = 'deviation', + child_parent_confidence = 'child_parent_confidence', + subpattern_confidence = 'subpattern_confidence', + cross_support_confidence = 'cross_support_confidence', + maximal = 'maximal', + closed = 'closed', +} + +export class SubvariantPattern { + id: number; + size: number; + isSelected: boolean = false; + variant: VariantElement; + support: number; + child_parent_confidence: number; + subpattern_confidence: number; + cross_support_confidence: number; + maximal: boolean; + valid: boolean; + closed: boolean; + bids: Set<number>; + activities: Set<string>; + + calculationInProgress; + + alignment: VariantElement | undefined; + deviations: number | undefined; + isTimeouted: boolean; + isConformanceOutdated: boolean; + usedTreeForConformanceChecking: ProcessTree; + + infixType: InfixType; + + constructor( + id: number, + size: number, + variant: VariantElement, + support: number, + child_parent_confidence: number, + subpattern_confidence: number, + cross_support_confidence: number, + maximal: boolean, + valid: boolean, + closed: boolean, + infixType: InfixType, + bids: Set<number> + ) { + this.id = id; + this.size = size; + this.variant = variant; + this.support = support; + this.child_parent_confidence = child_parent_confidence; + this.subpattern_confidence = subpattern_confidence; + this.cross_support_confidence = cross_support_confidence; + this.maximal = maximal; + this.valid = valid; + this.closed = closed; + this.infixType = infixType; + this.bids = bids; + this.activities = this.variant.getActivities(); + } + + get isSkipGroupPattern() { + return this.variant instanceof SkipGroup; + } +} diff --git a/src/frontend/src/app/objects/Variants/variant-sorter.ts b/src/frontend/src/app/objects/Variants/variant-sorter.ts new file mode 100644 index 0000000000000000000000000000000000000000..a27c3dc802f6cb540b57e56ed31ee6b577031d82 --- /dev/null +++ b/src/frontend/src/app/objects/Variants/variant-sorter.ts @@ -0,0 +1,84 @@ +import { SubvariantPattern } from './variant-miner-types'; +import { Variant } from 'src/app/objects/Variants/variant'; + +export class VariantSorter { + static sort( + variants: Variant[] | SubvariantPattern[], + sortKey: string, + isAscendingOrder: boolean + ): Variant[] | SubvariantPattern[] { + let sortFn: any; + sortFn = (a: Variant | SubvariantPattern, b: Variant | SubvariantPattern) => + VariantSorter.attributeSorting(a, b, sortKey); + + if (sortKey == 'conformance') { + sortFn = VariantSorter.conformanceSorting; + } + + if (sortKey == 'sub_variants') { + sortFn = VariantSorter.subvariantsSorting; + } + + return variants.sort( + (a: Variant | SubvariantPattern, b: Variant | SubvariantPattern) => + VariantSorter.applyOrder(sortFn(a, b), isAscendingOrder) + ); + } + + static attributeSorting( + a: Variant | SubvariantPattern, + b: Variant | SubvariantPattern, + sortAttribute: string + ) { + if (a[sortAttribute] < b[sortAttribute]) { + return -1; + } else if (a[sortAttribute] > b[sortAttribute]) { + return 1; + } else { + return a.id > b.id ? 1 : -1; + } + } + + static subvariantsSorting(a: Variant, b: Variant) { + if (a.nSubVariants < b.nSubVariants) { + return -1; + } else if (a.nSubVariants > b.nSubVariants) { + return 1; + } else { + return a.id > b.id ? 1 : -1; + } + } + + static conformanceSorting( + a: Variant | SubvariantPattern, + b: Variant | SubvariantPattern + ) { + if (a.calculationInProgress && !b.calculationInProgress) { + return -1; + } else if (!a.calculationInProgress && b.calculationInProgress) { + return 1; + } else if (a.isTimeouted && !b.isTimeouted) { + return -1; + } else if (b.isTimeouted && !a.isTimeouted) { + return 1; + } else if (a.isConformanceOutdated && !b.isConformanceOutdated) { + return -1; + } else if (!a.isConformanceOutdated && b.isConformanceOutdated) { + return 1; + } else if (a.deviations === undefined && b.deviations !== undefined) { + return -1; + } else if (b.deviations === undefined && a.deviations !== undefined) { + return 1; + } else if (a.deviations > b.deviations) { + return -1; + } else if (a.deviations < b.deviations) { + return 1; + } + + return a.id > b.id ? 1 : -1; + } + + static applyOrder(sortFnResult: number, isAscendingOrder: boolean) { + return isAscendingOrder ? sortFnResult : sortFnResult * -1; + } +} diff --git a/src/frontend/src/app/objects/Variants/variant.ts b/src/frontend/src/app/objects/Variants/variant.ts new file mode 100644 index 0000000000000000000000000000000000000000..576664218ee16344f088ae65ff2df0a14a317d81 --- /dev/null +++ b/src/frontend/src/app/objects/Variants/variant.ts @@ -0,0 +1,103 @@ +import { Transform, TransformationType, Type } from 'class-transformer'; +import { ProcessTree } from '../ProcessTree/ProcessTree'; +import { InfixType } from './infix_selection'; +import { VariantElement, deserialize } from './variant_element'; +import { IVariant } from './variant_interface'; + +export interface FragmentStatistics { + totalOccurrences: number; + traceOccurrences: number; + variantOccurrences: number; +} + +export class Variant implements IVariant { + id: string; + bid: number; //Positive Numbers indicate Log Variants, Negative Number User Variants + count: number; + length: number; + number_of_activities: number; + @Type(() => VariantElement) + @Transform(({ value, key, obj, type }) => { + if (type === TransformationType.PLAIN_TO_CLASS && value) + return deserialize(value); + if (type === TransformationType.CLASS_TO_PLAIN && value) + return (<VariantElement>value).serialize(); + return value; + }) + variant: VariantElement; + isSelected: boolean; + isDisplayed: boolean; + isAddedFittingVariant: boolean; + percentage: number; + calculationInProgress: boolean | undefined; + userDefined: boolean; + @Type(() => VariantElement) + @Transform(({ value, key, obj, type }) => { + if (type === TransformationType.PLAIN_TO_CLASS && value) + return deserialize(value); + if (type === TransformationType.CLASS_TO_PLAIN && value) + return (<VariantElement>value).serialize(); + return value; + }) + alignment: VariantElement | undefined; + deviations: number | undefined; + isTimeouted: boolean; + isConformanceOutdated: boolean; + @Type(() => ProcessTree) + usedTreeForConformanceChecking: ProcessTree; + nSubVariants: number; + infixType: InfixType; + fragmentStatistics: FragmentStatistics; + collapsedVariantId: string; + clusterId: number; // id of the cluster to which the variant belongs to, default value (no clustering) = -1 + + constructor( + count: number, + variant: VariantElement, + isSelected: boolean, + isDisplayed: boolean, + isAddedFittingVariant: boolean, + percentage: number, + calculationInProgress: boolean | undefined, + userDefined: boolean, + isTimeouted: boolean, + isConformanceOutdated: boolean, + nSubVariants: number, + infixType: InfixType = InfixType.NOT_AN_INFIX, + clusterId: number = -1 + ) { + this.count = count; + this.variant = variant; + this.isSelected = isSelected; + this.isDisplayed = isDisplayed; + this.isAddedFittingVariant = isAddedFittingVariant; + this.percentage = percentage; + this.calculationInProgress = calculationInProgress; + this.userDefined = userDefined; + this.isTimeouted = isTimeouted; + this.isConformanceOutdated = isConformanceOutdated; + this.nSubVariants = nSubVariants; + this.infixType = infixType; + this.clusterId = clusterId; + } + + public equals(variant: Variant): boolean { + let equals = false; + if ( + this.variant.getElements().length !== variant.variant.getElements().length + ) { + equals = false; + } else { + equals = this.variant.getElements().every((value, index) => { + return value.equals(variant.variant.getElements()[index]); + }); + } + if (equals) { + // check infix + if (variant.infixType !== this.infixType) { + equals = false; + } + } + return equals; + } +} diff --git a/src/frontend/src/app/objects/Variants/variant_element.ts b/src/frontend/src/app/objects/Variants/variant_element.ts new file mode 100644 index 0000000000000000000000000000000000000000..f015af00c8d07bf17f41af4bb181bdcb7ac76c6a --- /dev/null +++ b/src/frontend/src/app/objects/Variants/variant_element.ts @@ -0,0 +1,1639 @@ +import { VARIANT_Constants } from 'src/app/constants/variant_element_drawer_constants'; +import { + isElementWithActivity, + SelectableState, + setParent, + updateSelectionAttributesForGroup, +} from './infix_selection'; + +export class PerformanceStats { + public min: number; + public max: number; + public mean: number; + public median: number; + public stdev: number | undefined = 0; + public n: number; + + constructor(dict) { + if (dict) { + this.min = dict.min; + this.max = dict.max; + this.mean = dict.mean; + this.median = dict.median; + this.stdev = dict.stdev || 0; + this.n = dict.n; + } + } +} + +export abstract class VariantElement { + public expanded = false; + public serviceTime: PerformanceStats; + public waitingTime: PerformanceStats; + public waitingTimeStart: PerformanceStats; + public waitingTimeEnd: PerformanceStats; + public selected = false; + public infixSelectableState: SelectableState = SelectableState.Selectable; + public isAnyInfixSelected = false; + + public height; + width; + + public inspectionMode = false; + + public parent; + + public id; + + constructor(performance: any = undefined) { + this.serviceTime = performance?.service_time; + this.waitingTime = performance?.wait_time; + this.waitingTimeStart = performance?.wait_time_start; + this.waitingTimeEnd = performance?.wait_time_end; + this.parent = null; + } + + equals(variantElement: VariantElement) { + let equals = false; + + if ( + (this instanceof SequenceGroup && + variantElement instanceof SequenceGroup) || + (this instanceof ParallelGroup && + variantElement instanceof ParallelGroup) || + (this instanceof LoopGroup && variantElement instanceof LoopGroup) || + (this instanceof SkipGroup && variantElement instanceof SkipGroup) || + (this instanceof LeafNode && variantElement instanceof LeafNode) || + (this instanceof WaitingTimeNode && + variantElement instanceof WaitingTimeNode) || + (this instanceof StartGroup && variantElement instanceof StartGroup) || + (this instanceof EndGroup && variantElement instanceof EndGroup) + ) { + equals = ((a, b) => + a.size === b.size && [...a].every((value) => b.has(value)))( + this.getActivities(), + variantElement.getActivities() + ); + } else if ( + this instanceof InvisibleSequenceGroup && + variantElement instanceof InvisibleSequenceGroup + ) { + if (this.asString() === variantElement.asString()) { + equals = true; + } + } + + return equals; + } + + public asSequenceGroup(): SequenceGroup { + const self: unknown = this; + return self as SequenceGroup; + } + + public asParallelGroup(): ParallelGroup { + const self: unknown = this; + return self as ParallelGroup; + } + + public asChoiceGroup(): ChoiceGroup { + let self: unknown = this; + return <ChoiceGroup>self; + } + + public asFallthroughGroup(): FallthroughGroup { + let self: unknown = this; + return <FallthroughGroup>self; + } + + public asLeafNode(): LeafNode { + const self: unknown = this; + return self as LeafNode; + } + + public asLoopGroup(): LoopGroup { + const self: unknown = this; + return self as LoopGroup; + } + + public asSkipGroup(): SkipGroup { + const self: unknown = this; + return self as SkipGroup; + } + + public setExpanded(expanded: boolean) { + this.expanded = expanded; + } + + public getExpanded(): boolean { + return this.expanded; + } + + // Creates a deep copy of a Variant Element + public copy(): VariantElement { + if (this instanceof ParallelGroup) { + return this.asParallelGroup().copy(); + } else if (this instanceof SequenceGroup) { + return this.asSequenceGroup().copy(); + } else { + return this.asLeafNode().copy(); + } + } + + public getElements() { + if (this instanceof ParallelGroup) { + return this.asParallelGroup().getElements(); + } else if (this instanceof SequenceGroup) { + return this.asSequenceGroup().getElements(); + } else { + return null; + } + } + + public setElements(children: VariantElement[]) { + if (this instanceof ParallelGroup) { + this.asParallelGroup().setElements(children); + setParent(this); + } else if (this instanceof SequenceGroup) { + this.asSequenceGroup().setElements(children); + setParent(this); + } + } + + public getHeadLength() { + return ( + Math.tan((VARIANT_Constants.ARROW_HEAD_ANGLE / 360) * Math.PI * 2) * + (this.getHeight() / 2) + ); + } + + public getMarginX() { + return VARIANT_Constants.MARGIN_X; + } + + public getMarginY() { + return VARIANT_Constants.MARGIN_Y; + } + + public abstract getHeight(): number; + + public abstract getWidth(includeWaiting): number; + + public abstract recalculateWidth(includeWaiting): number; + + public abstract recalculateHeight(includeWaiting): number; + + public abstract updateWidth(includeWaiting); + + public abstract serialize(l?): Object; + + public abstract updateSelectionAttributes(): void; + + public abstract getActivities(): Set<string>; + + public updateConformance(confValue: number): void { + // pass + } + + public setInfixSelectableState( + state: SelectableState, + recursive: boolean = false + ): void { + this.infixSelectableState = state; + + if ( + recursive && + (this instanceof ParallelGroup || this instanceof SequenceGroup) + ) { + for (const elem of this.elements) { + elem.setInfixSelectableState(state, recursive); + } + } + } + + public setRootAnyInfixSelected(selected) { + if (this.parent !== null) { + this.parent.setRootAnyInfixSelected(selected); + } else { + this.isAnyInfixSelected = selected; + } + } + + public setAllChildrenSelected(): void { + this.setSelectedStateRecursive(true); + } + + public setAllChildrenUnselected(): void { + this.setSelectedStateRecursive(false); + } + + public setSelectedStateRecursive(selected: boolean): void { + this.selected = selected; + if (this instanceof SequenceGroup || this instanceof ParallelGroup) { + for (const child of this.elements) { + child.setSelectedStateRecursive(selected); + } + } + } + + public isVisibleParentSelected(): boolean { + if (this.parent === null || this.parent.parent === null) { + return false; + } + + if (this.parent instanceof InvisibleSequenceGroup) { + return this.parent.isVisibleParentSelected(); + } + + return this.parent.selected; + } + + public resetSelectionStatus(): void { + this.setRootAnyInfixSelected(false); + this.setAllChildrenUnselected(); + this.setInfixSelectableState(SelectableState.Selectable, true); + } + + public updateSurroundingSelectableElements() { + return; + } + + public abstract asString(): string; + + public abstract deleteActivity( + activityName: string + ): [VariantElement[], boolean]; + + public abstract renameActivity( + activityName: string, + newActivityName: string + ): void; +} + +export class SequenceGroup extends VariantElement { + public getActivities(): Set<string> { + const res: Set<string> = new Set<string>(); + + this.elements.forEach((e) => e.getActivities().forEach((a) => res.add(a))); + + return res; + } + + public renameActivity(activityName: string, newActivityName: string) { + this.elements.forEach((e) => { + e.renameActivity(activityName, newActivityName); + }); + } + + public deleteActivity(activityName: string): [VariantElement[], boolean] { + let newElems: VariantElement[] = []; + + for (const elem of this.elements) { + if (!(elem instanceof WaitingTimeNode)) { + const [variantElements, isFallthrough] = + elem.deleteActivity(activityName); + + if (isFallthrough) { + // Found a Fallthrough Stop Early + return [[], true]; + } else { + // We append the result + if (variantElements) { + newElems = newElems.concat(variantElements); + variantElements.forEach((e) => (e.parent = this)); + } + } + } + } + + if ( + newElems.length > 1 || + (newElems.length === 1 && + !this.parent && + !(this instanceof InvisibleSequenceGroup)) + ) { + this.elements = newElems; + return [[this], false]; + } else if (newElems.length === 1) { + if (newElems[0] instanceof ParallelGroup) { + return [newElems[0].elements, false]; + } else { + return [newElems, false]; + } + } else { + return [null, false]; + } + } + + public asString(): string { + return ( + '->(' + + this.elements + .filter((v) => { + return !(v instanceof WaitingTimeNode); + }) + .map((v) => { + return v.asString(); + }) + .join(', ') + + ')' + ); + } + + constructor( + public elements: VariantElement[], + performance: any = undefined, + public id: number = undefined + ) { + super(performance); + } + + public setExpanded(expanded: boolean) { + super.setExpanded(expanded); + + for (const el of this.elements) { + el.setExpanded(expanded); + } + } + + public setElements(elements: VariantElement[]) { + this.elements = elements; + } + + public getElements() { + return this.elements; + } + + public getHeight(): number { + if (this.height) { + return this.height; + } + return this.recalculateHeight(); + } + + public getWidth(includeWaiting = false): number { + if (this.width) { + return this.width; + } + return this.recalculateWidth(includeWaiting); + } + + public getServiceTime(): Object { + throw new Error('Method not implemented.'); + } + + public getWaitingTime(): Object { + throw new Error('Method not implemented.'); + } + + public updateWidth(includeWaiting) { + for (const el of this.elements) { + el.updateWidth(includeWaiting); + } + } + + public copy(): SequenceGroup { + const res = new SequenceGroup(this.elements.map((e) => e.copy())); + res.expanded = this.expanded; + return res; + } + + public recalculateHeight(): number { + this.elements.forEach((el) => (el.height = undefined)); + this.height = Math.max( + ...this.elements.map((el: VariantElement) => el.getHeight()) + ); + if (!(this.parent instanceof SkipGroup)) + this.height += this.getMarginY() * 2; + return this.height; + } + + public recalculateWidth(includeWaiting = false): number { + this.elements.forEach((el) => (el.width = undefined)); + this.width = this.elements + .filter((el) => !(el instanceof WaitingTimeNode) || includeWaiting) + .map((el: VariantElement) => el.getWidth(includeWaiting)) + .reduce((a: number, b: number) => a + b); + if (!(this.parent instanceof SkipGroup)) + this.width += + 2 * this.getMarginX() + + this.getHeadLength() - + this.elements[0].getHeadLength(); + return this.width; + } + + public serialize(l = 1): any { + return { + follows: this.elements + .map((e) => e.serialize(l)) + .flat() + .filter((e) => e !== null), + }; + } + + public updateSelectionAttributes(): void { + updateSelectionAttributesForGroup(this); + } + + public updateSurroundingSelectableElements(): void { + const children = this.elements.filter((c) => isElementWithActivity(c)); + + // If no children is partly selected, then selection happens on this level + // Then calculate the next selectable elements + let first = -1; + let last = children.length; + // First selected child + for (let i = 0; i < children.length; i++) { + if (children[i].selected) { + first = i; + children[first].infixSelectableState = SelectableState.Unselectable; + break; + } + } + // Last selected child + for (let i = children.length - 1; i >= 0; i--) { + if (children[i].selected) { + last = i; + children[last].infixSelectableState = SelectableState.Unselectable; + break; + } + } + + // Adding two new selectable elements, disabling selection in lower levels + if (first > 0) { + children[first - 1].setInfixSelectableState( + SelectableState.Selectable, + false + ); + } + if (last < children.length - 1) { + children[last + 1].setInfixSelectableState( + SelectableState.Selectable, + false + ); + } + } + + public updateConformance(confValue: number): void { + this.elements.forEach((el) => el.updateConformance(confValue)); + } +} + +export class ParallelGroup extends VariantElement { + public getActivities(): Set<string> { + const res: Set<string> = new Set<string>(); + + this.elements.forEach((e) => e.getActivities().forEach((a) => res.add(a))); + + return res; + } + + public renameActivity(activityName: string, newActivityName: string) { + this.elements.forEach((e) => { + e.renameActivity(activityName, newActivityName); + }); + } + + public deleteActivity(activityName: string): [VariantElement[], boolean] { + let newElems = []; + + for (const elem of this.elements) { + if (!(elem instanceof WaitingTimeNode)) { + const [variantElements, isFallthrough] = + elem.deleteActivity(activityName); + + if (isFallthrough) { + // Found a Fallthrough Stop Early + return [[], true]; + } else { + // We append the result + if (variantElements) { + newElems = newElems.concat(variantElements); + variantElements.forEach((e) => (e.parent = this)); + } + } + } + } + + if (newElems.length > 1) { + this.elements = newElems; + return [[this], false]; + } else if (newElems.length === 1) { + if (newElems[0] instanceof SequenceGroup) { + return [newElems[0].elements, false]; + } else { + return [newElems, false]; + } + } else { + return [null, false]; + } + } + + constructor( + public elements: VariantElement[], + performance: any = undefined, + public id: number = undefined + ) { + super(performance); + } + + public asString(): string { + return ( + '+(' + + this.elements + .filter((v) => { + return !(v instanceof WaitingTimeNode); + }) + .map((v) => { + return v.asString(); + }) + .join(', ') + + ')' + ); + } + + public setExpanded(expanded: boolean) { + super.setExpanded(expanded); + + for (const el of this.elements) { + el.setExpanded(expanded); + } + } + + public setElements(elements: VariantElement[]) { + this.elements = elements; + } + + public getElements() { + return this.elements; + } + + public getHeight(): number { + if (this.height) { + return this.height; + } + return this.recalculateHeight(); + } + + public getWidth(includeWaiting = false): number { + if (this.width) { + return this.width; + } + return this.recalculateWidth(includeWaiting); + } + + public copy(): ParallelGroup { + const res = new ParallelGroup(this.elements.map((e) => e.copy())); + res.expanded = this.expanded; + return res; + } + + public updateWidth(includeWaiting) { + const headLength = this.getHeadLength(); + for (const el of this.elements) { + el.width = this.width - VARIANT_Constants.MARGIN_X - 2 * headLength; + } + + for (const el of this.elements) { + el.updateWidth(includeWaiting); + } + } + + public recalculateHeight(): number { + this.elements.forEach((el) => (el.height = undefined)); + this.height = + this.elements + .map((el: VariantElement) => el.getHeight() + this.getMarginY()) + .reduce((a: number, b: number) => a + b) + VARIANT_Constants.MARGIN_Y; + return this.height; + } + + public recalculateWidth(includeWaiting = false): number { + this.elements.forEach((el) => (el.width = undefined)); + const headLength = this.getHeadLength(); + this.width = + Math.max( + ...this.elements + .filter((el) => !(el instanceof WaitingTimeNode) || includeWaiting) + .map((el: VariantElement) => el.getWidth(includeWaiting)) + ) + + VARIANT_Constants.MARGIN_X + + 2 * headLength; + return this.width; + } + + public serialize(l = 1) { + return { + parallel: this.elements + .map((e) => e.serialize(l)) + .flat() + .filter((e) => e !== null), + }; + } + + public updateSelectionAttributes(): void { + updateSelectionAttributesForGroup(this); + } + + public updateSurroundingSelectableElements(): void { + const children = this.elements.filter((c) => isElementWithActivity(c)); + children.forEach((c) => { + if (!c.selected) { + c.setInfixSelectableState(SelectableState.Selectable, false); + } else { + c.setInfixSelectableState(SelectableState.Unselectable, false); + } + }); + } + + public updateConformance(confValue: number): void { + this.elements.forEach((el) => el.updateConformance(confValue)); + } +} + +export class FallthroughGroup extends VariantElement { + public getActivities(): Set<string> { + const res: Set<string> = new Set<string>(); + + this.elements.forEach((e) => e.getActivities().forEach((a) => res.add(a))); + + return res; + } + + public renameActivity(activityName: string, newActivityName: string) { + this.elements.forEach((e) => { + e.renameActivity(activityName, newActivityName); + }); + } + + public deleteActivity(activityName: string): [VariantElement[], boolean] { + let newElems = []; + + for (let elem of this.elements) { + if (!(elem instanceof WaitingTimeNode)) { + const [variantElements, isFallthrough] = + elem.deleteActivity(activityName); + + if (isFallthrough) { + // Found a Fallthrough Stop Early + return [[], true]; + } else { + // We append the result + if (variantElements) { + newElems = newElems.concat(variantElements); + variantElements.forEach((e) => (e.parent = this)); + } + } + } + } + + if (newElems.length > 1) { + this.elements = newElems; + return [[this], false]; + } else if (newElems.length === 1) { + if (newElems[0] instanceof SequenceGroup) { + return [newElems[0].elements, false]; + } else { + return [newElems, false]; + } + } else { + return [null, false]; + } + } + + constructor(public elements: VariantElement[], performance: any = undefined) { + super(performance); + } + + public asString(): string { + return ( + 'x(' + + this.elements + .filter((v) => { + return !(v instanceof WaitingTimeNode); + }) + .map((v) => { + return v.asString(); + }) + .join(', ') + + ')' + ); + } + + public setExpanded(expanded: boolean) { + super.setExpanded(expanded); + + for (let el of this.elements) { + el.setExpanded(expanded); + } + } + + public setElements(elements: VariantElement[]) { + this.elements = elements; + } + + public getElements() { + return this.elements; + } + + public getHeight(): number { + if (this.height) { + return this.height; + } + return this.recalculateHeight(); + } + + public getWidth(includeWaiting = false): number { + if (this.width) { + return this.width; + } + return this.recalculateWidth(includeWaiting); + } + + public copy(): FallthroughGroup { + const res = new FallthroughGroup(this.elements.map((e) => e.copy())); + res.expanded = this.expanded; + return res; + } + + public updateWidth(includeWaiting) { + let headLength = this.getHeadLength(); + for (let el of this.elements) { + el.width = this.width - VARIANT_Constants.MARGIN_X - 2 * headLength; + } + + for (let el of this.elements) { + el.updateWidth(includeWaiting); + } + } + + public recalculateHeight(): number { + this.elements.forEach((el) => (el.height = undefined)); + this.height = + this.elements + .map((el: VariantElement) => el.getHeight() + this.getMarginY()) + .reduce((a: number, b: number) => a + b) + VARIANT_Constants.MARGIN_Y; + return this.height; + } + + public recalculateWidth(includeWaiting = false): number { + this.elements.forEach((el) => (el.width = undefined)); + let headLength = this.getHeadLength(); + this.width = + Math.max( + ...this.elements + .filter((el) => !(el instanceof WaitingTimeNode) || includeWaiting) + .map((el: VariantElement) => el.getWidth(includeWaiting)) + ) + + VARIANT_Constants.MARGIN_X + + 2 * headLength; + return this.width; + } + + public serialize(l = 1) { + return { + fallthrough: this.elements + .map((e) => e.serialize(l)) + .flat() + .filter((e) => e !== null), + }; + } + + public updateSelectionAttributes(): void { + updateSelectionAttributesForGroup(this); + } + + public updateSurroundingSelectableElements(): void { + let children = this.elements.filter((c) => isElementWithActivity(c)); + children.forEach((c) => { + if (!c.selected) { + c.setInfixSelectableState(SelectableState.Selectable, false); + } else { + c.setInfixSelectableState(SelectableState.Unselectable, false); + } + }); + } + + public updateConformance(confValue: number): void { + this.elements.forEach((el) => el.updateConformance(confValue)); + } +} + +export class ChoiceGroup extends VariantElement { + public getActivities(): Set<string> { + const res: Set<string> = new Set<string>(); + + this.elements.forEach((e) => e.getActivities().forEach((a) => res.add(a))); + + return res; + } + + public renameActivity(activityName: string, newActivityName: string) { + this.elements.forEach((e) => { + e.renameActivity(activityName, newActivityName); + }); + } + + public deleteActivity(activityName: string): [VariantElement[], boolean] { + let newElems = []; + + for (let elem of this.elements) { + if (!(elem instanceof WaitingTimeNode)) { + const [variantElements, isFallthrough] = + elem.deleteActivity(activityName); + + if (isFallthrough) { + // Found a Fallthrough Stop Early + return [[], true]; + } else { + // We append the result + if (variantElements) { + newElems = newElems.concat(variantElements); + variantElements.forEach((e) => (e.parent = this)); + } + } + } + } + + if (newElems.length > 1) { + this.elements = newElems; + return [[this], false]; + } else if (newElems.length === 1) { + if (newElems[0] instanceof SequenceGroup) { + return [newElems[0].elements, false]; + } else { + return [newElems, false]; + } + } else { + return [null, false]; + } + } + + constructor(public elements: VariantElement[], performance: any = undefined) { + super(performance); + } + + public asString(): string { + return ( + 'v(' + + this.elements + .filter((v) => { + return !(v instanceof WaitingTimeNode); + }) + .map((v) => { + return v.asString(); + }) + .join(', ') + + ')' + ); + } + + public setExpanded(expanded: boolean) { + super.setExpanded(expanded); + + for (let el of this.elements) { + el.setExpanded(expanded); + } + } + + public setElements(elements: VariantElement[]) { + this.elements = elements; + } + + public getElements() { + return this.elements; + } + + public getHeight(): number { + if (this.height) { + return this.height; + } + return this.recalculateHeight(); + } + + public getWidth(includeWaiting = false): number { + if (this.width) { + return this.width; + } + return this.recalculateWidth(includeWaiting); + } + + public copy(): ChoiceGroup { + const res = new ChoiceGroup(this.elements.map((e) => e.copy())); + res.expanded = this.expanded; + return res; + } + + public updateWidth(includeWaiting) { + let headLength = this.getHeadLength(); + for (let el of this.elements) { + el.width = + this.width - + VARIANT_Constants.MARGIN_X - + 2 * headLength - + (2 * + ((VARIANT_Constants.LEAF_HEIGHT + VARIANT_Constants.MARGIN_Y) * + this.elements.length + + VARIANT_Constants.MARGIN_Y)) / + 2.8; + } + + for (let el of this.elements) { + el.updateWidth(includeWaiting); + } + } + + public recalculateHeight(): number { + this.elements.forEach((el) => (el.height = undefined)); + this.height = + this.elements + .map((el: VariantElement) => el.getHeight() + this.getMarginY()) + .reduce((a: number, b: number) => a + b) + VARIANT_Constants.MARGIN_Y; + return this.height; + } + + public recalculateWidth(includeWaiting = false): number { + this.elements.forEach((el) => (el.width = undefined)); + let headLength = this.getHeadLength(); + this.width = + Math.max( + ...this.elements + .filter((el) => !(el instanceof WaitingTimeNode) || includeWaiting) + .map((el: VariantElement) => el.getWidth(includeWaiting)) + ) + + VARIANT_Constants.MARGIN_X + + 2 * headLength + + (2 * + ((VARIANT_Constants.LEAF_HEIGHT + VARIANT_Constants.MARGIN_Y) * + this.elements.length + + VARIANT_Constants.MARGIN_Y)) / + 2.8; + return this.width; + } + + public serialize(l = 1) { + return { + choice: this.elements + .map((e) => e.serialize(l)) + .flat() + .filter((e) => e !== null), + }; + } + + public updateSelectionAttributes(): void { + updateSelectionAttributesForGroup(this); + } + + public updateSurroundingSelectableElements(): void { + let children = this.elements.filter((c) => isElementWithActivity(c)); + children.forEach((c) => { + if (!c.selected) { + c.setInfixSelectableState(SelectableState.Selectable, false); + } else { + c.setInfixSelectableState(SelectableState.Unselectable, false); + } + }); + } + + public updateConformance(confValue: number): void { + this.elements.forEach((el) => el.updateConformance(confValue)); + } +} + +export class LoopGroup extends VariantElement { + public getActivities(): Set<string> { + return this.elements[0].getActivities(); + } + + public renameActivity(activityName: string, newActivityName: string) { + this.elements[0].renameActivity(activityName, newActivityName); + } + + public deleteActivity(activityName: string): [VariantElement[], boolean] { + const res = this.elements[0].deleteActivity(activityName); + if (res[0].length == 0) { + return [null, res[1]]; + } + + return [[new LoopGroup(res[0])], res[1]]; + } + + constructor(public elements: VariantElement[], performance: any = undefined) { + super(performance); + } + + public asString(): string { + return 'L(' + this.elements[0].asString() + ')'; + } + + public setExpanded(expanded: boolean) { + super.setExpanded(expanded); + + for (const el of this.elements) { + el.setExpanded(expanded); + } + } + + public setElements(elements: VariantElement[]) { + this.elements = elements; + } + + public getElements() { + return this.elements; + } + + public getHeight(): number { + return this.elements[0].getHeight() * 2; + } + + public getWidth(includeWaiting = false): number { + return this.elements[0].getWidth(includeWaiting); + } + + public copy(): LoopGroup { + const res = new LoopGroup(this.elements.map((e) => e.copy())); + res.expanded = this.expanded; + return res; + } + + public updateWidth(includeWaiting) { + const headLength = this.getHeadLength(); + for (const el of this.elements) { + el.width = this.width - VARIANT_Constants.MARGIN_X - 2 * headLength; + } + + for (const el of this.elements) { + el.updateWidth(includeWaiting); + } + } + + public recalculateHeight(includeWating = false): number { + return this.elements[0].recalculateHeight(includeWating) * 2; + } + + public recalculateWidth(includeWaiting = false): number { + return this.elements[0].recalculateWidth(includeWaiting); + } + + public serialize(l = 1) { + return { + loop: this.elements + .map((e) => e.serialize(l)) + .flat() + .filter((e) => e !== null), + }; + } + + public updateSelectionAttributes(): void { + updateSelectionAttributesForGroup(this); + } + + public updateSurroundingSelectableElements(): void { + const children = this.elements.filter((c) => isElementWithActivity(c)); + children.forEach((c) => { + if (!c.selected) { + c.setInfixSelectableState(SelectableState.Selectable, false); + } else { + c.setInfixSelectableState(SelectableState.Unselectable, false); + } + }); + } +} + +export class SkipGroup extends VariantElement { + public getActivities(): Set<string> { + const res: Set<string> = new Set<string>(); + this.elements.forEach((e) => e.getActivities().forEach((a) => res.add(a))); + + return res; + } + + public renameActivity(activityName: string, newActivityName: string) { + this.elements.forEach((e) => { + e.renameActivity(activityName, newActivityName); + }); + } + + public deleteActivity(activityName: string): [VariantElement[], boolean] { + // TODO check if correct + return [[], true]; + } + + public asString(): string { + return 'skip(' + this.elements.map((v) => v.asString()).join(', ') + ')'; + } + + constructor(public elements: VariantElement[], performance: any = undefined) { + super(performance); + } + + public setExpanded(expanded: boolean) { + super.setExpanded(expanded); + + for (const el of this.elements) { + el.setExpanded(expanded); + } + } + + public setElements(elements: VariantElement[]) { + this.elements = elements; + } + + public getElements() { + return this.elements; + } + + public getHeight(): number { + if (this.height) { + return this.height; + } + return this.recalculateHeight(); + } + + public getWidth(includeWaiting = false): number { + if (this.width) { + return this.width; + } + return this.recalculateWidth(includeWaiting); + } + + public getServiceTime(): Object { + throw new Error('Method not implemented.'); + } + + public getWaitingTime(): Object { + throw new Error('Method not implemented.'); + } + + public updateWidth(includeWaiting) { + for (const el of this.elements) { + el.updateWidth(includeWaiting); + } + } + + public copy(): SkipGroup { + const res = new SkipGroup(this.elements.map((e) => e.copy())); + res.expanded = this.expanded; + return res; + } + + public recalculateHeight(): number { + this.elements.forEach((el) => (el.height = undefined)); + this.height = + Math.max(...this.elements.map((el: VariantElement) => el.getHeight())) + + this.getMarginY() * 2; + return this.height; + } + + public recalculateWidth(includeWaiting = false): number { + this.elements.forEach((el) => (el.width = undefined)); + this.width = + this.elements + .filter((el) => !(el instanceof WaitingTimeNode) || includeWaiting) + .map((el: VariantElement) => { + if (el instanceof SequenceGroup) { + return el.elements + .filter( + (el) => !(el instanceof WaitingTimeNode) || includeWaiting + ) + .map((el: VariantElement) => el.getWidth(includeWaiting)) + .reduce((a: number, b: number) => a + b); + } else { + return el.getWidth(includeWaiting); + } + }) + .reduce((a: number, b: number) => a + b) + + 2 * this.getMarginX() + + this.getHeadLength() - + this.elements[0].getHeadLength(); + this.width += + (this.elements.length - 1) * + (VARIANT_Constants.SKIP_WIDTH + 2 * VARIANT_Constants.SKIP_MARGIN); + return this.width; + } + + public serialize(l = 1): any { + return { + skip: this.elements + .map((e) => e.serialize(l)) + .flat() + .filter((e) => e !== null), + }; + } + + public updateSelectionAttributes(): void { + updateSelectionAttributesForGroup(this); + } + + public updateConformance(confValue: number): void { + this.elements.forEach((el) => el.updateConformance(confValue)); + } +} + +export class LeafNode extends VariantElement { + constructor( + public activity: string[], + performance: any = undefined, + public conformance: number[] = undefined, + public id: number = undefined + ) { + super(performance); + } + + public textLength = 10; + + public getActivities(): Set<string> { + return new Set<string>(this.activity); + } + + public renameActivity(activityName: string, newActivityName: string) { + this.activity = this.activity.map((a) => { + return a === activityName ? newActivityName : a; + }); + } + + public deleteActivity(activityName: string): [VariantElement[], boolean] { + if (this.activity.includes(activityName)) { + if (this.activity.length > 1) { + return [[this], true]; + } else { + return [null, false]; + } + } + + return [[this], false]; + } + + public asString(): string { + return this.activity.join(';'); + } + + public getHeight(): number { + this.height = + this.activity.length * + (VARIANT_Constants.FONT_SIZE + 2 * VARIANT_Constants.MARGIN_Y); + return this.height; + } + + public getWidth( + includeWaiting = false, + full_text_width: boolean = false + ): number { + if (this.width) { + return this.width; + } + if (this.expanded || includeWaiting) { + if (this.activity.length > 1) { + this.width = + VARIANT_Constants.LEAF_WIDTH_EXPANDED + 2 * this.getHeadLength(); + } else { + this.width = VARIANT_Constants.LEAF_WIDTH_EXPANDED; + } + } else if (full_text_width) { + this.width = this.activity[0].length * VARIANT_Constants.CHAR_WIDTH; + } else { + this.width = VARIANT_Constants.LEAF_WIDTH; + } + this.width += VARIANT_Constants.MARGIN_X; + + this.width = Math.max( + this.width * 0.75 + this.getHeadLength() * 2, + this.width - this.getHeadLength() * 2 + ); + + return this.width; + } + + public updateWidth() {} + + public recalculateHeight(): number { + this.height = VARIANT_Constants.LEAF_HEIGHT; + return this.height; + } + + public copy(): LeafNode { + const res = new LeafNode([...this.activity]); + res.expanded = this.expanded; + return res; + } + + public recalculateWidth(): number { + if (this.expanded) { + this.width = VARIANT_Constants.LEAF_WIDTH_EXPANDED; + } else { + this.width = VARIANT_Constants.LEAF_WIDTH; + } + //this.width += VARIANT_Constants.MARGIN_X; + return this.width; + } + + public serialize(l = 1) { + return { leaf: this.activity }; + } + + public updateSelectionAttributes(): void { + // pass + } + + public updateConformance(confValue: number): void { + this.conformance = new Array(this.activity.length).fill(confValue); + } +} + +export class WaitingTimeNode extends VariantElement { + public getActivities(): Set<string> { + return new Set<string>(); + } + + public renameActivity(activityName: string, newActivityName: string) {} + + public deleteActivity(activityName: string): [VariantElement[], boolean] { + return [null, false]; + } + + public asString(): string { + return ''; + } + + constructor(waitingTime: PerformanceStats) { + super({ wait_time: waitingTime }); + } + + public getHeight(): number { + return VARIANT_Constants.LEAF_HEIGHT; + } + + public getWidth(): number { + if (this.width) { + return this.width; + } + this.width = VARIANT_Constants.WAITING_WIDTH + VARIANT_Constants.MARGIN_X; + + return this.width; + } + + public updateWidth() {} + + public recalculateHeight(): number { + this.height = VARIANT_Constants.LEAF_HEIGHT; + return this.height; + } + + public recalculateWidth(): number { + if (this.expanded) { + this.width = VARIANT_Constants.LEAF_WIDTH_EXPANDED; + } else { + this.width = VARIANT_Constants.LEAF_WIDTH; + } + this.width += VARIANT_Constants.MARGIN_X; + return this.width; + } + + public serialize(l = 1) { + return null; + } + + public updateSelectionAttributes(): void { + // pass + } +} + +export class InvisibleSequenceGroup extends SequenceGroup { + public asString(): string { + return this.elements + .filter((e) => { + return !(e instanceof WaitingTimeNode); + })[0] + .asString(); + } + + public deleteActivity(activityName: string): [VariantElement[], boolean] { + return this.elements + .filter((e) => { + return !(e instanceof WaitingTimeNode); + })[0] + .deleteActivity(activityName); + } + + public getMarginX() { + return 0; + } + + public getMarginY() { + return 0; + } + + public setInfixSelectableState( + state: SelectableState, + recursive = false + ): void { + this.infixSelectableState = state; + + for (const child of this.elements) { + if (isElementWithActivity(child)) { + child.setInfixSelectableState(state, recursive); + } + } + } + + public updateWidth(includeWaiting = false) { + const waiting = includeWaiting ? 1 : 0; + const waitingLengths = this.elements + .filter((e) => e instanceof WaitingTimeNode) + .map((e) => e.getWidth(true)) + .reduce((a, b) => a + b, 0); + this.elements + .filter((e) => !(e instanceof WaitingTimeNode)) + .forEach((e) => (e.width = this.width - waitingLengths * waiting)); + return this.width; + } + + public serialize(l = 1) { + return this.elements.map((e) => e.serialize(l)).filter((e) => e !== null); + } +} + +export class StartGroup extends VariantElement { + public updateSelectionAttributes(): void {} + + public getActivities(): Set<string> { + return new Set<string>(); + } + + public asString(): string { + return 'END'; + } + + public deleteActivity(activityName: string): [VariantElement[], boolean] { + return [[this], false]; + } + + public renameActivity(activityName: string, newActivityName: string): void {} + + public calculateSelectableElements(): void {} + + public getHeight(): number { + return VARIANT_Constants.LEAF_HEIGHT; + } + + public getWidth(includeWaiting: any): number { + return 25; + } + + public recalculateWidth(includeWaiting: any): number { + return 25; + } + + public recalculateHeight(includeWaiting: any): number { + return VARIANT_Constants.LEAF_HEIGHT; + } + + public updateWidth(includeWaiting: any) {} + + public serialize(l = 1): Object { + return { start: true }; + } +} + +export class EndGroup extends VariantElement { + public updateSelectionAttributes(): void {} + + public getActivities(): Set<string> { + return new Set<string>(); + } + + public asString(): string { + return 'START'; + } + + public deleteActivity(activityName: string): [VariantElement[], boolean] { + return [[this], false]; + } + + public renameActivity(activityName: string, newActivityName: string): void {} + + public calculateSelectableElements(): void {} + + public getHeight(): number { + return VARIANT_Constants.LEAF_HEIGHT; + } + + public getWidth(includeWaiting: any): number { + return 25; + } + + public recalculateWidth(includeWaiting: any): number { + return 25; + } + + public recalculateHeight(includeWaiting: any): number { + return VARIANT_Constants.LEAF_HEIGHT; + } + + public updateWidth(includeWaiting: any) {} + + public serialize(l = 1): Object { + return { end: true }; + } +} + +export function deserialize(obj: any): VariantElement { + if ('follows' in obj) { + return new SequenceGroup( + obj.follows.map((e: any) => deserialize(e)).filter((e) => e), + obj.performance, + obj.id + ); + } else if ('parallel' in obj) { + return new ParallelGroup( + obj.parallel.map((e: any) => deserialize(e)).filter((e) => e), + obj.performance, + obj.id + ); + } else if ('choice' in obj) { + return new ChoiceGroup( + obj.choice.map((e: any) => deserialize(e)).filter((e) => e), + obj.performance + ); + } else if ('fallthrough' in obj) { + return new FallthroughGroup( + obj.fallthrough.map((e: any) => deserialize(e)).filter((e) => e), + obj.performance + ); + } else if ('leaf' in obj) { + return new LeafNode( + obj.leaf.map((el) => { + return typeof el === 'string' ? el : el[0]; + }), + obj.performance, + obj.leaf.map((el) => { + return typeof el === 'string' ? undefined : el[1]; + }), + obj.id + ); + } else if ('loop' in obj) { + return new LoopGroup( + obj.loop.map((e: any) => deserialize(e)), + obj.performance + ); + } else if ('skip' in obj) { + return new SkipGroup( + obj.skip.map((e: any) => deserialize(e)), + obj.performance + ); + } +} + +export function injectWaitingTimeNodes(variants: VariantElement[]) { + variants.forEach((v) => injectWaitingTimeNodesVariant(v)); +} + +export function injectWaitingTimeNodesVariant(variant: VariantElement) { + if (variant instanceof SequenceGroup) { + variant + .asSequenceGroup() + .elements.filter((v) => !(v instanceof LeafNode)) + .forEach((e) => injectWaitingTimeNodesVariant(e)); + + for (let i = 0; i < variant.asSequenceGroup().elements.length; i++) { + const v = variant.asSequenceGroup().elements[i]; + + if (v.waitingTime?.mean !== undefined) { + const wait = new WaitingTimeNode(v.waitingTime); + v.waitingTime = undefined; + variant.elements.splice(i, 0, wait); + i += 1; + } + } + } + + if (variant instanceof ParallelGroup) { + variant + .asParallelGroup() + .elements.filter((v) => !(v instanceof LeafNode)) + .forEach((e) => injectWaitingTimeNodesVariant(e)); + + for (let i = 0; i < variant.asSequenceGroup().elements.length; i++) { + const v = variant.asParallelGroup().elements[i]; + const waitGroup = [v]; + if (v.waitingTimeStart?.mean !== undefined) { + const wait = new WaitingTimeNode(v.waitingTimeStart); + waitGroup.splice(0, 0, wait); + } + + if (v.waitingTimeEnd?.mean !== undefined) { + const wait = new WaitingTimeNode(v.waitingTimeEnd); + waitGroup.splice(waitGroup.length, 0, wait); + } + variant.elements[i] = new InvisibleSequenceGroup(waitGroup); + } + } +} + +export type GroupsWithChildElements = + | ParallelGroup + | ChoiceGroup + | FallthroughGroup + | SequenceGroup + | LoopGroup + | SkipGroup; diff --git a/src/frontend/src/app/objects/Variants/variant_interface.ts b/src/frontend/src/app/objects/Variants/variant_interface.ts new file mode 100644 index 0000000000000000000000000000000000000000..6dd0690697cfe9afe2e30383317c2facb2bda9cd --- /dev/null +++ b/src/frontend/src/app/objects/Variants/variant_interface.ts @@ -0,0 +1,30 @@ +import { ProcessTree } from '../ProcessTree/ProcessTree'; +import { InfixType } from './infix_selection'; +import { VariantElement } from './variant_element'; + +export interface IVariant { + id: string; + bid: number; //Positive Numbers indicate Log Variants, Negative Number User Variants + count: number; + length: number; + number_of_activities: number; + variant: VariantElement; + isSelected: boolean; + isDisplayed: boolean; + isAddedFittingVariant: boolean; + percentage: number; + calculationInProgress: boolean | undefined; + userDefined: boolean; + alignment: VariantElement | undefined; + deviations: number | undefined; + isTimeouted: boolean; + isConformanceOutdated: boolean; + usedTreeForConformanceChecking: ProcessTree; + nSubVariants: number; + infixType: InfixType; + fragmentStatistics: any; + collapsedVariantId: string; + clusterId: number; + + equals(variant: IVariant): boolean; +} diff --git a/src/frontend/src/app/objects/ViewMode.ts b/src/frontend/src/app/objects/ViewMode.ts new file mode 100644 index 0000000000000000000000000000000000000000..90d0260f7e123d0bce4e796ca311eea7fbf5d665 --- /dev/null +++ b/src/frontend/src/app/objects/ViewMode.ts @@ -0,0 +1,5 @@ +export enum ViewMode { + STANDARD = 'Standard', + PERFORMANCE = 'Performance', + CONFORMANCE = 'Conformance', +} diff --git a/src/frontend/src/app/objects/toast-event.ts b/src/frontend/src/app/objects/toast-event.ts new file mode 100644 index 0000000000000000000000000000000000000000..38a5d877c910b5c8b3453d2a89ce90137efa6717 --- /dev/null +++ b/src/frontend/src/app/objects/toast-event.ts @@ -0,0 +1,14 @@ +export type ToastEvent = { + title: string; + body: string; + delay: number; + autoclose: boolean; + icon: string; + type: ToastType; +}; + +export enum ToastType { + SUCCESS = 0, + WARNING = 1, + ERROR = 2, +} diff --git a/src/frontend/src/app/pipes/enum-to-array.pipe.spec.ts b/src/frontend/src/app/pipes/enum-to-array.pipe.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..c568baf23459db613ae28d28f6b2e2a2b5ac2d28 --- /dev/null +++ b/src/frontend/src/app/pipes/enum-to-array.pipe.spec.ts @@ -0,0 +1,8 @@ +import { EnumToArrayPipe } from './enum-to-array.pipe'; + +describe('EnumToArrayPipe', () => { + it('create an instance', () => { + const pipe = new EnumToArrayPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/pipes/enum-to-array.pipe.ts b/src/frontend/src/app/pipes/enum-to-array.pipe.ts new file mode 100644 index 0000000000000000000000000000000000000000..342dc7a9db7692c3daba900e69090cf0a2114337 --- /dev/null +++ b/src/frontend/src/app/pipes/enum-to-array.pipe.ts @@ -0,0 +1,13 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'enumToArray', +}) +export class EnumToArrayPipe implements PipeTransform { + transform(enumObject: any): any { + return Object.keys(enumObject).map((key) => ({ + key: key, + value: enumObject[key], + })); + } +} diff --git a/src/frontend/src/app/pipes/group-by.pipe.spec.ts b/src/frontend/src/app/pipes/group-by.pipe.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..ebd3bd033e08eb30fbaf840422d060600dec20be --- /dev/null +++ b/src/frontend/src/app/pipes/group-by.pipe.spec.ts @@ -0,0 +1,8 @@ +import { GroupByPipe } from './group-by.pipe'; + +describe('GroupByPipe', () => { + it('create an instance', () => { + const pipe = new GroupByPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/pipes/group-by.pipe.ts b/src/frontend/src/app/pipes/group-by.pipe.ts new file mode 100644 index 0000000000000000000000000000000000000000..9977a23d47e8dcc1e9380ce09dcaae0cec94eb2f --- /dev/null +++ b/src/frontend/src/app/pipes/group-by.pipe.ts @@ -0,0 +1,48 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { extractDeepPropertyByMapKey, isFunction } from '../utils/util'; + +@Pipe({ name: 'groupBy' }) +export class GroupByPipe implements PipeTransform { + transform(input: any, discriminator: any = [], delimiter: string = '|'): any { + if (!Array.isArray(input)) { + return input; + } + + let result = this.groupBy(input, discriminator, delimiter); + return result; + } + + private groupBy(list: any[], discriminator: any, delimiter: string) { + return list.reduce((acc: any, payload: string) => { + const key = this.extractKeyByDiscriminator( + discriminator, + payload, + delimiter + ); + + acc[key] = Array.isArray(acc[key]) + ? acc[key].concat([payload]) + : [payload]; + + return acc; + }, {}); + } + + private extractKeyByDiscriminator( + discriminator: any, + payload: string, + delimiter: string + ) { + if (isFunction(discriminator)) { + return (<Function>discriminator)(payload); + } + + if (Array.isArray(discriminator)) { + return discriminator + .map((k) => extractDeepPropertyByMapKey(payload, k)) + .join(delimiter); + } + + return extractDeepPropertyByMapKey(payload, <string>discriminator); + } +} diff --git a/src/frontend/src/app/pipes/humanize-duration.pipe.spec.ts b/src/frontend/src/app/pipes/humanize-duration.pipe.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..6641f84efbd5f4a294c0ee904bcaa4c783527210 --- /dev/null +++ b/src/frontend/src/app/pipes/humanize-duration.pipe.spec.ts @@ -0,0 +1,8 @@ +import { HumanizeDurationPipe } from './humanize-duration.pipe'; + +describe('HumanizeDurationPipe', () => { + it('create an instance', () => { + const pipe = new HumanizeDurationPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/pipes/humanize-duration.pipe.ts b/src/frontend/src/app/pipes/humanize-duration.pipe.ts new file mode 100644 index 0000000000000000000000000000000000000000..530bb9a35097889eebacd5305da8b9edbcbc8b7a --- /dev/null +++ b/src/frontend/src/app/pipes/humanize-duration.pipe.ts @@ -0,0 +1,59 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { + HumanizeDuration, + HumanizeDurationLanguage, + HumanizeDurationOptions, +} from 'humanize-duration-ts'; + +@Pipe({ + name: 'humanizeDuration', +}) +export class HumanizeDurationPipe implements PipeTransform { + private shortEnLang = { + shortEn: { + y: () => 'y', + mo: () => 'mo', + w: () => 'w', + d: () => 'd', + h: () => 'h', + m: () => 'm', + s: () => 's', + ms: () => 'ms', + decimal: ',', + }, + }; + + constructor() { + const durationLang = new HumanizeDurationLanguage(); + this.humanizeDuration = new HumanizeDuration(durationLang); + } + + humanizeDuration: HumanizeDuration; + + public static apply( + value: number, + options?: HumanizeDurationOptions + ): string { + return new HumanizeDurationPipe().humanizeDuration.humanize(value, options); + } + + transform( + value: number, + isMilliseconds = false, + round = true, + largest?: number, + shortEn = false + ): string { + if (!isMilliseconds) { + value = value * 1000; + } + + const options: HumanizeDurationOptions = { round, largest }; + if (shortEn) { + options.languages = this.shortEnLang; + options.language = 'shortEn'; + options.spacer = ''; + } + return this.humanizeDuration.humanize(value, options); + } +} diff --git a/src/frontend/src/app/pipes/str-filter/str-filter.pipe.spec.ts b/src/frontend/src/app/pipes/str-filter/str-filter.pipe.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..1af0e6f896f5c892f66eec159c471318c10a1592 --- /dev/null +++ b/src/frontend/src/app/pipes/str-filter/str-filter.pipe.spec.ts @@ -0,0 +1,8 @@ +import { StrFilterPipe } from './str-filter.pipe'; + +describe('StrFilterPipe', () => { + it('create an instance', () => { + const pipe = new StrFilterPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/pipes/str-filter/str-filter.pipe.ts b/src/frontend/src/app/pipes/str-filter/str-filter.pipe.ts new file mode 100644 index 0000000000000000000000000000000000000000..14df1690160e14fcf4a60c7d0f22e4d876943421 --- /dev/null +++ b/src/frontend/src/app/pipes/str-filter/str-filter.pipe.ts @@ -0,0 +1,22 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'strFilter', +}) +export class StrFilterPipe implements PipeTransform { + transform(items: any[], searchText: string): any[] { + if (!items) { + return []; + } + if (!searchText) { + return items; + } + return (items.includes(searchText) ? [] : [searchText]).concat( + items.filter((item) => { + return item + .toLocaleLowerCase() + .includes(searchText.toLocaleLowerCase()); + }) + ); + } +} diff --git a/src/frontend/src/app/pipes/table-sorting/table-sorting.pipe.spec.ts b/src/frontend/src/app/pipes/table-sorting/table-sorting.pipe.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..6489ad275c93e3d8257d39bbac2c0f052cd1c9ed --- /dev/null +++ b/src/frontend/src/app/pipes/table-sorting/table-sorting.pipe.spec.ts @@ -0,0 +1,8 @@ +import { TableSortingPipe } from './table-sorting.pipe'; + +describe('Pipe: TableSortinge', () => { + it('create an instance', () => { + let pipe = new TableSortingPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/pipes/table-sorting/table-sorting.pipe.ts b/src/frontend/src/app/pipes/table-sorting/table-sorting.pipe.ts new file mode 100644 index 0000000000000000000000000000000000000000..3badb9dfd31497c4a22c247ac53af692476b3b53 --- /dev/null +++ b/src/frontend/src/app/pipes/table-sorting/table-sorting.pipe.ts @@ -0,0 +1,46 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { ActivityField } from 'src/app/components/activity-overview/activity-overview.component'; + +@Pipe({ + name: 'tableSorting', +}) +export class TableSortingPipe implements PipeTransform { + transform(array: any, sortKey: string, ascending: boolean): any { + if (!Array.isArray(array)) { + throw new Error('Input Data is not a sortable Array'); + } + + // Reverse behavior for string keys + if ( + sortKey == 'activityName' || + sortKey == 'case_id' || + sortKey == 'earliest_time' || + sortKey == 'latest_time' || + sortKey == 'total_duration' + ) { + ascending = !ascending; + } + + array.sort((a: ActivityField, b: ActivityField) => { + if (a[sortKey] == undefined && a[sortKey] == undefined) { + if (a['property'][sortKey] < b['property'][sortKey]) { + return ascending ? -1 : 1; + } else if (a['property'][sortKey] > b['property'][sortKey]) { + return ascending ? 1 : -1; + } else { + return 0; + } + } else { + if (a[sortKey] < b[sortKey]) { + return ascending ? -1 : 1; + } else if (a[sortKey] > b[sortKey]) { + return ascending ? 1 : -1; + } else { + return 0; + } + } + }); + + return array; + } +} diff --git a/src/frontend/src/app/pipes/variant-sort.pipe.spec.ts b/src/frontend/src/app/pipes/variant-sort.pipe.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..fdd3cb17f34c1d2abd80c7654c11a57a2ff7591b --- /dev/null +++ b/src/frontend/src/app/pipes/variant-sort.pipe.spec.ts @@ -0,0 +1,8 @@ +import { VariantSortPipe } from './variant-sort.pipe'; + +describe('VariantSortPipe', () => { + it('create an instance', () => { + const pipe = new VariantSortPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/pipes/variant-sort.pipe.ts b/src/frontend/src/app/pipes/variant-sort.pipe.ts new file mode 100644 index 0000000000000000000000000000000000000000..e6d5dfe90591285f91241d191657f4b996ce6b78 --- /dev/null +++ b/src/frontend/src/app/pipes/variant-sort.pipe.ts @@ -0,0 +1,29 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { Variant } from '../objects/Variants/variant'; +import { VariantSorter } from '../objects/Variants/variant-sorter'; + +@Pipe({ + name: 'variantSort', +}) +export class VariantSortPipe implements PipeTransform { + transform(input: unknown, isAscending: boolean, feature: string): unknown { + // if we dont get an array just return back the input + if (!Array.isArray(input)) { + return input; + } + + // if any of the params is not defined we just return the input + if (isAscending === undefined || feature === undefined) { + return input; + } + + // apply search + let result = this.search(input, isAscending, feature); + return result; + } + + search(input: any[], isAscending: boolean, feature: string) { + const variants = input as Variant[]; + return VariantSorter.sort(variants, feature, isAscending); + } +} diff --git a/src/frontend/src/app/services/arcDiagramService/arc-diagram.service.spec.ts b/src/frontend/src/app/services/arcDiagramService/arc-diagram.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..3617e1883c976b875a366974707ba3ab320b931c --- /dev/null +++ b/src/frontend/src/app/services/arcDiagramService/arc-diagram.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ArcDiagramService } from './arc-diagram.service'; + +describe('ArcDiagramService', () => { + let service: ArcDiagramService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ArcDiagramService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/arcDiagramService/arc-diagram.service.ts b/src/frontend/src/app/services/arcDiagramService/arc-diagram.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..547aec62550b10e93f63f4869026baedf93de2a2 --- /dev/null +++ b/src/frontend/src/app/services/arcDiagramService/arc-diagram.service.ts @@ -0,0 +1,100 @@ +import { Injectable } from '@angular/core'; +import { BackgroundTaskInfoService } from '../backgroundTaskInfoService/background-task-info.service'; +import { webSocket, WebSocketSubject } from 'rxjs/webSocket'; +import { ArcDiagramComputationResult } from './model'; +import { Observable } from 'rxjs'; +import { FilterParams } from '../../components/variant-explorer/arc-diagram/filter/filter-params'; +import { ROUTES } from '../../constants/backend_route_constants'; +import { catchError, map, tap } from 'rxjs/operators'; +import Swal from 'sweetalert2'; + +@Injectable({ + providedIn: 'root', +}) +export class ArcDiagramService { + constructor(private infoService: BackgroundTaskInfoService) {} + + private socket: WebSocketSubject<any>; + private runningRequests: number[] = []; + + public arcDiagramsResult: Observable<ArcDiagramComputationResult>; + + public connect(): boolean { + if (!this.socket || this.socket.closed) { + this.socket = webSocket( + ROUTES.WS_HTTP_BASE_URL + ROUTES.REPETITIONS_MINING + ); + this.arcDiagramsResult = this.socket.pipe( + catchError((error) => { + this.runningRequests.forEach((r: number) => + this.infoService.removeRequest(r) + ); + this.runningRequests = []; + this.socket = null; + + throw error; + }), + tap((_) => { + this.infoService.removeRequest(this.runningRequests.pop()); + }), + map((result) => { + if ('error' in result) { + Swal.fire({ + title: 'Error occurred', + html: + '<b>Error message: </b><br>' + + '<code>' + + 'Calculating arc diagrams failed' + + '</code>', + icon: 'error', + showCloseButton: false, + showConfirmButton: false, + showCancelButton: true, + cancelButtonText: 'close', + }); + return result; + } + return new ArcDiagramComputationResult( + result['pairs'], + result['maximal_values'] + ); + }) + ); + + return true; + } + + return false; + } + + public computeArcDiagrams( + bids: string[] | number[], + filterParams: FilterParams + ): boolean { + const resubscribe = this.connect(); + const rid = this.infoService.setRequest('repetitions mining', () => + this.cancelArcDiagramComputationRequests() + ); + this.runningRequests.push(rid); + this.socket.next({ + name: 'repetition_mining', + bids, + filters: { + activitiesToInclude: Array.from( + filterParams ? filterParams.activitiesSelection.selectedItems : [] + ), + }, + }); + + return resubscribe; + } + + private cancelArcDiagramComputationRequests(): void { + this.socket.next({ isCancellationRequested: true }); + this.runningRequests.forEach((r: number) => + this.infoService.removeRequest(r) + ); + this.runningRequests = []; + this.socket.unsubscribe(); + } +} diff --git a/src/frontend/src/app/services/arcDiagramService/model.ts b/src/frontend/src/app/services/arcDiagramService/model.ts new file mode 100644 index 0000000000000000000000000000000000000000..882f1a11bfd9b903a564b3ec20479321bfa4a47a --- /dev/null +++ b/src/frontend/src/app/services/arcDiagramService/model.ts @@ -0,0 +1,12 @@ +import { Pair } from '../../directives/arc-diagram/data'; + +export class ArcDiagramComputationResult { + constructor( + public pairs: PairsPerBid, + public maximal_values: { size: number; length: number } + ) {} +} + +export interface PairsPerBid { + [bid: string]: Pair[]; +} diff --git a/src/frontend/src/app/services/backendInfoService/backend-info.service.spec.ts b/src/frontend/src/app/services/backendInfoService/backend-info.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..444973d0b580441d51f0e9ba545ad321e226dfa7 --- /dev/null +++ b/src/frontend/src/app/services/backendInfoService/backend-info.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { BackendInfoService } from './backend-info.service'; + +describe('BackendInfoService', () => { + let service: BackendInfoService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(BackendInfoService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/backendInfoService/backend-info.service.ts b/src/frontend/src/app/services/backendInfoService/backend-info.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..8fd35c4f3d51a8077930f1deb24496c7e73b072e --- /dev/null +++ b/src/frontend/src/app/services/backendInfoService/backend-info.service.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, timer, Observable } from 'rxjs'; +import { BackendService } from '../backendService/backend.service'; + +@Injectable({ + providedIn: 'root', +}) +export class BackendInfoService { + private isRunning: BehaviorSubject<boolean> = new BehaviorSubject<boolean>( + false + ); + + private timer = timer(10000, 10000); + + constructor(private backendService: BackendService) { + this.timer.subscribe((_) => { + this.backendService.getInfo().subscribe( + () => this.setRunning(true), + () => this.setRunning(false) + ); + }); + } + + public setRunning(isRunning: boolean): void { + this.isRunning.next(isRunning); + } + + public getIsRunningSubscription(): Observable<boolean> { + return this.isRunning.asObservable(); + } +} diff --git a/src/frontend/src/app/services/backendService/backend.service.spec.ts b/src/frontend/src/app/services/backendService/backend.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..bd90d07c63e4a0ebed2dc4a4e5692c789a83be17 --- /dev/null +++ b/src/frontend/src/app/services/backendService/backend.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { BackendService } from './backend.service'; + +describe('BackendService', () => { + let service: BackendService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(BackendService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/backendService/backend.service.ts b/src/frontend/src/app/services/backendService/backend.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..2c4c378e0de3e98cb206096f11af7544d15a1428 --- /dev/null +++ b/src/frontend/src/app/services/backendService/backend.service.ts @@ -0,0 +1,665 @@ +import { SharedDataService } from 'src/app/services/sharedDataService/shared-data.service'; +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable, Subject } from 'rxjs'; +import { catchError, map, mergeMap, take, tap, toArray } from 'rxjs/operators'; +import { Configuration } from 'src/app/components/settings/model'; +import { ProcessTree } from 'src/app/objects/ProcessTree/ProcessTree'; +import { TimeUnit } from 'src/app/objects/TimeUnit'; +import { mapVariants, mapVariantsList } from 'src/app/utils/util'; +import { LogService } from '../logService/log.service'; +import { ProcessTreeService } from './../processTreeService/process-tree.service'; +import { VariantElement } from 'src/app/objects/Variants/variant_element'; +import { ROUTES } from 'src/app/constants/backend_route_constants'; +import { MiningConfig } from 'src/app/objects/Variants/variant-miner-types'; +import { ElectronService } from '../electronService/electron.service'; +import { InfixType } from 'src/app/objects/Variants/infix_selection'; +import { treeConformanceResult } from '../conformanceChecking/model'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { ClusteringConfig } from 'src/app/objects/ClusteringConfig'; + +@Injectable({ + providedIn: 'root', +}) +export class BackendService { + public retryEventLogSelection = new Subject(); + public cancelOtherBgTasks = new Subject(); + + constructor( + private httpClient: HttpClient, + private logService: LogService, + private processTreeService: ProcessTreeService, + private sharedDataService: SharedDataService, + private electronService: ElectronService + ) {} + + exportEventLog( + bids: number[], + sequentializeVariants = false, + exportAsIntervalLog = true, + includeOriginalLogInfo = true + ) { + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.EXPORT + 'exportLogVariants', + { + bids: bids, + sequentializeVariants: sequentializeVariants, + exportAsIntervalLog: exportAsIntervalLog, + includeOriginalLogInfo: includeOriginalLogInfo, + }, + { responseType: 'blob' } + ); + } + + exportEventLogFromLog(bids: number[]) { + throw new Error('Deprecated'); + } + + loadEventLogFromFilePath(filePath: string): Observable<any> { + return this.httpClient + .post(ROUTES.HTTP_BASE_URL + ROUTES.IMPORT + 'loadEventLogFromFilePath', { + file_path: filePath, + }) + .pipe( + catchError((err) => { + this.retryEventLogSelection.next(filePath); + throw ( + 'Error during event log import. Prompting user for different path. Details: ' + + err + ); + }), + mapVariants(), + tap((res) => { + this.logService.processEventLog(res, filePath); + }) + ); + } + + uploadEventLog(file: File) { + let formData = new FormData(); + formData.append('file', file); + + return this.httpClient + .post( + ROUTES.HTTP_BASE_URL + ROUTES.IMPORT + 'loadEventLogFromFile', + formData + ) + .pipe( + mapVariants(), + tap((res) => { + this.logService.processEventLog(res, file['path']); + }) + ); + } + + loadProcessTreeFromFilePath(filePath: string): void { + this.httpClient + .post( + ROUTES.HTTP_BASE_URL + + ROUTES.IMPORT + + 'loadProcessTreeFromPtmlFilePath', + { + file_path: filePath, + } + ) + .subscribe((tree) => { + this.processTreeService.set_currentDisplayedProcessTree_with_Cache( + tree + ); + }); + } + + loadProcessTreeFromFile(file: File) { + let formData = new FormData(); + formData.append('file', file); + + this.httpClient + .post( + ROUTES.HTTP_BASE_URL + ROUTES.IMPORT + 'loadProcessTreeFromPtmlFile', + formData + ) + .subscribe((tree) => { + this.processTreeService.set_currentDisplayedProcessTree_with_Cache( + tree + ); + }); + } + + discoverProcessModelFromVariants(variants: any[]): void { + this.httpClient + .post( + ROUTES.HTTP_BASE_URL + + ROUTES.DISCOVER + + 'discoverProcessModelFromVariants', + { + variants: variants, + } + ) + .subscribe((tree) => { + this.processTreeService.currentDisplayedProcessTree = tree; + }); + } + + discoverProcessModelFromConcurrencyVariants( + variants: Variant[] + ): Observable<any> { + const variantsSerialized = variants.map((v) => [ + v.variant.serialize(1), + v.infixType, + ]); + return this.httpClient + .post( + ROUTES.HTTP_BASE_URL + + ROUTES.DISCOVER + + 'discoverProcessModelFromConcurrencyVariants', + { + variants: variantsSerialized, + } + ) + .pipe( + tap((tree) => { + this.processTreeService.set_currentDisplayedProcessTree_with_Cache( + tree + ); + }) + ); + } + + computeTreeString(tree: ProcessTree): void { + this.httpClient + .post( + ROUTES.HTTP_BASE_URL + ROUTES.PT_STRING + 'computeTreeStringFromTree', + { + pt: tree.copy(false), + } + ) + .subscribe((tree) => { + this.processTreeService.currentTreeString = tree; + }); + } + + renderStringToPT(treeString: string) { + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.PT_STRING + 'parseStringToPT', + { + pt_string: treeString, + } + ); + } + + downloadCurrentTreeAsBPMN(): void { + this.processTreeService.currentDisplayedProcessTree$ + .pipe(take(1)) + .subscribe((tree) => { + this.httpClient + .post( + ROUTES.HTTP_BASE_URL + ROUTES.EXPORT + 'convertPtToBPMN', + { pt: tree.copy(false) }, + { responseType: 'blob' } + ) + .subscribe((blob) => { + this.electronService.showSaveDialog( + 'bpmn_model', + 'bpmn', + blob, + 'Save BPMN model', + 'Download current tree as BPMN' + ); + // FileSaver.saveAs(blob, 'bpmn_model.bpmn'); + }); + }); + } + + downloadCurrentTreeAsPTML(): void { + this.processTreeService.currentDisplayedProcessTree$ + .pipe(take(1)) + .subscribe((tree) => { + this.httpClient + .post( + ROUTES.HTTP_BASE_URL + ROUTES.EXPORT + 'convertPtToPTML', + { pt: tree.copy(false) }, + { responseType: 'blob' } + ) + .subscribe((blob) => { + this.electronService.showSaveDialog( + 'process_tree', + 'ptml', + blob, + 'Save as ptml', + 'Download current tree as PTML' + ); + // FileSaver.saveAs(blob, 'process_tree.ptml'); + }); + }); + } + + downloadCurrentTreeAsPNML(): void { + this.processTreeService.currentDisplayedProcessTree$ + .pipe(take(1)) + .subscribe((tree) => { + this.httpClient + .post( + ROUTES.HTTP_BASE_URL + ROUTES.EXPORT + 'convertPtToPNML', + { pt: tree.copy(false) }, + { responseType: 'blob' } + ) + .subscribe((blob) => { + this.electronService.showSaveDialog( + 'petri_net', + 'pnml', + blob, + 'Save as pnml', + 'Download current tree as PNML' + ); + // FileSaver.saveAs(blob, 'petri_net.pnml'); + }); + }); + } + + applyTreeReductionRules(): void { + this.processTreeService.currentDisplayedProcessTree$ + .pipe(take(1)) + .subscribe((tree) => { + this.httpClient + .post( + ROUTES.HTTP_BASE_URL + + ROUTES.MODIFY_TREE + + 'applyReductionRulesToTree', + { + pt: tree.copy(false), + } + ) + .subscribe((tree) => + this.processTreeService.set_currentDisplayedProcessTree_with_Cache( + tree + ) + ); + }); + } + + // TODO this function is currently unused + addVariantsToModel( + variantsToAdd: any[], + explicitlyAddedVariants: any[] + ): void { + const body = { + pt: this.processTreeService.currentDisplayedProcessTree.copy(false), + variants_to_add: variantsToAdd, + fitting_variants: explicitlyAddedVariants, + }; + this.httpClient + .post( + ROUTES.HTTP_BASE_URL + ROUTES.DISCOVER + 'addVariantsToProcessModel', + body + ) + .subscribe((res) => { + this.processTreeService.set_currentDisplayedProcessTree_with_Cache(res); + }); + } + + getTreePerformance(variants: number[], remove?: number[]): Observable<any> { + const body = { + pt: this.processTreeService.currentDisplayedProcessTree.copy(false), + variants: variants, + delete: remove, + }; + + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + + ROUTES.TREE_PERFORMANCE + + 'calculateVariantsPerformance', + body + ); + } + + addConcurrencyVariantsToProcessModel( + variantsToAdd: Variant[], + variantsInModelLanguage: Variant[] + ): Observable<any> { + const body = { + pt: this.processTreeService.currentDisplayedProcessTree.copy(false), + variants_to_add: variantsToAdd.map((v) => [ + v.variant.serialize(1), + v.infixType, + ]), + fitting_variants: variantsInModelLanguage.map((v) => [ + v.variant.serialize(1), + v.infixType, + ]), + }; + return this.httpClient + .post( + ROUTES.HTTP_BASE_URL + + ROUTES.DISCOVER + + 'addConcurrencyVariantsToProcessModel', + body + ) + .pipe( + tap((res) => { + this.processTreeService.set_currentDisplayedProcessTree_with_Cache( + res + ); + }) + ); + } + + addConcurrencyVariantsToProcessModelForUnknownConformance( + selectedVariants: Variant[] + ): Observable<any> { + const body = { + pt: this.processTreeService.currentDisplayedProcessTree.copy(false), + selected_variants: selectedVariants.map((v) => [ + v.variant.serialize(1), + v.infixType, + ]), + }; + return this.httpClient + .post( + ROUTES.HTTP_BASE_URL + + ROUTES.DISCOVER + + 'addConcurrencyVariantsToProcessModelUnknownConformance', + body + ) + .pipe( + tap((res) => { + this.processTreeService.set_currentDisplayedProcessTree_with_Cache( + res + ); + }) + ); + } + + frequentSubtreeMining(config: MiningConfig): void { + this.httpClient + .post<Array<any>>( + ROUTES.HTTP_BASE_URL + ROUTES.VARIANTMINING + 'frequentSubtreeMining', + config.serialize() + ) + .subscribe((res) => { + this.sharedDataService.frequentMiningResults = res; + }); + } + + saveConfiguration(configuration: Configuration): Observable<any> { + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.CONFIG + 'saveConfiguration', + configuration + ); + } + + getConfiguration(): Observable<any> { + return this.httpClient.get<Configuration>( + ROUTES.HTTP_BASE_URL + ROUTES.CONFIG + 'getConfiguration' + ); + } + + variantQuery(query: string): Observable<any> { + const queryBody = { queryString: query }; + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.QUERY + 'variant-query', + queryBody + ); + } + + getInfo(): Observable<any> { + return this.httpClient.get(ROUTES.HTTP_BASE_URL + 'info'); + } + + public getEventLog(): Observable<any> { + return this.httpClient.get(ROUTES.HTTP_BASE_URL + 'log'); + } + + /** + * Fetches the properties of the log that is currently cached in the backend. + * If no time granularity is provided the granularity of the log is computed in + * the backend. + * @param timeGranularity + * @param logName + */ + public getLogPropsAndUpdateState( + timeGranularity?: TimeUnit, + logName?: string + ): Observable<any> { + return this.getProperties(timeGranularity).pipe( + tap((properties) => { + this.logService.processEventLog(properties, logName); + }) + ); + } + + public getProperties(timeGranularity?: TimeUnit): Observable<any> { + return this.httpClient + .post(ROUTES.HTTP_BASE_URL + ROUTES.LOG + 'properties', { + timeGranularity: timeGranularity, + }) + .pipe(mapVariants()); + } + + public getLogGranularity(): Observable<TimeUnit> { + return this.httpClient.get<TimeUnit>( + ROUTES.HTTP_BASE_URL + ROUTES.LOG + 'granularity' + ); + } + + public resetLogCache(): Observable<any> { + return this.httpClient.get( + ROUTES.HTTP_BASE_URL + ROUTES.LOG + 'resetLogCache' + ); + } + + getLogBasedPerformance(start: number, end: number): Observable<any> { + const body = { start: start, end: end }; + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + + ROUTES.VARIANT_PERFORMANCE + + 'logBasedVariantPerformance', + body + ); + } + + getSubvariantsForVariant(bid: number): Observable<any> { + let body = { + bid: bid, + }; + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.SUBVARIANT_PERFORMANCE + 'subvariants', + body + ); + } + + public applyVariantSequentializer(sourcePattern, targetPattern) { + this.httpClient + .post(ROUTES.HTTP_BASE_URL + ROUTES.SEQUENTIALIZER + 'apply', { + sourcePattern: sourcePattern, + targetPattern: targetPattern, + }) + .pipe(mapVariants()) + .subscribe((res) => { + this.logService.processEventLog(res); + }); + } + + public getTreeConformance( + pt: ProcessTree, + variants: Variant[] + ): Observable<treeConformanceResult> { + const body = { + pt: pt, + variants: variants.map((variant) => { + console.log(variant); + return { + variant: variant.variant.serialize(), + infixType: variant.infixType, + count: + variant.infixType == InfixType.NOT_AN_INFIX + ? variant.count + : variant.fragmentStatistics.traceOccurrences, + }; + }), + }; + + return this.httpClient + .post( + ROUTES.HTTP_BASE_URL + + ROUTES.TREE_CONFORMANCE + + 'calculateVariantsConformance', + body + ) + .pipe( + map((res: treeConformanceResult) => { + const treeConfRes = { + merged_conformance_tree: ProcessTree.fromObj( + res.merged_conformance_tree + ), + variants_tree_conformance: res.variants_tree_conformance.map((pt) => + ProcessTree.fromObj(pt) + ), + }; + return treeConfRes; + }) + ); + } + addUserDefinedVariant(variant: Variant) { + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.MODIFY_LOG + 'addUserDefinedVariant', + { + variant: variant.variant.serialize(), + bid: variant.bid, + } + ); + } + addUserDefinedInfix(variant: Variant) { + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.MODIFY_LOG + 'addUserDefinedInfix', + { + variant: variant.variant.serialize(), + bid: variant.bid, + infixType: variant.infixType, + } + ); + } + + changeActivityName(mergeList, renameList, activityName, newActivityName) { + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.MODIFY_LOG + 'changeActivityName', + { + mergeList: mergeList, + renameList: renameList, + activityName: activityName, + newActivityName: newActivityName, + } + ); + } + + deleteActivity( + activityName, + fallthrough, + delete_member_list, + merge_list, + delete_variant_list + ) { + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.MODIFY_LOG + 'deleteActivity', + { + activityName: activityName, + fallthrough: fallthrough, + delete_member_list: delete_member_list, + merge_list: merge_list, + delete_variant_list: delete_variant_list, + } + ); + } + + deleteVariants(bids: number[]) { + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.MODIFY_LOG + 'deleteVariants', + { + bids: bids, + } + ); + } + + revertLastLogModification() { + return this.httpClient + .post(ROUTES.HTTP_BASE_URL + ROUTES.MODIFY_LOG + 'revertLastChange', {}) + .pipe(mapVariants()); + } + + countFragmentOccurrences(variant: Variant) { + return this.httpClient.post<any>( + ROUTES.HTTP_BASE_URL + ROUTES.VARIANT + 'countFragmentOccurrences', + { + infixType: InfixType[variant.infixType], + fragment: variant.variant.serialize(), + } + ); + } + + getCollapsedVariants() { + return this.httpClient.get( + ROUTES.HTTP_BASE_URL + ROUTES.IMPORT + 'collapsedVariants' + ); + } + + computeClusters(clusteringConfig: ClusteringConfig): Observable<any[][]> { + return this.httpClient + .post<any>( + ROUTES.HTTP_BASE_URL + ROUTES.VARIANT + 'cluster', + clusteringConfig + ) + .pipe(mergeMap((clusters) => clusters)) // flat map + .pipe(mapVariantsList()) // deserialize + .pipe(toArray()); // collect to array + } + + public discoverLpms(patterns) { + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.LPMMINER + 'lpmMining', + { + patterns: patterns, + } + ); + } + + public getLpmMetrics(lpm: ProcessTree) { + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.LPMMINER + 'lpmStatistics', + { + lpm: lpm.copy(false), + } + ); + } + + public sortInVariantModeler(variant: VariantElement) { + const variants = variant.serialize(); + return this.httpClient.post( + ROUTES.BASE_URL + ROUTES.VARIANT + 'sortvariant', + { + variants, + } + ); + } + + public calculateCaseStatistics(index) { + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.VARIANT + 'caseStatistics', + { + index: index, + } + ); + } + + public getCaseActivities(index, caseId) { + return this.httpClient.post( + ROUTES.HTTP_BASE_URL + ROUTES.VARIANT + 'caseActivities', + { + index: index, + caseId: caseId, + } + ); + } + + get _cancelOtherBgTasks$(): Observable<any> { + return this.cancelOtherBgTasks.asObservable(); + } +} diff --git a/src/frontend/src/app/services/backgroundTaskInfoService/background-task-info.service.spec.ts b/src/frontend/src/app/services/backgroundTaskInfoService/background-task-info.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..8dfedfe2c2d43b144a28aed858bc3593cf8ceb98 --- /dev/null +++ b/src/frontend/src/app/services/backgroundTaskInfoService/background-task-info.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { BackgroundTaskInfoService } from './background-task-info.service'; + +describe('BackgroundTaskInfoService', () => { + let service: BackgroundTaskInfoService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(BackgroundTaskInfoService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/backgroundTaskInfoService/background-task-info.service.ts b/src/frontend/src/app/services/backgroundTaskInfoService/background-task-info.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..12560e00a6e1cda4038d6cc62705ea8eb191747b --- /dev/null +++ b/src/frontend/src/app/services/backgroundTaskInfoService/background-task-info.service.ts @@ -0,0 +1,46 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { BackgroundTask } from './model'; + +@Injectable({ + providedIn: 'root', +}) +export class BackgroundTaskInfoService { + constructor() {} + + activeRequests = new Map<number, BackgroundTask>(); + + private currentBackgroundTask = new BehaviorSubject<BackgroundTask>( + undefined + ); + + private numberBackgroundTask = new BehaviorSubject<number>(0); + + public setRequest( + description: string, + cancellationFunc: Function = null + ): number { + const id = Math.random(); + this.activeRequests.set( + id, + new BackgroundTask(description, cancellationFunc) + ); + this.currentBackgroundTask.next(this.activeRequests.values().next().value); + this.numberBackgroundTask.next(this.numberBackgroundTask.getValue() + 1); + return id; + } + + public removeRequest(id: number): void { + this.activeRequests.delete(id); + this.currentBackgroundTask.next(this.activeRequests.values().next().value); + this.numberBackgroundTask.next(this.numberBackgroundTask.getValue() - 1); + } + + public currentBackgroundTask$(): Observable<BackgroundTask> { + return this.currentBackgroundTask.asObservable(); + } + + public numberBackgroundTasks$(): Observable<number> { + return this.numberBackgroundTask.asObservable(); + } +} diff --git a/src/frontend/src/app/services/backgroundTaskInfoService/model.ts b/src/frontend/src/app/services/backgroundTaskInfoService/model.ts new file mode 100644 index 0000000000000000000000000000000000000000..e52b01e4be5ffe2f2e20855c7df6163bc9cd8c22 --- /dev/null +++ b/src/frontend/src/app/services/backgroundTaskInfoService/model.ts @@ -0,0 +1,9 @@ +export class BackgroundTask { + public Description: string; + public CancellationFunc: Function; + + constructor(description: string, cancellationFunc: Function) { + this.Description = description; + this.CancellationFunc = cancellationFunc; + } +} diff --git a/src/frontend/src/app/services/colorMapService/color-map.service.spec.ts b/src/frontend/src/app/services/colorMapService/color-map.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..691fc12528d3135986f4e60e6c089ee0e792856d --- /dev/null +++ b/src/frontend/src/app/services/colorMapService/color-map.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ColorMapService } from './color-map.service'; + +describe('ColorMapService', () => { + let service: ColorMapService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ColorMapService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/colorMapService/color-map.service.ts b/src/frontend/src/app/services/colorMapService/color-map.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..a9ce27b643178ad1a2f2b8a1b9174c2541860489 --- /dev/null +++ b/src/frontend/src/app/services/colorMapService/color-map.service.ts @@ -0,0 +1,71 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { filter } from 'rxjs/operators'; +import * as constants from './predefinedColors'; + +@Injectable({ + providedIn: 'root', +}) +export class ColorMapService { + constructor() {} + + createColorMap(activities: string[]): void { + //TODO: ensure activities are ordered based on frequency + // Note that the color map also contains keys for deleted activities because the removal can be reverted afterwards + const colorMap: Map<string, string> = new Map(); + activities.sort(); + activities.forEach((a, i) => { + colorMap.set(a, this.get_color(i)); + }); + this._colorMap.next(colorMap); + } + + changeActivityColor(activity: string, color: string): void { + let colorMap: Map<string, string> = this._colorMap.getValue(); + colorMap.set(activity, color); + this._colorMap.next(colorMap); + } + + // tslint:disable-next-line:variable-name + private _colorMap = new BehaviorSubject<Map<string, string>>(null); + + get colorMap$(): Observable<Map<string, string>> { + return this._colorMap.asObservable().pipe(filter((map) => map !== null)); + } + + get colorMap(): Map<string, string> { + return this._colorMap.getValue(); + } + + set colorMap(newColorMap: Map<string, string>) { + this._colorMap.next(newColorMap); + } + + private get_color(activityNameCount): string { + let color = ''; + if (activityNameCount >= constants.colorRange.length) { + color = this.generate_random_color(); + while (constants.colorRange.includes(color)) { + color = this.generate_random_color(); + } + } else { + color = constants.colorRange[activityNameCount]; + } + return color; + } + + private generate_random_color(): string { + const color = + '#' + (0x1000000 + Math.random() * 0xffffff).toString(16).substr(1, 6); + return color; + } + + public renameColorInActivityColorMap(activityName, newActivityName) { + if (!this.colorMap.get(newActivityName)) { + this.changeActivityColor( + newActivityName, + this.colorMap.get(activityName) + ); + } + } +} diff --git a/src/frontend/src/app/services/colorMapService/predefinedColors.ts b/src/frontend/src/app/services/colorMapService/predefinedColors.ts new file mode 100644 index 0000000000000000000000000000000000000000..09237c03efe067ace642c2009728c2ffc8faf3e0 --- /dev/null +++ b/src/frontend/src/app/services/colorMapService/predefinedColors.ts @@ -0,0 +1,88 @@ +export const colorRange: string[] = [ + '#ed5525', + '#3991ff', + '#e2c613', + '#9f74ff', + '#76bb17', + '#b216a4', + '#1ca119', + '#ec54d2', + '#399000', + '#ff80ff', + '#00b367', + '#df0079', + '#9bd763', + '#ad0077', + '#77da9c', + '#f61f63', + '#01cfc0', + '#c90028', + '#0267cd', + '#ffb41c', + '#6e3a95', + '#9ba200', + '#f699ff', + '#5e8700', + '#ffa7e5', + '#136006', + '#ff585d', + '#018bbc', + '#e06600', + '#32518e', + '#bf7200', + '#01705d', + '#b5002c', + '#6dbea8', + '#ad4100', + '#77a275', + '#952462', + '#6f7300', + '#823867', + '#e7c178', + '#9c2522', + '#918c56', + '#ff687b', + '#826600', + '#cd8bab', + '#ff8045', + '#a56072', + '#ffaf78', + '#874000', + '#815834', + '#414A6B', + '#ABDDA4', + '#d55459', + '#6967CE', + '#fed436', + '#6daebd', + '#91916d', + '#66C2A5', + '#a798f5', + '#D53E4F', + '#19AfD5', + '#FDAE61', + '#404580', + '#B49A86', + '#976df2', + '#f48c8a', + '#7b7ba3', + '#2c0d10', + '#1f2333', + '#4b5c5b', + '#9E0142', + '#05252d', + '#6c775a', + '#8c72ea', + '#2b9ad5', + '#805c1b', + '#fd781f', + '#608876', + '#362e28', + '#38126b', + '#467ed5', + '#673b3a', + '#dd5b39', + '#505050', + '#662405', + '#6f722b', +]; diff --git a/src/frontend/src/app/services/conformanceChecking/conformance-checking.service.spec.ts b/src/frontend/src/app/services/conformanceChecking/conformance-checking.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..ecf796448c66d54815e4e040324d198decc0016d --- /dev/null +++ b/src/frontend/src/app/services/conformanceChecking/conformance-checking.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ConformanceCheckingService } from './conformance-checking.service'; + +describe('ConformanceCheckingService', () => { + let service: ConformanceCheckingService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ConformanceCheckingService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/conformanceChecking/conformance-checking.service.ts b/src/frontend/src/app/services/conformanceChecking/conformance-checking.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..10c61a6975867b038cd7caea233a72db4a6cc74a --- /dev/null +++ b/src/frontend/src/app/services/conformanceChecking/conformance-checking.service.ts @@ -0,0 +1,307 @@ +import { Injectable } from '@angular/core'; +import { + BehaviorSubject, + Observable, + partition, + Subject, + Subscription, +} from 'rxjs'; +import { catchError, map, tap } from 'rxjs/operators'; +import { webSocket, WebSocketSubject } from 'rxjs/webSocket'; +import { BackgroundTaskInfoService } from '../backgroundTaskInfoService/background-task-info.service'; +import { ConformanceCheckingResult, treeConformanceResult } from './model'; +import Swal from 'sweetalert2'; +import { ProcessTree } from 'src/app/objects/ProcessTree/ProcessTree'; +import { VariantService } from '../variantService/variant.service'; +import { InfixType } from 'src/app/objects/Variants/infix_selection'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { ColorMap } from 'src/app/objects/ColorMap'; +import * as d3 from 'd3'; +import { COLORS_BLUE, COLORS_PURPLE } from 'src/app/objects/Colors'; +import { ROUTES } from 'src/app/constants/backend_route_constants'; +import { ProcessTreeService } from '../processTreeService/process-tree.service'; +import { BackendService } from '../backendService/backend.service'; +import { processTreesEqual } from 'src/app/objects/ProcessTree/utility-functions/process-tree-integrity-check'; +import { ModelViewModeService } from '../viewModeServices/model-view-mode.service'; +import { ViewMode } from 'src/app/objects/ViewMode'; + +@Injectable({ + providedIn: 'root', +}) +export class ConformanceCheckingService { + constructor( + private infoService: BackgroundTaskInfoService, + private variantService: VariantService, + private processTreeService: ProcessTreeService, + private backendService: BackendService, + private modelViewModeService: ModelViewModeService + ) { + this.processTreeService.currentDisplayedProcessTree$.subscribe((pt) => { + if (!processTreesEqual(pt, this.usedProcessTreeForTreeConformance)) { + this.activeTreeConformances.clear(); + this.mergedTreeConformance = undefined; + this.variantsTreeConformance.clear(); + this.hideTreeConformance(); + } + }); + + this.modelViewModeService.viewMode$.subscribe((viewMode) => { + if (viewMode === ViewMode.CONFORMANCE && this.anyTreeConformanceActive) + this.showTreeConformance(); + }); + } + + public readonly modelConformanceColorMap = new ColorMap( + d3 + .scaleThreshold<any, any>() + .domain( + COLORS_PURPLE.map((value, index) => index / (COLORS_PURPLE.length - 1)) + ) + .range(['#d3d3d3', ...COLORS_PURPLE]) + ); + public readonly modelConformanceStripeColors = [ + COLORS_PURPLE[0], + COLORS_PURPLE[1], + ]; + + public readonly variantConformanceColorMap = new ColorMap( + d3 + .scaleThreshold<any, any>() + .domain( + COLORS_BLUE.map((value, index) => index / (COLORS_BLUE.length - 1)) + ) + .range(['#d3d3d3', ...COLORS_BLUE]) + ); + public readonly variantConformanceStripeColors = [ + COLORS_BLUE[0], + COLORS_BLUE[1], + ]; + + private socket: WebSocketSubject<any>; + private runningRequests: number[] = []; + public varResults: Observable<ConformanceCheckingResult>; + public patternResults: Observable<ConformanceCheckingResult>; + public showConformanceCheckingTimeoutDialog: Subject<any> = + new Subject<any>(); + + private usedProcessTreeForTreeConformance: ProcessTree; + + public isConformanceWeighted$: BehaviorSubject<Boolean> = + new BehaviorSubject<Boolean>(false); + + set isConformanceWeighted(isWeighted: Boolean) { + if (this.isConformanceWeighted !== isWeighted) { + this.isConformanceWeighted$.next(isWeighted); + } + } + + get isConformanceWeighted() { + return this.isConformanceWeighted$.value; + } + + private activeTreeConformances: Set<Variant> = new Set<Variant>(); + private mergedTreeConformance: ProcessTree; + public variantsTreeConformance: Map<Variant, ProcessTree> = new Map< + Variant, + ProcessTree + >(); + private latestRequest: Subscription; + public calculationInProgress = new Set<Variant>(); + + public connect(): boolean { + if (!this.socket || this.socket.closed) { + this.socket = webSocket( + ROUTES.WS_HTTP_BASE_URL + ROUTES.VARIANT_CONFORMANCE + ); + const results = this.socket.pipe( + catchError((error) => { + this.runningRequests.forEach((r: number) => + this.infoService.removeRequest(r) + ); + this.runningRequests = []; + this.socket = null; + + throw error; + }), + tap((_) => { + this.infoService.removeRequest(this.runningRequests.pop()); + }), + map((result) => { + if ('error' in result) { + Swal.fire({ + title: 'Error occurred', + html: + '<b>Error message: </b><br>' + + '<code>' + + 'Calculating conformance statistics failed' + + '</code>', + icon: 'error', + showCloseButton: false, + showConfirmButton: false, + showCancelButton: true, + cancelButtonText: 'close', + }); + return result; + } + return new ConformanceCheckingResult( + result['id'], + result['type'], + result['isTimeout'], + result['cost'], + result['deviations'], + result['alignment'], + result['pt'] + ); + }) + ); + [this.varResults, this.patternResults] = partition( + results, + (ccr: ConformanceCheckingResult) => ccr.type === 1 || 'error' in ccr + ); + + return true; + } + + return false; + } + + public calculateConformance( + id: string, + infixType: InfixType, + pt: ProcessTree, + variant: any, + timeout: number, + alignType: AlignmentType + ): boolean { + const resubscribe = this.connect(); + const rid = this.infoService.setRequest('conformance checking', () => + this.cancelConformanceCheckingRequests() + ); + this.runningRequests.push(rid); + this.socket.next({ + id: id, + infixType: infixType, + alignType: alignType, + pt: pt.copy(false), + variant: variant, + timeout: timeout, + }); + + return resubscribe; + } + + private cancelConformanceCheckingRequests(): void { + this.socket.next({ isCancellationRequested: true }); + this.runningRequests.forEach((r: number) => + this.infoService.removeRequest(r) + ); + this.runningRequests = []; + this.variantService.variants.forEach((v) => { + v.calculationInProgress = false; + }); + this.socket.unsubscribe(); + } + + public showConformanceTimeoutDialog(variant: Variant, callbackFunc) { + this.showConformanceCheckingTimeoutDialog.next([variant, callbackFunc]); + } + + public isTreeConformanceActive(v: Variant) { + return this.activeTreeConformances.has(v); + } + + public isTreeConformanceCalcInProgress(v: Variant) { + return this.calculationInProgress.has(v); + } + + public anyTreeConformanceActive() { + return this.activeTreeConformances.size > 0; + } + + private updateTreeConformance(variants: Variant[]) { + this.latestRequest?.unsubscribe(); + + this.usedProcessTreeForTreeConformance = + this.processTreeService.currentDisplayedProcessTree.copy(false); + + this.latestRequest = this.backendService + .getTreeConformance(this.usedProcessTreeForTreeConformance, variants) + .subscribe((res: treeConformanceResult) => { + this.mergedTreeConformance = res.merged_conformance_tree; + + variants.forEach((variant, index) => { + const pt = res.variants_tree_conformance[index]; + this.activeTreeConformances.add(variant); + this.variantsTreeConformance.set(variant, pt); + + this.calculationInProgress.delete(variant); + }); + + this.showTreeConformance(); + }); + } + + public showTreeConformance() { + if ( + this.processTreeService.currentDisplayedProcessTree !== + this.mergedTreeConformance + ) + this.processTreeService.currentDisplayedProcessTree = + this.mergedTreeConformance; + if (this.modelViewModeService.viewMode !== ViewMode.CONFORMANCE) + this.modelViewModeService.viewMode = ViewMode.CONFORMANCE; + } + + public hideTreeConformance() { + this.stopRunningRequest(); + this.modelViewModeService.viewMode = ViewMode.STANDARD; + this.activeTreeConformances.clear(); + } + + private stopRunningRequest() { + this.latestRequest?.unsubscribe(); + this.calculationInProgress.clear(); + } + + public toggleTreeConformance() { + if (this.anyTreeConformanceActive()) this.hideTreeConformance(); + else this.showTreeConformance(); + } + + public addToTreeConformance(variant: Variant) { + if ( + !this.activeTreeConformances.has(variant) && + !this.calculationInProgress.has(variant) + ) { + this.calculationInProgress.add(variant); + const variantsCombined: Variant[] = Array.from( + new Set([...this.activeTreeConformances, ...this.calculationInProgress]) + ); + this.updateTreeConformance(Array.from(variantsCombined)); + } else { + this.showTreeConformance(); + } + } + + public removeFromTreeConformance(variant: Variant) { + const wasActive = this.activeTreeConformances.delete(variant); + const wasInProgress = this.calculationInProgress.delete(variant); + if (wasActive || wasInProgress) { + if (this.activeTreeConformances.size == 0) this.hideTreeConformance(); + else { + const variantsCombined: Variant[] = Array.from( + new Set([ + ...this.activeTreeConformances, + ...this.calculationInProgress, + ]) + ); + this.updateTreeConformance(Array.from(variantsCombined)); + } + } + } +} + +export enum AlignmentType { + VariantAlignment = 1, + PatternAlignment = 2, +} diff --git a/src/frontend/src/app/services/conformanceChecking/model.ts b/src/frontend/src/app/services/conformanceChecking/model.ts new file mode 100644 index 0000000000000000000000000000000000000000..20ef12fbe8ff56674436e252ce6bda32504c1256 --- /dev/null +++ b/src/frontend/src/app/services/conformanceChecking/model.ts @@ -0,0 +1,17 @@ +import { ProcessTree } from 'src/app/objects/ProcessTree/ProcessTree'; + +export class ConformanceCheckingResult { + constructor( + public id: string, + public type: number, + public isTimeout: boolean, + public cost: number, + public deviations: number, + public alignment: string, + public processTree: ProcessTree + ) {} +} +export interface treeConformanceResult { + merged_conformance_tree: ProcessTree; + variants_tree_conformance: ProcessTree[]; +} diff --git a/src/frontend/src/app/services/editorService/editor.service.spec.ts b/src/frontend/src/app/services/editorService/editor.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..cbead93a6bbca7eedf13106404d2f25d896957a8 --- /dev/null +++ b/src/frontend/src/app/services/editorService/editor.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { EditorService } from './editor.service'; + +describe('EditorService', () => { + let service: EditorService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(EditorService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/editorService/editor.service.ts b/src/frontend/src/app/services/editorService/editor.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..6a737942dce511d3db70e6d3590e98e96bfab48f --- /dev/null +++ b/src/frontend/src/app/services/editorService/editor.service.ts @@ -0,0 +1,132 @@ +import { Injectable } from '@angular/core'; +import { Subject } from 'rxjs/internal/Subject'; +import { + getVQLTokenizer, + vqlConfig, +} from 'src/app/components/editor-zone/editor-languages/vql-language'; +import { take } from 'rxjs/operators'; +import { generateVQLTheme } from 'src/app/components/editor-zone/editor-languages/vql-language-theme'; +import { ColorMapService } from '../colorMapService/color-map.service'; +import { getVQLCompletionProvider } from 'src/app/components/editor-zone/editor-languages/vql-language-completion-provider'; + +import * as Monaco from 'monaco-editor'; +import { EditorOptions } from 'src/app/components/variant-explorer/variant-query/variant-query.component'; +import { LogService } from '../logService/log.service'; + +declare var monaco: typeof Monaco; +@Injectable({ + providedIn: 'root', +}) +export class EditorService { + loaded: boolean = false; + completionProvider: Monaco.IDisposable; + + options: EditorOptions = new EditorOptions(); + + private _monacoPath = 'assets/monaco-editor/min/vs'; + + public loadingFinished: Subject<void> = new Subject<void>(); + + constructor( + private colorMapService: ColorMapService, + private logService: LogService + ) { + this.colorMapService.colorMap$.subscribe((colormap: any) => { + if (colormap && this.loaded) { + this.updateVQLTheme(); + } + }); + + this.logService.activitiesInEventLog$.subscribe((act) => { + if (this.colorMapService.colorMap && this.loaded) { + this.updateVQLTheme(); + } + }); + } + + private finishLoading() { + if (!this.colorMapService.colorMap) { + this.colorMapService.colorMap$.pipe(take(1)).subscribe(() => { + this.finishLoading(); + }); + return; + } + + // Register a tokens provider for the language + monaco.languages.register({ id: 'VQL' }); + monaco.languages.setMonarchTokensProvider('VQL', getVQLTokenizer()); + monaco.languages.setLanguageConfiguration('VQL', vqlConfig); + + this.updateVQLTheme(); + + this.loaded = true; + this.loadingFinished.next(); + } + + public load() { + const onGotAmdLoader = () => { + let vsPath = this._monacoPath; + (<any>window).amdRequire = (<any>window).require; + (<any>window).amdRequire.config({ paths: { vs: vsPath } }); + + // Load monaco + (<any>window).amdRequire( + ['vs/editor/editor.main'], + () => { + this.finishLoading(); + }, + (error) => console.error('Error loading monaco-editor: ', error) + ); + }; + + const loaderScript: HTMLScriptElement = document.createElement('script'); + loaderScript.type = 'text/javascript'; + loaderScript.src = `${this._monacoPath}/loader.js`; + loaderScript.addEventListener('load', onGotAmdLoader); + document.body.appendChild(loaderScript); + } + + updateTheme() { + const cMap: Map<string, string> = new Map<string, string>(); + + this.colorMapService.colorMap.forEach((v, k) => { + if (Object.keys(this.logService.activitiesInEventLog).includes(k)) { + cMap.set(k, v); + } + }); + + monaco.editor.defineTheme('VQLTheme', generateVQLTheme(cMap, this.options)); + } + + private updateVQLTheme() { + // Define a new theme that matches the activity names and Colormap + + if (this.completionProvider) { + this.completionProvider.dispose(); + } + + const createProposals = getVQLCompletionProvider( + Object.keys(this.logService.activitiesInEventLog) + ); + + this.updateTheme(); + + this.completionProvider = monaco.languages.registerCompletionItemProvider( + 'VQL', + { + provideCompletionItems: function (model, position) { + var word = model.getWordUntilPosition(position); + var range = { + startLineNumber: position.lineNumber, + endLineNumber: position.lineNumber, + startColumn: word.startColumn, + endColumn: word.endColumn, + }; + return { + suggestions: createProposals(range), + }; + }, + } + ); + } +} diff --git a/src/frontend/src/app/services/electronService/electron-dummy.service.spec.ts b/src/frontend/src/app/services/electronService/electron-dummy.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..2a6e108a938060ca2522cbd3b02e78a6dee08038 --- /dev/null +++ b/src/frontend/src/app/services/electronService/electron-dummy.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ElectronDummyService } from './electron-dummy.service'; + +describe('ElectronDummyService', () => { + let service: ElectronDummyService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ElectronDummyService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/electronService/electron-dummy.service.ts b/src/frontend/src/app/services/electronService/electron-dummy.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..d16ba7ee8b8d7315ac6a4e02cccb4c97f58cf91e --- /dev/null +++ b/src/frontend/src/app/services/electronService/electron-dummy.service.ts @@ -0,0 +1,50 @@ +import { Injectable } from '@angular/core'; +import { ElectronInterface } from './electron-interface'; +import { Subject } from 'rxjs'; +import { saveAs } from 'file-saver'; +import { ROUTES } from '../../constants/backend_route_constants'; + +@Injectable({ + providedIn: 'root', +}) +export class ElectronDummyService implements ElectronInterface { + constructor() {} + + checkUnsavedChanges$: Subject<any>; + saveProject$: Subject<any>; + + showSaveDialog( + fileName: string, + fileExtension: string, + blob: Blob, + buttonLabel: string, + title: string + ): Promise<string> { + saveAs(blob, fileName + '.' + fileExtension); + return null; + } + saveToUserFolder( + fileName: string, + fileExtension: string, + data: string + ): Promise<undefined> { + throw new Error('Method not implemented.'); + } + readFromUserFolder(fileName: string, fileExtension: string): Promise<string> { + throw new Error('Method not implemented.'); + } + + getWSPort(): Promise<number> { + const url = ROUTES.BASE_URL; + const port = Number(url.match(/(?<=\:).+?(?=\/)/g)[0]); + return Promise.resolve(port); + } + + unsavedChangesStatus(unsavedChanges: boolean): void { + throw new Error('Method not implemented.'); + } + + quit(): void { + throw new Error('Method not implemented.'); + } +} diff --git a/src/frontend/src/app/services/electronService/electron-interface.ts b/src/frontend/src/app/services/electronService/electron-interface.ts new file mode 100644 index 0000000000000000000000000000000000000000..84224a72d5f4012d860e1c4d24c8a467e63f573f --- /dev/null +++ b/src/frontend/src/app/services/electronService/electron-interface.ts @@ -0,0 +1,28 @@ +import { Subject } from 'rxjs'; + +export interface ElectronInterface { + checkUnsavedChanges$: Subject<any>; + saveProject$: Subject<any>; + + showSaveDialog( + fileName: string, + fileExtension: string, + blob: Blob, + buttonLabel: string, + title: string + ): Promise<string>; + + saveToUserFolder( + fileName: string, + fileExtension: string, + data: string + ): Promise<undefined>; + + readFromUserFolder(fileName: string, fileExtension: string): Promise<string>; + + getWSPort(): Promise<number>; + + unsavedChangesStatus(unsavedChanges: boolean): void; + + quit(): void; +} diff --git a/src/frontend/src/app/services/electronService/electron.service.spec.ts b/src/frontend/src/app/services/electronService/electron.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..534229c6685958c41c2ccb1f2b97bddd6bfc43bd --- /dev/null +++ b/src/frontend/src/app/services/electronService/electron.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ElectronService } from './electron.service'; + +describe('ElectronService', () => { + let service: ElectronService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ElectronService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/electronService/electron.service.ts b/src/frontend/src/app/services/electronService/electron.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..93d43517f36de6b0ef77a6d3a8a85c1250964b93 --- /dev/null +++ b/src/frontend/src/app/services/electronService/electron.service.ts @@ -0,0 +1,68 @@ +import { Injectable } from '@angular/core'; +import { blobToBase64 } from 'src/app/utils/util'; +import { Subject } from 'rxjs'; +import { ElectronInterface } from './electron-interface'; + +@Injectable() +export class ElectronService implements ElectronInterface { + private electronApi = (<any>window).electronAPI; + + public checkUnsavedChanges$ = new Subject<void>(); + public saveProject$ = new Subject<void>(); + + constructor() { + this.electronApi?.onCheckUnsavedChanges(() => { + this.checkUnsavedChanges$.next(); + }); + + this.electronApi?.onSaveProject(() => { + this.saveProject$.next(); + }); + } + + public async showSaveDialog( + fileName: string, + fileExtension: string, + blob: Blob, + buttonLabel: string, + title: string + ): Promise<string> { + let base64File = await blobToBase64(blob); + + // returns filePath of savedFile or undefined if aborted + return this.electronApi.showSaveDialog( + fileName, + fileExtension, + base64File, + buttonLabel, + title + ); + } + + public saveToUserFolder( + fileName: string, + fileExtension: string, + data: string + ): Promise<undefined> { + return this.electronApi.saveToUserFolder(fileName, fileExtension, data); + } + + public readFromUserFolder( + fileName: string, + fileExtension: string + ): Promise<string> { + return this.electronApi.readFromUserFolder(fileName, fileExtension); + } + + public async getWSPort(): Promise<number> { + return this.electronApi.getWSPort(); + } + + public unsavedChangesStatus(unsavedChanges: boolean) { + this.electronApi.unsavedChanges(unsavedChanges); + } + + public quit(): void { + this.electronApi.quit(); + } +} diff --git a/src/frontend/src/app/services/errorService/error.service.spec.ts b/src/frontend/src/app/services/errorService/error.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..71f2b7a12a0af9d26ecdac8f34b30c57c98e8057 --- /dev/null +++ b/src/frontend/src/app/services/errorService/error.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ErrorService } from './error.service'; + +describe('ErrorService', () => { + let service: ErrorService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ErrorService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/errorService/error.service.ts b/src/frontend/src/app/services/errorService/error.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..f4dedbc1ce689386551aec7140850d54d9094573 --- /dev/null +++ b/src/frontend/src/app/services/errorService/error.service.ts @@ -0,0 +1,22 @@ +import { HttpErrorResponse } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class ErrorService { + private apiErrorSubject = new BehaviorSubject<HttpErrorResponse>( + {} as HttpErrorResponse + ); + + constructor() {} + + public addApiError(err: HttpErrorResponse) { + this.apiErrorSubject.next(err); + } + + public getErrors(): Observable<HttpErrorResponse> { + return this.apiErrorSubject.asObservable(); + } +} diff --git a/src/frontend/src/app/services/goldenLayoutService/golden-layout-component.service.spec.ts b/src/frontend/src/app/services/goldenLayoutService/golden-layout-component.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..694cfee382a90a1530b6d6ec0371422be8f1f23d --- /dev/null +++ b/src/frontend/src/app/services/goldenLayoutService/golden-layout-component.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { GoldenLayoutComponentService } from './golden-layout-component.service'; + +describe('GoldenLayoutComponentService', () => { + let service: GoldenLayoutComponentService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(GoldenLayoutComponentService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/goldenLayoutService/golden-layout-component.service.ts b/src/frontend/src/app/services/goldenLayoutService/golden-layout-component.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..f2912010d91c7ab30bd8b01b0baa4ca9e02cf2cb --- /dev/null +++ b/src/frontend/src/app/services/goldenLayoutService/golden-layout-component.service.ts @@ -0,0 +1,221 @@ +import { + EnvironmentInjector, + Injectable, + Injector, + StaticProvider, + Type, + createComponent, +} from '@angular/core'; +import { + ComponentContainer, + ComponentItemConfig, + ContentItem, + GoldenLayout, + JsonValue, + LayoutManager, + RowOrColumn, + Stack, +} from 'golden-layout'; +import { ActivityOverviewComponent } from 'src/app/components/activity-overview/activity-overview.component'; +import { GoldenLayoutHostComponent } from 'src/app/components/golden-layout-host/golden-layout-host.component'; +import { LpmMetricsTabComponent } from 'src/app/components/lpm-explorer/lpm-metrics-tab/lpm-metrics-tab.component'; +import { LayoutChangeDirective } from 'src/app/directives/layout-change/layout-change.directive'; + +@Injectable({ + providedIn: 'root', +}) +export class GoldenLayoutComponentService { + private _componentTypeMap = new Map<string, Type<LayoutChangeDirective>>(); + private _goldenLayoutHostComponent: GoldenLayoutHostComponent; + private _goldenLayout: GoldenLayout; + + constructor(private environmentInjector: EnvironmentInjector) {} + + splitViewIds = []; + + registerComponentType( + name: string, + componentType: Type<LayoutChangeDirective> + ) { + this._componentTypeMap.set(name, componentType); + } + + getRegisteredComponentTypeNames(): string[] { + const count = this._componentTypeMap.size; + const result = new Array<string>(count); + let idx = 0; + for (let [key, value] of this._componentTypeMap) { + result[idx++] = key; + } + return result; + } + + set goldenLayout(goldenLayout: GoldenLayout) { + this._goldenLayout = goldenLayout; + } + + get goldenLayout() { + return this._goldenLayout; + } + + set goldenLayoutHostComponent( + goldenLayoutHostComponent: GoldenLayoutHostComponent + ) { + this._goldenLayoutHostComponent = goldenLayoutHostComponent; + } + + get goldenLayoutHostComponent() { + return this._goldenLayoutHostComponent; + } + + createComponent( + componentTypeJsonValue: JsonValue, + container: ComponentContainer + ) { + const componentType = this._componentTypeMap.get( + componentTypeJsonValue as string + ); + if (componentType === undefined) { + throw new Error('Unknown component type'); + } else { + const provider: StaticProvider = { + provide: LayoutChangeDirective.GoldenLayoutContainerInjectionToken, + useValue: container, + }; + const injector = Injector.create({ + providers: [provider], + }); + return createComponent(componentType, { + environmentInjector: this.environmentInjector, + elementInjector: injector, + }); + } + } + + openWindow( + componentID: string, + parentContainerID: string, + LocationSelectors: LayoutManager.LocationSelector[], + itemConfig: ComponentItemConfig + ) { + const editor = this._goldenLayout.findFirstComponentItemById(componentID); + + const createComponent = ( + parentContainerID, + itemConfig, + LocationSelectors + ) => { + if (parentContainerID) { + this._goldenLayout + .findFirstComponentItemById(parentContainerID) + .focus(); + } + + if (LocationSelectors) { + this._goldenLayout.addItemAtLocation(itemConfig, LocationSelectors); + } else { + this._goldenLayout.addItem(itemConfig); + } + }; + + // Destroy the split window instance, and register the creation after the semaphor fires TODO carry over the state + // Issue, when in the Future multiple Editor might exist and can be closed in rapid succesion + + // TODO READD SPLIT WINDOW CHECK + if (editor && this.splitViewIds.includes(componentID)) { + editor.close(); + + this.splitViewIds.forEach((item, index) => { + if (item === componentID) this.splitViewIds.splice(index, 1); + }); + + createComponent(parentContainerID, itemConfig, LocationSelectors); + + // Create the component at the specified selector + } else if (!editor) { + createComponent(parentContainerID, itemConfig, LocationSelectors); + } else { + editor.focus(); + } + } + + createBPMNSplitViewWindow(splitParentID, componentID) { + const parent = this._goldenLayout.findFirstComponentItemById(splitParentID); + + if (this.splitViewIds.includes(componentID)) { + this._goldenLayout.findFirstComponentItemById(componentID)?.close(); + + this.splitViewIds.forEach((item, index) => { + if (item === componentID) this.splitViewIds.splice(index, 1); + }); + } else { + this.splitViewIds.push(componentID); + this._goldenLayout.findFirstComponentItemById(componentID)?.close(); + + const itemConfig: ComponentItemConfig = { + id: componentID, + type: 'component', + title: 'BPMN Editor', + isClosable: true, + header: { + show: false, + }, + componentType: componentID, + }; + + const pt_editor_row = findContentItemByUniqueID( + splitParentID + '_Container_Row', + this._goldenLayout.rootItem + ); + + (pt_editor_row as RowOrColumn).addItem(itemConfig, 1); + } + } + + activateLpmMetricsView() { + if (!this.goldenLayout.rootItem) { + return; + } + + const stackItem = findContentItemByUniqueID( + ActivityOverviewComponent.componentName + '_Container_Stack', + this.goldenLayout.rootItem + ) as Stack; + + stackItem.setActiveComponentItem( + this.goldenLayout.findFirstComponentItemById( + LpmMetricsTabComponent.componentName + ), + true + ); + } +} + +export function findContentItemByUniqueID( + id: string, + groundItem: ContentItem +): ContentItem | undefined { + const contentItems = groundItem.contentItems; + + const contentItemCount = contentItems.length; + if (contentItemCount === 0) { + return undefined; + } else { + for (let i = 0; i < contentItemCount; i++) { + const contentItem = contentItems[i]; + if (contentItem.id === id) { + return contentItem; + } + } + + for (let i = 0; i < contentItemCount; i++) { + const contentItem = contentItems[i]; + const foundContentItem = findContentItemByUniqueID(id, contentItem); + if (foundContentItem !== undefined) { + return foundContentItem; + } + } + + return undefined; + } +} diff --git a/src/frontend/src/app/services/imageExportService/image-export-service.spec.ts b/src/frontend/src/app/services/imageExportService/image-export-service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..b0691ce4b88dbd4660c9be28fcd94b9247568e42 --- /dev/null +++ b/src/frontend/src/app/services/imageExportService/image-export-service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ImageExportService } from './image-export-service'; + +describe('ImageExportServiceService', () => { + let service: ImageExportService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ImageExportService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/imageExportService/image-export-service.ts b/src/frontend/src/app/services/imageExportService/image-export-service.ts new file mode 100644 index 0000000000000000000000000000000000000000..b67c3faf5bfa3d31f563272978e04fb4542f7eb4 --- /dev/null +++ b/src/frontend/src/app/services/imageExportService/image-export-service.ts @@ -0,0 +1,160 @@ +import { Inject, Injectable } from '@angular/core'; +import * as d3 from 'd3'; +import { saveAs } from 'file-saver'; +import { ElectronService } from '../electronService/electron.service'; +import { HttpClient } from '@angular/common/http'; +import { optimize } from 'svgo/dist/svgo.browser.js'; +import { ConformanceCheckingService } from '../conformanceChecking/conformance-checking.service'; +import { addPatternDefinitions } from 'src/app/utils/render-utils'; + +/*** +A service that recieves SVG elements from member components and provides conversion and saving functionality. +***/ + +@Injectable({ + providedIn: 'root', +}) +export class ImageExportService { + constructor( + private electronService: ElectronService, + private http: HttpClient, + private conformanceCheckingService: ConformanceCheckingService + ) {} + + async export( + filename: string, + width?: number, + height?: number, + ...svgs: SVGGraphicsElement[] + ) { + let svg = await this.constructSVG(svgs); + + const base64EncodedFont = await this.getBase64EncodedFont( + '/assets/fonts/Roboto/Roboto-Regular.ttf' + ); + const fontFace = `@font-face { + font-family: 'Roboto'; + src: url(data:font/truetype;base64,${base64EncodedFont}) format('truetype'); + }`; + + svg.mainSVG.append('style').attr('type', 'text/css').text(fontFace); + + if (height) svg.svg_width = width; + if (width) svg.svg_height = height; + + svg.store(filename, this.electronService); + } + + constructSVG(svgs: SVGGraphicsElement[]): SVG { + let svg = new SVG(); + svg.appendDefs(this.conformanceCheckingService); + svg.appendRight(svgs); + return svg; + } + + // TODO Implement in new Issue + convert_svg_to_png() {} + + // TODO Implement in new Issue + convert_svg_to_pdf() {} + + private convertBlobToBase64(blob: Blob): Promise<string> { + return new Promise<string>((resolve, reject) => { + const reader = new FileReader(); + reader.onload = () => { + const base64String = reader.result.toString().split(',')[1]; + resolve(base64String); + }; + reader.onerror = () => { + reject('Error converting blob to Base64'); + }; + reader.readAsDataURL(blob); + }); + } + + async getBase64EncodedFont(fontFilePath: string): Promise<string> { + const fontFile = await this.http + .get(fontFilePath, { responseType: 'blob' }) + .toPromise(); + return this.convertBlobToBase64(fontFile); + } +} + +class SVG { + readonly mainSVG; + + private width = 0; + private height = 0; + + constructor() { + this.mainSVG = d3 + .create('svg') + .attr('xmlns', 'http://www.w3.org/2000/svg') + .attr('font-family', 'Roboto, sans-serif'); + } + + public append(x: number, y: number, svgs: SVGGraphicsElement[]): SVG { + let lastSVG; + for (let svg of svgs) { + const svgX = svg.getAttribute('x'); + const svgY = svg.getAttribute('y'); + + lastSVG = this.mainSVG + .append(svg.nodeName) + .attr('x', svgX === null ? x : svgX) + .attr('y', svgY === null ? y : svgY) + .html(svg.innerHTML); + + for (let attr of svg.getAttributeNames()) { + lastSVG.attr(attr, svg.getAttribute(attr)); + } + + y += Number.parseFloat(svg.getAttribute('height')); + this.height = Math.max(this.height, y); + this.width = Math.max( + this.width, + x + Number.parseFloat(svg.getAttribute('width')) + ); + } + return this; + } + + public appendDefs(conformanceCheckingService: ConformanceCheckingService) { + addPatternDefinitions(this.mainSVG, conformanceCheckingService); + } + + public appendRight(svgs: SVGGraphicsElement[]) { + return this.append(this.width, 0, svgs); + } + + public appendBottom(svgs: SVGGraphicsElement[]) { + return this.append(0, this.height, svgs); + } + + public store(filename: string, electronService: ElectronService) { + this.mainSVG.attr('height', this.height); + this.mainSVG.attr('width', this.width); + + const blob = optimize(this.mainSVG.node().outerHTML).data; + + const file = new Blob([blob], { + type: 'image/svg+xml', + }); + //filename = filename.endsWith('.svg') ? filename : filename + '.svg'; + electronService.showSaveDialog( + filename, + 'svg', + file, + 'Save svg', + 'Save svg' + ); + //saveAs(file, filename); + } + + set svg_width(width: number) { + this.width = width; + } + set svg_height(height: number) { + this.height = height; + } +} diff --git a/src/frontend/src/app/services/init.service.spec.ts b/src/frontend/src/app/services/init.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..55a7022f269817203e7d3dbe02eb7f7f303d1bb3 --- /dev/null +++ b/src/frontend/src/app/services/init.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { InitService } from './init.service'; + +describe('InitService', () => { + let service: InitService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(InitService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/init.service.ts b/src/frontend/src/app/services/init.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..f6e93ff1f00a52b8465f02267b97033d4e3d4bcb --- /dev/null +++ b/src/frontend/src/app/services/init.service.ts @@ -0,0 +1,41 @@ +import { Injectable } from '@angular/core'; +import { delay, retryWhen, take, tap } from 'rxjs/operators'; +import { BackendInfoService } from './backendInfoService/backend-info.service'; +import { BackendService } from './backendService/backend.service'; +import { ROUTES } from '../constants/backend_route_constants'; +import { ElectronService } from './electronService/electron.service'; + +export function initApp(initService: InitService) { + return (): Promise<any> => { + return initService.init(); + }; +} + +@Injectable({ + providedIn: 'root', +}) +export class InitService { + constructor( + private backendService: BackendService, + private backendInfoService: BackendInfoService, + private electronService: ElectronService + ) {} + + init = async () => { + let port = await this.electronService.getWSPort(); + console.log('got the port from electron API: ' + port); + this.changePort(port); + + return this.backendService + .getInfo() + .pipe(retryWhen((errors) => errors.pipe(delay(500), take(100)))) // wait for backend + .pipe(tap(() => this.backendInfoService.setRunning(true))) // set running status + .toPromise(); + }; + + changePort(port: number) { + ROUTES.BASE_URL = '127.0.0.1:' + port + '/'; + ROUTES.HTTP_BASE_URL = 'http://' + ROUTES.BASE_URL; + ROUTES.WS_HTTP_BASE_URL = 'ws://' + ROUTES.BASE_URL; + } +} diff --git a/src/frontend/src/app/services/ipcService/ipc.service.spec.ts b/src/frontend/src/app/services/ipcService/ipc.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..6c930fe0aa909e4a00ce4c673b17405f3f8340f1 --- /dev/null +++ b/src/frontend/src/app/services/ipcService/ipc.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { IpcService } from './ipc.service'; + +describe('IpcService', () => { + let service: IpcService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(IpcService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/ipcService/ipc.service.ts b/src/frontend/src/app/services/ipcService/ipc.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..9bf3031fb026b895a47eadbb95344accb6504846 --- /dev/null +++ b/src/frontend/src/app/services/ipcService/ipc.service.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@angular/core'; + +declare var electron: any; + +@Injectable({ + providedIn: 'root', +}) +export class IpcService { + private ipcRenderer = electron.ipcRenderer; + + constructor() {} + + public send(channel, data): void { + this.ipcRenderer.send(channel, data); + } + + public receive(channel, func: Function) { + this.ipcRenderer.on(channel, (event: any, ...args: any) => func(...args)); + } +} diff --git a/src/frontend/src/app/services/lazyLoadingService/lazy-loading.service.spec.ts b/src/frontend/src/app/services/lazyLoadingService/lazy-loading.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..d1036027441e9173016fe8166e6c7936aceb7bb2 --- /dev/null +++ b/src/frontend/src/app/services/lazyLoadingService/lazy-loading.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { LazyLoadingServiceService } from './lazy-loading.service'; + +describe('LazyLoadingServiceService', () => { + let service: LazyLoadingServiceService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LazyLoadingServiceService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/lazyLoadingService/lazy-loading.service.ts b/src/frontend/src/app/services/lazyLoadingService/lazy-loading.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..c623d9bb843e653fc411a6f7d1811268205c770d --- /dev/null +++ b/src/frontend/src/app/services/lazyLoadingService/lazy-loading.service.ts @@ -0,0 +1,122 @@ +import { ElementRef, Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class LazyLoadingServiceService { + private intersectionObserver: any; + + private variantMinerMapping: Map<any, Function> = new Map<any, Function>(); + private variantMinerIntersectionObserver: IntersectionObserver; + private mapping: Map<any, Function> = new Map<any, Function>(); + + private lpmExplorerMapping: Map<any, Function> = new Map<any, Function>(); + private lpmExplorerIntersectionObserver: IntersectionObserver; + + private initialize(rootElement: ElementRef): void { + const self = this; + this.intersectionObserver = new IntersectionObserver( + function (entries) { + for (let entry of entries) { + const callback = self.mapping.get(entry.target); + + if (callback !== undefined) { + callback(entry.isIntersecting); + } + } + }, + { + root: rootElement.nativeElement, + rootMargin: '2000px 2000px 2000px 2000px', + } + ); + } + + public destoryVariantMinerObserver() { + this.variantMinerIntersectionObserver = null; + } + + private initializeVariantMiner(rootElement: ElementRef) { + const self = this; + this.variantMinerIntersectionObserver = new IntersectionObserver( + function (entries) { + for (let entry of entries) { + const callback = self.variantMinerMapping.get(entry.target); + + if (callback !== undefined) { + callback(entry.isIntersecting); + } + } + }, + { + root: rootElement.nativeElement, + rootMargin: '2000px 2000px 2000px 2000px', + } + ); + } + + public addVariant( + variantElement: any, + rootElement: ElementRef, + callback: Function + ): void { + if ( + this.intersectionObserver === null || + this.intersectionObserver === undefined + ) { + this.initialize(rootElement); + } + + this.mapping.set(variantElement, callback); + this.intersectionObserver.observe(variantElement); + } + + public addSubPattern( + variantElement: any, + rootElement: ElementRef, + callback: Function + ): void { + if ( + this.variantMinerIntersectionObserver === null || + this.variantMinerIntersectionObserver === undefined + ) { + this.initializeVariantMiner(rootElement); + } + + this.variantMinerMapping.set(variantElement, callback); + this.variantMinerIntersectionObserver.observe(variantElement); + } + + public destoryLpmExplorerObserver() { + this.lpmExplorerIntersectionObserver = null; + this.lpmExplorerMapping = new Map<any, Function>(); + } + + public initializeLpmExplorer(rootElement: ElementRef) { + const self = this; + this.lpmExplorerIntersectionObserver = new IntersectionObserver( + function (entries) { + for (let entry of entries) { + const callback = self.lpmExplorerMapping.get(entry.target); + + if (callback !== undefined) { + callback(entry.isIntersecting); + } + } + }, + { + root: rootElement.nativeElement, + rootMargin: '2000px 2000px 2000px 2000px', + } + ); + + this.lpmExplorerMapping.forEach((callback, element) => { + this.lpmExplorerIntersectionObserver.observe(element); + }); + } + + public addLpm(elem: any, callback: Function): void { + this.lpmExplorerMapping.set(elem, callback); + this.intersectionObserver.observe(elem); + } +} diff --git a/src/frontend/src/app/services/loadingOverlayService/loading-overlay.service.spec.ts b/src/frontend/src/app/services/loadingOverlayService/loading-overlay.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..d8d949f55158c8ec1bdf672126d7a743c58df55f --- /dev/null +++ b/src/frontend/src/app/services/loadingOverlayService/loading-overlay.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { LoadingOverlayService } from './loading-overlay.service'; + +describe('LoadingOverlayService', () => { + let service: LoadingOverlayService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LoadingOverlayService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/loadingOverlayService/loading-overlay.service.ts b/src/frontend/src/app/services/loadingOverlayService/loading-overlay.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..9ccf0ffa1ccfc61ad43ae43c6f698f6d9771829e --- /dev/null +++ b/src/frontend/src/app/services/loadingOverlayService/loading-overlay.service.ts @@ -0,0 +1,23 @@ +import { EventEmitter, Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class LoadingOverlayService { + public loadingText = ''; + public loadingInProgress = false; + + loadingInProgressEvent = new EventEmitter(); + + public showLoader(text = '') { + this.loadingText = text; + this.loadingInProgress = true; + this.loadingInProgressEvent.emit(this.loadingInProgress); + } + + public hideLoader() { + this.loadingInProgress = false; + this.loadingText = ''; + this.loadingInProgressEvent.emit(this.loadingInProgress); + } +} diff --git a/src/frontend/src/app/services/logExportService/log-export.service.spec.ts b/src/frontend/src/app/services/logExportService/log-export.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..ca676b2f06795ae0dfa5d02683e1398c2858f85b --- /dev/null +++ b/src/frontend/src/app/services/logExportService/log-export.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { LogExportService } from './log-export.service'; + +describe('LogExportService', () => { + let service: LogExportService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LogExportService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/logExportService/log-export.service.ts b/src/frontend/src/app/services/logExportService/log-export.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..bb733c50cdf00a13ecd398cebcf0e10b641dd53b --- /dev/null +++ b/src/frontend/src/app/services/logExportService/log-export.service.ts @@ -0,0 +1,81 @@ +import { Injectable } from '@angular/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { LogExporterDialogComponent } from 'src/app/components/log-exporter-dialog/log-exporter-dialog/log-exporter-dialog.component'; +import { LogExportConfig } from 'src/app/objects/LogExportConfig/LogExportConfig'; +import { VariantSelectionMethod } from 'src/app/objects/VariantSelectionMethod'; +import { BackendService } from '../backendService/backend.service'; +import { ElectronService } from '../electronService/electron.service'; +import { take } from 'rxjs/operators'; +import { VariantService } from '../variantService/variant.service'; +import { InfixType } from 'src/app/objects/Variants/infix_selection'; + +@Injectable({ + providedIn: 'root', +}) +export class LogExportService { + constructor( + private backendService: BackendService, + private variantService: VariantService, + private modalService: NgbModal, + private electronService: ElectronService + ) {} + + showLogExportDialog() { + this.modalService + .open(LogExporterDialogComponent, { size: 'lg' }) + .result.then( + (config: LogExportConfig) => this.exportLog(config), + () => {} + ); + } + + exportLog(config: LogExportConfig) { + const variants = this.variantService.variants; + const bids = variants + .filter((variant) => { + switch (config.variantSelectionMethod) { + case VariantSelectionMethod.ALL: + return true; + + case VariantSelectionMethod.SELECTED: + return variant.isSelected; + + case VariantSelectionMethod.FITTING: + return variant.deviations == 0; + + case VariantSelectionMethod.NON_FITTING: + return variant.deviations > 0; + + case VariantSelectionMethod.DISPLAYED: + return variant.isDisplayed; + } + }) + .filter( + (variant) => !variant.userDefined || config.includeUserCreatedVariants + ) + .filter( + (variant) => + variant.infixType == InfixType.NOT_AN_INFIX || + config.includeTraceFragments + ) + .map((variant) => variant.bid); + + this.backendService + .exportEventLog( + bids, + config.sequentializeVariants, + config.exportAsIntervalLog, + config.includeOriginalLogInfo + ) + .pipe(take(1)) + .subscribe((blob) => { + this.electronService.showSaveDialog( + 'log', + 'xes', + blob, + 'Save event log', + 'Export event log' + ); + }); + } +} diff --git a/src/frontend/src/app/services/logService/log.service.spec.ts b/src/frontend/src/app/services/logService/log.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..4a99f772734eb6601ac51af96d56ca47b2489b39 --- /dev/null +++ b/src/frontend/src/app/services/logService/log.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { LogService } from './log.service'; + +describe('LogService', () => { + let service: LogService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LogService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/logService/log.service.ts b/src/frontend/src/app/services/logService/log.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3a832285259651c39c423f5e0b4f8e0630a3cc8 --- /dev/null +++ b/src/frontend/src/app/services/logService/log.service.ts @@ -0,0 +1,272 @@ +import { ColorMapService } from './../colorMapService/color-map.service'; +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { TimeUnit } from 'src/app/objects/TimeUnit'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { addVariantInformation } from '../variantService/variant-transformation'; +import { LogModification } from 'src/app/objects/LogModification'; + +@Injectable({ + providedIn: 'root', +}) +export class LogService { + [x: string]: any; + constructor(private colorMapService: ColorMapService) {} + + logModifications: LogModification[] = []; + + variants: Variant[]; + + public performanceInfoAvailable = false; + private _timeGranularity: BehaviorSubject<TimeUnit> = new BehaviorSubject( + TimeUnit.SEC + ); + + private _numberFittingTraces: number = undefined; + private _numberFittingVariants: number = undefined; + private _totalNumberTraces: number = 0; + private _totalNumberVariants: number = 0; + + private _logStatistics = new BehaviorSubject<LogStats>( + new LogStats( + this._numberFittingTraces, + this._numberFittingVariants, + this._totalNumberTraces, + this._totalNumberVariants + ) + ); + + get logStatistics$(): Observable<LogStats> { + return this._logStatistics.asObservable(); + } + + set logStatistics(logStats: LogStats) { + this._logStatistics.next(logStats); + } + + get logStatistics(): LogStats { + return this._logStatistics.getValue(); + } + + public update_log_stats( + numberFittingTraces: number = null, + numberFittingVariants: number = null, + totalNumberTraces: number = null, + totalNumberVariants: number = null + ): void { + if (numberFittingTraces) this._numberFittingTraces = numberFittingTraces; + if (numberFittingVariants) + this._numberFittingVariants = numberFittingVariants; + if (totalNumberTraces) this._totalNumberTraces = totalNumberTraces; + if (totalNumberVariants) this._totalNumberVariants = totalNumberVariants; + + this.logStatistics = new LogStats( + this._numberFittingTraces, + this._numberFittingVariants, + this._totalNumberTraces, + this._totalNumberVariants + ); + } + + // Runs Code that should be run everytime the event log changes + private eventLogChanged(): void { + this.colorMapService.createColorMap(Object.keys(this.activitiesInEventLog)); + } + + private _logGranularity: BehaviorSubject<TimeUnit> = new BehaviorSubject( + TimeUnit.SEC + ); + + public get logGranularity$(): Observable<TimeUnit> { + return this._logGranularity.asObservable(); + } + + public get logGranularity(): TimeUnit { + return this._logGranularity.value; + } + + public set logGranularity(value: TimeUnit) { + this._logGranularity.next(value); + } + + private _loadedEventLog = new BehaviorSubject<string>(''); + + get loadedEventLog$(): Observable<string> { + return this._loadedEventLog.asObservable(); + } + + get loadedEventLog(): string { + return this._loadedEventLog.value; + } + + set loadedEventLog(name: string) { + this.eventLogChanged(); + + this._loadedEventLog.next(name); + } + + private _activitiesInEventLog = new BehaviorSubject<Set<string>>(new Set()); + + get activitiesInEventLog$(): Observable<any> { + return this._activitiesInEventLog.asObservable(); + } + + set activitiesInEventLog(activities: any) { + this._activitiesInEventLog.next(activities); + } + + get activitiesInEventLog(): any { + return this._activitiesInEventLog.getValue(); + } + + public deleteActivityInEventLog(activityName: string): any { + let activities = {}; + for (let activity in this.activitiesInEventLog) { + if (activity !== activityName) { + activities[activity] = this.activitiesInEventLog[activity]; + } + } + + this.activitiesInEventLog = activities; + } + + //edited + public addActivityInEventLog(activityName: string): any { + let activities = {}; + for (let activity in this.activitiesInEventLog) { + activities[activity] = this.activitiesInEventLog[activity]; + } + activities[activityName] = activityName; + this.activitiesInEventLog = activities; + } + + public renameActivitiesInEventLog( + activityName: string, + newActivityName: string + ): any { + // modifying related data in shared data service. Similar to processEventLog in backend service + // relabeling activities + + let activityNameMapping: Map<string, string> = new Map(); + for (let activity in this.activitiesInEventLog) { + activityNameMapping.set(activity, activity); + } + + activityNameMapping.set(activityName, newActivityName); + + let activities = {}; + for (let activity in this.activitiesInEventLog) { + let newActivityName = activityNameMapping.get(activity); + if (!activities[newActivityName]) { + activities[newActivityName] = this.activitiesInEventLog[activity]; + } else { + activities[newActivityName] += this.activitiesInEventLog[activity]; + } + } + + if (this.endActivitiesInEventLog.delete(activityName)) + this.endActivitiesInEventLog.add(newActivityName); + if (this.startActivitiesInEventLog.delete(activityName)) + this.startActivitiesInEventLog.add(newActivityName); + + this.activitiesInEventLog = activities; + } + + public get timeGranularity$(): Observable<TimeUnit> { + return this._timeGranularity.asObservable(); + } + public set timeGranularity(value: TimeUnit) { + this._timeGranularity.next(value); + } + + public get timeGranularity() { + return this._timeGranularity.getValue(); + } + + private _startActivitiesInEventLog = new BehaviorSubject<Set<string>>( + new Set() + ); + + get startActivitiesInEventLog$(): Observable<Set<string>> { + return this._startActivitiesInEventLog.asObservable(); + } + + set startActivitiesInEventLog(activities: Set<string>) { + this._startActivitiesInEventLog.next(activities); + } + + get startActivitiesInEventLog(): Set<string> { + return this._startActivitiesInEventLog.getValue(); + } + + private _endActivitiesInEventLog = new BehaviorSubject<Set<string>>( + new Set() + ); + + get endActivitiesInEventLog$(): Observable<Set<string>> { + return this._endActivitiesInEventLog.asObservable(); + } + + set endActivitiesInEventLog(activities: Set<string>) { + this._endActivitiesInEventLog.next(activities); + } + + get endActivitiesInEventLog(): Set<string> { + return this._endActivitiesInEventLog.getValue(); + } + + public computeLogStats(variants: Variant[]): void { + const totalNumberTraces = variants + .map((v) => v.count) + .reduce((a, b) => a + b); + + variants.forEach((v) => { + v.percentage = Number.parseFloat( + ((v.count / totalNumberTraces) * 100).toFixed(2) + ); + }); + + const numberFittingVariants = 0; + const numberFittingTraces = 0; + const totalNumberVariants = variants.length; + + this.update_log_stats( + numberFittingTraces, + numberFittingVariants, + totalNumberTraces, + totalNumberVariants + ); + } + + public processEventLog(res, filePath = null) { + this.activitiesInEventLog = res['activities']; + this.startActivitiesInEventLog = new Set(res['startActivities']); + this.endActivitiesInEventLog = new Set(res['endActivities']); + this.variants = addVariantInformation(res['variants']); + this.computeLogStats(this.variants); + this.loadedEventLog = filePath; + this.performanceInfoAvailable = true; + this.timeGranularity = res['timeGranularity']; + this.logGranularity = res['timeGranularity']; + this.logModifications = []; + } +} + +export class LogStats { + numberFittingTraces: number; + numberFittingVariants: number; + totalNumberTraces: number; + totalNumberVariants: number; + + constructor( + numberFittingTraces: number, + numberFittingVariants: number, + totalNumberTraces: number, + totalNumberVariants: number + ) { + this.numberFittingTraces = numberFittingTraces; + this.numberFittingVariants = numberFittingVariants; + this.totalNumberTraces = totalNumberTraces; + this.totalNumberVariants = totalNumberVariants; + } +} diff --git a/src/frontend/src/app/services/lpmService/lpm.service.spec.ts b/src/frontend/src/app/services/lpmService/lpm.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..2108a3736011ad3cc81479b367ea43c16d5b0c58 --- /dev/null +++ b/src/frontend/src/app/services/lpmService/lpm.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { LpmService } from './lpm.service'; + +describe('LpmService', () => { + let service: LpmService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LpmService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/lpmService/lpm.service.ts b/src/frontend/src/app/services/lpmService/lpm.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..c448fdb31916d0c7addb81bc61b14bb79cea08e1 --- /dev/null +++ b/src/frontend/src/app/services/lpmService/lpm.service.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { LocalProcessModelWithPatterns } from 'src/app/objects/LocalProcessModelWithPatterns'; +import { LpmMetrics } from 'src/app/objects/LpmMetrics'; + +@Injectable({ + providedIn: 'root', +}) +export class LpmService { + private _localProcessModels = new BehaviorSubject< + LocalProcessModelWithPatterns[] + >([]); + + private _lpmMetrics = new BehaviorSubject<LpmMetrics>(null); + + set localProcessModels(lpms: LocalProcessModelWithPatterns[]) { + this._localProcessModels.next(lpms); + } + + get localProcessModels$(): Observable<LocalProcessModelWithPatterns[]> { + return this._localProcessModels.asObservable(); + } + + set lpmMetrics(metrics: LpmMetrics) { + this._lpmMetrics.next(metrics); + } + + get lpmMetrics$(): Observable<LpmMetrics> { + return this._lpmMetrics.asObservable(); + } +} diff --git a/src/frontend/src/app/services/performance-color-scale.service.ts b/src/frontend/src/app/services/performance-color-scale.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..f876f4b93d7287267a297163469a1e1dd0ef95cd --- /dev/null +++ b/src/frontend/src/app/services/performance-color-scale.service.ts @@ -0,0 +1,202 @@ +import { Injectable } from '@angular/core'; +import { ProcessTree } from '../objects/ProcessTree/ProcessTree'; +import { PerformanceService } from './performance.service'; +import { SharedDataService } from './sharedDataService/shared-data.service'; +import * as d3 from 'd3'; +import { BehaviorSubject } from 'rxjs'; +import { COLORS_TEAL } from '../objects/Colors'; +import { ColorMap } from '../objects/ColorMap'; + +@Injectable({ + providedIn: 'root', +}) +export class ModelPerformanceColorScaleService { + public static readonly COLOR_MAPS: { + key: string; + name: string; + description: string; + longDescription: string; + }[] = [ + { + key: 'compareNodes', + name: 'All Nodes', + description: + 'Compare the performance of nodes to other nodes in the same tree.', + longDescription: `This mode allows to compare the performance of nodes to all other nodes. + There is one color map for all nodes and variants, the lower/upper bound of the scale is the minimum/maximum performance value among all computed performance values.`, + }, + { + key: 'compareVariants', + name: 'Variant Comparison', + description: + 'Compare the performance of nodes to the performance of the same node in other variants.', + longDescription: `This mode allows to compare the performance of a node to the performance of the same node in other variants. + Each node has it's own color map where the lower/upper bound of the scale is the minimum/maximum performance of that node among all variants.`, + }, + ]; + + public selectedColorScale = { + mode: 'compareNodes', + statistic: 'mean', + performanceIndicator: 'service_time', + }; + + variantComparisonColorScale; + nodeComparisonColorScale; + + currentColorScale = new BehaviorSubject<Map<number, any>>(undefined); + + constructor( + private sharedDataService: SharedDataService, + private performanceService: PerformanceService + ) { + performanceService.newValues.subscribe((n) => { + if (n) { + this.variantComparisonColorScale = + this.computeVariantComparisonColorScale('service_time', 'mean'); + this.nodeComparisonColorScale = this.computeNodeComparisonColorScale( + 'service_time', + 'mean' + ); + this.updateCurrentColorScale(); + } + }); + } + + public updateCurrentColorScale(): void { + this.currentColorScale.next( + this.computeColorScale( + this.selectedColorScale.mode, + this.selectedColorScale.performanceIndicator, + this.selectedColorScale.statistic + ) + ); + this.variantComparisonColorScale = this.computeVariantComparisonColorScale( + this.selectedColorScale.performanceIndicator, + this.selectedColorScale.statistic + ); + } + + public getColorScale() { + return this.currentColorScale.value; + } + + public getNodeComparisonColorScale() { + return this.nodeComparisonColorScale; + } + + public getVariantComparisonColorScale() { + return this.variantComparisonColorScale; + } + + private computeColorScale( + selection: string, + performanceValue: string, + statistic: string + ) { + switch (selection) { + case 'compareVariants': + return this.computeVariantComparisonColorScale( + performanceValue, + statistic + ); + case 'compareNodes': + return this.computeNodeComparisonColorScale( + performanceValue, + statistic + ); + } + } + + private computeNodeComparisonColorScale( + performanceValue = 'service_time', + statistic = 'mean' + ) { + const colorScales = new Map<number, ColorMap>(); + + const values = this.getAllAllValues(); + const min = Math.min(...values); + const max = Math.max(...values); + + let thresholds = [...Array(COLORS_TEAL.length - 1).keys()] + .map((i) => i + 1) + .map((i) => min + (i / COLORS_TEAL.length) * (max - min)); + + const colorScale = d3 + .scaleThreshold<any, any, any>() + .domain(thresholds) + .range(COLORS_TEAL); + + const leafNodes = getAllNodes( + this.performanceService.mergedTreePerformance + ); + leafNodes.forEach((n) => colorScales.set(n.id, new ColorMap(colorScale))); + + return colorScales; + } + + private computeVariantComparisonColorScale( + performanceValue = 'service_time', + statistic = 'mean' + ) { + const colorScales = new Map<number, ColorMap>(); + this.performanceService.allValues.forEach((performanceValues, treeId) => { + const values = Array.from(performanceValues.values()) + .filter((p) => p[performanceValue]) + .map((p) => p[performanceValue][statistic]); + const min = Math.min(...values); + const max = Math.max(...values); + + let thresholds = [...Array(COLORS_TEAL.length - 1).keys()] + .map((i) => i + 1) + .map((i) => min + (i / COLORS_TEAL.length) * (max - min)); + + const colorScale = d3 + .scaleThreshold<any, any, any>() + .domain(thresholds) + .range(COLORS_TEAL); + + colorScales.set(treeId, new ColorMap(colorScale)); + }); + return colorScales; + } + + public getAllAllValues() { + let allValues = []; + this.performanceService.allValues.forEach((pValues, treeId) => { + const values = Array.from(pValues.values()) + .filter((p) => p[this.selectedColorScale.performanceIndicator]) + .map( + (p) => + p[this.selectedColorScale.performanceIndicator][ + this.selectedColorScale.statistic + ] + ); + allValues.push(...values); + }); + return allValues; + } +} + +export function getLeafNodes(tree: ProcessTree): ProcessTree[] { + if (tree.label && tree.children?.length === 0) { + return [tree]; + } + return tree.children.map((t) => getLeafNodes(t)).flat(); +} + +export function getAllNodes(tree: ProcessTree): ProcessTree[] { + return [tree].concat(tree.children.map((t) => getAllNodes(t)).flat()); +} + +export function getAllTreeValues( + tree: ProcessTree, + performanceValue: string, + statistic: string +): number[] { + const leafNodes = getAllNodes(tree); + return leafNodes + .map((t) => t.performance) + .filter((p) => p && p[performanceValue]) + .map((p) => p[performanceValue][statistic]); +} diff --git a/src/frontend/src/app/services/performance.service.ts b/src/frontend/src/app/services/performance.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..a02d15c8e56183b6b517dbb32d55cce5da849bba --- /dev/null +++ b/src/frontend/src/app/services/performance.service.ts @@ -0,0 +1,253 @@ +import { Injectable } from '@angular/core'; +import { + ProcessTree, + TreePerformance, +} from '../objects/ProcessTree/ProcessTree'; +import { BackendService } from './backendService/backend.service'; +import { BehaviorSubject, Subscription } from 'rxjs'; +import { HumanizeDurationPipe } from '../pipes/humanize-duration.pipe'; +import { ProcessTreeService } from './processTreeService/process-tree.service'; +import { VariantService } from './variantService/variant.service'; +import { Variant } from '../objects/Variants/variant'; +import { ModelViewModeService } from './viewModeServices/model-view-mode.service'; +import { ViewMode } from '../objects/ViewMode'; + +@Injectable({ + providedIn: 'root', +}) +export class PerformanceService { + mergedTreePerformance: ProcessTree; + + // key is variant, value is process tree + variantsTreePerformance: Map<Variant, ProcessTree> = new Map< + Variant, + ProcessTree + >(); + + public availablePerformances: Set<Variant> = new Set<Variant>(); + + // key is id of node, value is map with performance stats for each variant + allValues: Map<number, Map<Variant, TreePerformance>> = new Map< + number, + Map<Variant, TreePerformance> + >(); + + allValuesMean: Map<number, TreePerformance> = new Map< + number, + TreePerformance + >(); + + // colorScale for each tree node; + private activeTreePerformances: Set<Variant> = new Set<Variant>(); + newValues: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); + calculationInProgress = new Set<Variant>(); + latestRequest: Subscription; + fitness = new Map<Variant, number>(); + + private currentPt: ProcessTree; + + constructor( + private variantService: VariantService, + private backendService: BackendService, + private processTreeService: ProcessTreeService, + private modelViewModeService: ModelViewModeService + ) { + this.currentPt = processTreeService.currentDisplayedProcessTree; + + this.variantService.variants$.subscribe((_variants) => { + this.clear(); + }); + processTreeService.currentDisplayedProcessTree$.subscribe((pt) => { + if (pt) { + this.processTreeService.selectedTree = pt; + } else { + this.clear(); + this.processTreeService.selectedTree = undefined; + this.currentPt = undefined; + return; + } + + if ( + !this.currentPt?.equals(pt) || + (this.currentPt.equals(pt) && + !pt.performance && + this.currentPt.performance) + ) { + this.clear(); + this.currentPt = pt; + } + }); + + this.modelViewModeService.viewMode$.subscribe((viewMode) => { + if ( + viewMode === ViewMode.PERFORMANCE && + this.anyTreePerformanceActive() + ) { + this.showTreePerformance(); + } + }); + } + + private updateTreePerformance(variants: Variant[]): void { + this.latestRequest?.unsubscribe(); + + this.latestRequest = this.backendService + .getTreePerformance(variants.map((v) => v.bid)) + .subscribe( + (performance) => { + this.mergedTreePerformance = ProcessTree.fromObj( + performance.merged_performance_tree + ); + + this.allValues.clear(); + + variants.forEach((variant, i) => { + const pt = performance.variants_tree_performance[i]; + + this.fitness.set(variant, performance.fitness_values[i]); + this.variantsTreePerformance.set(variant, pt); + this.calculationInProgress.delete(variant); + this.collectPerformance(pt, variant, this.allValues); + this.activeTreePerformances.add(variant); + }); + + this.allValuesMean.clear(); + this.setMeanPerformanceMap(this.mergedTreePerformance); + + this.newValues.next(true); + + this.processTreeService.currentDisplayedProcessTree = + performance.merged_performance_tree; + + this.showTreePerformance(); + }, + (error) => { + variants.forEach((v) => this.calculationInProgress.delete(v)); + } + ); + } + + public hideTreePerformance() { + this.modelViewModeService.viewMode = ViewMode.STANDARD; + this.activeTreePerformances.clear(); + } + + public setVariantsPerformance( + variants: Variant[], + performanceTrees: ProcessTree[] + ): void { + for (let i = 0; i < variants.length; i++) { + this.variantsTreePerformance.set(variants[i], performanceTrees[i]); + } + + variants.forEach((variant, i) => { + const tree = performanceTrees[i]; + this.collectPerformance(tree, variant, this.allValues); + }); + } + + // Stores performance values for each tree node in the performances map under the given variantIdx + collectPerformance( + vp: ProcessTree, + variant: Variant, + performances: Map<number, Map<Variant, TreePerformance>> + ): Map<number, Map<Variant, TreePerformance>> { + if (!performances.has(vp.id)) { + performances.set(vp.id, new Map<Variant, TreePerformance>()); + } + performances.get(vp.id).set(variant, vp.performance); + + for (const child of vp.children) { + this.collectPerformance(child, variant, performances); + } + return performances; + } + + public showTreePerformance() { + if ( + this.processTreeService.currentDisplayedProcessTree !== + this.mergedTreePerformance + ) + this.processTreeService.currentDisplayedProcessTree = + this.mergedTreePerformance; + if (this.modelViewModeService.viewMode !== ViewMode.PERFORMANCE) + this.modelViewModeService.viewMode = ViewMode.PERFORMANCE; + } + + public toggleTreePerformance() { + if (this.anyTreePerformanceActive()) this.hideTreePerformance(); + else this.showTreePerformance(); + } + + private stopRunningRequest() { + this.latestRequest.unsubscribe(); + this.calculationInProgress.clear(); + } + + private clear(): void { + this.mergedTreePerformance = undefined; + this.variantsTreePerformance.clear(); + this.availablePerformances.clear(); + this.allValues.clear(); + this.allValuesMean.clear(); + this.activeTreePerformances.clear(); + this.calculationInProgress.clear(); + this.processTreeService.selectedTree = undefined; + + this.modelViewModeService.viewMode = ViewMode.STANDARD; + } + + public addToTreePerformance(variant: Variant) { + if ( + !this.activeTreePerformances.has(variant) && + !this.calculationInProgress.has(variant) + ) { + this.calculationInProgress.add(variant); + const variantsCombined: Variant[] = Array.from( + new Set([...this.activeTreePerformances, ...this.calculationInProgress]) + ); + this.updateTreePerformance(Array.from(variantsCombined)); + } else { + this.showTreePerformance(); + } + } + + public removeFromTreePerformance(variant: Variant) { + const wasActive = this.activeTreePerformances.delete(variant); + const wasInProgress = this.calculationInProgress.delete(variant); + if (wasActive || wasInProgress) { + if (this.activeTreePerformances.size == 0) this.hideTreePerformance(); + else { + const variantsCombined: Variant[] = Array.from( + new Set([ + ...this.activeTreePerformances, + ...this.calculationInProgress, + ]) + ); + this.updateTreePerformance(Array.from(variantsCombined)); + } + } + } + + private setMeanPerformanceMap(tree: ProcessTree): void { + this.allValuesMean.set(tree.id, tree.performance); + tree.children.forEach((node) => this.setMeanPerformanceMap(node)); + } + + public isTreePerformanceActive(v: Variant) { + return this.activeTreePerformances.has(v); + } + + public anyTreePerformanceActive() { + return this.activeTreePerformances.size > 0; + } + + public isTreePerformanceCalcInProgress(v: Variant) { + return this.calculationInProgress.has(v); + } + + public isTreePerformanceFitting(v: Variant) { + const fitness = this.fitness.get(v); + return fitness == undefined || fitness == 1; + } +} diff --git a/src/frontend/src/app/services/polygon-drawing.service.ts b/src/frontend/src/app/services/polygon-drawing.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..75f4d5f93d59b183c875a932e43edc9856267ea9 --- /dev/null +++ b/src/frontend/src/app/services/polygon-drawing.service.ts @@ -0,0 +1,133 @@ +import { VARIANT_Constants } from './../constants/variant_element_drawer_constants'; +import { ElementRef, Injectable } from '@angular/core'; +import { Selection } from 'd3'; +import { PolygonGeneratorService } from './polygon-generator.service'; +import * as d3 from 'd3'; +import { LeafNode } from '../objects/Variants/variant_element'; +import { textColorForBackgroundColor } from '../utils/render-utils'; + +@Injectable({ + providedIn: 'root', +}) +export class PolygonDrawingService { + private textLengthCache = new Map<string, number>(); + + private variantExplorerDiv: HTMLElement; + private tooltipContainer: Selection<any, any, any, any>; + private tooltipInner: Selection<any, any, any, any>; + + constructor(private polygonService: PolygonGeneratorService) {} + + public setElementRefereneces( + variantExplorerRef: ElementRef<HTMLDivElement>, + tooltipContainerRef: ElementRef<HTMLDivElement> + ) { + this.variantExplorerDiv = variantExplorerRef.nativeElement; + this.tooltipContainer = d3.select(tooltipContainerRef.nativeElement); + this.tooltipInner = d3.select( + tooltipContainerRef.nativeElement.firstChild as HTMLElement + ); + } + + public drawLegend( + elements: LeafNode[], + parent: Selection<any, any, any, any>, + colorMap: Map<string, string>, + textUnderLegend: string = 'Variants' + ): void { + let offsetY = VARIANT_Constants.LEGEND_MARGIN_Y + 20; + let offsetX = VARIANT_Constants.LEGEND_MARGIN_X; + let parent_width = 0; + + let width = Math.max(...elements.map((e) => e.getWidth(false, true))); + let height = elements[0].getHeight(); + + parent + .append('line') + .attr('x1', VARIANT_Constants.LEGEND_MARGIN_X) + .attr('x2', (VARIANT_Constants.MAX_OFFSETWIDTH + width).toString()) + .attr('y1', '20') + .attr('y2', '20') + .attr('stroke', 'black') + .attr('stroke-width', '1.5'); + + parent + .append('text') + .attr('x', VARIANT_Constants.LEGEND_MARGIN_X) + .attr('y', '15') + .attr('fill', 'black') + .attr('font-size', '15') + .insert('tspan') + .attr('height', '10') + .text('Activities'); + + for (let element of elements) { + const polygonPoints = this.polygonService.getPolygonPoints(width, height); + + let color = colorMap.get(element.activity[0]); + + const polygon = parent + .append('polygon') + .attr('points', polygonPoints) + .style('fill', color) + .style('stWroke', 'none') + .attr('transform', `translate(${offsetX}, ${offsetY})`); + + const activityText = parent + .append('text') + .attr('x', width / 2) + .attr('y', height / 2) + .attr('transform', `translate(${offsetX}, ${offsetY})`) + .attr('text-anchor', 'middle') + .attr('dominant-baseline', 'middle') + .attr('font-size', VARIANT_Constants.FONT_SIZE) + .attr('fill', textColorForBackgroundColor(color)); + + activityText + .append('tspan') + .attr('x', width / 2) + .attr('y', height / 2) + .text(element.activity[0]) + .attr( + 'height', + VARIANT_Constants.FONT_SIZE + VARIANT_Constants.MARGIN_Y + ); + + offsetX += width + VARIANT_Constants.LEGEND_MARGIN_X; + + if (offsetX >= VARIANT_Constants.MAX_OFFSETWIDTH) { + parent_width = Math.max(parent_width, offsetX); + offsetX = VARIANT_Constants.LEGEND_MARGIN_X; + offsetY += height + VARIANT_Constants.LEGEND_MARGIN_Y; + } + } + + offsetY = + offsetX === VARIANT_Constants.LEGEND_MARGIN_X + ? offsetY + : offsetY + height + VARIANT_Constants.LEGEND_MARGIN_Y; + + parent + .attr('width', parent_width) + .attr('height', offsetY + VARIANT_Constants.MARGIN_Y + 40); + + parent + .append('line') + .attr('x1', VARIANT_Constants.LEGEND_MARGIN_X) + .attr('x2', (VARIANT_Constants.MAX_OFFSETWIDTH + width).toString()) + .attr('y1', offsetY) + .attr('y2', offsetY) + .attr('stroke', 'black') + .attr('stroke-width', '1.5'); + + parent + .append('text') + .attr('x', VARIANT_Constants.LEGEND_MARGIN_X) + .attr('y', offsetY + 20) + .attr('fill', 'black') + .attr('font-size', '15') + .insert('tspan') + .attr('height', '10') + .text(textUnderLegend); + } +} diff --git a/src/frontend/src/app/services/polygon-generator.service.ts b/src/frontend/src/app/services/polygon-generator.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..9b2cf592e2c73756b2af5c1c6ea5e2d3ef0e6c3d --- /dev/null +++ b/src/frontend/src/app/services/polygon-generator.service.ts @@ -0,0 +1,39 @@ +import { VARIANT_Constants } from './../constants/variant_element_drawer_constants'; +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class PolygonGeneratorService { + constructor() {} + + private cache = new Map<string, string>(); + + getPolygonPoints(width: number, height: number): string { + let key = `${width},${height}`; + if (this.cache.has(key)) { + return this.cache.get(key); + } + + let x = 0, + y = 0; + let headLength = + Math.tan((VARIANT_Constants.ARROW_HEAD_ANGLE / 360) * Math.PI * 2) * + (height / 2); + + width -= headLength; + + let points = []; + points.push(`${x},${y}`); // Top left + points.push(`${x + width},${y}`); // Top right + points.push(`${x + width + headLength},${y + height / 2}`); // Arrow Head + points.push(`${x + width},${y + height}`); // Bottom right + points.push(`${x},${y + height}`); // Bottom left + points.push(`${x + headLength},${y + height / 2}`); // Arrow feather + + let str = points.join(' '); + this.cache.set(key, str); + + return str; + } +} diff --git a/src/frontend/src/app/services/processTreeService/process-tree.service.spec.ts b/src/frontend/src/app/services/processTreeService/process-tree.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..0cb6ec8735cebd86a449e56b556946747101cd4e --- /dev/null +++ b/src/frontend/src/app/services/processTreeService/process-tree.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ProcessTreeService } from './process-tree.service'; + +describe('ProcessTreeService', () => { + let service: ProcessTreeService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ProcessTreeService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/processTreeService/process-tree.service.ts b/src/frontend/src/app/services/processTreeService/process-tree.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..582ea18ff211b5af0d1f1c8cd58e8861a1193d80 --- /dev/null +++ b/src/frontend/src/app/services/processTreeService/process-tree.service.ts @@ -0,0 +1,546 @@ +import { LogService } from 'src/app/services/logService/log.service'; +import { Injectable } from '@angular/core'; +import { Observable, BehaviorSubject } from 'rxjs'; + +import Swal from 'sweetalert2'; +import { + ProcessTree, + ProcessTreeOperator, +} from 'src/app/objects/ProcessTree/ProcessTree'; +import { + markNodeAsFrozen, + markNodeAsNonFrozen, +} from 'src/app/objects/ProcessTree/utility-functions/process-tree-freeze'; +import { + checkForLoadedTreeIntegrity, + processTreesEqual, +} from 'src/app/objects/ProcessTree/utility-functions/process-tree-integrity-check'; +import { + renameProcessTreeLeafs, + getSetOfActivitiesInProcessTree, +} from 'src/app/objects/ProcessTree/utility-functions/process-tree-transform'; +import { + delete_subtree, + NodeInsertionStrategy, + createNewRandomNode, + insertNode, +} from 'src/app/objects/ProcessTree/utility-functions/process-tree-edit-tree'; +import { computeLeafNodeWidth } from 'src/app/utils/render-utils'; + +@Injectable({ + providedIn: 'root', +}) +export class ProcessTreeService { + constructor(private logService: LogService) { + this.logService.activitiesInEventLog$.subscribe((activites) => { + this.nodeWidthCache = computeLeafNodeWidth( + Object.keys(activites), + this.nodeWidthCache + ); + }); + + this.logService.loadedEventLog$.subscribe((log) => { + if (log && log !== 'preload') { + this.nodeWidthCache = computeLeafNodeWidth( + Object.keys(this.logService.activitiesInEventLog), + this.nodeWidthCache + ); + } + }); + } + + private _selectedRootNodeID = new BehaviorSubject<number>(null); + + get selectedRootNodeID$(): Observable<number> { + return this._selectedRootNodeID.asObservable(); + } + + set selectedRootNodeID(node: number) { + this._selectedRootNodeID.next(node); + } + + get selectedRootNodeID(): number { + return this._selectedRootNodeID.getValue(); + } + + private _nodeWidthCache = new BehaviorSubject<Map<string, number>>( + new Map<string, number>() + ); + + get nodeWidthCache$(): Observable<Map<string, number>> { + return this._nodeWidthCache.asObservable(); + } + + get nodeWidthCache() { + return this._nodeWidthCache.getValue(); + } + + set nodeWidthCache(map: Map<string, number>) { + this._nodeWidthCache.next(map); + } + + private _correctTreeSyntax = new BehaviorSubject<boolean>(false); + + get correctTreeSyntax$(): Observable<boolean> { + return this._correctTreeSyntax.asObservable(); + } + + set correctTreeSyntax(flag: boolean) { + this._correctTreeSyntax.next(flag); + } + + get correctTreeSyntax(): boolean { + return this._correctTreeSyntax.getValue(); + } + + private _currentTreeString = new BehaviorSubject<string>(''); + + get currentTreeString$(): Observable<string> { + return this._currentTreeString.asObservable(); + } + + set currentTreeString(syntaxObj: any) { + this._currentTreeString.next(syntaxObj); + } + + get currentTreeString() { + return this._currentTreeString.getValue(); + } + + private _selectedTree: BehaviorSubject<ProcessTree> = + new BehaviorSubject<ProcessTree>(undefined); + + get selectedTree$(): Observable<any> { + return this._selectedTree.asObservable(); + } + + get selectedTree(): any { + return this._selectedTree.getValue(); + } + + set selectedTree(pt: ProcessTree) { + this._selectedTree.next(pt); + } + + private _currentDisplayedProcessTree = new BehaviorSubject<ProcessTree>(null); + + get currentDisplayedProcessTree$(): Observable<ProcessTree> { + return this._currentDisplayedProcessTree.asObservable(); + } + + get currentDisplayedProcessTree(): ProcessTree { + return this._currentDisplayedProcessTree.getValue(); + } + + private _activitiesInCurrentTree = new BehaviorSubject<Set<string>>( + new Set<string>() + ); + + private processTreeBuffer = new BehaviorSubject<ProcessTree>(null); + + get bufferedProcessTree() { + return this.processTreeBuffer.getValue(); + } + + public deleteActivityFromProcessTreeActivities(activityName: string): any { + if (this.activitiesInCurrentTree) { + this.activitiesInCurrentTree.delete(activityName); + } + } + + public renameActivityInProcessTree( + activityName: string, + newActivityName: string + ): any { + if ( + this.activitiesInCurrentTree && + this.activitiesInCurrentTree.delete(activityName) + ) + this.activitiesInCurrentTree.add(newActivityName); + + if (this.currentDisplayedProcessTree) { + this.currentDisplayedProcessTree = renameProcessTreeLeafs( + this.currentDisplayedProcessTree, + activityName, + newActivityName + ); + } + } + + get activitiesInCurrentTree$(): Observable<Set<string>> { + return this._activitiesInCurrentTree.asObservable(); + } + + get activitiesInCurrentTree(): Set<string> { + return this._activitiesInCurrentTree.getValue(); + } + + set activitiesInCurrentTree(activities) { + this._activitiesInCurrentTree.next(activities); + } + + set currentDisplayedProcessTree(tree: any) { + if (tree && !(tree instanceof ProcessTree)) { + tree = ProcessTree.fromObj(tree); + } + + this.activitiesInCurrentTree = getSetOfActivitiesInProcessTree(tree); + const activites = Object.keys(this.logService.activitiesInEventLog); + + if (checkForLoadedTreeIntegrity(tree, activites).size > 0) { + const unknownActivities = Array.from( + checkForLoadedTreeIntegrity(tree, activites) + ); + this.nodeWidthCache = computeLeafNodeWidth( + unknownActivities, + this.nodeWidthCache + ); + + Swal.fire({ + title: + '<tspan class = "text-warning">Current process tree contains unkown activites</tspan>', + html: + '<b>Error Message: </b><br>' + + '<code> The loaded tree contains activities \ + that do not appear in the currently loaded log.\ + </code> <br> <br> Unknown Activites: ' + + '<tspan class = "text-danger">' + + unknownActivities.join(', ') + + '</tspan>', + icon: 'warning', + showCloseButton: false, + showConfirmButton: false, + showCancelButton: true, + cancelButtonText: 'close', + }); + } + + this._currentDisplayedProcessTree.next(tree); + } + + public set_currentDisplayedProcessTree_with_Cache(tree: any) { + if (tree && !(tree instanceof ProcessTree)) { + tree = ProcessTree.fromObj(tree); + } + this._currentDisplayedProcessTree.next(tree); + this.activitiesInCurrentTree = getSetOfActivitiesInProcessTree(tree); + + // add activities in the tree to nodeWidthCache in processTreeService + this.nodeWidthCache = computeLeafNodeWidth( + Array.from(this.activitiesInCurrentTree), + this.nodeWidthCache + ); + + this.cacheCurrentTree(tree); + } + + previousTreeObjects: ProcessTree[] = []; + + private _treeCacheLength = new BehaviorSubject<number>(0); + private _treeCacheIndex = new BehaviorSubject<number>(0); + + get treeCacheLength$(): Observable<number> { + return this._treeCacheLength.asObservable(); + } + + set treeCacheLength(node: number) { + this._treeCacheLength.next(node); + } + + get treeCacheLength(): number { + return this._treeCacheLength.getValue(); + } + + get treeCacheIndex$(): Observable<number> { + return this._treeCacheIndex.asObservable(); + } + + set treeCacheIndex(node: number) { + this._treeCacheIndex.next(node); + } + + get treeCacheIndex(): number { + return this._treeCacheIndex.getValue(); + } + + cacheCurrentTree(root: ProcessTree): void { + if (processTreesEqual(root, this.previousTreeObjects[this.treeCacheIndex])) + return; + if (this.treeCacheIndex < this.previousTreeObjects.length - 1) { + // before change, undo was pressed --> remove newer versions since older version of process tree was changed + this.previousTreeObjects = this.previousTreeObjects.slice( + 0, + this.treeCacheIndex + 1 + ); + } + + const lastTreeObject = + this.previousTreeObjects[this.previousTreeObjects.length - 1]; + + if (root) { + if (lastTreeObject !== null) { + this.previousTreeObjects.push(root.copy(true)); + } else { + this.previousTreeObjects[this.previousTreeObjects.length - 1] = + root.copy(true); + this.treeCacheIndex--; + } + } else { + this.previousTreeObjects.push(null); + } + + if (this.treeCacheIndex) { + this.treeCacheIndex += 1; + } else { + this.treeCacheIndex = this.previousTreeObjects.length - 1; + } + + this.treeCacheLength = this.previousTreeObjects.length; + } + + getFrozenList(previousTree) { + let frozen_list = []; + if (previousTree.frozen) { + frozen_list.push(previousTree.id); + } + for (const child of previousTree.children) { + frozen_list = frozen_list.concat(this.getFrozenList(child)); + } + return frozen_list; + } + + getFrozenTree(treeToLoad, previousTree) { + let frozen_list = this.getFrozenList(previousTree); + var nodesToCheck = []; + nodesToCheck.push(treeToLoad); + while (nodesToCheck.length > 0) { + let nodeToCheck = nodesToCheck.pop(); + if (frozen_list.includes(nodeToCheck.id)) { + markNodeAsFrozen(nodeToCheck); + } + nodesToCheck = nodesToCheck.concat(nodeToCheck.children); + } + } + + undo() { + if ( + this.treeCacheIndex && + this.treeCacheIndex > 0 && + this.previousTreeObjects.length > 1 + ) { + this.treeCacheIndex--; + + let treeToLoad = null; + if (this.previousTreeObjects[this.treeCacheIndex]) { + treeToLoad = this.previousTreeObjects[this.treeCacheIndex].copy(); + this.getFrozenTree( + treeToLoad, + this.previousTreeObjects[this.treeCacheIndex + 1] + ); + } + + this.selectedRootNodeID = null; + this.currentDisplayedProcessTree = treeToLoad; + } + } + + redo() { + if (this.treeCacheIndex < this.previousTreeObjects.length - 1) { + this.treeCacheIndex++; + + let treeToLoad = null; + if (this.previousTreeObjects[this.treeCacheIndex]) { + treeToLoad = this.previousTreeObjects[this.treeCacheIndex].copy(); + this.getFrozenTree( + treeToLoad, + this.previousTreeObjects[this.treeCacheIndex - 1] + ); + } + + this.selectedRootNodeID = null; + + this.currentDisplayedProcessTree = treeToLoad; + } + } + + deleteTreeHistory() { + this.previousTreeObjects = []; + this.treeCacheIndex = 0; + this.treeCacheLength = 0; + } + + freezeSubtree(node: ProcessTree) { + if (!node.frozen) { + markNodeAsFrozen(node); + } else { + markNodeAsNonFrozen(node); + } + + this.currentDisplayedProcessTree = this.currentDisplayedProcessTree; + this.selectedRootNodeID = null; + } + + shiftSubtreeUp(tree: ProcessTree): void { + if (tree.parent && tree.parent.parent) { + const siblings = tree.parent.children; + const idxInParentChildList = siblings.indexOf(tree); + + const parentSiblings = tree.parent.parent.children; + const parentIdxInItsSiblingsList = parentSiblings.indexOf(tree.parent); + + // Remove tree as child from old parent + siblings.splice(idxInParentChildList, 1); + + // Add tree as sibling to old parent + tree.parent = tree.parent.parent; + parentSiblings.splice(parentIdxInItsSiblingsList + 1, 0, tree); + + this.set_currentDisplayedProcessTree_with_Cache( + this.currentDisplayedProcessTree + ); + } + } + + shiftSubtreeToLeft(tree: ProcessTree): void { + if (tree.parent) { + const siblings = tree.parent.children; + const idxInParentChildList = siblings.indexOf(tree); + if (idxInParentChildList > 0) { + const childToRight = siblings[idxInParentChildList - 1]; + const childToLeft = siblings[idxInParentChildList]; + siblings[idxInParentChildList] = childToRight; + siblings[idxInParentChildList - 1] = childToLeft; + + this.set_currentDisplayedProcessTree_with_Cache( + this.currentDisplayedProcessTree + ); + } + } + } + + shiftSubtreeToRight(tree: ProcessTree): void { + if (tree.parent) { + const siblings = tree.parent.children; + const idxInParentChildList = siblings.indexOf(tree); + if (idxInParentChildList < siblings.length - 1) { + const childToRight = siblings[idxInParentChildList]; + const childToLeft = siblings[idxInParentChildList + 1]; + siblings[idxInParentChildList + 1] = childToRight; + siblings[idxInParentChildList] = childToLeft; + + this.set_currentDisplayedProcessTree_with_Cache( + this.currentDisplayedProcessTree + ); + } + } + } + + deleteSelected(tree_to_delete: ProcessTree) { + // this.cacheCurrentTree(this.currentDisplayedProcessTree); + const newTree = this.currentDisplayedProcessTree; + + if (this.currentDisplayedProcessTree === tree_to_delete) { + this.set_currentDisplayedProcessTree_with_Cache(null); + } else { + this.set_currentDisplayedProcessTree_with_Cache( + delete_subtree(newTree, tree_to_delete) + ); + } + + this.selectedRootNodeID = null; + } + + insertNewNode( + selectedNode: ProcessTree, + strat: NodeInsertionStrategy, + operator: ProcessTreeOperator, + label: string + ) { + const newNode: ProcessTree = createNewRandomNode(label, operator); + //newNode.selected = true; + + if (this.currentDisplayedProcessTree) { + insertNode(selectedNode, newNode, strat, operator, label); + + if (!newNode.parent || selectedNode.parent == newNode) { + this.currentDisplayedProcessTree = newNode; + } + this.selectedRootNodeID = newNode.id; + //this.selectedRootNodeID = selectedNode.id; //edited + this.set_currentDisplayedProcessTree_with_Cache( + this.currentDisplayedProcessTree + ); + } else { + // empty tree - just add a single node + this.currentDisplayedProcessTree = newNode; + this.selectedRootNodeID = newNode.id; + } + } + + copySubtreeToBuffer(processTree: ProcessTree) { + this.processTreeBuffer.next(processTree.copy()); + } + + pasteSubtreeFromBuffer(parentNode: ProcessTree) { + if (this.processTreeBuffer) { + const copiedTree = this.bufferedProcessTree.copy(true, true); + if (parentNode) { + if (parentNode.label) + throw new Error('Cannot insert children below activities.'); + + copiedTree.parent = parentNode; + parentNode.children.push(copiedTree); + } else { + this.currentDisplayedProcessTree = copiedTree; + } + this.set_currentDisplayedProcessTree_with_Cache( + this.currentDisplayedProcessTree + ); + } + } + + makeSubtreeOptional(processTree: ProcessTree) { + const choice = createNewRandomNode(null, ProcessTreeOperator.choice); + const tau = createNewRandomNode(ProcessTreeOperator.tau, null); + + if (processTree.parent) { + const siblings = processTree.parent.children; + const idxInParentChildList = siblings.indexOf(processTree); + + siblings.splice(idxInParentChildList, 1, choice); + } else { + this.currentDisplayedProcessTree = choice; + } + + choice.parent = processTree.parent; + choice.children = [tau, processTree]; + processTree.parent = choice; + tau.parent = choice; + + this.set_currentDisplayedProcessTree_with_Cache( + this.currentDisplayedProcessTree + ); + } + + makeSubtreeRepeatable(processTree: ProcessTree) { + const loop = createNewRandomNode(null, ProcessTreeOperator.loop); + const tau = createNewRandomNode(ProcessTreeOperator.tau, null); + + if (processTree.parent) { + const siblings = processTree.parent.children; + const idxInParentChildList = siblings.indexOf(processTree); + + siblings.splice(idxInParentChildList, 1, loop); + } else { + this.currentDisplayedProcessTree = loop; + } + loop.parent = processTree.parent; + loop.children = [processTree, tau]; + processTree.parent = loop; + tau.parent = loop; + + this.set_currentDisplayedProcessTree_with_Cache( + this.currentDisplayedProcessTree + ); + } +} diff --git a/src/frontend/src/app/services/projectService/project.service.spec.ts b/src/frontend/src/app/services/projectService/project.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..c70ac34bd0412b72895f9556d99d2d959a081f39 --- /dev/null +++ b/src/frontend/src/app/services/projectService/project.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ProjectService } from './project.service'; + +describe('ProjectService', () => { + let service: ProjectService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ProjectService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/projectService/project.service.ts b/src/frontend/src/app/services/projectService/project.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..d5de922e4e3b2019761b40bcb5b5f35cde92f6a4 --- /dev/null +++ b/src/frontend/src/app/services/projectService/project.service.ts @@ -0,0 +1,349 @@ +import { Injectable } from '@angular/core'; +import { ProcessTreeService } from '../processTreeService/process-tree.service'; +import { ElectronService } from '../electronService/electron.service'; +import { ProcessTree } from 'src/app/objects/ProcessTree/ProcessTree'; +import { + Transform, + TransformationType, + Type, + instanceToPlain, + plainToInstance, +} from 'class-transformer'; +import { Variant } from 'src/app/objects/Variants/variant'; +import { VariantService } from '../variantService/variant.service'; +import { LogService } from '../logService/log.service'; +import { DatePipe } from '@angular/common'; +import { + VariantFilterService, + VariantFilter, +} from '../variantFilterService/variant-filter.service'; +import { VariantQueryService } from '../variantQueryService/variant-query.service'; +import { environment } from 'src/environments/environment'; +import { isEqualWith } from 'lodash'; +import { Observable } from 'rxjs'; +import { mergeMap, take, tap } from 'rxjs/operators'; +import { BackendService } from '../backendService/backend.service'; +import { ClusteringConfig } from 'src/app/objects/ClusteringConfig'; +import { TimeUnit } from 'src/app/objects/TimeUnit'; +import { + ActivityDeletion, + ActivityRenaming, + LogModification, + LogModificationType, + UserDefinedInfixAddition, + UserDefinedVariantAddition, + VariantsDeletion, +} from 'src/app/objects/LogModification'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { ContinueLastProjectDialogComponent } from 'src/app/components/dialogs/continue-last-project-dialog/continue-last-project-dialog.component'; +import { LoadingOverlayService } from '../loadingOverlayService/loading-overlay.service'; +@Injectable({ + providedIn: 'root', +}) +export class ProjectService { + constructor( + private logService: LogService, + private processTreeService: ProcessTreeService, + private variantService: VariantService, + private variantFilterService: VariantFilterService, + private variantQueryService: VariantQueryService, + private backendService: BackendService, + private loadingOverlayService: LoadingOverlayService, + private modalService: NgbModal, + private electronService: ElectronService + ) { + try { + this.electronService + .readFromUserFolder('latest_project', 'json') + .then((lastProjectJson) => { + if (!lastProjectJson) { + this.getInitialProject(); + return; + } + + const lastProject = plainToInstance( + Project, + JSON.parse(lastProjectJson) + ); + + const modalRef = this.modalService.open( + ContinueLastProjectDialogComponent + ); + + modalRef.componentInstance.projectName = lastProject.eventlogPath + .split('/') + .pop(); + modalRef.result.then( + () => { + // on confirmation + this.loadProject(lastProject); + }, + () => { + // on dismiss + this.getInitialProject(); + } + ); + }); + + this.electronService.checkUnsavedChanges$.subscribe(() => { + // save already to default project on checking for changes + this.saveProject(false); + + this.electronService.unsavedChangesStatus(this.unsavedChanges); + }); + + this.electronService.saveProject$.subscribe(() => + this.saveProject().then((filePath) => { + if (filePath) this.electronService.quit(); + }) + ); + } catch (error) { + console.error('Cannot access user folder.', error); + this.getInitialProject(); + } + } + + private getInitialProject() { + // wait for variants to be loaded + this.variantService.variants$.pipe(take(2)).subscribe((variants) => { + const project = this.currentProject; + this.latestSavedProject = instanceToPlain(project, { + enableCircularCheck: true, + }); + }); + } + + private latestSavedProject: Record<string, any>; + + get unsavedChanges(): boolean { + return !isEqualWith( + this.latestSavedProject, + JSON.parse( + JSON.stringify( + instanceToPlain(this.currentProject, { enableCircularCheck: true }) + ) + ), + (a, b, key) => { + // ignore parent property + if (key === 'parent') return true; + return undefined; + } + ); + } + + get currentProject(): Project { + return new Project( + this.logService.loadedEventLog, + this.logService.timeGranularity, + this.logService.logModifications, + this.processTreeService.currentDisplayedProcessTree, + this.processTreeService.previousTreeObjects, + this.processTreeService.treeCacheIndex, + this.processTreeService.selectedRootNodeID, + this.variantService.variants, + this.variantFilterService.variantFilters, + this.variantQueryService.variantQuery, + this.variantService.clusteringConfig + ); + } + + public loadProjectFromFile(file: File) { + const fileReader = new FileReader(); + fileReader.onload = (e) => { + const project = plainToInstance( + Project, + JSON.parse(fileReader.result.toString()) + ); + this.loadProject(project); + }; + fileReader.readAsText(file); + } + + public loadProject(project: Project) { + this.loadingOverlayService.showLoader('Loading Project ...'); + this.latestSavedProject = instanceToPlain(project); + + let loadingLog: Observable<any>; + + if (project.eventlogPath == 'preload') { + loadingLog = this.backendService.resetLogCache(); + } else { + loadingLog = this.backendService.loadEventLogFromFilePath( + project.eventlogPath + ); + } + + loadingLog + .pipe( + mergeMap(() => this.replayLogModifications(project.logModifications)), + mergeMap(() => + this.backendService.getLogPropsAndUpdateState( + project.timeGranularity, + project.eventlogPath + ) + ) + ) + .subscribe(() => { + this.restoreProjectAfterLog(project); + this.loadingOverlayService.hideLoader(); + }); + } + + private restoreProjectAfterLog(project: Project) { + this.processTreeService.previousTreeObjects = project.processTreeHistory; + this.processTreeService.treeCacheLength = project.processTreeHistory.length; + this.processTreeService.treeCacheIndex = project.treeCacheIndex; + this.processTreeService.currentDisplayedProcessTree = project.processTree; + this.processTreeService.selectedRootNodeID = project.selectedRootNodeID; + // this.variantService.variants = project.variants; + this.variantFilterService.variantFilters = project.variantFilters; + this.variantQueryService.variantQuery = project.variantQuery; + this.variantService.clusteringConfig = project.clusteringConfiguration; + } + + private replayLogModifications(logModifications: LogModification[]) { + return logModifications.reduce( + (previous, current) => + previous.pipe( + tap(() => console.log('Replaying Log Modification:', current.type)), + mergeMap(() => { + switch (current.type) { + case LogModificationType.ACTIVITY_DELETION: + return this.variantService.deleteActivity( + (<ActivityDeletion>current).activityName + ); + case LogModificationType.ACTIVITY_RENAMING: + return this.variantService.renameActivity( + (<ActivityRenaming>current).activityName, + (<ActivityRenaming>current).newActivityName + ); + case LogModificationType.VARIANT_DELETION: + return this.variantService.deleteVariants( + (<VariantsDeletion>current).variantsBids + ); + case LogModificationType.USER_DEFINED_VARIANT_ADDITION: + return this.variantService.addUserDefinedVariant( + (<UserDefinedVariantAddition>current).variant + ); + case LogModificationType.USER_DEFINED_INFIX_ADDITION: + console.log((<UserDefinedInfixAddition>current).infix); + console.log((<UserDefinedInfixAddition>current).infix.variant); + return this.variantService.addInfixToBackend( + (<UserDefinedInfixAddition>current).infix + ); + } + }) + ), + new Observable((subscriber) => { + subscriber.next(); + subscriber.complete(); + }) + ); + } + + public async saveProject(askUserForPath: boolean = true) { + const project = JSON.stringify( + instanceToPlain(this.currentProject, { + enableCircularCheck: true, + }) + ); + + if (askUserForPath) { + const now = new Date(); + const datepipe: DatePipe = new DatePipe('en-US'); + const formattedDate = datepipe.transform(now, 'YYYY_MM_dd_HH_mm'); + + const filePath = await this.electronService.showSaveDialog( + `cortado_${ + this.logService.loadedEventLog.split('.')[0] + }_${formattedDate}`, + 'json', + new Blob([project]), + 'Save project', + 'Save Cortado Project' + ); + if (filePath) this.latestSavedProject = JSON.parse(project); + return filePath; + } else { + this.electronService.saveToUserFolder('latest_project', 'json', project); + } + } +} + +class Project { + public cortadoVersion: string; + public eventlogPath: string; + public timeGranularity: TimeUnit; + @Transform(({ value, key, obj, type }) => { + if (type === TransformationType.PLAIN_TO_CLASS) { + const transformed = []; + for (let logModification of value) { + if ( + logModification.type === + LogModificationType.USER_DEFINED_VARIANT_ADDITION + ) + transformed.push( + plainToInstance(UserDefinedVariantAddition, logModification) + ); + else if ( + logModification.type === + LogModificationType.USER_DEFINED_INFIX_ADDITION + ) + transformed.push( + plainToInstance(UserDefinedInfixAddition, logModification) + ); + else transformed.push(logModification); + } + return transformed; + } + return value; + }) + public logModifications: LogModification[]; + @Type(() => ProcessTree) + public processTree: ProcessTree; + @Type(() => ProcessTree) + public processTreeHistory: ProcessTree[]; + public treeCacheIndex: number; + public selectedRootNodeID: number; + @Type(() => Variant) + public variants: Variant[]; + @Transform(({ value, key, obj, type }) => { + if (type === TransformationType.PLAIN_TO_CLASS) { + let map = new Map<string, VariantFilter>(); + for (let entry of Object.entries(value)) + map.set(entry[0], plainToInstance(VariantFilter, entry[1])); + return map; + } + return value; + }) + public variantFilters: Map<string, VariantFilter>; + public variantQuery: string; + public clusteringConfiguration: ClusteringConfig; + constructor( + eventlogPath: string, + timeGranularity: TimeUnit, + logModifications: LogModification[], + processTree: ProcessTree, + processTreeHistory: ProcessTree[], + treeCacheIndex: number, + selectedRootNodeID: number, + variants: Variant[], + variantFilters: Map<string, VariantFilter>, + variantQuery: string, + clusteringConfiguration: ClusteringConfig, + cortadoVersion: string = environment.VERSION + ) { + this.eventlogPath = eventlogPath; + this.timeGranularity = timeGranularity; + this.logModifications = logModifications; + this.processTree = processTree; + this.processTreeHistory = processTreeHistory; + this.treeCacheIndex = treeCacheIndex; + this.selectedRootNodeID = selectedRootNodeID; + this.variants = variants; + this.variantFilters = variantFilters; + this.variantQuery = variantQuery; + this.clusteringConfiguration = clusteringConfiguration; + this.cortadoVersion = cortadoVersion; + } +} diff --git a/src/frontend/src/app/services/settingsService/settings.service.spec.ts b/src/frontend/src/app/services/settingsService/settings.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..e42e4a99f0da235f318516607707058a41bad587 --- /dev/null +++ b/src/frontend/src/app/services/settingsService/settings.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { SettingsService } from './settings.service'; + +describe('SettingsServiceService', () => { + let service: SettingsService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(SettingsService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/settingsService/settings.service.ts b/src/frontend/src/app/services/settingsService/settings.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..b8614cf03605a08875057c13e69e98dc8fc8bc87 --- /dev/null +++ b/src/frontend/src/app/services/settingsService/settings.service.ts @@ -0,0 +1,41 @@ +import { Injectable } from '@angular/core'; +import * as _ from 'lodash'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { filter, skip, tap } from 'rxjs/operators'; +import { Configuration } from 'src/app/components/settings/model'; + +@Injectable({ + providedIn: 'root', +}) +export class SettingsService { + private _onSettingChange: BehaviorSubject<Configuration> = + new BehaviorSubject({} as Configuration); + + private _changedSetting: BehaviorSubject<Configuration> = new BehaviorSubject( + null + ); + + constructor() {} + + public get changedSetting(): Observable<any> { + return this._changedSetting.asObservable().pipe( + skip(2), + filter((val) => !_.isEmpty(val)) + ); + } + + public get onSettingChange(): Observable<Configuration> { + return this._onSettingChange.asObservable(); + } + + public notify(setting: Configuration) { + this._changedSetting.next( + this.getDifference(this._onSettingChange.value, setting) + ); + this._onSettingChange.next(setting); + } + + public getDifference(prev, curr): Configuration { + return _.omitBy(curr, (v, k) => prev[k] === v) as Configuration; + } +} diff --git a/src/frontend/src/app/services/sharedDataService/debug_tree.js b/src/frontend/src/app/services/sharedDataService/debug_tree.js new file mode 100644 index 0000000000000000000000000000000000000000..9a46d8f618bd5a6c57934b07b85e03944b78d36a --- /dev/null +++ b/src/frontend/src/app/services/sharedDataService/debug_tree.js @@ -0,0 +1,120 @@ +export const dummy_tree = { + operator: "\u2715", + label: null, + id: 7823782323, + children: [ + { + operator: "\u21BA", + label: null, + id: 7823342323, + children: [ + { + operator: null, + label: "\u03C4", + id: 7822782323, + children: [], + }, + { + operator: null, + label: "W_Nabellen incomplete dossiers", + id: 7823782399, + children: [], + }, + ], + }, + { + operator: "\u21BA", + label: null, + id: 1245152, + children: [ + { + operator: null, + label: "\u03C4", + id: 3637465332, + children: [], + }, + { + operator: null, + label: "\u03C4", + id: 1352136346, + children: [], + }, + ], + }, + { + operator: "\u2227", + label: null, + id: 1123782323, + children: [ + { + operator: null, + label: "O_SENT", + id: 7823782823, + children: [], + }, + { + operator: null, + label: "O_CREATED", + id: 7823782023, + children: [], + }, + { + operator: null, + label: "W_Nabellen incomplete dossiers", + id: 7824782323, + children: [], + }, + { + operator: null, + label: "W_Valideren aanvraag", + id: 7124782321, + children: [], + }, + ], + }, + { + operator: "\u2794", + label: null, + id: 7829482323, + children: [ + { + operator: "\u2794", + label: null, + id: 7829492323, + children: [ + { + operator: null, + label: "W_Nabellen incomplete dossiers", + id: 7004982323, + children: [], + }, + { + operator: null, + label: "W_Wijzigen contractgegevens", + id: 7854715323, + children: [], + }, + ], + }, + { + operator: null, + label: "W_Nabellen incomplete dossiers", + id: 7854782323, + children: [], + }, + { + operator: null, + label: "O_SENT", + id: 7899782323, + children: [], + }, + { + operator: null, + label: "O_CREATED", + id: 3339782323, + children: [], + }, + ], + }, + ], +}; diff --git a/src/frontend/src/app/services/sharedDataService/dummy_backend_response.js b/src/frontend/src/app/services/sharedDataService/dummy_backend_response.js new file mode 100644 index 0000000000000000000000000000000000000000..0840fec777938d1bd557be6c83fb3f2b0c6f6086 --- /dev/null +++ b/src/frontend/src/app/services/sharedDataService/dummy_backend_response.js @@ -0,0 +1,3555 @@ +export const startActivities = new Set(["place order", "send invoice"]); + +export const endActivities = new Set([ + "confirm payment", + "make delivery", + "cancel order", +]); + +export const activitiesInLog = { + "place order": 2532, + "send invoice": 2532, + pay: 2250, + "prepare delivery": 2250, + "make delivery": 2250, + "confirm payment": 2250, + "send reminder": 1872, + "cancel order": 282, +}; + +export const variant = [ + { + count: 483, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 132, + max: 17967, + mean: 2559.569358178054, + median: 579, + n: 483, + n_not_none: 483, + "50th": 579, + "95th": 13845.099999999997, + stdev: 4510.023251273316, + percentage_variance: 176.2024239297672, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 6046, + max: 1107524, + mean: 382822.8944099379, + median: 361228, + n: 483, + n_not_none: 483, + "50th": 361228, + "95th": 748808.3999999994, + stdev: 218908.6942445881, + percentage_variance: 57.18275929709008, + }, + service_time: { + min: 123, + max: 15799, + mean: 756.6770186335403, + median: 375, + n: 483, + n_not_none: 483, + "50th": 375, + "95th": 1669.5, + stdev: 1878.0087061688146, + percentage_variance: 248.19158768165744, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 14839, + max: 3338924, + mean: 947606.7867494824, + median: 850341, + n: 483, + n_not_none: 483, + "50th": 850341, + "95th": 2156000.899999996, + stdev: 539500.6387723964, + percentage_variance: 56.93296484536718, + }, + service_time: { + min: 123, + max: 14203, + mean: 728.4285714285714, + median: 353, + n: 483, + n_not_none: 483, + "50th": 353, + "95th": 1537.499999999999, + stdev: 1871.2004402868492, + percentage_variance: 256.88180196132464, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 46693, + max: 1569912, + mean: 448404.39544513455, + median: 431231, + n: 483, + n_not_none: 483, + "50th": 431231, + "95th": 859237.7999999999, + stdev: 226760.83055793986, + percentage_variance: 50.5706083306415, + }, + service_time: { + min: 168, + max: 9600, + mean: 1933.2277432712215, + median: 439, + n: 483, + n_not_none: 483, + "50th": 439, + "95th": 9235.4, + stdev: 3225.296373190123, + percentage_variance: 166.8347862488559, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: { + min: 22173, + max: 408519, + mean: 134525.29192546583, + median: 88682, + n: 483, + n_not_none: 483, + "50th": 88682, + "95th": 318392.49999999994, + stdev: 88514.38030793877, + percentage_variance: 65.7975753414313, + }, + service_time: { + min: 542, + max: 5996, + mean: 2054.1469979296066, + median: 1427, + n: 483, + n_not_none: 483, + "50th": 1427, + "95th": 5632.9, + stdev: 1682.1559944161236, + percentage_variance: 81.89073109721863, + }, + }, + }, + { + leaf: ["confirm payment"], + performance: { + wait_time: { + min: 103, + max: 390885, + mean: 82584.1552795031, + median: 66207, + n: 483, + n_not_none: 483, + "50th": 66207, + "95th": 262339.8, + stdev: 87108.05626698812, + percentage_variance: 105.47792851083119, + }, + service_time: { + min: 150, + max: 16989, + mean: 894.8633540372671, + median: 449, + n: 483, + n_not_none: 483, + "50th": 449, + "95th": 1798.1999999999998, + stdev: 2257.9208383841706, + percentage_variance: 252.32018142181497, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1195080, + max: 4229533, + mean: 2004870.436853002, + median: 1895309, + n: 483, + n_not_none: 483, + "50th": 1895309, + "95th": 3017733.599999998, + stdev: 506995.7444056687, + percentage_variance: 25.288204917694728, + }, + }, + }, + length: 6, + number_of_activities: 6, + percentage: 38.15, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["make delivery", "start"]], + [["make delivery", "complete"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + ], + count: 483, + percentage: 100, + }, + ], + }, + { + count: 230, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 130, + max: 17125, + mean: 2208.6478260869567, + median: 544.5, + n: 230, + n_not_none: 230, + "50th": 544.5, + "95th": 13008.049999999985, + stdev: 3922.362028140537, + percentage_variance: 177.59110265622354, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 10929, + max: 1255206, + mean: 388702.3869565217, + median: 383101, + n: 230, + n_not_none: 230, + "50th": 383101, + "95th": 813054.5999999996, + stdev: 230387.40964459148, + percentage_variance: 59.27090169126269, + }, + service_time: { + min: 122, + max: 15920, + mean: 1040.6478260869565, + median: 408, + n: 230, + n_not_none: 230, + "50th": 408, + "95th": 5679.299999999889, + stdev: 2567.2362762588405, + percentage_variance: 246.69597263390835, + }, + }, + }, + { + leaf: ["send reminder"], + performance: { + wait_time: { + min: 375277, + max: 1283271, + mean: 708481.9434782609, + median: 612289, + n: 230, + n_not_none: 230, + "50th": 612289, + "95th": 1201539.8499999999, + stdev: 197962.96652712472, + percentage_variance: 27.94185064974758, + }, + service_time: { + min: 387, + max: 2697, + mean: 1172.5086956521739, + median: 1098.5, + n: 230, + n_not_none: 230, + "50th": 1098.5, + "95th": 2418.9999999999995, + stdev: 578.569390155896, + percentage_variance: 49.34457137088298, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 30669, + max: 951232, + mean: 305340.2304347826, + median: 266269.5, + n: 230, + n_not_none: 230, + "50th": 266269.5, + "95th": 584381.2499999998, + stdev: 160919.21557962947, + percentage_variance: 52.701609398306935, + }, + service_time: { + min: 122, + max: 13797, + mean: 727.0347826086957, + median: 357.5, + n: 230, + n_not_none: 230, + "50th": 357.5, + "95th": 1528.0999999999997, + stdev: 1801.72781911033, + percentage_variance: 247.81865492672793, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 78259, + max: 999954, + mean: 417386.48260869563, + median: 428265.5, + n: 230, + n_not_none: 230, + "50th": 428265.5, + "95th": 763160.7, + stdev: 195134.65939141967, + percentage_variance: 46.751552223688215, + }, + service_time: { + min: 169, + max: 9585, + mean: 1705.682608695652, + median: 437, + n: 230, + n_not_none: 230, + "50th": 437, + "95th": 9097.8, + stdev: 3033.91816494347, + percentage_variance: 177.87120238410176, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: { + min: 27866, + max: 400235, + mean: 132349.00869565218, + median: 86735, + n: 230, + n_not_none: 230, + "50th": 86735, + "95th": 321561.89999999997, + stdev: 90247.78633610693, + percentage_variance: 68.1892423868768, + }, + service_time: { + min: 549, + max: 5925, + mean: 2085.230434782609, + median: 1387.5, + n: 230, + n_not_none: 230, + "50th": 1387.5, + "95th": 5463.499999999999, + stdev: 1738.6280200441897, + percentage_variance: 83.37822002993384, + }, + }, + }, + { + leaf: ["confirm payment"], + performance: { + wait_time: { + min: 102, + max: 330986, + mean: 70944.93913043478, + median: 62884, + n: 230, + n_not_none: 230, + "50th": 62884, + "95th": 256678.84999999995, + stdev: 79578.84219900583, + percentage_variance: 112.1698646505247, + }, + service_time: { + min: 150, + max: 15507, + mean: 645.7608695652174, + median: 442, + n: 230, + n_not_none: 230, + "50th": 442, + "95th": 1564.2999999999975, + stdev: 1294.4485022972822, + percentage_variance: 200.45322708525495, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1246929, + max: 3951467, + mean: 2032790.5043478261, + median: 1862219.5, + n: 230, + n_not_none: 230, + "50th": 1862219.5, + "95th": 3089398.9, + stdev: 525580.7196371906, + percentage_variance: 25.855134531229574, + }, + }, + }, + length: 7, + number_of_activities: 7, + percentage: 18.17, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["make delivery", "start"]], + [["make delivery", "complete"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + ], + count: 230, + percentage: 100, + }, + ], + }, + { + count: 141, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 126, + max: 17307, + mean: 2927.340425531915, + median: 636, + n: 141, + n_not_none: 141, + "50th": 636, + "95th": 15398, + stdev: 5036.418067904137, + percentage_variance: 172.04757000508374, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 27435, + max: 1107211, + mean: 384868.8085106383, + median: 333510, + n: 141, + n_not_none: 141, + "50th": 333510, + "95th": 918132, + stdev: 235942.95625925332, + percentage_variance: 61.30477478086706, + }, + service_time: { + min: 125, + max: 8232, + mean: 600.6524822695036, + median: 388, + n: 141, + n_not_none: 141, + "50th": 388, + "95th": 1636, + stdev: 963.7916786304838, + percentage_variance: 160.45745369916665, + }, + }, + }, + { + leaf: ["send reminder"], + performance: { + wait_time: { + min: 548200, + max: 1286443, + mean: 752714.390070922, + median: 619302, + n: 141, + n_not_none: 141, + "50th": 619302, + "95th": 1206769, + stdev: 219835.54042055339, + percentage_variance: 29.20570449036322, + }, + service_time: { + min: 387, + max: 2641, + mean: 1221.2624113475176, + median: 1114, + n: 141, + n_not_none: 141, + "50th": 1114, + "95th": 2421, + stdev: 576.6385057925938, + percentage_variance: 47.21659329188245, + }, + }, + }, + { + leaf: ["send reminder"], + performance: { + wait_time: { + min: 545199, + max: 1448911, + mean: 729094.1134751773, + median: 612812, + n: 141, + n_not_none: 141, + "50th": 612812, + "95th": 1203702, + stdev: 208404.1374070408, + percentage_variance: 28.583982994142787, + }, + service_time: { + min: 406, + max: 2693, + mean: 1234.5106382978724, + median: 1103, + n: 141, + n_not_none: 141, + "50th": 1103, + "95th": 2385, + stdev: 613.8524789861541, + percentage_variance: 49.724357161678746, + }, + }, + }, + { + leaf: ["cancel order"], + performance: { + wait_time: { + min: 3547, + max: 583746, + mean: 170027.02836879433, + median: 150403, + n: 141, + n_not_none: 141, + "50th": 150403, + "95th": 417025, + stdev: 132064.51090503045, + percentage_variance: 77.67265720752238, + }, + service_time: { + min: 291, + max: 27162, + mean: 1100.9219858156027, + median: 787, + n: 141, + n_not_none: 141, + "50th": 787, + "95th": 2156, + stdev: 2301.8865153574793, + percentage_variance: 209.0871601271691, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1302313, + max: 3520078, + mean: 2043789.0283687944, + median: 1836697, + n: 141, + n_not_none: 141, + "50th": 1836697, + "95th": 3024568, + stdev: 530408.5633064241, + percentage_variance: 25.9522169824817, + }, + }, + }, + length: 5, + number_of_activities: 5, + percentage: 11.14, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["cancel order", "start"]], + [["cancel order", "complete"]], + ], + count: 141, + percentage: 100, + }, + ], + }, + { + count: 132, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 139, + max: 17635, + mean: 2770.409090909091, + median: 582.5, + n: 132, + n_not_none: 132, + "50th": 582.5, + "95th": 14128.99999999998, + stdev: 4656.278861816664, + percentage_variance: 168.07188790622752, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 71084, + max: 1494889, + mean: 393764.5909090909, + median: 371388.5, + n: 132, + n_not_none: 132, + "50th": 371388.5, + "95th": 863978.4999999999, + stdev: 242670.29684370736, + percentage_variance: 61.628267865185734, + }, + service_time: { + min: 122, + max: 14798, + mean: 889.689393939394, + median: 330.5, + n: 132, + n_not_none: 132, + "50th": 330.5, + "95th": 1662.9499999999973, + stdev: 2426.350962740236, + percentage_variance: 272.71888136114165, + }, + }, + }, + { + leaf: ["send reminder"], + performance: { + wait_time: { + min: 379411, + max: 1219531, + mean: 700458.3333333334, + median: 610784, + n: 132, + n_not_none: 132, + "50th": 610784, + "95th": 1197394.9, + stdev: 193723.64679641405, + percentage_variance: 27.656698132853112, + }, + service_time: { + min: 387, + max: 2680, + mean: 1277.6060606060605, + median: 1213, + n: 132, + n_not_none: 132, + "50th": 1213, + "95th": 2320.25, + stdev: 558.4362129486718, + percentage_variance: 43.7095776364559, + }, + }, + }, + { + leaf: ["send reminder"], + performance: { + wait_time: { + min: 380237, + max: 1271596, + mean: 666956.0378787878, + median: 609798.5, + n: 132, + n_not_none: 132, + "50th": 609798.5, + "95th": 981930.4999999993, + stdev: 145543.0676022561, + percentage_variance: 21.82198815759233, + }, + service_time: { + min: 389, + max: 2591, + mean: 1183.1515151515152, + median: 1071.5, + n: 132, + n_not_none: 132, + "50th": 1071.5, + "95th": 2443.4499999999994, + stdev: 568.3546694653174, + percentage_variance: 48.03735296679509, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 82523, + max: 685506, + mean: 297569.3106060606, + median: 297402.5, + n: 132, + n_not_none: 132, + "50th": 297402.5, + "95th": 525395.2999999998, + stdev: 151170.6169548363, + percentage_variance: 50.80181711176684, + }, + service_time: { + min: 133, + max: 12902, + mean: 627.7727272727273, + median: 342.5, + n: 132, + n_not_none: 132, + "50th": 342.5, + "95th": 1219.8999999999965, + stdev: 1529.7837974814545, + percentage_variance: 243.68433527327494, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 86846, + max: 1206838, + mean: 416000.50757575757, + median: 424106.5, + n: 132, + n_not_none: 132, + "50th": 424106.5, + "95th": 703366.1499999999, + stdev: 196687.7002588286, + percentage_variance: 47.280639488885704, + }, + service_time: { + min: 169, + max: 9556, + mean: 2187.530303030303, + median: 447, + n: 132, + n_not_none: 132, + "50th": 447, + "95th": 9029.449999999999, + stdev: 3378.8002397512964, + percentage_variance: 154.4572998632646, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: { + min: 20473, + max: 398675, + mean: 124381.98484848485, + median: 84344, + n: 132, + n_not_none: 132, + "50th": 84344, + "95th": 294520.1999999996, + stdev: 87332.63982179883, + percentage_variance: 70.21325469937028, + }, + service_time: { + min: 553, + max: 5887, + mean: 2070.7727272727275, + median: 1413.5, + n: 132, + n_not_none: 132, + "50th": 1413.5, + "95th": 5454.399999999999, + stdev: 1683.775345347967, + percentage_variance: 81.31145070495263, + }, + }, + }, + { + leaf: ["confirm payment"], + performance: { + wait_time: { + min: 35, + max: 267522, + mean: 72641.91666666667, + median: 64273.5, + n: 132, + n_not_none: 132, + "50th": 64273.5, + "95th": 249154.19999999998, + stdev: 72305.96278802272, + percentage_variance: 99.53752062987881, + }, + service_time: { + min: 152, + max: 17744, + mean: 978.2727272727273, + median: 440.5, + n: 132, + n_not_none: 132, + "50th": 440.5, + "95th": 1871.2499999999986, + stdev: 2545.1704095407176, + percentage_variance: 260.1698216239002, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1837662, + max: 4088395, + mean: 2683757.8863636362, + median: 2495645, + n: 132, + n_not_none: 132, + "50th": 2495645, + "95th": 3856404.0999999987, + stdev: 531077.766422058, + percentage_variance: 19.788587082333382, + }, + }, + }, + length: 8, + number_of_activities: 8, + percentage: 10.43, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["make delivery", "start"]], + [["make delivery", "complete"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + ], + count: 132, + percentage: 100, + }, + ], + }, + { + count: 127, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 132, + max: 17836, + mean: 2350.244094488189, + median: 550, + n: 127, + n_not_none: 127, + "50th": 550, + "95th": 14004.799999999988, + stdev: 4347.390393511469, + percentage_variance: 184.9761224251984, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 9569, + max: 1098492, + mean: 400599.031496063, + median: 423871, + n: 127, + n_not_none: 127, + "50th": 423871, + "95th": 687465.9, + stdev: 222259.19128240104, + percentage_variance: 55.48170959184792, + }, + service_time: { + min: 124, + max: 13235, + mean: 842.0314960629921, + median: 410, + n: 127, + n_not_none: 127, + "50th": 410, + "95th": 1427.9999999999964, + stdev: 2091.193465490756, + percentage_variance: 248.35097918169967, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 15400, + max: 2838765, + mean: 908979.9133858267, + median: 763669, + n: 127, + n_not_none: 127, + "50th": 763669, + "95th": 1965313.999999996, + stdev: 472141.2308531801, + percentage_variance: 51.94187725166755, + }, + service_time: { + min: 121, + max: 13638, + mean: 729.3858267716536, + median: 358, + n: 127, + n_not_none: 127, + "50th": 358, + "95th": 1567.5999999999992, + stdev: 1857.096646147114, + percentage_variance: 254.61101353817628, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 76658, + max: 1309384, + mean: 477131.7874015748, + median: 493050, + n: 127, + n_not_none: 127, + "50th": 493050, + "95th": 1004405.5999999994, + stdev: 253604.41498543601, + percentage_variance: 53.151859021287876, + }, + service_time: { + min: 169, + max: 9556, + mean: 1204.007874015748, + median: 424, + n: 127, + n_not_none: 127, + "50th": 424, + "95th": 8996.9, + stdev: 2461.8896326662516, + percentage_variance: 204.4745458727831, + }, + }, + }, + { + leaf: ["confirm payment"], + performance: { + wait_time: { + min: 18862, + max: 327414, + mean: 120669.55905511811, + median: 84153, + n: 127, + n_not_none: 127, + "50th": 84153, + "95th": 274912.6, + stdev: 79770.07737297074, + percentage_variance: 66.10621435728811, + }, + service_time: { + min: 155, + max: 10171, + mean: 560.6850393700787, + median: 445, + n: 127, + n_not_none: 127, + "50th": 445, + "95th": 929.6999999999975, + stdev: 908.5612794001277, + percentage_variance: 162.0448586288093, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: { + min: 40, + max: 238744, + mean: 21835.67716535433, + median: 6719, + n: 127, + n_not_none: 127, + "50th": 6719, + "95th": 64234.09999999999, + stdev: 39712.31112197978, + percentage_variance: 181.86892406061713, + }, + service_time: { + min: 554, + max: 5986, + mean: 1909.5905511811025, + median: 1476, + n: 127, + n_not_none: 127, + "50th": 1476, + "95th": 5374.599999999998, + stdev: 1479.5046594621892, + percentage_variance: 77.47758589123201, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1214683, + max: 3733661, + mean: 1936811.9133858269, + median: 1826695, + n: 127, + n_not_none: 127, + "50th": 1826695, + "95th": 3000295.7999999993, + stdev: 454900.0795747125, + percentage_variance: 23.487055011938743, + }, + }, + }, + length: 6, + number_of_activities: 6, + percentage: 10.03, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + [["make delivery", "start"]], + [["make delivery", "complete"]], + ], + count: 127, + percentage: 100, + }, + ], + }, + { + count: 53, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 134, + max: 15967, + mean: 2268.377358490566, + median: 444, + n: 53, + n_not_none: 53, + "50th": 444, + "95th": 13151.799999999997, + stdev: 4348.626057231335, + percentage_variance: 191.70646545886075, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 31242, + max: 1261579, + mean: 374752.88679245283, + median: 335315, + n: 53, + n_not_none: 53, + "50th": 335315, + "95th": 935150.1999999997, + stdev: 276537.7476767698, + percentage_variance: 73.79202600510536, + }, + service_time: { + min: 133, + max: 14451, + mean: 701.5094339622641, + median: 384, + n: 53, + n_not_none: 53, + "50th": 384, + "95th": 1042.2, + stdev: 1942.389385254087, + percentage_variance: 276.8871366822663, + }, + }, + }, + { + leaf: ["send reminder"], + performance: { + wait_time: { + min: 554016, + max: 1457789, + mean: 716895.1509433963, + median: 613103, + n: 53, + n_not_none: 53, + "50th": 613103, + "95th": 1124571.5999999999, + stdev: 195914.01871655099, + percentage_variance: 27.328127196667246, + }, + service_time: { + min: 411, + max: 2693, + mean: 1152.4150943396226, + median: 1042, + n: 53, + n_not_none: 53, + "50th": 1042, + "95th": 2459.1999999999994, + stdev: 618.6529235102502, + percentage_variance: 53.68316733691879, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 85637, + max: 676369, + mean: 352023.6603773585, + median: 354346, + n: 53, + n_not_none: 53, + "50th": 354346, + "95th": 582937, + stdev: 152079.22890665897, + percentage_variance: 43.20142252473448, + }, + service_time: { + min: 135, + max: 10168, + mean: 751.377358490566, + median: 352, + n: 53, + n_not_none: 53, + "50th": 352, + "95th": 1752.5999999999997, + stdev: 1800.542399330045, + percentage_variance: 239.63224057577878, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 103592, + max: 849012, + mean: 415170.9811320755, + median: 410031, + n: 53, + n_not_none: 53, + "50th": 410031, + "95th": 758648.4, + stdev: 196042.01383195416, + percentage_variance: 47.21958487979887, + }, + service_time: { + min: 176, + max: 9525, + mean: 991.7924528301887, + median: 450, + n: 53, + n_not_none: 53, + "50th": 450, + "95th": 4402.59999999999, + stdev: 2003.6125581106912, + percentage_variance: 202.01933906566464, + }, + }, + }, + { + leaf: ["confirm payment"], + performance: { + wait_time: { + min: 16743, + max: 326500, + mean: 125223.54716981133, + median: 84132, + n: 53, + n_not_none: 53, + "50th": 84132, + "95th": 273165.6, + stdev: 86039.02056548485, + percentage_variance: 68.70834001276958, + }, + service_time: { + min: 178, + max: 2085, + mean: 526.5094339622641, + median: 436, + n: 53, + n_not_none: 53, + "50th": 436, + "95th": 1137.9999999999998, + stdev: 344.302786168127, + percentage_variance: 65.39346951052045, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: { + min: 87, + max: 238127, + mean: 35600.03773584906, + median: 7990, + n: 53, + n_not_none: 53, + "50th": 7990, + "95th": 228310.19999999998, + stdev: 65910.77541762344, + percentage_variance: 185.14243132740174, + }, + service_time: { + min: 541, + max: 5960, + mean: 2075.8490566037735, + median: 1521, + n: 53, + n_not_none: 53, + "50th": 1521, + "95th": 5765.2, + stdev: 1740.1603418189593, + percentage_variance: 83.8288475880793, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1318382, + max: 3459417, + mean: 2028134.0943396227, + median: 1894354, + n: 53, + n_not_none: 53, + "50th": 1894354, + "95th": 3143323.5999999996, + stdev: 504286.7401233176, + percentage_variance: 24.864565983617446, + }, + }, + }, + length: 7, + number_of_activities: 7, + percentage: 4.19, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + [["make delivery", "start"]], + [["make delivery", "complete"]], + ], + count: 53, + percentage: 100, + }, + ], + }, + { + count: 35, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 157, + max: 17485, + mean: 2597, + median: 568, + n: 35, + n_not_none: 35, + "50th": 568, + "95th": 15542.899999999996, + stdev: 4788.305803787832, + percentage_variance: 184.37835209040554, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 15364, + max: 947677, + mean: 347881.14285714284, + median: 295926, + n: 35, + n_not_none: 35, + "50th": 295926, + "95th": 758118.2999999995, + stdev: 252659.2134188266, + percentage_variance: 72.62802787864273, + }, + service_time: { + min: 147, + max: 7217, + mean: 660.8285714285714, + median: 425, + n: 35, + n_not_none: 35, + "50th": 425, + "95th": 1277.799999999999, + stdev: 1173.129261362765, + percentage_variance: 177.52399216436842, + }, + }, + }, + { + leaf: ["send reminder"], + performance: { + wait_time: { + min: 590093, + max: 1213242, + mean: 732170.1428571428, + median: 614132, + n: 35, + n_not_none: 35, + "50th": 614132, + "95th": 1108989.9999999998, + stdev: 189014.8651826316, + percentage_variance: 25.815702405596614, + }, + service_time: { + min: 430, + max: 2695, + mean: 1201.7142857142858, + median: 1045, + n: 35, + n_not_none: 35, + "50th": 1045, + "95th": 2294.7, + stdev: 573.6472359041785, + percentage_variance: 47.73574240762303, + }, + }, + }, + { + leaf: ["send reminder"], + performance: { + wait_time: { + min: 543267, + max: 1449333, + mean: 785155.8857142857, + median: 662019, + n: 35, + n_not_none: 35, + "50th": 662019, + "95th": 1215015.4, + stdev: 247626.9811369241, + percentage_variance: 31.538575414441244, + }, + service_time: { + min: 423, + max: 2638, + mean: 1225.6285714285714, + median: 1105, + n: 35, + n_not_none: 35, + "50th": 1105, + "95th": 2439.2999999999993, + stdev: 571.0359052126379, + percentage_variance: 46.59126904548646, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 85938, + max: 867948, + mean: 347997.28571428574, + median: 331329, + n: 35, + n_not_none: 35, + "50th": 331329, + "95th": 699676.1, + stdev: 221593.49952208748, + percentage_variance: 63.67678962416424, + }, + service_time: { + min: 138, + max: 1757, + mean: 407.77142857142854, + median: 341, + n: 35, + n_not_none: 35, + "50th": 341, + "95th": 871.8999999999993, + stdev: 306.9686787734201, + percentage_variance: 75.27959471040992, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 83700, + max: 1113896, + mean: 481413.14285714284, + median: 442856, + n: 35, + n_not_none: 35, + "50th": 442856, + "95th": 1060697.9999999998, + stdev: 274251.37792255514, + percentage_variance: 56.967987266591514, + }, + service_time: { + min: 176, + max: 9597, + mean: 1192.9142857142858, + median: 385, + n: 35, + n_not_none: 35, + "50th": 385, + "95th": 9060.399999999998, + stdev: 2551.455690286586, + percentage_variance: 213.88424305429803, + }, + }, + }, + { + leaf: ["confirm payment"], + performance: { + wait_time: { + min: 23804, + max: 357954, + mean: 125982.34285714285, + median: 83579, + n: 35, + n_not_none: 35, + "50th": 83579, + "95th": 336981, + stdev: 91824.32535520103, + percentage_variance: 72.8866627439409, + }, + service_time: { + min: 153, + max: 14184, + mean: 1183.5714285714287, + median: 477, + n: 35, + n_not_none: 35, + "50th": 477, + "95th": 3864.5999999999754, + stdev: 2779.2464201408166, + percentage_variance: 234.8186474470213, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: { + min: 708, + max: 234916, + mean: 28270.742857142857, + median: 8051, + n: 35, + n_not_none: 35, + "50th": 8051, + "95th": 61847.899999999994, + stdev: 43383.65681393836, + percentage_variance: 153.45778861618095, + }, + service_time: { + min: 554, + max: 5933, + mean: 2210.9142857142856, + median: 1074, + n: 35, + n_not_none: 35, + "50th": 1074, + "95th": 5757.999999999999, + stdev: 1866.8949743834416, + percentage_variance: 84.43995257737001, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1786884, + max: 4652025, + mean: 2859551.0285714287, + median: 2522965, + n: 35, + n_not_none: 35, + "50th": 2522965, + "95th": 4319466, + stdev: 867770.6558479908, + percentage_variance: 30.346395192028126, + }, + }, + }, + length: 8, + number_of_activities: 8, + percentage: 2.76, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + [["make delivery", "start"]], + [["make delivery", "complete"]], + ], + count: 35, + percentage: 100, + }, + ], + }, + { + count: 27, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 180, + max: 16969, + mean: 2631.6296296296296, + median: 545, + n: 27, + n_not_none: 27, + "50th": 545, + "95th": 12273.199999999999, + stdev: 4617.839506057319, + percentage_variance: 175.4745217208709, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 25948, + max: 758441, + mean: 365906.1111111111, + median: 355154, + n: 27, + n_not_none: 27, + "50th": 355154, + "95th": 721041, + stdev: 208316.88031667477, + percentage_variance: 56.93178495546286, + }, + service_time: { + min: 175, + max: 7393, + mean: 701.3703703703703, + median: 405, + n: 27, + n_not_none: 27, + "50th": 405, + "95th": 1696.599999999999, + stdev: 1385.078035795155, + percentage_variance: 197.4816864681269, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 374202, + max: 1465547, + mean: 924921.9629629629, + median: 952042, + n: 27, + n_not_none: 27, + "50th": 952042, + "95th": 1439154.2, + stdev: 312738.0814043895, + percentage_variance: 33.81237487350191, + }, + service_time: { + min: 123, + max: 11684, + mean: 1294.148148148148, + median: 407, + n: 27, + n_not_none: 27, + "50th": 407, + "95th": 8246.099999999993, + stdev: 2931.5704862188654, + percentage_variance: 226.52510768676484, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 109810, + max: 1258289, + mean: 501084.14814814815, + median: 426419, + n: 27, + n_not_none: 27, + "50th": 426419, + "95th": 1145464.1999999997, + stdev: 291405.2236890837, + percentage_variance: 58.15494758036692, + }, + service_time: { + min: 174, + max: 9295, + mean: 2348.5925925925926, + median: 472, + n: 27, + n_not_none: 27, + "50th": 472, + "95th": 8993.4, + stdev: 3530.047986808931, + percentage_variance: 150.3048250234043, + }, + }, + }, + { + parallel: [ + { + leaf: ["confirm payment"], + performance: { + wait_time: null, + service_time: { + min: 160, + max: 16966, + mean: 2130.925925925926, + median: 406, + n: 27, + n_not_none: 27, + "50th": 406, + "95th": 15205.599999999997, + stdev: 4785.020544332762, + percentage_variance: 224.55123784997753, + }, + wait_time_start: { + min: 0, + max: 5016, + mean: 1245.5925925925926, + median: 748, + n: 27, + n_not_none: 27, + "50th": 748, + "95th": 3665.2, + stdev: 1429.8428977516069, + percentage_variance: 114.79218054560786, + }, + wait_time_end: { + min: 0, + max: 5074, + mean: 1630.7407407407406, + median: 1339, + n: 27, + n_not_none: 27, + "50th": 1339, + "95th": 4221.9, + stdev: 1502.1960998841405, + percentage_variance: 92.11740789659731, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: null, + service_time: { + min: 700, + max: 5987, + mean: 3457.3333333333335, + median: 3557, + n: 27, + n_not_none: 27, + "50th": 3557, + "95th": 5894.5, + stdev: 1968.9798217507305, + percentage_variance: 56.95082399973188, + }, + wait_time_start: { + min: 0, + max: 7853, + mean: 474.51851851851853, + median: 0, + n: 27, + n_not_none: 27, + "50th": 0, + "95th": 1856.5999999999988, + stdev: 1550.6066150522752, + percentage_variance: 326.7747315517595, + }, + wait_time_end: { + min: 0, + max: 16239, + mean: 1075.4074074074074, + median: 0, + n: 27, + n_not_none: 27, + "50th": 0, + "95th": 8955.49999999999, + stdev: 3903.1018656690444, + percentage_variance: 362.9416943555042, + }, + }, + }, + ], + performance: { + wait_time: { + min: 69596, + max: 330401, + mean: 129900.29629629629, + median: 86254, + n: 27, + n_not_none: 27, + "50th": 86254, + "95th": 273921.7, + stdev: 80650.43665474564, + percentage_variance: 62.086414699767815, + }, + service_time: { + min: 700, + max: 18131, + mean: 5007.259259259259, + median: 4707, + n: 27, + n_not_none: 27, + "50th": 4707, + "95th": 15761.799999999997, + stdev: 4441.399065718893, + percentage_variance: 88.69920321193683, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1289978, + max: 2931453, + mean: 1933795.5185185184, + median: 1840085, + n: 27, + n_not_none: 27, + "50th": 1840085, + "95th": 2745875.3, + stdev: 371221.0361560855, + percentage_variance: 19.196498936996097, + }, + }, + }, + length: 5, + number_of_activities: 6, + percentage: 2.13, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["make delivery", "start"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + [["make delivery", "complete"]], + ], + count: 17, + percentage: 62.96, + }, + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["confirm payment", "start"]], + [["make delivery", "start"]], + [["confirm payment", "complete"]], + [["make delivery", "complete"]], + ], + count: 6, + percentage: 22.22, + }, + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["make delivery", "start"]], + [["confirm payment", "start"]], + [["make delivery", "complete"]], + [["confirm payment", "complete"]], + ], + count: 2, + percentage: 7.41, + }, + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["confirm payment", "start"]], + [["make delivery", "start"]], + [ + ["confirm payment", "complete"], + ["make delivery", "complete"], + ], + ], + count: 1, + percentage: 3.7, + }, + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["confirm payment", "start"]], + [["make delivery", "start"]], + [["make delivery", "complete"]], + [["confirm payment", "complete"]], + ], + count: 1, + percentage: 3.7, + }, + ], + }, + { + count: 21, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 175, + max: 12980, + mean: 2801.904761904762, + median: 433, + n: 21, + n_not_none: 21, + "50th": 433, + "95th": 12875, + stdev: 4550.372807856098, + percentage_variance: 162.40283644625774, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 61594, + max: 1020303, + mean: 405486.6666666667, + median: 415418, + n: 21, + n_not_none: 21, + "50th": 415418, + "95th": 858953, + stdev: 244947.04666689356, + percentage_variance: 60.40816303048852, + }, + service_time: { + min: 181, + max: 685, + mean: 375.8095238095238, + median: 375, + n: 21, + n_not_none: 21, + "50th": 375, + "95th": 586, + stdev: 125.44027226039452, + percentage_variance: 33.37868369828035, + }, + }, + }, + { + leaf: ["send reminder"], + performance: { + wait_time: { + min: 597111, + max: 1222993, + mean: 735683, + median: 612480, + n: 21, + n_not_none: 21, + "50th": 612480, + "95th": 1190020, + stdev: 217244.2198130942, + percentage_variance: 29.529596281699348, + }, + service_time: { + min: 490, + max: 2632, + mean: 1300.2857142857142, + median: 1166, + n: 21, + n_not_none: 21, + "50th": 1166, + "95th": 2401, + stdev: 627.411917551551, + percentage_variance: 48.25185039398877, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 93118, + max: 584187, + mean: 312486.1904761905, + median: 324853, + n: 21, + n_not_none: 21, + "50th": 324853, + "95th": 503282, + stdev: 161759.13949283332, + percentage_variance: 51.76521216708243, + }, + service_time: { + min: 145, + max: 766, + mean: 348.14285714285717, + median: 280, + n: 21, + n_not_none: 21, + "50th": 280, + "95th": 561, + stdev: 162.78030768931657, + percentage_variance: 46.75675641465802, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 83681, + max: 962358, + mean: 450514.61904761905, + median: 497816, + n: 21, + n_not_none: 21, + "50th": 497816, + "95th": 691566, + stdev: 201919.17132121857, + percentage_variance: 44.819671279052514, + }, + service_time: { + min: 184, + max: 8720, + mean: 855.7142857142857, + median: 421, + n: 21, + n_not_none: 21, + "50th": 421, + "95th": 1547, + stdev: 1835.6198174692151, + percentage_variance: 214.51316731693666, + }, + }, + }, + { + parallel: [ + { + leaf: ["confirm payment"], + performance: { + wait_time: null, + service_time: { + min: 240, + max: 2008, + mean: 660.1428571428571, + median: 459, + n: 21, + n_not_none: 21, + "50th": 459, + "95th": 1509, + stdev: 454.2335616964345, + percentage_variance: 68.80837333639995, + }, + wait_time_start: { + min: 0, + max: 4975, + mean: 1164.4285714285713, + median: 608, + n: 21, + n_not_none: 21, + "50th": 608, + "95th": 4209, + stdev: 1469.037527479423, + percentage_variance: 126.15952266416343, + }, + wait_time_end: { + min: 0, + max: 5431, + mean: 1916.4285714285713, + median: 1173, + n: 21, + n_not_none: 21, + "50th": 1173, + "95th": 5298, + stdev: 1853.1477429343988, + percentage_variance: 96.69798136817587, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: null, + service_time: { + min: 616, + max: 5968, + mean: 3557.0476190476193, + median: 4641, + n: 21, + n_not_none: 21, + "50th": 4641, + "95th": 5930, + stdev: 2068.383921717399, + percentage_variance: 58.14889602943235, + }, + wait_time_start: { + min: 0, + max: 1973, + mean: 138.14285714285714, + median: 0, + n: 21, + n_not_none: 21, + "50th": 0, + "95th": 421, + stdev: 438.0841569509546, + percentage_variance: 317.1240019293363, + }, + wait_time_end: { + min: 0, + max: 801, + mean: 45.80952380952381, + median: 0, + n: 21, + n_not_none: 21, + "50th": 0, + "95th": 161, + stdev: 176.55781462388433, + percentage_variance: 385.41726685047513, + }, + }, + }, + ], + performance: { + wait_time: { + min: 64589, + max: 354270, + mean: 130053.42857142857, + median: 88482, + n: 21, + n_not_none: 21, + "50th": 88482, + "95th": 329152, + stdev: 89312.67184872, + percentage_variance: 68.67383107833045, + }, + service_time: { + min: 945, + max: 6079, + mean: 3741, + median: 4641, + n: 21, + n_not_none: 21, + "50th": 4641, + "95th": 5930, + stdev: 1929.3091509657024, + percentage_variance: 51.57201686623102, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1189817, + max: 3028386, + mean: 2043646.761904762, + median: 1888818, + n: 21, + n_not_none: 21, + "50th": 1888818, + "95th": 3024460, + stdev: 538166.6753506672, + percentage_variance: 26.333644609358714, + }, + }, + }, + length: 6, + number_of_activities: 7, + percentage: 1.66, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["make delivery", "start"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + [["make delivery", "complete"]], + ], + count: 15, + percentage: 71.43, + }, + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["confirm payment", "start"]], + [["make delivery", "start"]], + [["confirm payment", "complete"]], + [["make delivery", "complete"]], + ], + count: 4, + percentage: 19.05, + }, + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["make delivery", "start"]], + [["confirm payment", "start"]], + [["make delivery", "complete"]], + [["confirm payment", "complete"]], + ], + count: 2, + percentage: 9.52, + }, + ], + }, + { + count: 8, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 153, + max: 1009, + mean: 528.25, + median: 521, + n: 8, + n_not_none: 8, + "50th": 521, + "95th": 953.6999999999999, + stdev: 340.07593689813285, + percentage_variance: 64.37783945066406, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 66568, + max: 891646, + mean: 403112.625, + median: 339428.5, + n: 8, + n_not_none: 8, + "50th": 339428.5, + "95th": 824243.7, + stdev: 288432.99691953097, + percentage_variance: 71.55146701732077, + }, + service_time: { + min: 120, + max: 10282, + mean: 1578.5, + median: 367, + n: 8, + n_not_none: 8, + "50th": 367, + "95th": 6867.049999999995, + stdev: 3518.652745420773, + percentage_variance: 222.9111653735048, + }, + }, + }, + { + leaf: ["send reminder"], + performance: { + wait_time: { + min: 587547, + max: 1277220, + mean: 769734.25, + median: 612001.5, + n: 8, + n_not_none: 8, + "50th": 612001.5, + "95th": 1252718.5999999999, + stdev: 293033.589146242, + percentage_variance: 38.0694491827851, + }, + service_time: { + min: 494, + max: 1839, + mean: 1073.5, + median: 904, + n: 8, + n_not_none: 8, + "50th": 904, + "95th": 1746.2499999999998, + stdev: 480.45752004878494, + percentage_variance: 44.75617326956544, + }, + }, + }, + { + leaf: ["send reminder"], + performance: { + wait_time: { + min: 549555, + max: 1053050, + mean: 701395.125, + median: 645778, + n: 8, + n_not_none: 8, + "50th": 645778, + "95th": 976939.6999999998, + stdev: 164842.71126695073, + percentage_variance: 23.5021181915045, + }, + service_time: { + min: 741, + max: 2193, + mean: 1477.375, + median: 1404, + n: 8, + n_not_none: 8, + "50th": 1404, + "95th": 2159.75, + stdev: 472.5526236757734, + percentage_variance: 31.98596318983152, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 109706, + max: 491910, + mean: 302402.375, + median: 320878.5, + n: 8, + n_not_none: 8, + "50th": 320878.5, + "95th": 462824.29999999993, + stdev: 134845.83230906693, + percentage_variance: 44.591525549052626, + }, + service_time: { + min: 240, + max: 879, + mean: 464.5, + median: 325.5, + n: 8, + n_not_none: 8, + "50th": 325.5, + "95th": 876.2, + stdev: 264.35419962077935, + percentage_variance: 56.91156073644335, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 236191, + max: 626432, + mean: 461208.5, + median: 436063.5, + n: 8, + n_not_none: 8, + "50th": 436063.5, + "95th": 619289.2, + stdev: 121193.1154303506, + percentage_variance: 26.277294418977664, + }, + service_time: { + min: 221, + max: 8410, + mean: 1761.625, + median: 708.5, + n: 8, + n_not_none: 8, + "50th": 708.5, + "95th": 6041.199999999996, + stdev: 2739.1484045489133, + percentage_variance: 155.48986898737888, + }, + }, + }, + { + parallel: [ + { + leaf: ["confirm payment"], + performance: { + wait_time: null, + service_time: { + min: 219, + max: 15959, + mean: 2802.375, + median: 509, + n: 8, + n_not_none: 8, + "50th": 509, + "95th": 11168.199999999993, + stdev: 5374.358936854037, + percentage_variance: 191.77872115095366, + }, + wait_time_start: { + min: 0, + max: 3394, + mean: 1227.875, + median: 989, + n: 8, + n_not_none: 8, + "50th": 989, + "95th": 3152.1499999999996, + stdev: 1238.0153977233078, + percentage_variance: 100.82584935138412, + }, + wait_time_end: { + min: 0, + max: 680, + mean: 174.625, + median: 0, + n: 8, + n_not_none: 8, + "50th": 0, + "95th": 641.5, + stdev: 284.0920059719084, + percentage_variance: 162.68690392092105, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: null, + service_time: { + min: 641, + max: 5654, + mean: 1990.625, + median: 1429, + n: 8, + n_not_none: 8, + "50th": 1429, + "95th": 4871.749999999999, + stdev: 1706.3262070893713, + percentage_variance: 85.71811401390876, + }, + wait_time_start: { + min: 0, + max: 10824, + mean: 1353, + median: 0, + n: 8, + n_not_none: 8, + "50th": 0, + "95th": 7035.599999999995, + stdev: 3826.861899781595, + percentage_variance: 282.842712474619, + }, + wait_time_end: { + min: 0, + max: 4254, + mean: 861.25, + median: 166.5, + n: 8, + n_not_none: 8, + "50th": 166.5, + "95th": 3415.049999999999, + stdev: 1505.552841033106, + percentage_variance: 174.81019924912698, + }, + }, + }, + ], + performance: { + wait_time: { + min: 70729, + max: 257712, + mean: 105597.875, + median: 86297, + n: 8, + n_not_none: 8, + "50th": 86297, + "95th": 198872.09999999992, + stdev: 61742.69636954757, + percentage_variance: 58.46963906191064, + }, + service_time: { + min: 641, + max: 15959, + mean: 4204.875, + median: 2370.5, + n: 8, + n_not_none: 8, + "50th": 2370.5, + "95th": 12352.249999999995, + stdev: 5000.2303786211405, + percentage_variance: 118.915077823268, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1960360, + max: 4069966, + mean: 2754539.375, + median: 2410590.5, + n: 8, + n_not_none: 8, + "50th": 2410590.5, + "95th": 3952224.25, + stdev: 758369.4798884431, + percentage_variance: 27.53162604141185, + }, + }, + }, + length: 7, + number_of_activities: 8, + percentage: 0.63, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["make delivery", "start"]], + [["confirm payment", "start"]], + [["make delivery", "complete"]], + [["confirm payment", "complete"]], + ], + count: 4, + percentage: 50, + }, + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["make delivery", "start"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + [["make delivery", "complete"]], + ], + count: 3, + percentage: 37.5, + }, + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["send reminder", "start"]], + [["send reminder", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["confirm payment", "start"]], + [["make delivery", "start"]], + [["make delivery", "complete"]], + [["confirm payment", "complete"]], + ], + count: 1, + percentage: 12.5, + }, + ], + }, + { + count: 5, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 323, + max: 2113, + mean: 738.8, + median: 421, + n: 5, + n_not_none: 5, + "50th": 421, + "95th": 1787.7999999999997, + stdev: 770.8567960393162, + percentage_variance: 104.33903573894374, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 810694, + max: 1026266, + mean: 878220.8, + median: 853630, + n: 5, + n_not_none: 5, + "50th": 853630, + "95th": 994930.7999999999, + stdev: 85722.56908889281, + percentage_variance: 9.76093587044315, + }, + service_time: { + min: 219, + max: 472, + mean: 318.4, + median: 322, + n: 5, + n_not_none: 5, + "50th": 322, + "95th": 447.2, + stdev: 102.47097149924949, + percentage_variance: 32.18309406383464, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 28918, + max: 503004, + mean: 198199.6, + median: 68301, + n: 5, + n_not_none: 5, + "50th": 68301, + "95th": 471733.39999999997, + stdev: 214600.05668522086, + percentage_variance: 108.27471734817873, + }, + service_time: { + min: 248, + max: 557, + mean: 352, + median: 303, + n: 5, + n_not_none: 5, + "50th": 303, + "95th": 520.4, + stdev: 123.69518988222622, + percentage_variance: 35.140678943814265, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 75171, + max: 1041036, + mean: 479001.2, + median: 489498, + n: 5, + n_not_none: 5, + "50th": 489498, + "95th": 971755, + stdev: 410267.8428766993, + percentage_variance: 85.6506920810844, + }, + service_time: { + min: 171, + max: 8990, + mean: 2119, + median: 473, + n: 5, + n_not_none: 5, + "50th": 473, + "95th": 7301.999999999998, + stdev: 3843.6208840102845, + percentage_variance: 181.3884324686307, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: { + min: 76875, + max: 274864, + mean: 158411.2, + median: 108744, + n: 5, + n_not_none: 5, + "50th": 108744, + "95th": 270498, + stdev: 97479.84395094197, + percentage_variance: 61.53595449749889, + }, + service_time: { + min: 630, + max: 3190, + mean: 1473.6, + median: 920, + n: 5, + n_not_none: 5, + "50th": 920, + "95th": 2907.2, + stdev: 1053.8020687017083, + percentage_variance: 71.51208392384014, + }, + }, + }, + { + leaf: ["confirm payment"], + performance: { + wait_time: { + min: 3917, + max: 226686, + mean: 84866.4, + median: 78675, + n: 5, + n_not_none: 5, + "50th": 78675, + "95th": 199500.39999999997, + stdev: 87188.62030850127, + percentage_variance: 102.73632475102193, + }, + service_time: { + min: 238, + max: 641, + mean: 466.4, + median: 422, + n: 5, + n_not_none: 5, + "50th": 422, + "95th": 634.8, + stdev: 163.78736214983132, + percentage_variance: 35.117358951507576, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1396638, + max: 2139718, + mean: 1804167.4, + median: 1964114, + n: 5, + n_not_none: 5, + "50th": 1964114, + "95th": 2112079.8, + stdev: 325814.3139808317, + percentage_variance: 18.058984658565038, + }, + }, + }, + length: 6, + number_of_activities: 6, + percentage: 0.39, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["make delivery", "start"]], + [["make delivery", "complete"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + ], + count: 5, + percentage: 100, + }, + ], + }, + { + count: 2, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 307, + max: 800, + mean: 553.5, + median: 553.5, + n: 2, + n_not_none: 2, + "50th": 553.5, + "95th": 775.35, + stdev: 348.6036431249679, + percentage_variance: 62.98168800812428, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 1118823, + max: 1229690, + mean: 1174256.5, + median: 1174256.5, + n: 2, + n_not_none: 2, + "50th": 1174256.5, + "95th": 1224146.65, + stdev: 78394.80750980896, + percentage_variance: 6.6761229347939715, + }, + service_time: { + min: 399, + max: 13789, + mean: 7094, + median: 7094, + n: 2, + n_not_none: 2, + "50th": 7094, + "95th": 13119.5, + stdev: 9468.159800087871, + percentage_variance: 133.46715252449778, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 42578, + max: 73247, + mean: 57912.5, + median: 57912.5, + n: 2, + n_not_none: 2, + "50th": 57912.5, + "95th": 71713.55, + stdev: 21686.257872210226, + percentage_variance: 37.44659248385103, + }, + service_time: { + min: 346, + max: 492, + mean: 419, + median: 419, + n: 2, + n_not_none: 2, + "50th": 419, + "95th": 484.7, + stdev: 103.23759005323593, + percentage_variance: 24.63904297213268, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 174840, + max: 591286, + mean: 383063, + median: 383063, + n: 2, + n_not_none: 2, + "50th": 383063, + "95th": 570463.7, + stdev: 294471.790598013, + percentage_variance: 76.8729401163811, + }, + service_time: { + min: 231, + max: 9459, + mean: 4845, + median: 4845, + n: 2, + n_not_none: 2, + "50th": 4845, + "95th": 8997.6, + stdev: 6525.181376789461, + percentage_variance: 134.678666187605, + }, + }, + }, + { + leaf: ["confirm payment"], + performance: { + wait_time: { + min: 75371, + max: 268623, + mean: 171997, + median: 171997, + n: 2, + n_not_none: 2, + "50th": 171997, + "95th": 258960.4, + stdev: 136649.79967786267, + percentage_variance: 79.44894368963567, + }, + service_time: { + min: 444, + max: 994, + mean: 719, + median: 719, + n: 2, + n_not_none: 2, + "50th": 719, + "95th": 966.5, + stdev: 388.90872965260115, + percentage_variance: 54.090226655438265, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: { + min: 7735, + max: 59426, + mean: 33580.5, + median: 33580.5, + n: 2, + n_not_none: 2, + "50th": 33580.5, + "95th": 56841.45, + stdev: 36551.05662631383, + percentage_variance: 108.84607622374244, + }, + service_time: { + min: 546, + max: 1948, + mean: 1247, + median: 1247, + n: 2, + n_not_none: 2, + "50th": 1247, + "95th": 1877.8999999999999, + stdev: 991.3637072235397, + percentage_variance: 79.49989632907295, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1690370, + max: 1981004, + mean: 1835687, + median: 1835687, + n: 2, + n_not_none: 2, + "50th": 1835687, + "95th": 1966472.3, + stdev: 205509.27224337106, + percentage_variance: 11.19522403565374, + }, + }, + }, + length: 6, + number_of_activities: 6, + percentage: 0.16, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + [["make delivery", "start"]], + [["make delivery", "complete"]], + ], + count: 2, + percentage: 100, + }, + ], + }, + { + count: 1, + variant: { + follows: [ + { + parallel: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 13259, + max: 13259, + mean: 13259, + median: 13259, + n: 1, + n_not_none: 1, + "50th": 13259, + "95th": 13259, + }, + wait_time_start: { + min: 0, + max: 0, + mean: 0, + median: 0, + n: 1, + n_not_none: 1, + "50th": 0, + "95th": 0, + }, + wait_time_end: { + min: 0, + max: 0, + mean: 0, + median: 0, + n: 1, + n_not_none: 1, + "50th": 0, + "95th": 0, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: null, + service_time: { + min: 240, + max: 240, + mean: 240, + median: 240, + n: 1, + n_not_none: 1, + "50th": 240, + "95th": 240, + }, + wait_time_start: { + min: 4611, + max: 4611, + mean: 4611, + median: 4611, + n: 1, + n_not_none: 1, + "50th": 4611, + "95th": 4611, + }, + wait_time_end: { + min: 8408, + max: 8408, + mean: 8408, + median: 8408, + n: 1, + n_not_none: 1, + "50th": 8408, + "95th": 8408, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 13259, + max: 13259, + mean: 13259, + median: 13259, + n: 1, + n_not_none: 1, + "50th": 13259, + "95th": 13259, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 1191549, + max: 1191549, + mean: 1191549, + median: 1191549, + n: 1, + n_not_none: 1, + "50th": 1191549, + "95th": 1191549, + }, + service_time: { + min: 273, + max: 273, + mean: 273, + median: 273, + n: 1, + n_not_none: 1, + "50th": 273, + "95th": 273, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 188982, + max: 188982, + mean: 188982, + median: 188982, + n: 1, + n_not_none: 1, + "50th": 188982, + "95th": 188982, + }, + service_time: { + min: 213, + max: 213, + mean: 213, + median: 213, + n: 1, + n_not_none: 1, + "50th": 213, + "95th": 213, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: { + min: 266112, + max: 266112, + mean: 266112, + median: 266112, + n: 1, + n_not_none: 1, + "50th": 266112, + "95th": 266112, + }, + service_time: { + min: 644, + max: 644, + mean: 644, + median: 644, + n: 1, + n_not_none: 1, + "50th": 644, + "95th": 644, + }, + }, + }, + { + leaf: ["confirm payment"], + performance: { + wait_time: { + min: 65412, + max: 65412, + mean: 65412, + median: 65412, + n: 1, + n_not_none: 1, + "50th": 65412, + "95th": 65412, + }, + service_time: { + min: 263, + max: 263, + mean: 263, + median: 263, + n: 1, + n_not_none: 1, + "50th": 263, + "95th": 263, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1726707, + max: 1726707, + mean: 1726707, + median: 1726707, + n: 1, + n_not_none: 1, + "50th": 1726707, + "95th": 1726707, + }, + }, + }, + length: 5, + number_of_activities: 6, + percentage: 0.08, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["place order", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["make delivery", "start"]], + [["make delivery", "complete"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + ], + count: 1, + percentage: 100, + }, + ], + }, + { + count: 1, + variant: { + follows: [ + { + leaf: ["place order"], + performance: { + wait_time: null, + service_time: { + min: 8171, + max: 8171, + mean: 8171, + median: 8171, + n: 1, + n_not_none: 1, + "50th": 8171, + "95th": 8171, + }, + }, + }, + { + leaf: ["pay"], + performance: { + wait_time: { + min: 1129219, + max: 1129219, + mean: 1129219, + median: 1129219, + n: 1, + n_not_none: 1, + "50th": 1129219, + "95th": 1129219, + }, + service_time: { + min: 324, + max: 324, + mean: 324, + median: 324, + n: 1, + n_not_none: 1, + "50th": 324, + "95th": 324, + }, + }, + }, + { + leaf: ["send invoice"], + performance: { + wait_time: { + min: 82728, + max: 82728, + mean: 82728, + median: 82728, + n: 1, + n_not_none: 1, + "50th": 82728, + "95th": 82728, + }, + service_time: { + min: 201, + max: 201, + mean: 201, + median: 201, + n: 1, + n_not_none: 1, + "50th": 201, + "95th": 201, + }, + }, + }, + { + leaf: ["prepare delivery"], + performance: { + wait_time: { + min: 164095, + max: 164095, + mean: 164095, + median: 164095, + n: 1, + n_not_none: 1, + "50th": 164095, + "95th": 164095, + }, + service_time: { + min: 231, + max: 231, + mean: 231, + median: 231, + n: 1, + n_not_none: 1, + "50th": 231, + "95th": 231, + }, + }, + }, + { + parallel: [ + { + leaf: ["confirm payment"], + performance: { + wait_time: null, + service_time: { + min: 426, + max: 426, + mean: 426, + median: 426, + n: 1, + n_not_none: 1, + "50th": 426, + "95th": 426, + }, + wait_time_start: { + min: 4206, + max: 4206, + mean: 4206, + median: 4206, + n: 1, + n_not_none: 1, + "50th": 4206, + "95th": 4206, + }, + wait_time_end: { + min: 997, + max: 997, + mean: 997, + median: 997, + n: 1, + n_not_none: 1, + "50th": 997, + "95th": 997, + }, + }, + }, + { + leaf: ["make delivery"], + performance: { + wait_time: null, + service_time: { + min: 5629, + max: 5629, + mean: 5629, + median: 5629, + n: 1, + n_not_none: 1, + "50th": 5629, + "95th": 5629, + }, + wait_time_start: { + min: 0, + max: 0, + mean: 0, + median: 0, + n: 1, + n_not_none: 1, + "50th": 0, + "95th": 0, + }, + wait_time_end: { + min: 0, + max: 0, + mean: 0, + median: 0, + n: 1, + n_not_none: 1, + "50th": 0, + "95th": 0, + }, + }, + }, + ], + performance: { + wait_time: { + min: 95809, + max: 95809, + mean: 95809, + median: 95809, + n: 1, + n_not_none: 1, + "50th": 95809, + "95th": 95809, + }, + service_time: { + min: 5629, + max: 5629, + mean: 5629, + median: 5629, + n: 1, + n_not_none: 1, + "50th": 5629, + "95th": 5629, + }, + }, + }, + ], + performance: { + wait_time: null, + service_time: { + min: 1486407, + max: 1486407, + mean: 1486407, + median: 1486407, + n: 1, + n_not_none: 1, + "50th": 1486407, + "95th": 1486407, + }, + }, + }, + length: 5, + number_of_activities: 6, + percentage: 0.08, + sub_variants: [ + { + variant: [ + [["place order", "start"]], + [["place order", "complete"]], + [["pay", "start"]], + [["pay", "complete"]], + [["send invoice", "start"]], + [["send invoice", "complete"]], + [["prepare delivery", "start"]], + [["prepare delivery", "complete"]], + [["make delivery", "start"]], + [["confirm payment", "start"]], + [["confirm payment", "complete"]], + [["make delivery", "complete"]], + ], + count: 1, + percentage: 100, + }, + ], + }, +]; diff --git a/src/frontend/src/app/services/sharedDataService/shared-data.service.spec.ts b/src/frontend/src/app/services/sharedDataService/shared-data.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..919d862d5217e5640a8c0b90c2358145f3792eca --- /dev/null +++ b/src/frontend/src/app/services/sharedDataService/shared-data.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { SharedDataService } from './shared-data.service'; + +describe('SharedDataService', () => { + let service: SharedDataService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(SharedDataService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/sharedDataService/shared-data.service.ts b/src/frontend/src/app/services/sharedDataService/shared-data.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..cdc8ac4cdc34ff988061e8ccfecd46a7322fba56 --- /dev/null +++ b/src/frontend/src/app/services/sharedDataService/shared-data.service.ts @@ -0,0 +1,37 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable, Subject } from 'rxjs'; +import { TimeUnit } from 'src/app/objects/TimeUnit'; + +@Injectable({ + providedIn: 'root', +}) +export class SharedDataService { + constructor() {} + + public computedTextLengthCache = new Map<string, number>(); + public performanceInfoAvailable = false; + + private _treePerformance = new BehaviorSubject<Object>({}); + + get treePerformance$(): Observable<Object> { + return this._treePerformance.asObservable(); + } + + get treePerformance(): Object { + return this._treePerformance.getValue(); + } + + set treePerformance(performance) { + this._treePerformance.next(performance); + } + + private _frequentMiningResults = new BehaviorSubject<Array<any>>(null); + + get frequentMiningResults$(): Observable<Array<any>> { + return this._frequentMiningResults.asObservable(); + } + + set frequentMiningResults(res: Array<any>) { + this._frequentMiningResults.next(res); + } +} diff --git a/src/frontend/src/app/services/toast/toast.service.spec.ts b/src/frontend/src/app/services/toast/toast.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..e0413db848d0436b5ed5939ae572827fbc4ed60c --- /dev/null +++ b/src/frontend/src/app/services/toast/toast.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ToastService } from './toast.service'; + +describe('ToastService', () => { + let service: ToastService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ToastService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/toast/toast.service.ts b/src/frontend/src/app/services/toast/toast.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..1d799f72781eeeb5a79e597b61e6292a9f494985 --- /dev/null +++ b/src/frontend/src/app/services/toast/toast.service.ts @@ -0,0 +1,68 @@ +import { Injectable } from '@angular/core'; +import { Observable, Subject } from 'rxjs'; +import { ToastEvent, ToastType } from 'src/app/objects/toast-event'; + +@Injectable({ + providedIn: 'root', +}) +export class ToastService { + toastEvents: Observable<ToastEvent>; + private _toastEvents = new Subject<ToastEvent>(); + defaultDelay = 5000; + defaultAutoclose = true; + + constructor() { + this.toastEvents = this._toastEvents.asObservable(); + } + + showSuccessToast(title: string, body: string, icon: string) { + this.showToastWithOptions( + title, + body, + this.defaultDelay, + this.defaultAutoclose, + icon, + ToastType.SUCCESS + ); + } + + showWarningToast(title: string, body: string, icon: string) { + this.showToastWithOptions( + title, + body, + this.defaultDelay, + this.defaultAutoclose, + icon, + ToastType.WARNING + ); + } + + showErrorToast(title: string, body: string, icon: string) { + this.showToastWithOptions( + title, + body, + this.defaultDelay, + this.defaultAutoclose, + icon, + ToastType.ERROR + ); + } + + showToastWithOptions( + title: string, + body: string, + delay: number, + autoclose: boolean, + icon: string, + type: ToastType + ) { + this._toastEvents.next({ + title, + body, + delay, + autoclose, + icon, + type, + }); + } +} diff --git a/src/frontend/src/app/services/variant-performance.service.ts b/src/frontend/src/app/services/variant-performance.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..afd91de18055b4aa8ad4dbc53dd4254e1fb7dea9 --- /dev/null +++ b/src/frontend/src/app/services/variant-performance.service.ts @@ -0,0 +1,283 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, from, Observable, of } from 'rxjs'; +import { map, finalize, concatMap, tap, catchError } from 'rxjs/operators'; +import * as d3 from 'd3'; +import { LogService } from './logService/log.service'; +import { VariantService } from './variantService/variant.service'; + +import { + VariantElement, + LeafNode, + ParallelGroup, + SequenceGroup, + WaitingTimeNode, + deserialize, + injectWaitingTimeNodes, +} from '../objects/Variants/variant_element'; +import { BackendService } from './backendService/backend.service'; +import { setParent } from '../objects/Variants/infix_selection'; +import { ViewMode } from '../objects/ViewMode'; +import { VariantViewModeService } from './viewModeServices/variant-view-mode.service'; +import { ColorMap } from '../objects/ColorMap'; +import { COLORS_CYAN, COLORS_PINK } from '../objects/Colors'; + +@Injectable({ + providedIn: 'root', +}) +export class VariantPerformanceService { + private _serviceTimeStatistic = 'mean'; + private _waitingTimeStatistic = 'mean'; + + public performanceInformationLoaded: boolean = false; + public performanceUpdateIsInProgress: boolean = false; + public performanceUpdateProgress: number = 0; + private results = new Map<string, any>(); + + get serviceTimeStatistic() { + return this._serviceTimeStatistic; + } + + set serviceTimeStatistic(statistic) { + this._serviceTimeStatistic = statistic; + this.updateServiceTimeColorMap(); + } + + get waitingTimeStatistic() { + return this._waitingTimeStatistic; + } + + set waitingTimeStatistic(statistic) { + this._waitingTimeStatistic = statistic; + this.updateWaitingTimeColorMap(); + } + + public performanceStatsForSelectedVariantElement$: BehaviorSubject< + [any, boolean] + > = new BehaviorSubject<[any, boolean]>(undefined); + + get performanceStatsForSelectedVariantElement(): [any, boolean] { + return this.performanceStatsForSelectedVariantElement$.value; + } + + public serviceTimeColorMap = new BehaviorSubject<any>(undefined); + public waitingTimeColorMap = new BehaviorSubject<any>(undefined); + + public minValues = {}; + public maxValues = {}; + + setPerformanceStatsSelectedVariantElement( + performanceStats: any, + isServiceTime: boolean + ) { + this.performanceStatsForSelectedVariantElement$.next([ + performanceStats, + isServiceTime, + ]); + } + + constructor( + private logService: LogService, + private variantService: VariantService, + private backendService: BackendService, + private variantViewModeService: VariantViewModeService + ) { + this.logService.loadedEventLog$.subscribe((log) => { + if (log !== undefined) { + this.updateServiceTimeColorMap(); + this.updateWaitingTimeColorMap(); + this.resetVariantPerformance(); + } + }); + + this.updateServiceTimeColorMap(); + this.updateWaitingTimeColorMap(); + } + + private updateServiceTimeColorMap() { + this.serviceTimeColorMap.next( + this.computeVariantPerformanceColorMap( + COLORS_CYAN, + 'serviceTime', + this.serviceTimeStatistic + ) + ); + return this.serviceTimeColorMap; + } + + getServiceTimeColorMapAll() { + return this.getVariantsComparisonColorMap( + COLORS_CYAN, + 'serviceTime', + this.serviceTimeStatistic + ); + } + + private updateWaitingTimeColorMap() { + this.waitingTimeColorMap.next( + this.computeVariantPerformanceColorMap( + COLORS_PINK, + 'waitingTime', + this.waitingTimeStatistic + ) + ); + return this.waitingTimeColorMap; + } + + getWaitingTimeColorMapAll() { + return this.getVariantsComparisonColorMap( + COLORS_PINK, + 'waitingTime', + this.waitingTimeStatistic + ); + } + + private getVariantsComparisonColorMap( + colors, + performanceIndicator, + statistic + ) { + let values = this.variantService.variants + .map((v) => v.variant) + .map((v) => v[performanceIndicator][statistic]); + let min = Math.min(...values); + let max = Math.max(...values); + + let thresholds = [...Array(colors.length - 1).keys()] + .map((i) => i + 1) + .map((i) => min + (i / colors.length) * (max - min)); + + let colorScale = d3 + .scaleThreshold<any, any, any>() + .domain(thresholds) + .range(colors); + + return colorScale; + } + + private computeVariantPerformanceColorMap( + colors, + performanceIndicator, + value + ): ColorMap { + let values = this.getAllValues(performanceIndicator, value).filter( + (v) => v !== undefined + ); + + let min = Math.min(...values); + let max = Math.max(...values); + + if (min == max) colors = [colors[0]]; + + this.minValues[performanceIndicator] = min; + this.maxValues[performanceIndicator] = max; + + let thresholds = [...Array(colors.length - 1).keys()] + .map((i) => i + 1) + .map((i) => min + (i / colors.length) * (max - min)); + + let colorScale = d3 + .scaleThreshold<any, any, any>() + .domain(thresholds) + .range(colors); + + return new ColorMap(colorScale); + } + + getAllValues(performanceIndicator, value): number[] { + let values = []; + this.variantService.variants.forEach((variant) => { + let vElement = variant.variant; + let vs = this.getAllValuesElement(vElement, performanceIndicator, value); + values.push(...vs); + }); + return values; + } + + resetVariantPerformance(): void { + this.performanceInformationLoaded = false; + this.performanceUpdateProgress = 0; + this.results = new Map<string, any>(); + } + + getAllValuesElement( + variantElement: VariantElement, + performanceIndicator, + value + ): number[] { + let values = []; + if ( + variantElement instanceof LeafNode || + variantElement instanceof WaitingTimeNode + ) { + if (variantElement[performanceIndicator]) { + values.push(variantElement[performanceIndicator][value]); + } + } + if ( + variantElement instanceof ParallelGroup || + variantElement instanceof SequenceGroup + ) { + variantElement + .asParallelGroup() + .elements.map((el) => + this.getAllValuesElement(el, performanceIndicator, value) + ) + .forEach((v) => values.push(...v)); + } + return values; + } + + addVariantPerformanceResults(chunkResult) { + for (const [k, v] of Object.entries(chunkResult)) { + this.results.set(k, v); + } + } + + addPerformanceInformationToVariants(): Observable<any> { + this.performanceUpdateIsInProgress = true; + let chunks = []; + const maxVariantId = Math.max( + ...this.variantService.variants.map((v) => v.bid) + ); + const nVariants = this.variantService.variants.length; + for (let i = 0; i < nVariants; i += 100) { + chunks.push([i, Math.min(i + 99, maxVariantId)]); + } + + return from(chunks).pipe( + concatMap((chunk) => + this.backendService.getLogBasedPerformance(chunk[0], chunk[1]) + ), + tap((res) => { + this.addVariantPerformanceResults(res); + this.performanceUpdateProgress = this.results.size / nVariants; + }), + catchError((_) => { + this.performanceUpdateIsInProgress = false; + this.resetVariantPerformance(); + return of('error when loading performance data'); + }), + finalize(() => { + this.variantService.variants.forEach((v) => { + if (!v.userDefined) { + let newVariant = deserialize(this.results.get(v.bid.toString())); + newVariant.setExpanded(v.variant.getExpanded()); + v.variant = newVariant; + setParent(v.variant); + } + }); + this.updateServiceTimeColorMap(); + this.updateWaitingTimeColorMap(); + injectWaitingTimeNodes( + this.variantService.variants.map((v) => v.variant) + ); + + setTimeout(() => { + this.performanceInformationLoaded = true; + this.performanceUpdateIsInProgress = false; + this.variantViewModeService.viewMode = ViewMode.PERFORMANCE; + }, 1000); + }) + ); + } +} diff --git a/src/frontend/src/app/services/variantFilterService/variant-filter.service.spec.ts b/src/frontend/src/app/services/variantFilterService/variant-filter.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..c7a29d6bab519b4eddae908a8a284e6f0da536bf --- /dev/null +++ b/src/frontend/src/app/services/variantFilterService/variant-filter.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { VariantFilterService } from './variant-filter.service'; + +describe('VariantFilterService', () => { + let service: VariantFilterService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(VariantFilterService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/variantFilterService/variant-filter.service.ts b/src/frontend/src/app/services/variantFilterService/variant-filter.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..923bd8d63630218a30590389c7f5aaeee032aa83 --- /dev/null +++ b/src/frontend/src/app/services/variantFilterService/variant-filter.service.ts @@ -0,0 +1,63 @@ +import { Injectable } from '@angular/core'; +import { Transform } from 'class-transformer'; +import { BehaviorSubject } from 'rxjs'; +import { Observable } from 'rxjs/internal/Observable'; + +@Injectable({ + providedIn: 'root', +}) +export class VariantFilterService { + private _variantFilters: BehaviorSubject<Map<string, VariantFilter>> = + new BehaviorSubject<Map<string, VariantFilter>>( + new Map<string, VariantFilter>() + ); + + get variantFilters$(): Observable<Map<string, VariantFilter>> { + return this._variantFilters.asObservable(); + } + + set variantFilters(filters: Map<string, VariantFilter>) { + this._variantFilters.next(filters); + } + + get variantFilters() { + return this._variantFilters.value; + } + + constructor() {} + + addVariantFilter(filter_name: string, bids: Set<number>, tooltip) { + const newFilterMap = new Map<string, VariantFilter>(this.variantFilters); + const filter = new VariantFilter(filter_name, bids, tooltip); + + newFilterMap.set(filter_name, filter); + + this.variantFilters = newFilterMap; + } + + removeVariantFilter(filter_name) { + const newFilterMap = new Map<string, VariantFilter>(this.variantFilters); + newFilterMap.delete(filter_name); + this.variantFilters = newFilterMap; + } + + clearAllFilters() { + const newFilterMap = new Map<string, VariantFilter>(this.variantFilters); + this.variantFilters = newFilterMap; + } +} + +export class VariantFilter { + @Transform(({ value, key, obj, type }) => new Set(value), { + toClassOnly: true, + }) + bids: Set<number>; + name: string; + tooltip: string; + + constructor(name, bids, tooltip) { + this.name = name; + this.bids = bids; + this.tooltip = tooltip; + } +} diff --git a/src/frontend/src/app/services/variantQueryService/variant-query.service.spec.ts b/src/frontend/src/app/services/variantQueryService/variant-query.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..ab212321c370b0cc7010222a7938d0e7013a6701 --- /dev/null +++ b/src/frontend/src/app/services/variantQueryService/variant-query.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { VariantQueryService } from './variant-query.service'; + +describe('VariantQueryService', () => { + let service: VariantQueryService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(VariantQueryService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/variantQueryService/variant-query.service.ts b/src/frontend/src/app/services/variantQueryService/variant-query.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..83232640210156a0a08a778f18eacf866024cac3 --- /dev/null +++ b/src/frontend/src/app/services/variantQueryService/variant-query.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; +import { distinctUntilChanged } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root', +}) +export class VariantQueryService { + //TODO Refactor more Code from VariantQueryComponent into this Service + constructor() {} + + private _variantQuery: BehaviorSubject<string> = new BehaviorSubject<string>( + '' + ); + + set variantQuery(nextQuery: string) { + if (this.variantQuery !== nextQuery) { + this._variantQuery.next(nextQuery); + } + } + + get variantQuery() { + return this._variantQuery.value; + } + + get variantQuery$() { + return this._variantQuery.pipe(distinctUntilChanged()); + } +} diff --git a/src/frontend/src/app/services/variantService/variant-transformation.ts b/src/frontend/src/app/services/variantService/variant-transformation.ts new file mode 100644 index 0000000000000000000000000000000000000000..e07ab2c0c33ca069cdada2074c38956ee785b873 --- /dev/null +++ b/src/frontend/src/app/services/variantService/variant-transformation.ts @@ -0,0 +1,174 @@ +import { InfixType, setParent } from 'src/app/objects/Variants/infix_selection'; +import { Variant } from 'src/app/objects/Variants/variant'; +import * as objectHash from 'object-hash'; + +export function compute_delete_activity_variants( + activityName: string, + cur_variants: Variant[] +): [Variant[], any[], any[], any[], any[]] { + const fallthrough = []; + const updateMap: Map<string, Variant[]> = new Map<string, Variant[]>(); + const changedStrings: Set<string> = new Set<string>(); + const delete_list = []; + + for (let variant of cur_variants) { + let tmp; + + if (variant.variant.getActivities().has(activityName)) { + const [variantElements, isFallthrough] = + variant.variant.deleteActivity(activityName); + + if (isFallthrough) { + fallthrough.push(variant.bid); + continue; + } + + if (variantElements) { + tmp = variantElements[0].asString(); + changedStrings.add(tmp); + + if (updateMap.has(tmp)) { + updateMap.get(tmp).push(variant); + } else { + updateMap.set(tmp, [variant]); + } + } else { + delete_list.push(variant); + } + } else { + tmp = variant.variant.asString(); + + if (updateMap.has(tmp)) { + updateMap.get(tmp).push(variant); + } else { + updateMap.set(tmp, [variant]); + } + } + } + + const variants = apply_update_map(updateMap); + + let delete_member_list = []; + let merge_list = []; + + for (let change of changedStrings) { + if (updateMap.get(change).length == 1) { + delete_member_list.push(updateMap.get(change)[0].bid); + } else { + merge_list.push( + updateMap.get(change).map((v) => { + return v.bid; + }) + ); + } + } + + return [variants, fallthrough, delete_member_list, merge_list, delete_list]; +} + +export function apply_update_map(updateMap: Map<string, Variant[]>): Variant[] { + const variants: Variant[] = []; + + for (let [key, ls] of updateMap.entries()) { + if (ls.length > 1) { + let count = 0; + let bids = []; + let selected = false; + let userAdded = false; + + for (let variant of ls) { + bids.push(variant.bid); + count += variant.count; + selected = selected || variant.isSelected; + userAdded = userAdded || variant.isAddedFittingVariant; + } + + const variant: Variant = new Variant( + count, + ls[0].variant, + selected, + true, + userAdded, + 0, + false, + false, + false, + true, + 0, + InfixType.NOT_AN_INFIX + ); + variant.bid = Math.min(...bids); + variant.id = objectHash(ls[0].variant); + + variants.push(variant); + } else { + variants.push(ls[0]); + } + } + + return variants; +} + +export function compute_rename_activity_variants( + activityName: string, + newActivityName: string, + cur_variants: Variant[] +): [Variant[], any[], any[], Map<string, Variant[]>] { + const updateMap: Map<string, Variant[]> = new Map<string, Variant[]>(); + const changedStrings: Set<string> = new Set<string>(); + + for (let variant of cur_variants) { + let change: boolean = false; + + if (variant.variant.getActivities().has(activityName)) { + variant.variant.renameActivity(activityName, newActivityName); + + change = true; + } + + const tmp = variant.variant.asString(); + + if (updateMap.has(tmp)) { + updateMap.get(tmp).push(variant); + } else { + updateMap.set(tmp, [variant]); + } + + if (change) { + changedStrings.add(tmp); + } + } + + const variants = apply_update_map(updateMap); + + let rename_list = []; + let merge_list = []; + + for (let change of changedStrings) { + if (updateMap.get(change).length == 1) { + rename_list.push(updateMap.get(change)[0].bid); + } else { + merge_list.push( + updateMap.get(change).map((v) => { + return v.bid; + }) + ); + } + } + + return [variants, rename_list, merge_list, updateMap]; +} + +export function addVariantInformation(variants: Variant[]): Variant[] { + variants.forEach((v, i) => { + v.isConformanceOutdated = true; + v.isTimeouted = false; + v.isSelected = false; + v.isDisplayed = true; + v.isAddedFittingVariant = false; + v.infixType = v.infixType; + setParent(v.variant); + }); + + return variants; +} diff --git a/src/frontend/src/app/services/variantService/variant.service.spec.ts b/src/frontend/src/app/services/variantService/variant.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..0b606c6b7576847abb7aa82ccb8b2fdb9349853e --- /dev/null +++ b/src/frontend/src/app/services/variantService/variant.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { VariantService } from './variant.service'; + +describe('VariantService', () => { + let service: VariantService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(VariantService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/variantService/variant.service.ts b/src/frontend/src/app/services/variantService/variant.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..729426cd6c39edc0fdf5dffcdd87c93e71054b35 --- /dev/null +++ b/src/frontend/src/app/services/variantService/variant.service.ts @@ -0,0 +1,501 @@ +import { VariantFilterService } from './../variantFilterService/variant-filter.service'; +import { ColorMapService } from 'src/app/services/colorMapService/color-map.service'; +import { ProcessTreeService } from 'src/app/services/processTreeService/process-tree.service'; +import { LogService } from 'src/app/services/logService/log.service'; +import * as objectHash from 'object-hash'; +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable, Subject } from 'rxjs'; +import { map, mergeMap, tap } from 'rxjs/operators'; +import { v4 as uuidv4 } from 'uuid'; +import { + getInfixTypeForSelectedInfix, + getSelectedChildren, + InfixType, + removeIntermediateGroupsWithSingleElements, +} from 'src/app/objects/Variants/infix_selection'; +import { FragmentStatistics, Variant } from 'src/app/objects/Variants/variant'; +import { + deserialize, + SequenceGroup, +} from 'src/app/objects/Variants/variant_element'; +import { + addVariantInformation, + compute_delete_activity_variants, + compute_rename_activity_variants, +} from './variant-transformation'; +import { ToastService } from '../toast/toast.service'; +import { VariantSorter } from 'src/app/objects/Variants/variant-sorter'; +import { LoopCollapsedVariant } from 'src/app/objects/Variants/loop_collapsed_variant'; +import { ClusteringConfig } from 'src/app/objects/ClusteringConfig'; +import { BackendService } from '../backendService/backend.service'; +import { + ActivityDeletion, + ActivityRenaming, + UserDefinedInfixAddition, + UserDefinedVariantAddition, + VariantsDeletion, +} from 'src/app/objects/LogModification'; + +@Injectable({ + providedIn: 'root', +}) +export class VariantService { + variantService: any; + nameChanges: BehaviorSubject<any> = new BehaviorSubject<any>(null); + + // reference for activity element to manually hide tooltips on activities upon click + private _activityTooltipReference; + get activityTooltipReference() { + return this._activityTooltipReference; + } + + set activityTooltipReference(value) { + this._activityTooltipReference = value; + } + + constructor( + private logService: LogService, + private processTreeService: ProcessTreeService, + private colorMapService: ColorMapService, + private toastService: ToastService, + private variantFilterService: VariantFilterService, + private backendService: BackendService + ) { + this.logService.loadedEventLog$.subscribe(() => { + this.variantFilterService.clearAllFilters(); + if (this.logService.variants) { + this.variants = this.logService.variants; + this.cachedChange = false; + } + }); + } + + public showVariantSequentializerDialog: Subject<any> = new Subject<any>(); + private _variants = new BehaviorSubject<Variant[]>([]); + private _collapsedVariants = new BehaviorSubject<LoopCollapsedVariant[]>( + null + ); + public areVariantLoopsCollapsed = false; + + set collapsedVariants(variants: LoopCollapsedVariant[]) { + this._collapsedVariants.next(variants); + } + + get collapsedVariants$(): Observable<LoopCollapsedVariant[]> { + return this._collapsedVariants.asObservable(); + } + + get variants$(): Observable<Variant[]> { + return this._variants.asObservable(); + } + + set variants(activities: Variant[]) { + this._variants.next(activities); + } + + get variants(): Variant[] { + return this._variants.getValue(); + } + + private _clusteringConfig = new BehaviorSubject<ClusteringConfig>(null); + + set clusteringConfig(clusteringConfig: ClusteringConfig) { + if (clusteringConfig) { + this.computeClusterClustering(clusteringConfig); + } else { + this.resetClusterAssignments(); + } + this._clusteringConfig.next(clusteringConfig); + } + + get clusteringConfig(): ClusteringConfig { + return this._clusteringConfig.getValue(); + } + + get clusteringConfig$(): Observable<ClusteringConfig> { + return this._clusteringConfig.asObservable(); + } + + public lastChangeRenaming = null; + private _cachedChange = new BehaviorSubject<boolean>(false); + + get cachedChange$(): Observable<boolean> { + return this._cachedChange.asObservable(); + } + + set cachedChange(change: boolean) { + this.lastChangeRenaming = null; + this._cachedChange.next(change); + } + + get cachedChange(): boolean { + return this._cachedChange.getValue(); + } + + // TODO Add Spinner Removal / Toast etc. + private afterVariantChange() { + this.variantFilterService.clearAllFilters(); + } + + public nUserVariants: number = 0; + + public addSelectedTraceInfix( + variant: Variant, + sortingFeature: string, + isAscending: boolean + ): void { + let isWholeVariantSelected = variant.variant.selected; + + if (isWholeVariantSelected) { + this.toastService.showWarningToast( + 'Variant Explorer', + `A complete variant is selected. It will not be added.`, + 'bi-list-ul' + ); + + return; + } + + let infixType: InfixType = getInfixTypeForSelectedInfix(variant); + + let newInfix = getSelectedChildren(variant.variant); + let reducedInfix = removeIntermediateGroupsWithSingleElements(newInfix); + if (!(reducedInfix instanceof SequenceGroup)) { + // Every variant should be a sequence group + reducedInfix = new SequenceGroup([reducedInfix]); + } + reducedInfix.parent = null; + const newVariant = new Variant( + 0, + reducedInfix, + false, + true, + false, + 0, + false, + true, + false, + true, + 0, + infixType + ); + + let currentVariants = this.variants; + + newVariant.alignment = undefined; + newVariant.deviations = undefined; + newVariant.id = objectHash(newVariant); + + const containsDuplicate = + currentVariants.filter((v) => v.id === newVariant.id).length > 0; + + if (containsDuplicate) { + this.toastService.showWarningToast( + 'Variant Explorer', + `The selected infix is already present in the variant explorer. It will not be added.`, + 'bi-list-ul' + ); + + return; + } + + this.nUserVariants += 1; + newVariant.bid = -this.nUserVariants; + + this.addInfixToBackend(newVariant) + .pipe( + mergeMap(() => this.backendService.countFragmentOccurrences(newVariant)) + ) + .subscribe((statistics: FragmentStatistics) => { + newVariant.count = statistics.traceOccurrences; + newVariant.fragmentStatistics = statistics; + currentVariants.push(newVariant); + this.variants = currentVariants; + + let sortedVariants = VariantSorter.sort( + this.variants, + sortingFeature, + isAscending + ) as Variant[]; + + this.toastService.showSuccessToast( + 'Variant Explorer', + `The selected infix is added at position ${ + sortedVariants.indexOf(newVariant) + 1 + }.`, + 'bi-list-ul' + ); + variant.variant.resetSelectionStatus(); + }); + } + + public deleteVariant(bid: number): void { + this.deleteVariants([bid]).subscribe(); + } + + public deleteVariants(bids: number[]): Observable<any> { + this.logService.logModifications.push(new VariantsDeletion(bids)); + return this.backendService.deleteVariants(bids).pipe( + tap((res) => { + this.logService.activitiesInEventLog = res['activities']; + this.logService.startActivitiesInEventLog = new Set( + res['startActivities'] + ); + this.logService.endActivitiesInEventLog = new Set(res['endActivities']); + + let filtered_variants = this.variants.filter( + (v) => !bids.includes(v.bid) + ); + + this.logService.computeLogStats(filtered_variants); + this.variants = filtered_variants; + this.cachedChange = true; + }) + ); + // Count deleted Activites, Recompute if an Activity is a Start or End Activity. + } + + /** + * Computes a mapping that maps the bid of each variant to + * a cluster. + * @param clusteringConfig + * @returns mapping of each bid to a clusterId + */ + private computeClusterClustering(clusteringConfig: ClusteringConfig) { + this.backendService + .computeClusters(clusteringConfig) + .pipe(map(this.createBidToClusterIdMapping())) + .subscribe((clusterMap) => { + this.assignClusters(clusterMap); + }); + } + + private assignClusters(clusterMap: any) { + this.variants = this.variants.map((variant: Variant) => { + variant.clusterId = clusterMap[variant.bid]; + return variant; + }); + } + + private createBidToClusterIdMapping() { + return (clusters: Variant[][]) => { + let result = {}; + clusters.forEach((cluster, clusterId) => { + cluster.forEach((variant) => (result[variant.bid] = clusterId)); + }); + return result; + }; + } + + private resetClusterAssignments() { + this.variants.forEach((variant) => { + // undefined is the default cluster id when no algorithm was applied + variant.clusterId = -1; + }); + + this.variants = this.variants; + } + + public deleteActivity(activityName: string) { + this.logService.logModifications.push(new ActivityDeletion(activityName)); + const [variants, fallthrough, delete_member_list, merge_list, delete_list] = + compute_delete_activity_variants(activityName, this.variants); + + this.logService.deleteActivityInEventLog(activityName); + + return this.backendService + .deleteActivity( + activityName, + fallthrough, + delete_member_list, + merge_list, + delete_list.map((v) => v.bid) + ) + .pipe( + tap((res) => { + this.logService.startActivitiesInEventLog = new Set( + res['startActivities'] + ); + + this.logService.endActivitiesInEventLog = new Set( + res['endActivities'] + ); + + variants.forEach((v) => { + for (let bid of Object.keys(res['update_variants'])) { + if (v.bid.toString() === bid) { + v.nSubVariants = res['update_variants'][v.bid]['nSubVariants']; + v.count = res['update_variants'][v.bid]['count']; + } + } + }); + + res['new_variants'].forEach((variant) => { + variant['id'] = objectHash(variant['variant']); + variant['variant'] = deserialize(variant.variant); + }); + + const new_variants = addVariantInformation(res['new_variants']); + + variants.push(...new_variants); + + this.cachedChange = true; + this.logService.computeLogStats(variants); + + this.afterVariantChange(); + this.variants = variants; + }) + ); + } + + public renameActivity(activityName: string, newActivityName: string) { + this.logService.logModifications.push( + new ActivityRenaming(activityName, newActivityName) + ); + + const [variants, rename_list, merge_list, updateMap] = + compute_rename_activity_variants( + activityName, + newActivityName, + this.variants + ); + + this.logService.renameActivitiesInEventLog(activityName, newActivityName); + this.processTreeService.renameActivityInProcessTree( + activityName, + newActivityName + ); + + this.colorMapService.renameColorInActivityColorMap( + activityName, + newActivityName + ); + + return this.backendService + .changeActivityName( + merge_list, + rename_list, + activityName, + newActivityName + ) + .pipe( + tap((res) => { + variants.forEach((v) => { + for (let bid of Object.keys(res)) { + if (v.bid.toString() === bid) { + v.nSubVariants = res[v.bid]['nSubVariants']; + } + } + }); + + this.afterVariantChange(); + this.variants = variants; + + this.logService.update_log_stats(null, null, null, updateMap.size); + this.cachedChange = true; + this.lastChangeRenaming = [activityName, newActivityName]; + this.nameChanges.next([activityName, newActivityName]); + }) + ); + } + + revertChangeInBackend() { + this.backendService.revertLastLogModification().subscribe((res) => { + this.logService.activitiesInEventLog = res['activities']; + this.logService.startActivitiesInEventLog = new Set( + res['startActivities'] + ); + this.logService.endActivitiesInEventLog = new Set(res['endActivities']); + + this.logService.performanceInfoAvailable = true; + this.logService.timeGranularity = res['timeGranularity']; + this.logService.logGranularity = res['timeGranularity']; + + const lastNameChange = this.lastChangeRenaming; + this.cachedChange = false; + + const variants = addVariantInformation(res['variants']); + this.afterVariantChange(); + + this.variants = variants; + this.logService.computeLogStats(variants); + if (lastNameChange !== null) { + this.nameChanges.next([lastNameChange[1], lastNameChange[0]]); + } + }); + } + + public addUserDefinedVariant(variant: Variant) { + this.logService.logModifications.push( + new UserDefinedVariantAddition(variant) + ); + return this.backendService.addUserDefinedVariant(variant).pipe( + tap( + (res) => console.log(res), + (err) => console.log('error ' + err) + ) + ); + } + + public expandCollapseLoopsInVariants() { + if (this.areVariantLoopsCollapsed) { + this.collapsedVariants = null; + } else { + this.loadLoopCollapsedVariants(); + this.toastService.showWarningToast( + 'Variant Explorer', + `Disabled severeal features that are not applicable after collapsing loops.`, + 'bi-arrow-repeat' + ); + } + this.areVariantLoopsCollapsed = !this.areVariantLoopsCollapsed; + } + + private loadLoopCollapsedVariants() { + this.backendService.getCollapsedVariants().subscribe((res) => { + let collapsedVariants = []; + + let bidToVariant = new Map<number, Variant>(); + for (let variant of this.variants) { + bidToVariant.set(variant.bid, variant); + } + + for (let idx in res) { + let collapsedVariant = res[idx]; + + let underlyingVariants = []; + + for (let bid of collapsedVariant['ids']) { + underlyingVariants.push(bidToVariant.get(bid)); + } + + collapsedVariants.push( + new LoopCollapsedVariant( + uuidv4(), + underlyingVariants, + deserialize(collapsedVariant['variant']) + ) + ); + } + + this.collapsedVariants = collapsedVariants; + }); + } + + public addInfixToBackend(variant: Variant) { + this.logService.logModifications.push( + new UserDefinedInfixAddition(variant) + ); + return this.backendService.addUserDefinedInfix(variant).pipe( + tap( + (_) => console.log('successfully added infix to backend'), + (_) => + this.toastService.showErrorToast( + 'Variant Explorer', + `Adding the selected infix failed`, + 'bi-exclamation-circle' + ) + ) + ); + } +} diff --git a/src/frontend/src/app/services/viewModeServices/model-view-mode.service.spec.ts b/src/frontend/src/app/services/viewModeServices/model-view-mode.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..7b2b395b0a5d034cb8e315ce83d9d2d4e85f1af9 --- /dev/null +++ b/src/frontend/src/app/services/viewModeServices/model-view-mode.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ModelViewModeService } from './model-view-mode.service'; + +describe('ModelViewModeService', () => { + let service: ModelViewModeService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ModelViewModeService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/viewModeServices/model-view-mode.service.ts b/src/frontend/src/app/services/viewModeServices/model-view-mode.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..2c008db4ad3180b28aa3cce9382056fe80ee9615 --- /dev/null +++ b/src/frontend/src/app/services/viewModeServices/model-view-mode.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; +import { distinctUntilChanged } from 'rxjs/operators'; +import { ViewMode } from 'src/app/objects/ViewMode'; + +@Injectable({ + providedIn: 'root', +}) +export class ModelViewModeService { + private _viewMode: BehaviorSubject<ViewMode> = new BehaviorSubject<ViewMode>( + ViewMode.STANDARD + ); + + set viewMode(nextViewMode: ViewMode) { + if (this.viewMode !== nextViewMode) { + this._viewMode.next(nextViewMode); + } + } + + get viewMode() { + return this._viewMode.value; + } + + get viewMode$() { + return this._viewMode.pipe(distinctUntilChanged()); + } +} diff --git a/src/frontend/src/app/services/viewModeServices/variant-view-mode.service.spec.ts b/src/frontend/src/app/services/viewModeServices/variant-view-mode.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..7cb282fc158d16db7b11b0c688d5dc22036fc127 --- /dev/null +++ b/src/frontend/src/app/services/viewModeServices/variant-view-mode.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { VariantViewModeService } from './variant-view-mode.service'; + +describe('VariantViewModeService', () => { + let service: VariantViewModeService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(VariantViewModeService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/frontend/src/app/services/viewModeServices/variant-view-mode.service.ts b/src/frontend/src/app/services/viewModeServices/variant-view-mode.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..79f70be0aaa6ca119fbda9a5bd56d0d486d3fbc1 --- /dev/null +++ b/src/frontend/src/app/services/viewModeServices/variant-view-mode.service.ts @@ -0,0 +1,47 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; +import { distinctUntilChanged } from 'rxjs/operators'; +import { ViewMode } from 'src/app/objects/ViewMode'; +import { ConformanceCheckingService } from '../conformanceChecking/conformance-checking.service'; +import { PerformanceService } from '../performance.service'; +import { ModelViewModeService } from './model-view-mode.service'; + +@Injectable({ + providedIn: 'root', +}) +export class VariantViewModeService { + constructor( + private modelViewModeService: ModelViewModeService, + private conformanceCheckingService: ConformanceCheckingService, + private performanceService: PerformanceService + ) {} + + private _viewMode: BehaviorSubject<ViewMode> = new BehaviorSubject<ViewMode>( + ViewMode.STANDARD + ); + + set viewMode(nextViewMode: ViewMode) { + if (this.viewMode !== nextViewMode) { + this._viewMode.next(nextViewMode); + + if ( + (nextViewMode === ViewMode.CONFORMANCE && + !this.conformanceCheckingService.anyTreeConformanceActive()) || + (nextViewMode === ViewMode.PERFORMANCE && + !this.performanceService.anyTreePerformanceActive()) + ) { + this.modelViewModeService.viewMode = ViewMode.STANDARD; + } else { + this.modelViewModeService.viewMode = nextViewMode; + } + } + } + + get viewMode() { + return this._viewMode.value; + } + + get viewMode$() { + return this._viewMode.pipe(distinctUntilChanged()); + } +} diff --git a/src/frontend/src/app/utils/render-utils.ts b/src/frontend/src/app/utils/render-utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..1cba4dc0733a0af663e0632f4f298c8b3e086e7f --- /dev/null +++ b/src/frontend/src/app/utils/render-utils.ts @@ -0,0 +1,265 @@ +import { VariantDrawerDirective } from '../directives/variant-drawer/variant-drawer.directive'; +import * as d3 from 'd3'; +import { Selection } from 'd3'; +import { PT_Constant } from '../constants/process_tree_drawer_constants'; +import { + GroupsWithChildElements, + LeafNode, + VariantElement, + WaitingTimeNode, +} from '../objects/Variants/variant_element'; +import { Variant } from '../objects/Variants/variant'; +import { ElementRef } from '@angular/core'; +import { ConformanceCheckingService } from '../services/conformanceChecking/conformance-checking.service'; + +export function textColorForBackgroundColor( + backgroundColorInHex: string, + unselectedElementInTraceInfixSelectionMode: boolean = false +): string { + if ( + backgroundColorInHex === undefined || + unselectedElementInTraceInfixSelectionMode + ) { + return 'white'; + } + if (!backgroundColorInHex.startsWith('#')) return 'black'; + return isDarkColor(backgroundColorInHex) ? 'white' : 'black'; + + function isDarkColor(color: string): boolean { + let res; + if (color === undefined) { + return true; + } + if (color.includes('rgb')) { + res = rgbToArray(color); + } else { + res = hexToRgb(color); + } + if (0.2126 * res['r'] + 0.7152 * res['g'] + 0.0722 * res['b'] >= 135) { + return false; + } else { + return true; + } + } + + function hexToRgb(hex) { + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result + ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16), + } + : null; + } + + function rgbToArray(rgb) { + let arr = rgb.slice(4, -1).split(','); + return { + r: arr[0], + g: arr[1], + b: arr[2], + }; + } +} + +export function applyInverseStrokeToPoly(poly: Selection<any, any, any, any>) { + const datum = poly.data()[0]; + if (datum) { + if (datum instanceof LeafNode) { + const rgb_code = poly.attr('style').match(/[\d.]+/g); + const inversed = rgb_code.map((d) => 255 - parseInt(d)); + + poly.attr('style', poly.attr('style').split(';')[0]); + poly.attr('stroke-width', 2); + poly.attr( + 'stroke', + `rgb(${inversed[0]}, ${inversed[1]}, ${inversed[2]})` + ); + } else { + poly + .attr('stroke', '#dc3545') + .attr('style', poly.attr('style').split(';')[0]) + .attr('stroke-width', 2); + } + } +} + +export function computeLeafNodeWidth( + nodeActivityLabels: string[], + nodeWidthCache: Map<string, number> +): Map<string, number> { + const dummy_container = d3 + .select('body') + .append('svg') + .style('top', '0px') + .style('left', '0px') + .style('position', 'absolute'); + + const dummy_select = dummy_container.append('text').attr('font-size', '12px'); + + let labels = nodeActivityLabels; + labels.push('...'); + + for (let nodeActivityLabel of labels) { + // Compute the width by rendering a dummy node + dummy_select.text(function (d: any) { + if (nodeActivityLabel.length <= 20) { + return nodeActivityLabel; + } else { + return nodeActivityLabel.substring(0, 20) + '...'; + } + }); + + // Retrieve the computed width + let rendered_width = dummy_select.node().getComputedTextLength(); + + // Compute the true node width as specified above + rendered_width = Math.max( + rendered_width + 10, + PT_Constant.BASE_HEIGHT_WIDTH + ); + + // Add to Cache + nodeWidthCache[nodeActivityLabel] = rendered_width; + } + + // Delete the Dummy + dummy_select.remove(); + dummy_container.remove(); + + return nodeWidthCache; +} + +export function computeActivityColor( + self: VariantDrawerDirective, + element: VariantElement, + variant: Variant +) { + let color; + color = this.colorMap.get(element.asLeafNode().activity[0]); + + if (!color) { + color = '#d3d3d3'; // lightgrey + } + + return color; +} + +export function setChevronIdsForArcDiagrams( + variant: VariantElement, + drawer: VariantDrawerDirective +) { + setDfsIds(variant, drawer.svgSelection, true); + setBfsIds(drawer.svgHtmlElement); +} + +const setDfsIds = ( + element: VariantElement, + svgElement: Selection<any, any, any, any>, + outerElement: boolean = false +) => { + if (!outerElement) { + svgElement.classed(`dfs-group-${element.id}`, true); + } else { + svgElement = svgElement + .select('.variant-element-group') + .classed('dfs-group-0', true); + } + + if (element instanceof LeafNode || element instanceof WaitingTimeNode) { + return; + } else { + (element as GroupsWithChildElements).elements.forEach((child, index) => { + const svg = d3.select( + svgElement + .selectAll(`.dfs-group-${element.id} > .variant-element-group`) + .nodes()[index] + ); + setDfsIds(child, svg); + }); + } +}; + +const setBfsIds = (svgElement: ElementRef<any>) => { + let outerElement = svgElement.nativeElement.querySelector('.dfs-group-0'); + + if (outerElement) { + d3.select( + outerElement.querySelectorAll(':scope > .variant-element-group') + ).each(function (d, i) { + let offset = 1; + this.forEach((child) => { + d3.select(child).classed(`bfs-group-${offset++}`, true); + }); + }); + } +}; + +export function addPatternDefinitions( + parentElement: Selection<any, any, any, any>, + conformanceCheckingService: ConformanceCheckingService +) { + const svg = parentElement.append('svg'); + + const defs = svg.append('defs'); + const whiteStripePattern = defs + .append('pattern') + .attr('id', 'whiteStriped') + .attr('width', '6') + .attr('height', '8') + .attr('patternUnits', 'userSpaceOnUse') + .attr('patternTransform', 'rotate(45)'); + whiteStripePattern + .append('rect') + .attr('width', '4') + .attr('height', '8') + .attr('transform', 'translate(2,0)') + .attr('fill', '#FFFFFF'); + whiteStripePattern + .append('rect') + .attr('width', '2') + .attr('height', '8') + .attr('transform', 'translate(0,0)') + .attr('fill', '#EEEEEE'); + + const modelConformanceStripePattern = defs + .append('pattern') + .attr('id', 'modelConformanceStriped') + .attr('width', '6') + .attr('height', '8') + .attr('patternUnits', 'userSpaceOnUse') + .attr('patternTransform', 'rotate(45)'); + modelConformanceStripePattern + .append('rect') + .attr('width', '4') + .attr('height', '8') + .attr('transform', 'translate(2,0)') + .attr('fill', conformanceCheckingService.modelConformanceStripeColors[0]); + modelConformanceStripePattern + .append('rect') + .attr('width', '2') + .attr('height', '8') + .attr('transform', 'translate(0,0)') + .attr('fill', conformanceCheckingService.modelConformanceStripeColors[1]); + + const variantConformanceStripePattern = defs + .append('pattern') + .attr('id', 'variantConformanceStriped') + .attr('width', '6') + .attr('height', '8') + .attr('patternUnits', 'userSpaceOnUse') + .attr('patternTransform', 'rotate(45)'); + variantConformanceStripePattern + .append('rect') + .attr('width', '4') + .attr('height', '8') + .attr('transform', 'translate(2,0)') + .attr('fill', conformanceCheckingService.variantConformanceStripeColors[0]); + variantConformanceStripePattern + .append('rect') + .attr('width', '2') + .attr('height', '8') + .attr('transform', 'translate(0,0)') + .attr('fill', conformanceCheckingService.variantConformanceStripeColors[1]); +} diff --git a/src/frontend/src/app/utils/util.ts b/src/frontend/src/app/utils/util.ts new file mode 100644 index 0000000000000000000000000000000000000000..88ff0fd04eca88bbec6a8901e4f4c2e20935024c --- /dev/null +++ b/src/frontend/src/app/utils/util.ts @@ -0,0 +1,68 @@ +import { KeyValue } from '@angular/common'; +import * as objectHash from 'object-hash'; +import { OperatorFunction } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { Variant } from '../objects/Variants/variant'; +import { deserialize } from '../objects/Variants/variant_element'; + +export function originalOrder( + a: KeyValue<number, string>, + b: KeyValue<number, string> +): number { + return 0; +} + +export function transformVariants(properties) { + properties['variants'].forEach((variant, i) => { + variant['id'] = objectHash(variant['variant']); + variant['variant'] = deserialize(variant.variant); + }); + return properties; +} + +export function transformVariantList(variants: Variant[]) { + variants.forEach((variant, i) => { + variant['id'] = objectHash(variant['variant']); + variant['variant'] = deserialize(variant.variant); + }); + return variants; +} + +export function mapVariantsList(): OperatorFunction<any, any> { + return map((result) => { + return transformVariantList(result); + }); +} + +export function mapVariants(): OperatorFunction<any, any> { + return map((result) => { + return transformVariants(result); + }); +} + +export function blobToBase64(blob) { + return new Promise((resolve, _) => { + const reader = new FileReader(); + reader.onloadend = () => resolve(reader.result); + reader.readAsDataURL(blob); + }); +} + +export function isUndefined(value: any) { + return typeof value === 'undefined'; +} + +export function extractDeepPropertyByMapKey(obj: any, map: string): any { + const keys = map.split('.'); + const head = keys.shift(); + + return keys.reduce((prop: any, key: string) => { + return !isUndefined(prop) && prop != null && !isUndefined(prop[key]) + ? prop[key] + : undefined; + }, obj[head || '']); +} + +export function isFunction(value: any) { + return typeof value === 'function'; +} diff --git a/src/frontend/src/assets/doc/contribution_guidelines.md b/src/frontend/src/assets/doc/contribution_guidelines.md new file mode 100644 index 0000000000000000000000000000000000000000..05d470f4054e9986466636d1e819f7a8683e94fa --- /dev/null +++ b/src/frontend/src/assets/doc/contribution_guidelines.md @@ -0,0 +1,59 @@ +# Contribution Guidelines + +Internal Notes (remove or move to different location before publication) + +## Sizing images / GIFs in the markdown: +* Size of images and GIFs can be specified the following way: + * `` + * The `medium` above specifies the width of the image/GIF used. + * Possible other sizes can be `xsmall`, `small`, `medium`, `large`, `xlarge`, `xxlarge` + +## Creating Screenshots + +Screenshots can be captured consistently by using the fixed cortado window of electron. + +### Screenshot without border + + + +### Screenshot with border + +|| +- + +### Producing GIFs + +* Use https://www.screentogif.com/screenshots for creating GIFs similar to the ones below. +* Any part of the screen can be put into the frame that records the GIF. +* There's also a convenient way to post-process and edit the recorded GIFs. +* It should also be made sure to crop out the extra cursor movements at the start or end of the recordings. + +|| +- + +|| +- + +### Drawing boxes on screenshots: + + * Drawing numbered boxes on images to refer to sections: + * Box: Rectangle with 3px border. + * Number Text: Calibri, size: 26pt, Bold. + * Color Palette for box border and text: + * Red: #C7171E + * Green: #22B14C + * Purple: #C659C7 + * Blue: #00A2E8 + * Yellow/Gold: #FFC90E + * See example below which was produced using **paint** in **windows**: + +|| +- + + + +## Referring to buttons / icons: + * Examples: + * Use (<i class="bi bi-diagram-2-fill btn-icon">discover initial model</i>) button to discover an initial model. + * Click `Files` → <i class="bi bi-file-earmark-arrow-up btn-icon"></i>`Import process tree (.ptml)` to import an existing process tree from a file. +* Use `code blocks` for referring to something in the UI like a button, an item in the menu or any displayed label in Cortado. diff --git a/src/frontend/src/assets/doc/screenshots/.gitkeep b/src/frontend/src/assets/doc/screenshots/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/assets/doc/screenshots/box_example.png b/src/frontend/src/assets/doc/screenshots/box_example.png new file mode 100644 index 0000000000000000000000000000000000000000..0fea3f8bf494ec9c9418e6bf17122cb08878e728 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/box_example.png differ diff --git a/src/frontend/src/assets/doc/screenshots/conformance_analysis/conformance_view.png b/src/frontend/src/assets/doc/screenshots/conformance_analysis/conformance_view.png new file mode 100644 index 0000000000000000000000000000000000000000..6ac3e912ebc607cbd22f0cc448612f7a03e24def Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/conformance_analysis/conformance_view.png differ diff --git a/src/frontend/src/assets/doc/screenshots/conformance_analysis/standard_view.png b/src/frontend/src/assets/doc/screenshots/conformance_analysis/standard_view.png new file mode 100644 index 0000000000000000000000000000000000000000..f8d15670ab1bb2ab2c9d0030a065c5badf085355 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/conformance_analysis/standard_view.png differ diff --git a/src/frontend/src/assets/doc/screenshots/frequent_pattern_mining/editor.png b/src/frontend/src/assets/doc/screenshots/frequent_pattern_mining/editor.png new file mode 100644 index 0000000000000000000000000000000000000000..9231142ac56a51ac2bb4d1902ab9c442282da5e2 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/frequent_pattern_mining/editor.png differ diff --git a/src/frontend/src/assets/doc/screenshots/frequent_pattern_mining/fold-loops.png b/src/frontend/src/assets/doc/screenshots/frequent_pattern_mining/fold-loops.png new file mode 100644 index 0000000000000000000000000000000000000000..59f89bfe5136f531768242d26704ff607f51ede6 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/frequent_pattern_mining/fold-loops.png differ diff --git a/src/frontend/src/assets/doc/screenshots/introduction/.gitkeep b/src/frontend/src/assets/doc/screenshots/introduction/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/assets/doc/screenshots/introduction/overview.png b/src/frontend/src/assets/doc/screenshots/introduction/overview.png new file mode 100644 index 0000000000000000000000000000000000000000..389a376b7973f57a7cb4afc0bd0c7dde2e91edf7 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/introduction/overview.png differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/.gitkeep b/src/frontend/src/assets/doc/screenshots/process_discovery/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/discover_initial_model.gif b/src/frontend/src/assets/doc/screenshots/process_discovery/discover_initial_model.gif new file mode 100644 index 0000000000000000000000000000000000000000..306a867e713e827bd792dc36d3aa940cedf5ac20 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/discover_initial_model.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/freeze_node.gif b/src/frontend/src/assets/doc/screenshots/process_discovery/freeze_node.gif new file mode 100644 index 0000000000000000000000000000000000000000..44f24d78cc52dde4fa5a4cb0a2c7cba460c30244 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/freeze_node.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/incremental_trace_addition.gif b/src/frontend/src/assets/doc/screenshots/process_discovery/incremental_trace_addition.gif new file mode 100644 index 0000000000000000000000000000000000000000..762b207cebc1e1725cb1c065c19fccbb9545c068 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/incremental_trace_addition.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/insert_node_below.gif b/src/frontend/src/assets/doc/screenshots/process_discovery/insert_node_below.gif new file mode 100644 index 0000000000000000000000000000000000000000..1f1bd4ed069144f0ebd66fc0793e947068bd048c Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/insert_node_below.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/insert_node_right.gif b/src/frontend/src/assets/doc/screenshots/process_discovery/insert_node_right.gif new file mode 100644 index 0000000000000000000000000000000000000000..d782468138f28283a4fd6bc60f667fcb9c5e277f Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/insert_node_right.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/proc_tree_toolbox.png b/src/frontend/src/assets/doc/screenshots/process_discovery/proc_tree_toolbox.png new file mode 100644 index 0000000000000000000000000000000000000000..990d68f1432c2856e34963bb6c426ca3b8067c64 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/proc_tree_toolbox.png differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/reduction_rules.gif b/src/frontend/src/assets/doc/screenshots/process_discovery/reduction_rules.gif new file mode 100644 index 0000000000000000000000000000000000000000..c91d36cf5d9b31f7788adf30275757c9b44af270 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/reduction_rules.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/remove_bpmn_node.gif b/src/frontend/src/assets/doc/screenshots/process_discovery/remove_bpmn_node.gif new file mode 100644 index 0000000000000000000000000000000000000000..70632a85c1eff8e280b1fa8cc8d03ad534491152 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/remove_bpmn_node.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/remove_node.gif b/src/frontend/src/assets/doc/screenshots/process_discovery/remove_node.gif new file mode 100644 index 0000000000000000000000000000000000000000..932aadd2303445fe8bb441b0ab05c6a8a9624548 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/remove_node.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/replace_node.gif b/src/frontend/src/assets/doc/screenshots/process_discovery/replace_node.gif new file mode 100644 index 0000000000000000000000000000000000000000..722b74aff6a9cfa177e22aba6ec6ec9b10ee0d35 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/replace_node.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/select_node_bpmn.gif b/src/frontend/src/assets/doc/screenshots/process_discovery/select_node_bpmn.gif new file mode 100644 index 0000000000000000000000000000000000000000..82bd4ef0fea92c49e1beafb96d0f079d49a84749 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/select_node_bpmn.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/selecting_nodes_for_updates.gif b/src/frontend/src/assets/doc/screenshots/process_discovery/selecting_nodes_for_updates.gif new file mode 100644 index 0000000000000000000000000000000000000000..6b57d7b6b86cc4a6e691fa5c950b1a7ba3c681a0 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/selecting_nodes_for_updates.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/process_discovery/shift_pt_node.gif b/src/frontend/src/assets/doc/screenshots/process_discovery/shift_pt_node.gif new file mode 100644 index 0000000000000000000000000000000000000000..0ae996125fadd800cae4fbda066208225e186d6f Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/process_discovery/shift_pt_node.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/software_architecture/.gitkeep b/src/frontend/src/assets/doc/screenshots/software_architecture/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/assets/doc/screenshots/software_architecture/architecture.png b/src/frontend/src/assets/doc/screenshots/software_architecture/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..24d5d51fbaae54e1c6180389db9271eb0ca5c59e Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/software_architecture/architecture.png differ diff --git a/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/.gitkeep b/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/model-performance_color-map.png b/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/model-performance_color-map.png new file mode 100644 index 0000000000000000000000000000000000000000..230b7f62d986f940bc03b8173f44a745671fb7de Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/model-performance_color-map.png differ diff --git a/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/model-performance_projection.png b/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/model-performance_projection.png new file mode 100644 index 0000000000000000000000000000000000000000..ae5747b49bfc224d8ed2682b814f5e9fac2405be Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/model-performance_projection.png differ diff --git a/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/variant-performance_color-map.png b/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/variant-performance_color-map.png new file mode 100644 index 0000000000000000000000000000000000000000..2f2af9004a8441c98dd054f5915de67aeeacab16 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/variant-performance_color-map.png differ diff --git a/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/variant-performance_selection.png b/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/variant-performance_selection.png new file mode 100644 index 0000000000000000000000000000000000000000..8559593f3059c4745db739071538b3bac5b2cb82 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/temporal_performance_analysis/variant-performance_selection.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_explorer/case_explorer.png b/src/frontend/src/assets/doc/screenshots/variant_explorer/case_explorer.png new file mode 100644 index 0000000000000000000000000000000000000000..ce7764c96634545d158077df461186d9730de262 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_explorer/case_explorer.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_explorer/case_explorer_detail.png b/src/frontend/src/assets/doc/screenshots/variant_explorer/case_explorer_detail.png new file mode 100644 index 0000000000000000000000000000000000000000..c538ff8a52994c2c4c697b9cf740d43a184338dc Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_explorer/case_explorer_detail.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_explorer/case_explorer_open.png b/src/frontend/src/assets/doc/screenshots/variant_explorer/case_explorer_open.png new file mode 100644 index 0000000000000000000000000000000000000000..e891f6dbf68e49644f469ed90aeb787eb5d3130d Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_explorer/case_explorer_open.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_explorer/main_page.png b/src/frontend/src/assets/doc/screenshots/variant_explorer/main_page.png new file mode 100644 index 0000000000000000000000000000000000000000..664d80d1a5a4528f98fd2b1ff9c727894d91a859 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_explorer/main_page.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_explorer/performance-view.png b/src/frontend/src/assets/doc/screenshots/variant_explorer/performance-view.png new file mode 100644 index 0000000000000000000000000000000000000000..ebdcc66a17136b28ecc4fa13aa167f83e8020141 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_explorer/performance-view.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_explorer/standard-view.png b/src/frontend/src/assets/doc/screenshots/variant_explorer/standard-view.png new file mode 100644 index 0000000000000000000000000000000000000000..6ba7ec2f8c4127d1e05d62fd03c0ce64f2786523 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_explorer/standard-view.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_explorer/variant_info_explorer.png b/src/frontend/src/assets/doc/screenshots/variant_explorer/variant_info_explorer.png new file mode 100644 index 0000000000000000000000000000000000000000..d230b1af68cee9756420a9918ca3e1bc6cd83c85 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_explorer/variant_info_explorer.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_explorer/variant_info_explorer_detail.png b/src/frontend/src/assets/doc/screenshots/variant_explorer/variant_info_explorer_detail.png new file mode 100644 index 0000000000000000000000000000000000000000..774706d5632589572e0415decdcc51054e8a9c46 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_explorer/variant_info_explorer_detail.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_explorer/variant_info_explorer_open.png b/src/frontend/src/assets/doc/screenshots/variant_explorer/variant_info_explorer_open.png new file mode 100644 index 0000000000000000000000000000000000000000..74f5828bc017c11848031ac1ea89500e50cfabed Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_explorer/variant_info_explorer_open.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_fragments/full-trace-variant.png b/src/frontend/src/assets/doc/screenshots/variant_fragments/full-trace-variant.png new file mode 100644 index 0000000000000000000000000000000000000000..b0d2864c39745f5a48d8b2d81b16bb9cff4ea4d2 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_fragments/full-trace-variant.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_fragments/infix-selection-mode.png b/src/frontend/src/assets/doc/screenshots/variant_fragments/infix-selection-mode.png new file mode 100644 index 0000000000000000000000000000000000000000..282eb70b7ae37b13f42f2397335524e0399ce4fe Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_fragments/infix-selection-mode.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_fragments/prefix.png b/src/frontend/src/assets/doc/screenshots/variant_fragments/prefix.png new file mode 100644 index 0000000000000000000000000000000000000000..1a974443b2f10d9de6c5b743d094a7e998f3bd8a Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_fragments/prefix.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_fragments/sequentially-complete-fragment.png b/src/frontend/src/assets/doc/screenshots/variant_fragments/sequentially-complete-fragment.png new file mode 100644 index 0000000000000000000000000000000000000000..85793b873c797c959e780436892e9bb797c15281 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_fragments/sequentially-complete-fragment.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_fragments/sequentially-incomplete-fragment.png b/src/frontend/src/assets/doc/screenshots/variant_fragments/sequentially-incomplete-fragment.png new file mode 100644 index 0000000000000000000000000000000000000000..f4d30dd95e89c4de30520f25b8656b46f24b26e7 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_fragments/sequentially-incomplete-fragment.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_fragments/suffix.png b/src/frontend/src/assets/doc/screenshots/variant_fragments/suffix.png new file mode 100644 index 0000000000000000000000000000000000000000..dc04868c7e4ef982f3aef068b6dab7fde69e1376 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_fragments/suffix.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_handling/.gitkeep b/src/frontend/src/assets/doc/screenshots/variant_handling/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/assets/doc/screenshots/variant_handling/variant_clustering/.gitkeep b/src/frontend/src/assets/doc/screenshots/variant_handling/variant_clustering/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/assets/doc/screenshots/variant_handling/variant_clustering/clustered_variant_explorer.png b/src/frontend/src/assets/doc/screenshots/variant_handling/variant_clustering/clustered_variant_explorer.png new file mode 100644 index 0000000000000000000000000000000000000000..87c156501fe00c226f71be3a9f14e60b34349102 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_handling/variant_clustering/clustered_variant_explorer.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_handling/variant_clustering/clustering_dialog.png b/src/frontend/src/assets/doc/screenshots/variant_handling/variant_clustering/clustering_dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..ea41c660e4b6e259197626c896ce409b75cee0d3 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_handling/variant_clustering/clustering_dialog.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_handling/variant_explorer/.gitkeep b/src/frontend/src/assets/doc/screenshots/variant_handling/variant_explorer/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/src/frontend/src/assets/doc/screenshots/variant_handling/variant_explorer/.gitkeep @@ -0,0 +1 @@ + diff --git a/src/frontend/src/assets/doc/screenshots/variant_handling/variant_fragments/.gitkeep b/src/frontend/src/assets/doc/screenshots/variant_handling/variant_fragments/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/assets/doc/screenshots/variant_handling/variant_frequent_pattern_mining/.gitkeep b/src/frontend/src/assets/doc/screenshots/variant_handling/variant_frequent_pattern_mining/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/assets/doc/screenshots/variant_handling/variant_modeler/.gitkeep b/src/frontend/src/assets/doc/screenshots/variant_handling/variant_modeler/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/assets/doc/screenshots/variant_handling/variant_querying/.gitkeep b/src/frontend/src/assets/doc/screenshots/variant_handling/variant_querying/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/assets/doc/screenshots/variant_handling/variant_sequentialization/.gitkeep b/src/frontend/src/assets/doc/screenshots/variant_handling/variant_sequentialization/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/frontend/src/assets/doc/screenshots/variant_modeler/model_a_variant.gif b/src/frontend/src/assets/doc/screenshots/variant_modeler/model_a_variant.gif new file mode 100644 index 0000000000000000000000000000000000000000..2d6eedc9f254ced71d218eb72dd7ab45ba50a714 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_modeler/model_a_variant.gif differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_modeler/variant_modeler.png b/src/frontend/src/assets/doc/screenshots/variant_modeler/variant_modeler.png new file mode 100644 index 0000000000000000000000000000000000000000..6dc18a4598e0f44736fbe53eb196afdd636a0f2a Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_modeler/variant_modeler.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/choicegroup.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/choicegroup.png new file mode 100644 index 0000000000000000000000000000000000000000..4fa3a31cb0818cb473e9f9c3b60786cc2c5020d3 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/choicegroup.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/create_choice_group.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/create_choice_group.png new file mode 100644 index 0000000000000000000000000000000000000000..308b6e2f76ef37121ec3f7ac554ff1cba8d28b97 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/create_choice_group.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/create_fallthrough_group.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/create_fallthrough_group.png new file mode 100644 index 0000000000000000000000000000000000000000..b45c45ce0d50df8f6d913fe0151dba993cd79460 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/create_fallthrough_group.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/fallthroughgroup.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/fallthroughgroup.png new file mode 100644 index 0000000000000000000000000000000000000000..4a64a0f3068454b9886adc290e5bdba18f23b653 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/fallthroughgroup.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/how_to_open.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/how_to_open.png new file mode 100644 index 0000000000000000000000000000000000000000..2922f02d33d14262af59b7dd3792bba199174552 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/how_to_open.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer.png new file mode 100644 index 0000000000000000000000000000000000000000..67c04e70dbf7f42eb223babf57cf77a9217b8e5e Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_1.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_1.png new file mode 100644 index 0000000000000000000000000000000000000000..7d473d692a44096cc00836476599ab900e9b56b0 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_1.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_10.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_10.png new file mode 100644 index 0000000000000000000000000000000000000000..5258d0ae8f2f6d8c55c666b6a9220fe28a5f43b1 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_10.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_11.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_11.png new file mode 100644 index 0000000000000000000000000000000000000000..534a918cbe1d2cfbbb2013e93978b5c2c90a62eb Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_11.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_12.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_12.png new file mode 100644 index 0000000000000000000000000000000000000000..03b527008b43f4024ff10e3a8d88c6ee9e8dc291 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_12.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_13.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_13.png new file mode 100644 index 0000000000000000000000000000000000000000..e6ca458ff8982e206482e8ef48d3ef73f1410d6f Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_13.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_14.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_14.png new file mode 100644 index 0000000000000000000000000000000000000000..e83d95296e9dee27155903e33da5c577d612da62 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_14.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_15.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_15.png new file mode 100644 index 0000000000000000000000000000000000000000..772964c8bc5e73a9e06c4b0936b32657c14924d5 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_15.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_16.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_16.png new file mode 100644 index 0000000000000000000000000000000000000000..2e1e317b3a5b7b2bfa06bff5f3e0501a45ed3175 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_16.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_17.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_17.png new file mode 100644 index 0000000000000000000000000000000000000000..6008768ff8eef8d918eb6a68b8533bcefaa154de Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_17.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_18.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_18.png new file mode 100644 index 0000000000000000000000000000000000000000..5fcbf9b668b76af379ed6411eaa337c3c922aca1 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_18.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_19.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_19.png new file mode 100644 index 0000000000000000000000000000000000000000..6f3e2c353b0dd6bd52e29a4aa49d3bd36d2c13a2 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_19.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_2.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_2.png new file mode 100644 index 0000000000000000000000000000000000000000..0e184049bd18ee596c38547b617c90b3854c041a Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_2.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_20.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_20.png new file mode 100644 index 0000000000000000000000000000000000000000..38761132cd47b9cae6fdbaafa741dc287b730688 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_20.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_21.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_21.png new file mode 100644 index 0000000000000000000000000000000000000000..5056a4798ed7d5ac589a44ec753dccb5f1287785 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_21.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_3.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_3.png new file mode 100644 index 0000000000000000000000000000000000000000..5f92a849c3445755ab7c788b396935eae161f569 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_3.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_4.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_4.png new file mode 100644 index 0000000000000000000000000000000000000000..abb17f7e5a6cc316be1eb55ffcf4353c78573b1d Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_4.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_5.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_5.png new file mode 100644 index 0000000000000000000000000000000000000000..8fcb366475c6004356afb5994d459e125ce65f18 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_5.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_6.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_6.png new file mode 100644 index 0000000000000000000000000000000000000000..09be5fa6e548efeb2d7acb24a72fdbcb4febcd87 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_6.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_7.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_7.png new file mode 100644 index 0000000000000000000000000000000000000000..64af5502eb754e5c84fc470c7dc49caecdfb3caf Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_7.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_8.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_8.png new file mode 100644 index 0000000000000000000000000000000000000000..e8d81b1b5cdeeb015408b83d0754297fbc7b3a03 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_8.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_9.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_9.png new file mode 100644 index 0000000000000000000000000000000000000000..b1c8fae624104e787bf657436dee8b95fecd4f67 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/sequentializer_examples_9.png differ diff --git a/src/frontend/src/assets/doc/screenshots/variant_sequentialization/wildcard.png b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/wildcard.png new file mode 100644 index 0000000000000000000000000000000000000000..0d02153e71f80c73699e2bc1f5c93e78c431ba36 Binary files /dev/null and b/src/frontend/src/assets/doc/screenshots/variant_sequentialization/wildcard.png differ diff --git a/src/frontend/src/assets/doc/user_manual.md b/src/frontend/src/assets/doc/user_manual.md new file mode 100644 index 0000000000000000000000000000000000000000..5dbd78518ae2d52c7ac7e8b03be23cf22c2f8b6b --- /dev/null +++ b/src/frontend/src/assets/doc/user_manual.md @@ -0,0 +1,830 @@ +# Introduction + +Process discovery is a critical discipline in process mining that deals with the data-driven generation of insights into operational processes. Given event data, process discovery algorithms learn process models that describe the execution of various activities in the process. These discovered process models are essential artifacts and are used in multiple process mining techniques. Most conventional process discovery techniques act as a black box and do not support user involvement apart from initial parameter tuning. These techniques often result in process models having poor quality. Cortado is a tool that allows for interactive process discovery, enabling users to gradually learn process models while having complete control during the increments. + + + + +#### Functionalities + +##### Event data handling + + Event data handling in Cortado includes exploring, filtering, preprocessing, querying, and visualization of event data. Different executions of the process are summarized by grouping them into process execution variants, which are visualized within the [*Variant Explorer*](#variant-explorer). + Cortado also provides [*Variant Querying*](#variant-querying), which includes a query language designed specifically for querying variants. Additionally, Cortado allows for the specification of time granularity, fixing a typo in docs which influences the ordering of activities within variants. Furthermore, Cortado allows manual extraction + and mining of frequent patterns through [*Frequent Pattern Mining*](#variant-frequent-pattern-mining). + + +##### Incremental process discovery + + A subset of variants or variant fragments can be selected by the user to initially discover and then incrementally add to the process model under construction during [*Incremental Process Discovery*](#incremental-process-discovery). + +##### Conformance checking + + Cortado implements alignments, a state-of-the-art conformance checking technique that provides diagnostics on the mismatches between the observed (i.e., event data) and modeled process behavior (i.e., the process model). + The user can compare the process model with the event data at any time during incremental process discovery allowing them to make informed decisions on which variants to add further. It also provides an overview of the degree of observed behavior which is covered in the current process model. + +##### Temporal performance analysis + + Cortado features [*Temporal Performance Analysis*](#temporal-performance-analysis), allowing, for example, the identification of slow process stages or activities, i.e., bottlenecks within the process. Temporal performance statistics can allow user to know which behavior to add to the process model incrementally based on any performance requirements. + + + + +A simplified overview of Cortado's functionality is depicted in the following figure: + +<img class="large" src="./assets/doc/screenshots/introduction/overview.png" style="max-width:700px;"> + +# Variant Handling + +## Variant Explorer + +In the Variant Explorer, users can get a comprehensive list of all variants present in the loaded event log. Unlike classical sequential variants found in other process mining tools, the Variant Explorer captures additional parallel behavior. The explorer also lists [*Variant Fragments*](#variant-fragments). + +<img class="large" src="./assets/doc/screenshots/variant_explorer/standard-view.png"> + + + +🔴 There are different views on the variants, including: + +- **Standard View:** Provides general information about each variant. +- **Performance View:** Refer to section [*Temporal Performance Analysis*](#temporal-performance-analysis). +- **Conformance View:** Refer to section [*Conformance Analysis*](#conformance-analysis). + +🟢 For each variant, the explorer displays its frequency within the log and the number of sub-variants it has. + +🟣 Variants can be selected for discovering an initial model (<i class="bi bi-diagram-2-fill btn-icon">discover initial model</i>), and they can also be added incrementally (<i class="bi bi-plus-lg btn-icon">add variant(s) to model</i>). When discovering an initial model, no variant fragments (infixes, prefixes, suffixes) may be selected. + +🔵 Variants can also be deleted by hovering over a variant row and clicking the deletion icon. + +🟡 Besides that, there are multiple actions available from the <i class="bi bi-tools btn-icon"></i>`Functions` dropdown menu within the toolbar of the variant explorer. For these functionalities, refer to the corresponding sections. + +When an initial model is present, conformance is available within the standard view. Click the (<i class="bi bi-question-square btn-icon"></i>) button for individual variant conformance or use (<i class="bi bi-layers-fill btn-icon">conformance check</i>) for all variants. For more detailed conformance insights, refer to the [*Conformance Analysis*](#conformance-analysis) section. + + +Beneath the listed variants, there are also statistics displayed for the entire event log, i.e. how many traces/variants are fitting the model or are currently selected. + +### Variant Information Explorer +<img class="medium" src="./assets/doc/screenshots/variant_explorer/variant_info_explorer_open.png"> <br> + +By clicking on the variant's <em>count</em> in <em>Variant Explorer</em>, a new <em>Variant Information Explorer</em> window opens in the stack of <em>Variant Explorer</em>. In the window, all cases of the selected variant are listed along with their information including <em>case ID, earliest, latest timestamp,</em> and <em>duration</em>. The <em>duration</em> column only exists if the starting time exists in the log. All the columns can also be sorted. + +<img class="medium" src="./assets/doc/screenshots/variant_explorer/variant_info_explorer_detail.png"> <br> + +### Case Information Explorer +<img class="medium" src="./assets/doc/screenshots/variant_explorer/case_explorer_open.png"><br> + +By clicking on the <em>case ID</em> in <em>Variant Information Explorer</em>, a new <em>Case Information Explorer</em> window opens in the stack of <em>Variant Explorer</em>. In <em>Case Information Explorer</em>, the events of the selected case are listed in time order, with their information including <em>starting timestamp, ending timestamp, duration,</em> and <em>resource</em> (when present) of the event. + +<img class="medium" src="./assets/doc/screenshots/variant_explorer/case_explorer_detail.png"><br> + +### Variant Sorting + +From the dropdown <i class="bi bi-sort-alpha-down btn-icon"></i>`Sorting` one can sort the listed variants based on different criteria: +- activites: the total number of activties in the event log +- conformance: how the variant conformance is (unknown, fitting and non-fitting) +- frequency: the frequency of variant in event log +- length: the length of the variant +- sub-variants: the number of sub-variants +- user-created: whether or not the variants are user-created (trace-fragments or modelled) + + +### Collapsing Activity Loops + +From the <i class="bi bi-tools btn-icon"></i>`Functions` dropdown menu one can collapse activities occuring multiple times within a trace into looped activites. This is useful for certain event logs where activities repeat very often. +Certain features may be disabled as they are not working with the collapsed loops. + + +### Low-level Variants + +By clicking on the number of sub-variants for a variant, users can inspect the corresponding low-level variants. For each sub-variant, the order in which the starting and ending of activities occur is displayed. Note that the length of the nodes does not correspond to a temporal length of the activity but only to how it started and ended relative to others. + + +## Variant Clustering + +Variant clustering can be used for listing the variants grouped into clusters in the Variant Explorer view. This allows for a convenient way to organize and access similar variants in their respective clusters. + +In the Variant Explorer view, clustering settings can be accessed using <i class="bi bi-grid-1x2 btn-icon"></i>`Variant clustering settings` option in the <i class="bi bi-tools btn-icon"></i>`Functions` dropdown menu. + +| <img class="small" src="./assets/doc/screenshots/variant_handling/variant_clustering/clustering_dialog.png"> | +- + +### Clustering Methods + +The Clustering Method dropdown allows for selection of the clustering method. The following clustering techniques are included: + +#### Agglomerative edit distance clustering + +- Using this technique, variants are represented as trees and their edit distances are pairwise compared and used as a distance measure between variants during clustering. +- Having selected `Agglomerative edit distance clustering`, the second input field can be used to specify the `Max. Variant Edit Distance Within a Cluster` + +#### Label vector clustering + +- Using this technique, each variant is represented by a vector containing labels of the activites. The order of activities is ignored while forming these vectors. Distances between these vector representations are used for forming the variant clusters. +- Having selected `Label vector clustering`, the second input field can be used to specify the `Number of Clusters` + + + +After selection of the desired settings, click <i class="bi bi-save btn-icon"></i>`Apply` to apply the settings and cluster all variants in Variant Explorer. + +<i class="bi bi-arrow-clockwise btn-icon"></i>`Reset` can be used to discard the clusters and restore to the default list of variants. + +### Cluster Information + +After applying clustering, variants are grouped in their respective clusters as shown below: + +- Using the <i class="bi bi-chevron-down btn-icon"></i> toggle, each cluster can be hidden or expanded. +- Using <i class="bi bi-sort-alpha-down btn-icon"></i>, each cluster can be individually sorted. Note that using the global sorting of Variant Explorer view overrides the sorting of individual clusters. +- Each cluster information bar shows the number of variants and the number traces in that cluster. + +|<img class="small" src="./assets/doc/screenshots/variant_handling/variant_clustering/clustered_variant_explorer.png">| +- + +## Variant Querying + +The variant querying window can be accessed by clicking <i class="bi bi-funnel btn-icon"></i>`Variant Query` from the Variant Explorers bottom right corner. +Here the user can enter and execute a query to search for variant with specific requirements. +Only variants which fulfill the query are then shown in the Variant Explorer. +Additionally, these variants can then be deleted from the pool of variants. +Another option is to delete everything except those variants returned by the query. + +Variant queries support autocompletion. Either click on of the suggestions with your cursor or select one by using the arrow keys on your keyboard and then complete it by pressing `<Tab>` your keyboard. + +### Variant Query Language + +A valid **Query** is made up of **Activities** and **Operators**, which together form +expressions that can be linked by logical operators to form more complex queries. +For syntactic reasons, every query ends with a semicolon `;`. + + +#### Activities and Groups + +Groups can be used both in unary and binary operators to replace single +activities. However, this is restricted to only one side of a binary +expression. In case of binary expressions, if the group is located on +the left-side of the expression, it is evaluated by simply checking for +every member of the group and the right-hand side, if the expression +would be fulfilled. The case of a right-hand side group will be covered +below. + +| Activities | Meaning | +|-----------------------|-----------------------------------------------------------------------------------------------------------| +| `'Activity'` | Activity names are written in single quotes | +| `ANY{'A','B'}` | Evaluated in an expression, returns true if any activity for the operator returns true | +| `ALL{'A','B'}` | Evaluated in an expression, returns true if all activities for the operator returns true | +| `~ [Group]` | Represents the group consisting of all activities besides the activites in the curly braces of the *Group*| + +#### Operators + +Operators express the behavior that activities or groups of activities need to fullfill for being included in the result of the query. +They come either as **unary** or **binary** operators, which express the relationships +between a single or multiple activities and the variant. As an example for a unary +operator, the following is a query made from a single unary expression that checks +if the activity `'A'` is an event happening in the variant: + +`'A' isContained;` + +Similarly, a query from a binary expression that checks if every +`'A'` activity in the variant is followed by a `'B'` activity, can be written as: + +`'A' isDirectlyFollowed 'B';` + +##### Unary Operators +Unary operators express the relationship between a single activity and the +variant. The following query evaluates to true if `'A'` is a start activity of the variant: + +`'A' isStart;` + +Note that it is not necessarily a unique start activity. + + +| Unary Operator | Short Form | Meaning | +|----------------------|------------|-------------------------------------------------------| +| `[Act] isStart` | `isS` | Returns true if *act* is a start activity | +| `[Act] isEnd` | `isE` | Returns true if *act* is an end activity | +| `[Act] isContained` | `isC` | Returns true if *act* is contained inside the variant | + +##### Binary Operators + + +Binary Operators express the relationship between multiple activities in a variant. +For example, `'A' isConcurrent 'B';` is fulfilled, if every occurrence of +`'A'` happens concurrently to a `'B'` activity. To add further expressive power, groups can be +used on the right-hand side of a binary expression to capture some deeper relations. +That is the query `'A' isDF ANY {'B','C'};` is fulfilled, if every `'A'` activity is directly followed by an `'B'` or `'C'` activity. +This is different to the interpretation of every `'A'` needing to be followed by a `'B'` or every `'A'` being followed by a `'C'`. + +| Binary Operator | Short Form | Meaning | +|-------------------------------------|------------|----------------------------------------------------------| +| `[Act1] isDirectlyFollowed [Act2]` | `isDF` | Returns true if *Act1* always directly-follows *Act2* | +| `[Act1] isEventuallyFollowed [Ac2]` | `isEF` | Returns true if *Act1* always follows *Act2* | +| `[Act1] isParallel [Act2]` | `isP` | Returns true if *Act1* always happens parallel to *Act2* | + +#### Quantifiers + +Quantifiers can be used to check for the frequency of relations. Instead +of checking if `'A'` is just contained any +number of times, `'A' isContained > 2;` will only return true, if `'A'` appears at least 3 times in the variant. +For binary expressions, this works similarly, thus `'A' isDF 'B' = 2;`, will return true if `'A'` is directly-followed 2 +times by `'B'` in the variant. Using Quantifiers in conjunction with Groups need some attention, +as the right-hand side rules also apply here. Thus, `'A' isDF ALL { 'B', 'C'} > 1;` will only be evaluated as true if at least +two A activities are followed by both a `'B'` and a `'C'` activity. + +| Quantifier | Meaning | +|---------------------|-----------------------------------------------------------------------| +| `[Exp] > [Number]` | Returns true if *Exp* appears more than *Number* of times in a variant| +| `[Exp] = [Number]` | Returns true if *Exp* appears exactly *Number* times in a variant | +| `[Exp] < [Number]` | Returns true if *Exp* appears less than *Number* of times in a variant| + +#### Combining Expressions with Logical Operators + + +Different unary and binary expressions can be linked using logical operators to build complex +queries. If we for example want to select all variants in which activity `'A'` is either +directly followed by activity `'B'` or eventually followed by activity `'E'`, we can write the +following query: + +`'A' isDF 'B' OR 'A' isEF 'E';` + +When linking multiple expressions, `AND` and `OR` operators linking expressions can be nested +inside each other by using `( )` parenthesis. We can use this to expand our previous +example by requiring that now every `'A'` activity needs to be followed by an`'E'` activity and +that every `'E'` needs to be followed by an `'F'` activity: + +`'A' isDF 'B' OR 'A' isEF 'E';` + +`'A' isDF 'B' OR ( 'A' isEF 'E' AND 'E' isEF 'F' );` + +Multiple instances of the same operator on the same level can be linked without the need of +parenthesis. `NOT` can be used to negate the expression written after it in `( )`. +As an example, if we want to get all variants that have `'B'` as the unique and only start +activity, we can write the following query: + +`'B' isStart AND NOT ( ~ ANY {'B'} isStart );` + +The first term checks if `'B'` is a start activity, while the second expression would be +fulfilled if any activity that is not `'B'` would be a start activity. Now, as we negate it, +the expression can only be true if `'B'` is a start activity and no other activity +is a start activity. + +| Logical Operator | Meaning | +|--------------------|------------------------------------------------------------------------| +| `[Exp1] AND [Exp2]`| Returns true if and only if *Exp1* and *Exp2* both are true | +| `[Exp1] OR [Exp2]` | Returns true if either *Exp1* or *Exp2* is true or if both of them are | +| `NOT ( [Exp] )` | Returns true if *Exp* is False | + +## Variant Fragments + +Variant fragments or trace fragments are portions of the trace variants which are sequentially complete, meaning that no activity is skipped in a sequence. + +For example, +<img class="xsmall" src="./assets/doc/screenshots/variant_fragments/sequentially-complete-fragment.png"> + +is a sequentially complete fragment of the full trace variant + +<img class="xlarge" src="./assets/doc/screenshots/variant_fragments/full-trace-variant.png">, + +while + +<img class="xsmall" src="./assets/doc/screenshots/variant_fragments/sequentially-incomplete-fragment.png"> + +is not. + +Trace fragments are in contrast to full trace executions which have a well-defined start *and* end activity. These only contain either the start activity or end activity or none. +Based on which of the activities they contain, trace fragments can be categorised into 3 kinds - **infix**, **prefix** and **suffix**. The dots preceding and/or succeeding represent the presence of other fragments before or after the one in question + +* **Infix** fragments contain none of the start or end activities and hence they are preceded *and* succeeded by dots. The fragments above are examples of the same + +* **Suffix** fragments contain only an end activity. + <img class="xsmall" src="./assets/doc/screenshots/variant_fragments/suffix.png"> +* **Prefix** fragments contain only an end activity. + <img class="xsmall" src="./assets/doc/screenshots/variant_fragments/prefix.png"> + +Trace fragments are used and can frequently be seen in [*Incremental Discovery*](#incremental-process-discovery), [*Variant Sequentializer (Tiebreaker)*](#variant-sequentialization-tiebreaker) and [*Frequent Pattern Mining*](#variant-frequent-pattern-mining), pool of which can either be - + +* manually extracted using [infix selection mode](#extracting-variant-fragments), +* automatically identified, +* discovered in the process of '[Frequent Pattern Mining](#variant-frequent-pattern-mining)', or +* manually created + +### Extracting variant fragments + +One way to select infixes (and add them to the pool) is through the `trace infix selection mode`. To enable it in the variant explorer, simply click on (<i class="bi bi-ui-checks-grid btn-icon">Exit trace infix selection mode</i>) option in the (<i class="bi bi-tools btn-icon">Functions</i>) menu. +With the icons on the right, one can add the current selection to the variant explorer, reset selection or select the whole variant. + +|<img class="medium" src="./assets/doc/screenshots/variant_fragments/infix-selection-mode.png">| +- + + +## Variant Modeler +<img class="medium" src="./assets/doc/screenshots/variant_modeler/variant_modeler.png"> + + +The <em>variant modeler</em> allows users to manually model a variant with sequential and parallel patterns. It could be opened by: the head toolbar -> `Editors` -> <i class="bi bi-tools btn-icon"></i>`Open Variant Modeler`. + +How to model a new variant: + +1. Select the <em>insertion strategy</em> (where to insert the activity) in the toolbar +2. Select a chevron in current variant (could be both single activity or an activity group). If no variant has been modeled, ignore this step +3. Click the colorful activity buttons with label to insert corresponding activity into the variant +4. Click `add new variant to log` button to add the user modeled variant to the variant list + +<img class="medium" src="./assets/doc/screenshots/variant_modeler/model_a_variant.gif"> + +Other functions in the tool: +1. Variant modeler allows the variant be displayed in 4 variant types: <em>full</em>, <em>prefix</em>, <em>infix</em>, and <em>postfix</em>. +2. View focus functions are also provided: + - <i class="bi bi-eye-fill btn-icon"></i> <em>focus selected:</em> move the selected activity/group to the view center. + - <i class="bi bi-arrows-fullscreen btn-icon"></i> <em>move to the start of the variant: </em>move the variant center to the view center. + +## Variant Frequent Pattern Mining + +As the number of variants in a process log increase, it becomes challenging for process analysts to explore event data. This section of Cortado helps mine frequent patterns in event log, or more precisely frequent *infixes* to make analysis easier and to assist incremental discovery. +Under the hood, concurrency variants are modelled as labeled, rooted, ordered trees and infixes as a specific kind of subtrees called *infix subtrees*. More about the representation can be read in one of the published [articles](https://dl.acm.org/doi/abs/10.14778/3603581.3603603). Frequent Miner can also use different algorithms with specific properties and goals - [*Valid Tree Miner*](https://dl.acm.org/doi/abs/10.14778/3603581.3603603), *Blanket Tree Miner* and *Eventually Follows Pattern Miner* being few of them. + +To open the `Variant Miner Editor`, go to `Editors` → (<i class="bi bi-minecart btn-icon"><b>Open</b> Variant Miner</i>). + +|<img class="medium" src="./assets/doc/screenshots/frequent_pattern_mining/editor.png">| +- + + +<br/> +The editor comprises primarily of <i>three sections</i>, all of which rely heavily upon the tree representation of variants - +<br/> +<br/> +1. shows the <b>parameter selection</b>, allowing a choice of support definition, the minimum support threshold used for mining and more + <br/> + <br/> + <table> + <thead> + <tr style="text-align: center;"> + <th>Pattern Selection</th> + <th>Options (if any)</th> + <th>Function</th> + </tr> + </thead> + <tbody> + <tr> + <td rowspan=4>Support Counting Strategy</td> + <td>Trace Transaction</td> + <td>counts the number of occurrences of a sub-pattern, counting each occurrence as one for each trace</td> + </tr> + <tr> + <td>Variant Transaction</td> + <td>counts the number of occurrences of a sub-pattern, counting each occurrence as one for each variant</td> + </tr> + <tr> + <td>Trace Root-Occurrence</td> + <td>counts the number of occurrences of a sub-pattern having unique parents, counting each occurrence as one for each trace</td> + </tr> + <tr> + <td>Variant Root-Occurrence</td> + <td>counts the number of occurrences of a sub-pattern having unique parents, counting each occurrence as one for each variant</td> + </tr> + <tr> + <td>Maximum Size</td> + <td colspan=2>max size of the pattern. It is not the number of activities but the number of nodes in its tree representation. + Hence, without any parallelism, it is the number of activities plus one</td> + </tr> + <tr> + <td>Support</td> + <td colspan=2>minimum number of occurrences to be counted as 'frequent'</td> + </tr> + <tr> + <td>Mine prefixes and suffixes</td> + <td colspan=2>allow mining prefixes and suffixes, instead of just infixes (see section on 'Variant Fragments' above to know more about infix/prefix/suffix)</td> + </tr> + <tr> + <td>Fold loops</td> + <td>Loop Threshold</td> + <td>when specified as `n`, folds all `n` or more consecutive occurrences of an activity into a one single loop before mining<br><img src="./assets/doc/screenshots/frequent_pattern_mining/fold-loops.png" alt="fold-loops" class="xsmall"/></td> + </tr> + </tbody> + </table> + <br> + +2. **Visualization table** shows further information on the infixes - `size`, `support`, `type`, and a `visualization` of the fragment. + Apart from the `Type` itself, all the rest of the properties are directly taken from the parameter selection before mining. An infix subtree is of *type* + `Maximal` if no frequent super-pattern exists and it is of *type* `Closed` if none of its proper super-patterns have the same support. + In addition, alignments between the infix and an existing process model, i.e., if the infix conforms to the process model, can be computed using + the (<i class="bi bi-layers-fill btn-icon">conformance check</i>) button right above the table. Subsequently, if the infixes 'fit' to the model or not can also be seen + in the `Fitting` column of the table. Apart from the above, it is also possible to export the mined infixes as svg for analysis, + by clicking on (<i class="bi bi-save"></i>) button located in the top-right corner of the editor. + + +3. finally in the **Filters** menu, a user can choose which of the infixes to retain. Here, the option `Valid` for `Type` retains only *valid* infixes, meaning the infixes in which all elements have at least activity. + The section at the bottom allows users to selectively filter in or out certain activities. For instance, for a particular activity, checking the box for `Filter` and turning the toggle switch for `Out/In` on, retains only the infixes *containing* the activity. + Switching the toggle off, retains only the infixes *not* containing the activity. + +## Variant Sequentialization (Tiebreaker) +<em>Variant Sequentializer</em> is a sequentialization tool which provides a function to match source pattern in variants and replace them with the target pattern. It could be opened by clicking the icon <i class="bi bi-bar-chart-steps"></i> in <em>variant explorer</em>'s toolbar: + +<img class="medium" src="./assets/doc/screenshots/variant_sequentialization/how_to_open.png"> + +In <em>sequentializer</em>, there are two <em>pattern editors</em> to model the source pattern and target pattern, respectively.<br> + +<img class="medium" src="./assets/doc/screenshots/variant_sequentialization/sequentializer.png"> + +In addition to sequential and parallel pattern, the <em>sequentializer</em> allows to model:<br> +1. <em>choice group</em>, which could match any combination of any activities in the group + +<img class="medium" src="./assets/doc/screenshots/variant_sequentialization/choicegroup.png"> + +It could be created by clicking the icon <i class="bi bi-slash"></i>: + +<img class="medium" src="./assets/doc/screenshots/variant_sequentialization/create_choice_group.png"> + +1. <em>fallthrough group</em>, which could model the case that activities in the group cannot be modeled by the combination of sequential/parallel relationship. + +<img class="medium" src="./assets/doc/screenshots/variant_sequentialization/fallthroughgroup.png"> + +It could be created by clicking the icon <i class="bi bi-arrow-down"></i>: + +<img class="medium" src="./assets/doc/screenshots/variant_sequentialization/create_fallthrough_group.png"> + +3. pattern with a <em>wildcard option</em> '..' to allow partial match, which represents "rest of the variant". <em>Wildcard</em> is listed beside the activity buttons. + +<img class="medium" src="./assets/doc/screenshots/variant_sequentialization/wildcard.png"> + +Note: +1. in source pattern, only parallel variants are allowed. +2. The invalid patterns are checked when editing. +3. The activities in target pattern should be consistent with activities in the source pattern. Acitivities in target pattern editor are only enabled when they are already in the source pattern. + +Here are some examples to show how variants are transformed by the <em>sequentializer</em>: + +(1) <img class="xxxsmall" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_1.png"> <br> + +(2) <img class="xxxsmall" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_2.png"> <br> + +(3) <img class="xxxsmall" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_3.png"> <br> + +(4) <img class="xxxsmall" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_4.png"> <br> + +(5) <img class="xxxsmall" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_5.png"> <br> + +<br> + +<table style="width: 50%; border-collapse: collapse;"> + <tr> + <td >Source Pattern</td> <td>Target Pattern</td> <td>Result for examples</td> + </tr> + + <tr> + <td rowspan="5" style="text-align: center;"><img class="xxxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_2.png"></td> + <td rowspan="5" style="text-align: center;"><img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_6.png"></td> + <td>(1) No match</td> + </tr> + <tr><td>(2) <img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_6.png"></td></tr> + <tr><td>(3) No match</td></tr> + <tr><td>(4) No match</td></tr> + <tr><td>(5) No match</td></tr> + + <tr> + <td rowspan="5" style="text-align: center;"><img class="xxxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_7.png"></td> + <td rowspan="5" style="text-align: center;"><img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_8.png"></td> + <td>(1) <img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_9.png"></td> + </tr> + <tr><td>(2) <img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_6.png"></td></tr> + <tr><td>(3) No match</td></tr> + <tr><td>(4) <img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_10.png"></td></tr> + <tr><td>(5) <img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_9.png"></td></tr> + + <tr> + <td rowspan="5" style="text-align: center;"><img class="xxxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_7.png"></td> + <td rowspan="5" style="text-align: center;"><img class="xsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_11.png"></td> + <td>(1) <img class="xsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_12.png"></td> + </tr> + <tr><td>(2) <img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_6.png"></td></tr> + <tr><td>(3) <img class="xsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_13.png"></td></tr> + <tr><td>(4) <img class="xsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_14.png"></td></tr> + <tr><td>(5) <img class="xsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_12.png"></td></tr> + + <tr> + <td rowspan="5" style="text-align: center;"><img class="xsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_15.png"></td> + <td rowspan="5" style="text-align: center;"><img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_16.png"></td> + <td>(1) No match</td> + </tr> + <tr><td>(2) <img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_6.png"></td></tr> + <tr><td>(3) No match</td></tr> + <tr><td>(4) <img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_17.png"></td></tr> + <tr><td>(5) No match</td></tr> + + <tr> + <td rowspan="5" style="text-align: center;"><img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_18.png"></td> + <td rowspan="5" style="text-align: center;"><img class="xxxmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_19.png"></td> + <td>(1) <img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_20.png"></td> + </tr> + <tr><td>(2) <img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_6.png"></td></tr> + <tr><td>(3) <img class="xsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_21.png"></td></tr> + <tr><td>(4) <img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_17.png"></td></tr> + <tr><td>(5) <img class="xxsmall-img" src="./assets/doc/screenshots/variant_sequentialization/sequentializer_examples_20.png"></td></tr> +</table> + +# Process Discovery + +## Visualizing and Editing Process Models + +### Process Tree Editor + +Process tree editor tab is open by default in the top pane, it can also be accessed using <i class="bi bi-diagram-2 btn-icon"></i> `Open Process Tree Editor` option in `Editors` dropdown menu. The `Process Tree Editor` tab is also always available in the list of tabs to the left of the top pane. +After a tree is available in the process tree editor by either importing or through discovery, it can be edited in the following ways. + +#### Selecting Nodes for Updates + +A tree node (either activity or operator) can be selected for updates by clicking on it. + +* After selection of a node, all buttons of updates available for that node are enabled. +* Clicking the <i class="bi bi-x-circle btn-icon"></i>`clear selection` button or clicking the node again, clears that selection. + +A selected node is highlighted with a red border as follows: + +|<img class="medium" src="./assets/doc/screenshots/process_discovery/selecting_nodes_for_updates.gif">| +- + +#### Inserting Nodes + +New nodes available for insertion in the tree are available in the process tree toolbox. The toolbox can be revealed using the <i class="btn-icon bi bi-chevron-bar-down"></i> button at the top of the editor. + +|<img class="xlarge" src="./assets/doc/screenshots/process_discovery/proc_tree_toolbox.png">| +- + +##### Inserting nodes along operators + +After selecting an operator node, the following choices are available: + +- insert new node above the selected one (<i class="bi bi-chevron-up"></i>) +- insert new node below the selected one (<i class="bi bi-chevron-down"></i>) +- insert new node left to the selected one (<i class="bi bi-chevron-left"></i>) +- insert new node right to the selected one (<i class="bi bi-chevron-right"></i>) + +Having selected the following operator and **insert new node below** option, adding an activity from the list of available activities in the toolbox adds it under the selected operator follows: + +|<img class="medium" src="./assets/doc/screenshots/process_discovery/insert_node_below.gif">| +- + +Similarly, adding an operator adds that operator **below** the selected operator. It works similarly for adding activities or operators **above**, to the **left** or to the **right**. + +##### Inserting nodes along activities + +After selecting an activity, the following choices are available: + +- insert new node left to the selected one (<i class="bi bi-chevron-left"></i>) +- insert new node right to the selected one (<i class="bi bi-chevron-right"></i>) + +Having selected the following activity and **insert new node right to the selected one** option, adding an activity from the list of available activities in the toolbox adds it to the right of the selected activity as follows: + +|<img class="medium" src="./assets/doc/screenshots/process_discovery/insert_node_right.gif">| +- + +Similarly, adding an operator adds that operator **to the right** the selected activity. It works similarly for adding activities or operators **to the left**. + +#### Replacing Nodes + +The `replace the currently selected node` (<i class="bi bi-arrow-repeat"></i>) option can be used to replace a selected activity or operator node with either an activity or an operator node from the list of available activities and operators in the toolbox. + +Having selected an activity and **replace the currently selected node** option, choosing another activity from the toolbox replaces the selected activity as follows: + +|<img class="medium" src="./assets/doc/screenshots/process_discovery/replace_node.gif">| +- + +Similarly, choosing an operator node from the toolbox **replaces** the selected activity with the selected operator. It works similarly for **replacing** selected operators with either operators or activities form the list of available operators and activities in the toolbox. + +#### Removing Nodes + +Selecting an operator node or an activity and clicking the <i class="bi bi-trash btn-icon"></i>`remove selected node(s)` button removes that activity or the operator node along with all child nodes. + +Having selected an operator node and removing it results as follows: + +|<img class="medium" src="./assets/doc/screenshots/process_discovery/remove_node.gif">| +- + +#### Shifting Nodes + +Selecting an operator node or an activity and clicking the <i class="bi bi-chevron-double-left btn-icon"></i>`shift selected node(s) to left` or <i class="bi bi-chevron-double-right btn-icon"></i>`shift selected node(s) to right` button **shifts** the selected node to the left or to the right respectively. +The shift to right or to the left is with respect to the sibling node(s) of the selected node under a single operator. + +Having selected the following operator node and clicking the <i class="bi bi-chevron-double-left btn-icon"></i>`shift selected node(s) to left` button **shifts** the operator node to the left as follows: + +|<img class="medium" src="./assets/doc/screenshots/process_discovery/shift_pt_node.gif">| +- + +#### Applying Reduction Rules + +Selecting an operator node and clicking the <i class="bi bi-diagram-2"></i> button applies **reduction rules** to remove redundant and unnecessary nodes from that subtree as follows: + +|<img class="medium" src="./assets/doc/screenshots/process_discovery/reduction_rules.gif">| +- + +#### (Un)Freezing Subtrees + +Freezing a subtree prevents that subtree from being updated during the incremental discovery process and this subtree always remains in the tree. + +Selecting an operator node and clicking the <i class="bi bi-snow btn-icon"></i>`(un)freeze subtrees` button **freezes** the subtree under that operator node. The frozen subtree is highlighted blue as seen below: + +|<img class="medium" src="./assets/doc/screenshots/process_discovery/freeze_node.gif">| +- + +Similarly, selecting root operator node of an already frozen subtree and clicking the <i class="bi bi-snow btn-icon"></i>`(un)freeze subtrees` button unfreezes that subtree. After unfreezing, that subtree may be updated diring the incremental discovery process and its presence is no longer ensured. + +#### Undo/Redo Applied Changes + +During the process of updating the tree, history is maintained and the edits can be undone or redone using the <i class="bi bi-arrow-counterclockwise btn-icon"></i>`undo` and <i class="bi bi-arrow-clockwise btn-icon"></i>`redo` buttons. + +#### Exporting the Model + +The current tree in the process tree editor can be exported (.svg) using the <i class="bi bi-save"></i>`export the tree as an .svg` button. + +### BPMN-Visualizer + +BPMN visualizer can be accessed using <i class="bi bi-diagram-2 btn-icon rotate-270"></i> `Open BPMN Viewer` option in `Editors` dropdown menu. The `BPMN Viewer` tab is also available in the list of tabs to the left of the top pane after it was accessed. +After a tree is available in the process tree editor by either importing or through discovery, the BPMN representation of that process tree is available in the BPMN viewer. + +#### Selecting Nodes for Updates + +A node can be selected for updates by clicking on it. + +* After selection of a node, all buttons of updates available for that node are enabled. +* Clicking the <i class="bi bi-x-circle btn-icon"></i>`clear selection` button or clicking the node again, clears that selection. + +A selected node is highlighted through a red border as follows: + +|<img class="medium" src="./assets/doc/screenshots/process_discovery/select_node_bpmn.gif">| +- + +#### Removing Nodes + +Selecting a node and clicking the <i class="bi bi-trash btn-icon"></i>`remove selected node(s)` button removes that node as well as the relevant connected nodes from the BPMN model. + +Having selected a node and removing it results as follows: + +|<img class="medium" src="./assets/doc/screenshots/process_discovery/remove_bpmn_node.gif">| +- + +#### Exporting the Model + +The current BPMN model in the BPMN viewer can be exported (.svg) using the <i class="bi bi-save"></i>`export the model as an .svg` button. + + +## Incremental Process Discovery + +### Idea and Overview + +Cortado uses incremental process discovery which involves incrementally discovering a process model by adding trace by trace to an existing process model. +Thereby, the process model under construction gets incrementally extended. Using the trace to be added in an iteration, specific parts +of the process tree which must be altered to fit the trace are identified. This is followed by updates to those identified parts which +allow the trace to fit the process tree. + +After discovering or importing an initial process tree, trace(s) can be chosen for incrementally adding them to the process tree. + +### Discovering Initial Model + +* An initial model can be discovered using the following steps: + 1. Select variant(s) in the `Variant Explorer` + * Infix, prefix and suffix can not be selected for the incremental process discovery. + 2. Press the <i class="bi bi-diagram-2-fill btn-icon"></i>`discover initial model` button + 3. The discovered process tree would be displayed in the `Process Tree Editor` as follows: + +|<img class="large" src="./assets/doc/screenshots/process_discovery/discover_initial_model.gif">| +- + +### Incrementally Adding Variants + +* Variant(s) can be incrementally added to the process model using the following steps: + 1. Select variant(s) in the `Variant Explorer` that are not yet added to the process tree. + 2. Press the <i class="bi bi-plus-lg btn-icon"></i>`add variant(s) to model` button. + * After selecting and adding to the model, the variant is in the language of the process tree and should not be un-selected. + * All variants in the variant explorer can be selected for the incremental process discovery including: + * Variants from the log. + * Variant fragments. + * Variants from the `Variant Modeler`. + 3. The modified process tree (which the selecting traces fit to) would be displayed in the `Process Tree Editor` as follows: + +|<img class="large" src="./assets/doc/screenshots/process_discovery/incremental_trace_addition.gif">| +- + +# Temporal Performance Analysis + +## Model-independent performance analysis +When opening the Performance View from the side bar, the performance of each variant is calculated, which may take a while depending on the size of the event log. + +<img class="large" src="./assets/doc/screenshots/variant_explorer/performance-view.png"> + +In this view the variants are no longer uniquely colored to be differentiated but based on their service times. Additionally, there are now nodes displayed in-between activites to show the waiting times. These are colored using a separate color scale to show their waiting times. + +Both color maps can be seen in a sub-tab from the `Variant Performance` tab. + +<img class="large" src="./assets/doc/screenshots/temporal_performance_analysis/variant-performance_color-map.png"> + +Here, the used statistic for the color maps can be changed. By default, they show the mean values of all instances for each variant. Other statisics are their minimum, maximum or standard deviation. Upon change the color map will be immediatley be updated. + +To get further insight into the performance of certain parts of a variant, let it be single activites, waiting nodes or parallel sections, one can simply click on them in the Variant Explorer and inspect their service or waiting times in the `Selection` sub-tab of the `Variant Performance` tab. + +<img class="large" src="./assets/doc/screenshots/temporal_performance_analysis/variant-performance_selection.png"> + + +## Model-based performance analysis +For understanding the performance of a process model, one can project the performance of selected variants onto the model from the Performance View. + +<img class="large" src="./assets/doc/screenshots/temporal_performance_analysis/model-performance_projection.png"> + + + +🔴 When there is a model present, there will be two additional columns in the Variant Explorer, namely `Model Projection` and by default `service time (mean)`. + +On the one hand, by clicking the toggle in the `Model Projection` column, the variant will be added to the pool of projected variant. On the other hand, unclicking the toggle of already projected variants will remove them again from the pool. To clear the whole pool, one can click (<i class="bi bi-x-circle-fill btn-icon"></i>) in the header of the `Model Projection` column. + +Please note, that in most cases, it only makes sense to project variants that are actually fitting the process tree as otherwise the projection is not complete. +Because of that, there will be a warning sign displayed for variant that are actually not fitting. + +The other column shows in the default setting the mean service overall model performance of the variant. + +🟢 Further information can be gained from `Model Performance` tab. Here, in the `Selection` subtab, the *service time*, *waiting time*, *cycle time* and *idle time* are shown for the selection made within the model. + +🟣 The same information can be gained for certain process tree nodes by hovering over them. + +In the `Color Map` subtab, adjustments can be made to how the model is colored and the statistics are aggregated. + +<img class="large" src="./assets/doc/screenshots/temporal_performance_analysis/model-performance_color-map.png"> + + + +One can choose which of the four performance times will be used for the projection as well between the statistical measure (mean, min, max, stdev). + +The changes made to this will also change what will be displayed in the variants explorer column. + +# Conformance Analysis + +To compare the discovered process model, including intermediate process models within the incremental discovery approach, with the event log provided, Cortado features conformance checking. +Cortado implements alignments, i.e., a state-of-the-art conformance checking technique that provides diagnostics on the mismatches between the observed (i.e., event data) and modeled process behavior (i.e., the process model). +Consequently, the user can compare the process model with the event data at any time during incremental process discovery. + +<img class="large" src="./assets/doc/screenshots/conformance_analysis/standard_view.png"> + + + +When an initial model is already present, a user can calculate conformance statistics of a variant using the (<i class="bi bi-question-square btn-icon"> (re)calculate conformance statistics</i>) button (see box labelled 1. in the image above) next to the checkboxes. +Alternatively, it is also possible to (re)calculate statistics for all variants at once using the (<i class="bi bi-layers-fill btn-icon"> conformance check</i>) button (see box 3.) +After the calculations, either one of the statuses is possible - + +- <i class="bi bi-check-square font-large text-success"></i> <em>variant fits the model</em> +- <i class="bi bi-x-square font-large text-danger"></i> <em>variant does not fit the model</em> + +The number of fitting traces and variants can also be seen at the bottom (see box 2.) + +After calculating statistics for a variant(s), if the model changes (using the process tree editor, for example), the statistics are consequently affected, too. +This is indicated through another status - + +- <i class="bi bi-check-square font-large text-warning"></i><i class="bi bi-x-square font-large text-warning"></i> <em>outdated results (model has changed)</em> + +which calls for the recalculation of statistics using one of the two ways mentioned above. + +For detailed view on the analysis, Cortado also dedicates a separate tab `Conformance View`. + +<img class="large" src="./assets/doc/screenshots/conformance_analysis/conformance_view.png"> + + + +The variant visualizations in this tab +represent the projected alignment results of all the sequentializations of that particular variant. Since it is cumbersome to browse through each alignment visualisation individually, instead of projecting one alignment to one variant at a time, Cortado also allows to project +all the alignment results into the model through <em>aggregation</em>. The method of aggregation can be selected from the dropdown in the `Color Maps` tab towards the right panel. Two options are available - +- aggregation by <em>equal weights</em>, or +- aggregation <em>weighted by their log frequency</em> + +Using this technique, it becomes easier to locate deviations, if the misalignments are concentrated at certain tasks in the model. +To project alignments onto the model, click on the `model projection` toggle switch to the left of a variant. The percentage value displayed post computation indicates the `tree conformance` of the projected set of variants, that is, it describes how many nodes contained in a sub-tree are properly aligned. + +`Color Maps` to the right complement the visualisation, in which the percentage values indicate the 'degree' of the respective type of conformance. Darker the color, better the alignment. + +# Import / Export + +## Log Export + +One can export the event-log with various setting through the guided event-log exporter. +It could be opened by: the head toolbar -> `Files` -> <b>Export</b> Log as XES (<samp class="text-primary fw-bold">.xes</samp>)</span>. + +The steps for including user-created variants or trace fragments will only be accesible if a variant of that type is present in the Variant Explorer. + +# Software Architecture + +Cortado is an end-user process mining tool offered as a standalone desktop application supporting all major operating systems. Cortado is built using a Python based backend and a frontend based on web development technologies. + +The following figure illustrates the main architecture of Cortado: + +<img class="large" src="./assets/doc/screenshots/software_architecture/architecture.png"> + +#### Backend +The library Cortado-core is central to Cortado's backend. The library implements algorithms and methods for incremental process discovery, temporal performance analysis, process execution variant detection, variant querying and conformance checking. The library can also be embedded and utilized in other software applications and is considered an independent contribution. + +The backend around Cortado-core is an application programming interface for the frontend i.e. it bundles functionality from Cortado-core into webservices tailored to the frontend using the framework FastAPI. Additionally, PyInstaller is used to bundle the backend, including Cortado-core library into a single executable package. + +#### Frontend + +The frontend is developed as a web application using web development languages including HTML, CSS, Javascript and Typescript bundled in Angular as an application framework. For various visualizations, the javascript library d3.js is used. + +Additionally, Electron framework is used to produce cross-platform desktop applications. + +#### Repository + +<a href="github.com/cortado-tool/cortado#readme" style="text-decoration:none"><i class="m-1 bi bi-link-45deg"></i>github.com/cortado-tool/cortado#readme</a> + +<p style="text-align: center;"><a href="https://cortado.fit.fraunhofer.de/#contact" style="text-decoration:none"><b>Contact <i class="m-1 bi bi-box-arrow-up-right"></i></b></a></p> diff --git a/src/frontend/src/assets/fonts/Roboto/Roboto-Black.ttf b/src/frontend/src/assets/fonts/Roboto/Roboto-Black.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0112e7da626ca2f959eca850c806779ba55dbfbd Binary files /dev/null and b/src/frontend/src/assets/fonts/Roboto/Roboto-Black.ttf differ diff --git a/src/frontend/src/assets/fonts/Roboto/Roboto-BlackItalic.ttf b/src/frontend/src/assets/fonts/Roboto/Roboto-BlackItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b2c6aca57bc0d92ab3197d595766bf9285deea00 Binary files /dev/null and b/src/frontend/src/assets/fonts/Roboto/Roboto-BlackItalic.ttf differ diff --git a/src/frontend/src/assets/fonts/Roboto/Roboto-Bold.ttf b/src/frontend/src/assets/fonts/Roboto/Roboto-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..43da14d84ecb949ca5f5e8ecca3a514aa7fe1c7d Binary files /dev/null and b/src/frontend/src/assets/fonts/Roboto/Roboto-Bold.ttf differ diff --git a/src/frontend/src/assets/fonts/Roboto/Roboto-BoldItalic.ttf b/src/frontend/src/assets/fonts/Roboto/Roboto-BoldItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..bcfdab4311f2201f45b341b36310e1cdb8051e34 Binary files /dev/null and b/src/frontend/src/assets/fonts/Roboto/Roboto-BoldItalic.ttf differ diff --git a/src/frontend/src/assets/fonts/Roboto/Roboto-Italic.ttf b/src/frontend/src/assets/fonts/Roboto/Roboto-Italic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1b5eaa361c7306b4246c48497c79475c0e05c5e2 Binary files /dev/null and b/src/frontend/src/assets/fonts/Roboto/Roboto-Italic.ttf differ diff --git a/src/frontend/src/assets/fonts/Roboto/Roboto-Light.ttf b/src/frontend/src/assets/fonts/Roboto/Roboto-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e7307e72c5e7bced5d36c776d0986bf71b605f15 Binary files /dev/null and b/src/frontend/src/assets/fonts/Roboto/Roboto-Light.ttf differ diff --git a/src/frontend/src/assets/fonts/Roboto/Roboto-LightItalic.ttf b/src/frontend/src/assets/fonts/Roboto/Roboto-LightItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2d277afb231f7613a49d983217c1aba871741433 Binary files /dev/null and b/src/frontend/src/assets/fonts/Roboto/Roboto-LightItalic.ttf differ diff --git a/src/frontend/src/assets/fonts/Roboto/Roboto-Medium.ttf b/src/frontend/src/assets/fonts/Roboto/Roboto-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ac0f908b9c9c73da558b45d65cc5c6094874d3e8 Binary files /dev/null and b/src/frontend/src/assets/fonts/Roboto/Roboto-Medium.ttf differ diff --git a/src/frontend/src/assets/fonts/Roboto/Roboto-MediumItalic.ttf b/src/frontend/src/assets/fonts/Roboto/Roboto-MediumItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..fc36a4785c50c04c9b18260e4709cda077ed352d Binary files /dev/null and b/src/frontend/src/assets/fonts/Roboto/Roboto-MediumItalic.ttf differ diff --git a/src/frontend/src/assets/fonts/Roboto/Roboto-Regular.ttf b/src/frontend/src/assets/fonts/Roboto/Roboto-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ddf4bfacb396e97546364ccfeeb9c31dfaea4c25 Binary files /dev/null and b/src/frontend/src/assets/fonts/Roboto/Roboto-Regular.ttf differ diff --git a/src/frontend/src/assets/fonts/Roboto/Roboto-Thin.ttf b/src/frontend/src/assets/fonts/Roboto/Roboto-Thin.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2e0dee6a833c4b568d44ac99727f7e0c17c6eb67 Binary files /dev/null and b/src/frontend/src/assets/fonts/Roboto/Roboto-Thin.ttf differ diff --git a/src/frontend/src/assets/fonts/Roboto/Roboto-ThinItalic.ttf b/src/frontend/src/assets/fonts/Roboto/Roboto-ThinItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..084f9c0f5365952d4d860431a1c2dca147e4a9b5 Binary files /dev/null and b/src/frontend/src/assets/fonts/Roboto/Roboto-ThinItalic.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Bold.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d8841280b87b058e919d994667a7866605e0bc19 Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Bold.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-BoldItalic.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-BoldItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e9c480255ed443af241d54fb73124e4441fdf775 Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-BoldItalic.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-ExtraLight.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-ExtraLight.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9ff7ac6ab9d244967084802fd60ec8b7208f3472 Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-ExtraLight.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-ExtraLightItalic.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-ExtraLightItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9e962d4d1ec5b3b90f6b99774deab7dffd1060f1 Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-ExtraLightItalic.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Italic.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Italic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..61e5303325a1b4d196d3ba631ac4681b1fdfb7c9 Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Italic.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Light.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4893662d796cd071a024142b8b97c292ef04eb64 Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Light.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-LightItalic.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-LightItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..39b72503b928b1981820f68e49df5a8c02cdbbff Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-LightItalic.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Medium.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f6c149a2035375cc8b09a0611afb89ae4896069d Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Medium.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-MediumItalic.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-MediumItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..70a1a75a30a427e2b4f15d0b44ad9673ab5bd07b Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-MediumItalic.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Regular.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6df2b253603094de7f39886aae03181c686e375b Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Regular.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-SemiBold.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-SemiBold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..82ddc82a9bae58c7fcd236d8c0158db235baba10 Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-SemiBold.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-SemiBoldItalic.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-SemiBoldItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..15b08461ffb6e18bc688cc7ee6ad7242366a34cf Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-SemiBoldItalic.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Thin.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Thin.ttf new file mode 100644 index 0000000000000000000000000000000000000000..aeb997ba31c7a12efa67212f04189ca2c3828d8f Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-Thin.ttf differ diff --git a/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-ThinItalic.ttf b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-ThinItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ab99e08b23f6d8006c8109c590b8537d3a81a53c Binary files /dev/null and b/src/frontend/src/assets/fonts/RobotoMono/RobotoMono-ThinItalic.ttf differ diff --git a/src/frontend/src/assets/icons/png/1024x1024.png b/src/frontend/src/assets/icons/png/1024x1024.png new file mode 100644 index 0000000000000000000000000000000000000000..1c09a4b70b2d87e58e5cac9306184e47484cb545 Binary files /dev/null and b/src/frontend/src/assets/icons/png/1024x1024.png differ diff --git a/src/frontend/src/assets/icons/png/128x128.png b/src/frontend/src/assets/icons/png/128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..d2d242d2143f18078f6238e8def8e98b0a63a293 Binary files /dev/null and b/src/frontend/src/assets/icons/png/128x128.png differ diff --git a/src/frontend/src/assets/icons/png/16x16.png b/src/frontend/src/assets/icons/png/16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..1007fc2ae989ad00d89488285b799fe26306adc1 Binary files /dev/null and b/src/frontend/src/assets/icons/png/16x16.png differ diff --git a/src/frontend/src/assets/icons/png/24x24.png b/src/frontend/src/assets/icons/png/24x24.png new file mode 100644 index 0000000000000000000000000000000000000000..64a8b8b13f9807f4deb0e4c1abfd7ff3268cc9a2 Binary files /dev/null and b/src/frontend/src/assets/icons/png/24x24.png differ diff --git a/src/frontend/src/assets/icons/png/256x256.png b/src/frontend/src/assets/icons/png/256x256.png new file mode 100644 index 0000000000000000000000000000000000000000..3d1e9f0b472c0aeb860e5021ae90d07226415214 Binary files /dev/null and b/src/frontend/src/assets/icons/png/256x256.png differ diff --git a/src/frontend/src/assets/icons/png/32x32.png b/src/frontend/src/assets/icons/png/32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..c9f9cd9eeee32bcf71bb73fa8b5356bc5de074da Binary files /dev/null and b/src/frontend/src/assets/icons/png/32x32.png differ diff --git a/src/frontend/src/assets/icons/png/48x48.png b/src/frontend/src/assets/icons/png/48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..2f9df7cc8608e6d50a71c478e0e2700f136ccc39 Binary files /dev/null and b/src/frontend/src/assets/icons/png/48x48.png differ diff --git a/src/frontend/src/assets/icons/png/512x512.png b/src/frontend/src/assets/icons/png/512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..4e0c9e8ded914c95cd46a1e4a4b03954af26b156 Binary files /dev/null and b/src/frontend/src/assets/icons/png/512x512.png differ diff --git a/src/frontend/src/assets/icons/png/64x64.png b/src/frontend/src/assets/icons/png/64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..a7b2255993e1a12a16016368dd4f259bd8ae8e60 Binary files /dev/null and b/src/frontend/src/assets/icons/png/64x64.png differ diff --git a/src/frontend/src/assets/icons/win/icon.ico b/src/frontend/src/assets/icons/win/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3be705ec3b1cab0396650a3386460fe272b99a96 Binary files /dev/null and b/src/frontend/src/assets/icons/win/icon.ico differ diff --git a/src/frontend/src/assets/pm4py-logo.svg b/src/frontend/src/assets/pm4py-logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..b2bd6309374e7b83067d0a1604703698211d7ea7 --- /dev/null +++ b/src/frontend/src/assets/pm4py-logo.svg @@ -0,0 +1,29 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="3300" + height="1515"> + + <g transform="scale(15) translate(10, 10)"> + <defs id="SvgjsDefs2730"> + <linearGradient id="SvgjsLinearGradient2734"> + <stop id="SvgjsStop2735" stop-color="#2d388a" offset="0"></stop> + <stop id="SvgjsStop2736" stop-color="#00aeef" offset="1"></stop> + </linearGradient> + <linearGradient id="SvgjsLinearGradient2737"> + <stop id="SvgjsStop2738" stop-color="#2d388a" offset="0"></stop> + <stop id="SvgjsStop2739" stop-color="#00aeef" offset="1"></stop> + </linearGradient> + </defs> + <g id="SvgjsG2731" featureKey="root" fill="#ffffff"></g> + <g id="SvgjsG2732" featureKey="text1" fill="url(#SvgjsLinearGradient2734)" + transform="matrix(2.8273062705993652,0,0,2.8273062705993652,-4.583328726991322,-4.1365319772262445)"> + <path + d="M8.36 5 q2.38 0 3.84 1.37 t1.46 3.65 t-1.44 3.64 t-3.86 1.36 l-3.82 0 l0 4.08 q0 0.28 -0.21 0.49 t-0.49 0.21 l-1.52 0 q-0.28 0 -0.49 -0.21 t-0.21 -0.49 l0 -6.2 q0 -0.28 0.21 -0.49 t0.49 -0.21 l5.92 0 q1.34 0 1.92 -0.58 q0.58 -0.52 0.58 -1.58 t-0.6 -1.63 t-1.9 -0.57 l-5.92 0 q-0.28 0 -0.49 -0.21 t-0.21 -0.49 l0 -1.44 q0 -0.28 0.21 -0.49 t0.49 -0.21 l6.04 0 z M29.439999999999998 5 q0.28 0 0.49 0.21 t0.21 0.49 l0 13.4 q0 0.28 -0.21 0.49 t-0.49 0.21 l-1.52 0 q-0.3 0 -0.5 -0.21 t-0.2 -0.49 l0 -9.04 l-3.7 4.76 q-0.22 0.26 -0.56 0.26 l0 0 q-0.16 0 -0.32 -0.07 t-0.24 -0.21 l-6.56 -8.68 q-0.12 -0.14 -0.14 -0.35 t0.08 -0.38 t0.26 -0.28 t0.36 -0.11 l1.76 0 q0.34 0 0.56 0.28 l4.24 5.6 l4.14 -5.6 q0.22 -0.28 0.58 -0.28 l1.76 0 z M17.92 14.7 q0.28 0 0.49 0.2 t0.21 0.5 l0 3.7 q0 0.28 -0.21 0.49 t-0.49 0.21 l-1.52 0 q-0.28 0 -0.49 -0.21 t-0.21 -0.49 l0 -3.7 q0 -0.3 0.21 -0.5 t0.49 -0.2 l1.52 0 z M42.42 13.559999999999999 q0.3 0 0.5 0.2 t0.2 0.48 l0 1.36 q0 0.28 -0.2 0.48 t-0.5 0.2 l-0.8 0 l0 2.7 q0 0.28 -0.21 0.49 t-0.49 0.21 l-1.5 0 q-0.28 0 -0.49 -0.21 t-0.21 -0.49 l0 -2.7 l-5.64 0 q-0.28 0 -0.49 -0.2 t-0.21 -0.48 l0 -1.48 q0 -0.2 0.12 -0.38 l5.58 -8.42 q0.08 -0.14 0.24 -0.23 t0.34 -0.09 l2.26 0 q0.28 0 0.49 0.21 t0.21 0.49 l0 7.86 l0.8 0 z M35.8 13.559999999999999 l2.92 0 l0 -4.32 z M52.26 5 q2.38 0 3.84 1.37 t1.46 3.65 t-1.44 3.64 t-3.86 1.36 l-3.82 0 l0 4.08 q0 0.28 -0.21 0.49 t-0.49 0.21 l-1.52 0 q-0.28 0 -0.49 -0.21 t-0.21 -0.49 l0 -6.2 q0 -0.28 0.21 -0.49 t0.49 -0.21 l5.92 0 q1.34 0 1.92 -0.58 q0.58 -0.52 0.58 -1.58 t-0.6 -1.63 t-1.9 -0.57 l-5.92 0 q-0.28 0 -0.49 -0.21 t-0.21 -0.49 l0 -1.44 q0 -0.28 0.21 -0.49 t0.49 -0.21 l6.04 0 z M72.2 5.380000000000001 q0.1 0.18 0.09 0.38 t-0.13 0.36 l-5.54 8 l0 5.14 q0 0.28 -0.21 0.49 t-0.49 0.21 l-1.54 0 q-0.3 0 -0.51 -0.21 t-0.21 -0.49 l0 -5.86 q0 -0.2 0.14 -0.4 l5.34 -7.7 q0.1 -0.14 0.25 -0.22 t0.33 -0.08 l1.86 0 q0.2 0 0.37 0.1 t0.25 0.28 z M63.779999999999994 9.78 q-0.08 0.18 -0.25 0.28 t-0.37 0.1 l-1.86 0 q-0.36 0 -0.6 -0.3 l-2.6 -3.74 q-0.1 -0.16 -0.11 -0.36 t0.07 -0.38 t0.25 -0.28 t0.37 -0.1 l1.88 0 q0.34 0 0.58 0.3 l2.6 3.74 q0.1 0.16 0.11 0.36 t-0.07 0.38 z"></path> + </g> + <!-- + <g id="SvgjsG2733" featureKey="text3" fill="url(#SvgjsLinearGradient2737)" + transform="matrix(0.5787849426269531,0,0,0.5787849426269531,13.876343228002979,65.95773486541121)"> + <path + d="M1.94 15.62 l0 -13.24 c0 -0.2 0.16 -0.38 0.38 -0.38 l4.56 0 c2.46 0 4.48 2 4.48 4.42 c0 2.48 -2.02 4.5 -4.46 4.5 l-2.9 0 l0 4.7 c0 0.2 -0.18 0.38 -0.38 0.38 l-1.3 0 c-0.22 0 -0.38 -0.18 -0.38 -0.38 z M4 8.96 l2.76 0 c1.38 0 2.54 -1.12 2.54 -2.56 c0 -1.36 -1.16 -2.4 -2.54 -2.4 l-2.76 0 l0 4.96 z M13.82 15.62 l0 -13.24 c0 -0.2 0.16 -0.38 0.38 -0.38 l5.44 0 c2.4 0 4.36 1.9 4.36 4.28 c0 1.84 -1.22 3.36 -2.96 4.06 l2.74 5.08 c0.14 0.26 0 0.58 -0.34 0.58 l-1.56 0 c-0.16 0 -0.28 -0.1 -0.32 -0.18 l-2.66 -5.3 l-3.02 0 l0 5.1 c0 0.2 -0.18 0.38 -0.38 0.38 l-1.3 0 c-0.22 0 -0.38 -0.18 -0.38 -0.38 z M15.920000000000002 8.8 l3.56 0 c1.3 0 2.44 -1.1 2.44 -2.48 c0 -1.3 -1.14 -2.38 -2.44 -2.38 l-3.56 0 l0 4.86 z M26.1 9.02 c0 -4 3.18 -7.22 7.18 -7.22 s7.2 3.22 7.2 7.22 s-3.2 7.18 -7.2 7.18 s-7.18 -3.18 -7.18 -7.18 z M28.1 9.02 c0 2.86 2.34 5.18 5.18 5.18 c2.86 0 5.2 -2.32 5.2 -5.18 c0 -2.84 -2.34 -5.22 -5.2 -5.22 c-2.84 0 -5.18 2.38 -5.18 5.22 z M42.32 9.02 c0 -4 3.22 -7.22 7.22 -7.22 c2.02 0 3.48 0.68 4.84 1.86 c0.18 0.16 0.18 0.4 0.02 0.56 l-0.88 0.9 c-0.14 0.18 -0.32 0.18 -0.5 0 c-0.94 -0.82 -2.22 -1.34 -3.46 -1.34 c-2.86 0 -5.02 2.4 -5.02 5.2 s2.18 5.18 5.04 5.18 c1.46 0 2.48 -0.58 3.44 -1.32 c0.18 -0.14 0.36 -0.12 0.48 -0.02 l0.92 0.9 c0.16 0.14 0.12 0.4 -0.02 0.54 c-1.36 1.32 -3.08 1.94 -4.86 1.94 c-4 0 -7.22 -3.18 -7.22 -7.18 z M57.26 15.62 l0 -13.24 c0 -0.2 0.16 -0.38 0.38 -0.38 l8 0 c0.22 0 0.38 0.18 0.38 0.38 l0 1.12 c0 0.2 -0.16 0.38 -0.38 0.38 l-6.32 0 l0 4.08 l5.34 0 c0.2 0 0.38 0.18 0.38 0.38 l0 1.12 c0 0.22 -0.18 0.38 -0.38 0.38 l-5.34 0 l0 4.3 l6.32 0 c0.22 0 0.38 0.18 0.38 0.38 l0 1.1 c0 0.2 -0.16 0.38 -0.38 0.38 l-8 0 c-0.22 0 -0.38 -0.18 -0.38 -0.38 z M68.25999999999999 14.620000000000001 c-0.18 -0.16 -0.32 -0.3 -0.12 -0.64 c0.18 -0.26 0.34 -0.56 0.52 -0.82 s0.46 -0.34 0.68 -0.16 c0.12 0.1 1.66 1.38 3.2 1.38 c1.38 0 2.26 -0.84 2.26 -1.86 c0 -1.2 -1.04 -1.96 -3.02 -2.78 c-2.04 -0.86 -3.64 -1.92 -3.64 -4.24 c0 -1.56 1.2 -3.7 4.38 -3.7 c2 0 3.5 1.04 3.7 1.18 c0.16 0.1 0.32 0.38 0.12 0.68 c-0.16 0.24 -0.34 0.52 -0.5 0.76 c-0.16 0.26 -0.42 0.38 -0.7 0.2 c-0.14 -0.08 -1.54 -1 -2.7 -1 c-1.68 0 -2.26 1.06 -2.26 1.8 c0 1.14 0.88 1.84 2.54 2.52 c2.32 0.94 4.3 2.04 4.3 4.48 c0 2.08 -1.86 3.78 -4.46 3.78 c-2.44 0 -3.98 -1.28 -4.3 -1.58 z M78.99999999999999 14.620000000000001 c-0.18 -0.16 -0.32 -0.3 -0.12 -0.64 c0.18 -0.26 0.34 -0.56 0.52 -0.82 s0.46 -0.34 0.68 -0.16 c0.12 0.1 1.66 1.38 3.2 1.38 c1.38 0 2.26 -0.84 2.26 -1.86 c0 -1.2 -1.04 -1.96 -3.02 -2.78 c-2.04 -0.86 -3.64 -1.92 -3.64 -4.24 c0 -1.56 1.2 -3.7 4.38 -3.7 c2 0 3.5 1.04 3.7 1.18 c0.16 0.1 0.32 0.38 0.12 0.68 c-0.16 0.24 -0.34 0.52 -0.5 0.76 c-0.16 0.26 -0.42 0.38 -0.7 0.2 c-0.14 -0.08 -1.54 -1 -2.7 -1 c-1.68 0 -2.26 1.06 -2.26 1.8 c0 1.14 0.88 1.84 2.54 2.52 c2.32 0.94 4.3 2.04 4.3 4.48 c0 2.08 -1.86 3.78 -4.46 3.78 c-2.44 0 -3.98 -1.28 -4.3 -1.58 z M93.96 15.54 l2.48 -13.44 c0.04 -0.16 0.2 -0.3 0.36 -0.3 l0.32 0 c0.12 0 0.3 0.1 0.34 0.22 l4.18 10.22 l0.08 0 l4.16 -10.22 c0.04 -0.12 0.2 -0.22 0.34 -0.22 l0.32 0 c0.16 0 0.32 0.14 0.36 0.3 l2.46 13.44 c0.06 0.28 -0.08 0.46 -0.36 0.46 l-1.3 0 c-0.18 0 -0.34 -0.14 -0.38 -0.28 l-1.48 -8.94 l-0.06 0 l-3.6 9.2 c-0.04 0.12 -0.16 0.22 -0.34 0.22 l-0.36 0 c-0.16 0 -0.3 -0.1 -0.34 -0.22 l-3.62 -9.2 l-0.08 0 l-1.44 8.94 c-0.02 0.14 -0.2 0.28 -0.36 0.28 l-1.3 0 c-0.28 0 -0.42 -0.18 -0.38 -0.46 z M112.29999999999998 15.62 l0 -13.24 c0 -0.2 0.18 -0.38 0.38 -0.38 l1.32 0 c0.2 0 0.38 0.18 0.38 0.38 l0 13.24 c0 0.2 -0.18 0.38 -0.38 0.38 l-1.32 0 c-0.2 0 -0.38 -0.18 -0.38 -0.38 z M118.25999999999998 15.62 l0 -13.46 c0 -0.2 0.18 -0.36 0.38 -0.36 l0.5 0 l8.68 10.04 l0.02 0 l0 -9.46 c0 -0.2 0.16 -0.38 0.38 -0.38 l1.28 0 c0.2 0 0.38 0.18 0.38 0.38 l0 13.46 c0 0.2 -0.18 0.36 -0.38 0.36 l-0.52 0 l-8.68 -10.32 l-0.02 0 l0 9.74 c0 0.2 -0.16 0.38 -0.38 0.38 l-1.26 0 c-0.2 0 -0.38 -0.18 -0.38 -0.38 z M133.76 15.62 l0 -13.24 c0 -0.2 0.18 -0.38 0.38 -0.38 l1.32 0 c0.2 0 0.38 0.18 0.38 0.38 l0 13.24 c0 0.2 -0.18 0.38 -0.38 0.38 l-1.32 0 c-0.2 0 -0.38 -0.18 -0.38 -0.38 z M139.72 15.62 l0 -13.46 c0 -0.2 0.18 -0.36 0.38 -0.36 l0.5 0 l8.68 10.04 l0.02 0 l0 -9.46 c0 -0.2 0.16 -0.38 0.38 -0.38 l1.28 0 c0.2 0 0.38 0.18 0.38 0.38 l0 13.46 c0 0.2 -0.18 0.36 -0.38 0.36 l-0.52 0 l-8.68 -10.32 l-0.02 0 l0 9.74 c0 0.2 -0.16 0.38 -0.38 0.38 l-1.26 0 c-0.2 0 -0.38 -0.18 -0.38 -0.38 z M154.2 9.02 c0 -4 3.22 -7.22 7.2 -7.22 c1.92 0 3.5 0.7 4.86 1.86 c0.16 0.16 0.18 0.4 0.02 0.56 c-0.3 0.32 -0.6 0.62 -0.9 0.94 c-0.16 0.18 -0.32 0.16 -0.52 -0.02 c-0.94 -0.82 -2.18 -1.36 -3.4 -1.36 c-2.84 0 -5.02 2.4 -5.02 5.2 c0 2.78 2.18 5.18 5.02 5.18 c1.66 0 2.8 -0.6 3 -0.68 l0 -2.24 l-1.96 0 c-0.22 0 -0.38 -0.16 -0.38 -0.36 l0 -1.16 c0 -0.22 0.16 -0.38 0.38 -0.38 l3.64 0 c0.2 0 0.36 0.18 0.36 0.38 c0 1.6 0.02 3.24 0.02 4.84 c0 0.1 -0.08 0.26 -0.16 0.32 c0 0 -2.06 1.32 -4.96 1.32 c-3.98 0 -7.2 -3.18 -7.2 -7.18 z M174.06 15.62 l0 -13.24 c0 -0.2 0.16 -0.38 0.38 -0.38 l8 0 c0.22 0 0.38 0.18 0.38 0.38 l0 1.12 c0 0.2 -0.16 0.38 -0.38 0.38 l-6.32 0 l0 4.62 l5.34 0 c0.2 0 0.38 0.18 0.38 0.38 l0 1.1 c0 0.2 -0.18 0.38 -0.38 0.38 l-5.34 0 l0 5.26 c0 0.2 -0.18 0.38 -0.38 0.38 l-1.3 0 c-0.22 0 -0.38 -0.18 -0.38 -0.38 z M184.35999999999999 9.02 c0 -4 3.18 -7.22 7.18 -7.22 s7.2 3.22 7.2 7.22 s-3.2 7.18 -7.2 7.18 s-7.18 -3.18 -7.18 -7.18 z M186.35999999999999 9.02 c0 2.86 2.34 5.18 5.18 5.18 c2.86 0 5.2 -2.32 5.2 -5.18 c0 -2.84 -2.34 -5.22 -5.2 -5.22 c-2.84 0 -5.18 2.38 -5.18 5.22 z M201.6 15.62 l0 -13.24 c0 -0.2 0.16 -0.38 0.38 -0.38 l5.44 0 c2.4 0 4.36 1.9 4.36 4.28 c0 1.84 -1.22 3.36 -2.96 4.06 l2.74 5.08 c0.14 0.26 0 0.58 -0.34 0.58 l-1.56 0 c-0.16 0 -0.28 -0.1 -0.32 -0.18 l-2.66 -5.3 l-3.02 0 l0 5.1 c0 0.2 -0.18 0.38 -0.38 0.38 l-1.3 0 c-0.22 0 -0.38 -0.18 -0.38 -0.38 z M203.7 8.8 l3.56 0 c1.3 0 2.44 -1.1 2.44 -2.48 c0 -1.3 -1.14 -2.38 -2.44 -2.38 l-3.56 0 l0 4.86 z M219.3 15.62 l0 -13.24 c0 -0.2 0.16 -0.38 0.38 -0.38 l4.56 0 c2.46 0 4.48 2 4.48 4.42 c0 2.48 -2.02 4.5 -4.46 4.5 l-2.9 0 l0 4.7 c0 0.2 -0.18 0.38 -0.38 0.38 l-1.3 0 c-0.22 0 -0.38 -0.18 -0.38 -0.38 z M221.36 8.96 l2.76 0 c1.38 0 2.54 -1.12 2.54 -2.56 c0 -1.36 -1.16 -2.4 -2.54 -2.4 l-2.76 0 l0 4.96 z M233.92000000000002 15.62 l0 -6.36 l-4.68 -6.68 c-0.16 -0.26 0 -0.58 0.32 -0.58 l1.48 0 c0.16 0 0.26 0.1 0.32 0.18 l3.62 5.1 l3.62 -5.1 c0.06 -0.08 0.18 -0.18 0.32 -0.18 l1.5 0 c0.32 0 0.48 0.32 0.32 0.58 l-4.74 6.66 l0 6.38 c0 0.2 -0.18 0.38 -0.38 0.38 l-1.32 0 c-0.22 0 -0.38 -0.18 -0.38 -0.38 z M244.58 15.62 l0 -11.74 l-3.26 0 c-0.22 0 -0.38 -0.18 -0.38 -0.38 l0 -1.12 c0 -0.2 0.16 -0.38 0.38 -0.38 l8.6 0 c0.22 0 0.38 0.18 0.38 0.38 l0 1.12 c0 0.2 -0.16 0.38 -0.38 0.38 l-3.26 0 l0 11.74 c0 0.2 -0.18 0.38 -0.38 0.38 l-1.32 0 c-0.2 0 -0.38 -0.18 -0.38 -0.38 z M252.46 15.62 l0 -13.24 c0 -0.2 0.18 -0.38 0.38 -0.38 l1.32 0 c0.22 0 0.38 0.18 0.38 0.38 l0 5.58 l7.32 0 l0 -5.58 c0 -0.2 0.16 -0.38 0.38 -0.38 l1.32 0 c0.2 0 0.38 0.18 0.38 0.38 l0 13.24 c0 0.2 -0.18 0.38 -0.38 0.38 l-1.32 0 c-0.22 0 -0.38 -0.18 -0.38 -0.38 l0 -5.78 l-7.32 0 l0 5.78 c0 0.2 -0.16 0.38 -0.38 0.38 l-1.32 0 c-0.2 0 -0.38 -0.18 -0.38 -0.38 z M266.8 9.02 c0 -4 3.18 -7.22 7.18 -7.22 s7.2 3.22 7.2 7.22 s-3.2 7.18 -7.2 7.18 s-7.18 -3.18 -7.18 -7.18 z M268.8 9.02 c0 2.86 2.34 5.18 5.18 5.18 c2.86 0 5.2 -2.32 5.2 -5.18 c0 -2.84 -2.34 -5.22 -5.2 -5.22 c-2.84 0 -5.18 2.38 -5.18 5.22 z M284.04 15.62 l0 -13.46 c0 -0.2 0.18 -0.36 0.38 -0.36 l0.5 0 l8.68 10.04 l0.02 0 l0 -9.46 c0 -0.2 0.16 -0.38 0.38 -0.38 l1.28 0 c0.2 0 0.38 0.18 0.38 0.38 l0 13.46 c0 0.2 -0.18 0.36 -0.38 0.36 l-0.52 0 l-8.68 -10.32 l-0.02 0 l0 9.74 c0 0.2 -0.16 0.38 -0.38 0.38 l-1.26 0 c-0.2 0 -0.38 -0.18 -0.38 -0.38 z"></path> + </g> + --> + </g> +</svg> diff --git a/src/frontend/src/environments/environment.browser.ts b/src/frontend/src/environments/environment.browser.ts new file mode 100644 index 0000000000000000000000000000000000000000..653646557c1bf96bf3e352ed7c0c99bbe806e8fc --- /dev/null +++ b/src/frontend/src/environments/environment.browser.ts @@ -0,0 +1,6 @@ +export const environment = { + production: false, + electron: false, + showLpms: false, + VERSION: require('../../package.json').version, +}; diff --git a/src/frontend/src/environments/environment.prod.ts b/src/frontend/src/environments/environment.prod.ts new file mode 100644 index 0000000000000000000000000000000000000000..3b250179eb567648312d5b8555799460c126b50e --- /dev/null +++ b/src/frontend/src/environments/environment.prod.ts @@ -0,0 +1,6 @@ +export const environment = { + production: true, + electron: true, + showLpms: false, + VERSION: require('../../package.json').version, +}; diff --git a/src/frontend/src/environments/environment.ts b/src/frontend/src/environments/environment.ts new file mode 100644 index 0000000000000000000000000000000000000000..abc42ecdf43b59ab4cf05b17c1089d3c61dc604e --- /dev/null +++ b/src/frontend/src/environments/environment.ts @@ -0,0 +1,18 @@ +// This file can be replaced during build by using the `fileReplacements` array. +// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. +// The list of file replacements can be found in `angular.json`. +export const environment = { + production: false, + electron: true, + showLpms: false, + VERSION: require('../../package.json').version, +}; + +/* + * For easier debugging in development mode, you can import the following file + * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. + * + * This import should be commented out in production mode because it will have a negative impact + * on performance if an error is thrown. + */ +// import 'zone.js/plugins/zone-error'; // Included with Angular CLI. diff --git a/src/frontend/src/index.html b/src/frontend/src/index.html new file mode 100644 index 0000000000000000000000000000000000000000..4a34afb27156e3ab14fdd5c7349969561b254b1d --- /dev/null +++ b/src/frontend/src/index.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8" /> + <title> + Cortado — Interactive Tool for Data-Driven Process Discovery & + Modeling + </title> + <base href="./" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + + <!-- https://www.electronjs.org/docs/faq#i-can-not-use-jqueryrequirejsmeteorangularjs-in-electron --> + + <!--- + <script> + + delete window.require; + delete window.exports; + delete window.module; + </script> + --> + + <link rel="icon" type="image/x-icon" href="assets/icons/png/256x256.png" /> + </head> + <body id="body"> + <app-root> + <div + class="loading-indicator-container d-flex flex-column justify-content-center align-items-center" + > + <img class="cortado-logo" src="assets/icons/png/256x256.png" /> + Starting Cortado ... + </div> + </app-root> + <div + id="monaco-editor-overflow-widgets-root" + class="monaco-editor" + style="z-index: 999" + ></div> + </body> +</html> diff --git a/src/frontend/src/main.ts b/src/frontend/src/main.ts new file mode 100644 index 0000000000000000000000000000000000000000..d9a2e7e4a582e265db779363bd8b2492c43c141b --- /dev/null +++ b/src/frontend/src/main.ts @@ -0,0 +1,13 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.error(err)); diff --git a/src/frontend/src/polyfills.ts b/src/frontend/src/polyfills.ts new file mode 100644 index 0000000000000000000000000000000000000000..7459dbc58b4d6bf818706ee7d38e7f71bd776c35 --- /dev/null +++ b/src/frontend/src/polyfills.ts @@ -0,0 +1,53 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/guide/browser-support + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** + * By default, zone.js will patch all possible macroTask and DomEvents + * user can disable parts of macroTask/DomEvents patch by setting following flags + * because those flags need to be set before `zone.js` being loaded, and webpack + * will put import in the top of bundle, so user need to create a separate file + * in this directory (for example: zone-flags.ts), and put the following flags + * into that file, and then add the following code before importing zone.js. + * import './zone-flags'; + * + * The flags allowed in zone-flags.ts are listed here. + * + * The following flags will work for all browsers. + * + * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame + * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick + * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + * + * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js + * with the following flag, it will bypass `zone.js` patch for IE/Edge + * + * (window as any).__Zone_enable_cross_context_check = true; + * + */ + +/*************************************************************************************************** + * Zone JS is required by default for Angular itself. + */ +import 'zone.js'; // Included with Angular CLI. + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ +import 'reflect-metadata'; diff --git a/src/frontend/src/styles.scss b/src/frontend/src/styles.scss new file mode 100644 index 0000000000000000000000000000000000000000..e5ef6002c1913fdf69273faa4d82155469994926 --- /dev/null +++ b/src/frontend/src/styles.scss @@ -0,0 +1,623 @@ +$tooltip-max-width: 450px; + +/* Define our main import here */ +@import "./styles/fonts"; +@import "./@theme/theme"; +@import "~bootstrap-icons/font/bootstrap-icons.css"; +@import "../node_modules/bootstrap/scss/bootstrap"; +@import "./styles/custom_golden_layout_styles"; +@import '@angular/cdk/overlay-prebuilt.css'; +@import '../node_modules/@perfectmemory/ngx-contextmenu/src/assets/stylesheets/base'; + +/* You can add global styles to this file, and also import other style files */ +.btn-icon { + font-size: var(--standard-font-size); +} + +:root { + --line-color: #485158; + --box-background-color: #2b2b2b; + --box-background-color-darker: #2f2f2f; + --footer-bar-height: 20px; + --header-bar-height: 25px; + --width-sidebar: 30px; + --text-primary: #ddd; + --text-secondary: #a0a0a0; + --thin-border-color: #1a1a1a; + --standard-font-size: 14px; + --bs-dark-rgb: 52 58 64; + --bs-bg-opacity: 100%; + --bs-font-sans-serif: "Roboto", sans-serif; + --bs-font-monospace: "Roboto Mono", monospace; + --bs-accordion-btn-icon-transform: rotate(-180deg); + --btn-hover-color: #515a64; +} + +.monaco-editor { + font-family: var(--bs-font-sans-serif) !important; +} + +body { + overflow: hidden; +} + +.bg-dark { + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)) !important; +} + +.table-dark { + --bs-table-bg: #343a40; + --bs-table-striped-bg: rgb(255 255 255 / 5%); + --bs-table-striped-color: var(--text-secondary); + --bs-table-active-bg: #373b3e; + --bs-table-active-color: var(--text-secondary); + --bs-table-hover-bg: rgb(0 0 0 / 5%); + --bs-table-hover-color: #fff; + + color: var(--text-secondary); + border-color: #373b3e; +} + +.btn-bar-text { + font-size: 13px; + color: whitesmoke; +} + +.button { + color: whitesmoke; + border: none; + padding: 2px 12px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: var(--standard-font-size); + cursor: pointer; + background-color: transparent; + user-select: none; + height: 100%; + + /* + vertical-align: top; + */ + white-space: nowrap; +} + +.button-active { + background-color: darkgray; +} + +.button:disabled { + color: #757575 !important; +} + +.button:focus { + outline: none; +} + +.button:hover:enabled { + background-color: var(--btn-hover-color); +} + +.btn-tool-bar { + min-height: 28px; + display: flex; + align-items: center; +} + +hr { + display: block; + margin: 0; + border-style: inset; + border-top: 1px solid var(--line-color); + width: 100%; +} + +.vr { + background-color: var(--line-color); + opacity: 1; +} + +.secondary-text { + color: var(--text-secondary); + font-size: var(--standard-font-size); +} + +.primary-text { + color: var(--text-primary); + font-size: var(--standard-font-size); +} + + +.secondary-text-color { + color: var(--text-secondary); +} + +.cursor-pointer { + cursor: pointer; +} + +.cursor-help { + cursor: help; +} + +/* style scroll bars */ +::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +::-webkit-scrollbar-corner { + background: var(--box-background-color); +} + +/* Track */ +::-webkit-scrollbar-track:hover { + background: #444; +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: #555; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: #888; +} + +.font-large { + font-size: large; +} + +.warning-highlight { + background-color: rgb(255 255 0 / 33.3%); +} + +.imbalanced-parenthesis { + border-bottom: 1.5px solid; + border-color: red; +} + +code { + color: var(--text-secondary); +} + +.swal2-modal { + background-color: var(--box-background-color) !important; +} + +.swal2-html-container { + text-align: left !important; +} + +.container-fluid { + padding-left: 0; + padding-right: 0; +} + +.row > * { + padding-left: unset; + padding-right: unset; +} + +th { + --bs-table-accent-bg: transparent !important; +} + +/* + Classes for the process tree SVG elements are used to easily differentiate the elements + and to add style that changes dynamically. Thus easier subtype specific selections can be made + and the styling can be stripped before tree export + + Used but Empty classes are: + + .node + .node-operator + .node-visible-activity + .node-invisible-activity + .node-text + +*/ + +.frozen-node-operator { + fill: #25306a !important; +} + +.frozen-node-visible-activity { + fill: #425bbf !important; +} + +.frozen-node-invisible-activity { + fill: #161e40 !important; +} + +.frozen-edge { + stroke: #425bbf; +} + +.selected-node { + stroke: #dc3545 !important; +} + +.selected-edge { + stroke: #dc3545 !important; +} + +.logical-operator { + color: rgb(65 141 213); +} + +.query-operator { + color: rgb(65 141 213); +} + +.number-operator { + color: rgb(238 205 21); +} + +.syntax-operator { + color: rgb(255 255 255); +} + +.syntax-info { + background-color: rgb(0 0 0 / 40%); + position: absolute; + font-size: small; + bottom: 0; + left: 0; + text-align: left; + cursor: auto; +} + +.syntax-info ul { + margin-bottom: 0; +} + +.grid { + background-image: radial-gradient(var(--line-color) 1px, transparent 0); + background-size: 20px 20px; +} + +.h-line-modal-bottom { + border-bottom: 1px solid var(--line-color); +} + +.h-line-modal-top { + border-top: 1px solid var(--line-color); +} + +.tooltip-table { + border-collapse: collapse; + border: none; + width: 100%; +} + +.nav-link { + border: none !important; + background-color: transparent !important; + color: #495057 !important; + + &.active { + background-color: none !important; + border-bottom: 1px solid whitesmoke !important; + color: whitesmoke !important; + } +} + +.nav-tabs { + border-bottom: none; +} + +.accordion-button { + color: whitesmoke !important; + display: flex; + justify-content: space-between; + + .collapsed { + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)) !important; + } +} + +.accordion-button:focus, +.accordion-button:active { + outline: none !important; + box-shadow: none; +} + +.accordion-item { + border-left: none; + border-right: none; + background-color: var(--box-background-color); + border-bottom-right-radius: unset; + border-bottom-left-radius: unset; + + table { + margin: 0; + } +} + +.modal-content { + background-color: var(--box-background-color); +} + +.dialog-label { + font-size: var(--standard-font-size); +} + +.standard-font-size { + font-size: var(--standard-font-size); +} + +.styled-input-field, +.styled-input-field:focus { + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); + padding: 0.45rem; + border-radius: 0.25rem; + color: var(--text-secondary); + font-size: small; +} + +.form-select.styled-select { + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); + color: var(--text-secondary); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='white' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e") !important; +} + +.tab-content { + overflow: auto; +} + +.performance-tooltip-hr { + height: 2px; + opacity: 1; + margin-top: 5px; +} + +/* Make the color picker looks more cortado-y */ + +.color-picker { + background-color: var(--box-background-color) !important; + z-index: 99999 !important; +} + +.color-picker .hex-text .box div, +.color-picker .cmyk-text .box div, +.color-picker .hsla-text .box div, +.color-picker .rgba-text .box div, +.color-picker .value-text .box div { + color: var(--text-secondary) !important; +} + +.color-picker .type-policy { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAgCAYAAAAffCjxAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEKSURBVEhL7ZXBDoIwDIaZJPoqEk6GBzHhyKtw5lU4En0YHoSjRsV16RY2WoqTi4lfQtqR7qddt5FINE0zwoNDFoWWJBSo65qN36GdoUUe6DqodxZWSJOinUK9M5CpSmtClTjLSIu80GWhYjyhPM/32iw2AFEY6/CEqqq6oSsSxrqvS+vCYdfLZLTUVgk715bGtnUFZq6KLSkkHYbhlGXZEcdRdF13RffPT6GKoriUZXnGcRTQ/s02pDlw34rBwbVn7Yk2BjN3s2vECQGfik3vbu+GbNv2gK5IGOsJ9X1/12ZNViPGOrzSLFKJ1O+IFAI4MUoE8EoLoLYEu03YjIAwKy6bVYCYvC2S5A27y2RrXIt7DgAAAABJRU5ErkJggg==") !important; +} + +.cp-button { + border: solid !important; + border-width: 1px !important; + border-radius: 5px; + color: var(--text-secondary); +} + +.variant-performance-button { + padding: 1px 5px; + margin-right: 5px; +} + +.selected-variant-performance { + border: solid grey !important; + border-radius: 5px !important; +} + +.light-dashed-border { + border-radius: 5px; + border: 1px dashed lightgrey; +} + +.selected-polygon { + stroke: whitesmoke !important; + stroke-width: 3 !important; + stroke-dasharray: 2; +} + +.selected-bpmn-operator { + outline: dashed 1px red; + outline-offset: 5px; +} + +.selected-bpmn-event { + rect { + stroke: red; + stroke-width: 2px; + stroke-dasharray: 0; + } + + text { + stroke: none; + } + + stroke: red; + stroke-width: 1px; + stroke-dasharray: 4; + marker-end: url("#arrow-red"); +} + +.selected-subvariant { + stroke-width: 3 !important; +} + +.subvariant-rect { + stroke-width: 0; + stroke: white; + stroke-dasharray: 2 1; +} + +.cortado-logo { + height: 100px; + animation: pulse 2s infinite ease-out; + padding: 5px; +} + +@keyframes pulse { + 0% { + transform: scale(0.66); + } + + 50% { + transform: scale(1); + } + + 100% { + transform: scale(0.66); + } +} + +.loading-indicator-container { + width: 100vw !important; + height: 100vh !important; + background-color: var(--box-background-color); + color: var(--text-primary); +} + +.activity-button-out { + filter: opacity(0.35); +} + +.activity-button-in { + filter: brightness(1.4) drop-shadow(2px 4px 6px black); +} + +.collapsed-golden-layout-container { + background-color: var(--box-background-color); +} + +.collapsed-golden-layout-container.horizontal-dots::after { + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='10' fill='white' viewBox='0 3 9 12'%3E%3Cpath d='M3 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z'/%3E%3C/svg%3E"); + position: absolute; + display: block; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: white; +} + +.collapsed-golden-layout-container.vertical-dots::after { + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='14' fill='white%0A' class='bi bi-three-dots-vertical' viewBox='2 0 12 12'%3E%3Cpath d='M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z'/%3E%3C/svg%3E"); + position: absolute; + display: block; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: white; +} + +.remove-variant-button { + display: none; +} + +tr:hover > td .remove-variant-button { + display: inline !important; +} + +tr:hover > .fixed-right { + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)) !important; +} + +.custom-dropdown { + font-size: small; + max-height: 90vh; + user-select: none; +} + +.general-dropdown { + background-color: var(--box-background-color); + color: var(--bs-white); +} + +.dropdown-item:hover:enabled { + background-color: #4d4e50; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.lm_header .lm_tabdropdown_list .lm_tab .lm_title { + width: 112px !important; +} + +svg *:focus { + outline: none; +} + +.info-bar { + font-size: var(--standard-font-size); + color: var(--text-secondary); + padding-left: 1em; + width: 100%; + text-align: right; +} + +code, +pre { + background-color: #d5d5d5; + color: rgb(56 75 211); + border-radius: 3px; + margin: 0 2px; + padding: 0 5px; + white-space: pre; + } + +pre code { + border: none; + margin: 0; + padding: 0; + white-space: pre; +} + +.markdown-table { + border: 1px solid rgb(255 255 255 / 68%); + padding: 3px; +} + +.accordion { + --bs-accordion-btn-icon-transform: rotate(-180deg); + --bs-accordion-active-bg: var(--btn-hover-color); +} + +/* stylelint-disable-next-line selector-class-pattern */ +.lm_header .lm_tab { + font-family: var(--bs-font-sans-serif); +} + +/* stylelint-disable scss/double-slash-comment-empty-line-before */ +.custom-style { + /* Styling of the context menu itself */ + // --ngx-contextmenu-font-family: sans-serif; + --ngx-contextmenu-background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)); + // --ngx-contextmenu-border-radius: 4px; + // --ngx-contextmenu-border: 1px solid rgba(0, 0, 0, 0.18); + // --ngx-contextmenu-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.18); + // --ngx-contextmenu-font-size: 14px; + // --ngx-contextmenu-margin: 2px 0 0; + // --ngx-contextmenu-min-width: 160px; + // --ngx-contextmenu-outline: 1px solid #70757e; + // --ngx-contextmenu-padding: 5px 0; + --ngx-contextmenu-text-color: var(--text-primary); + --ngx-contextmenu-text-disabled-color: #8a909a; + // --ngx-contextmenu-max-height: 100vh; + + /* Styling of context menu items */ + // --ngx-contextmenu-item-arrow-left: '◀'; + // --ngx-contextmenu-item-arrow-right: '▶'; + // --ngx-contextmenu-item-background-hover-color: #4d4e50; + --ngx-contextmenu-item-background-hover-color: #515a64; + --ngx-contextmenu-item-separator-color: var(--line-color); + // --ngx-contextmenu-item-separator-padding: 10px; + // --ngx-contextmenu-item-separator-width: 96%; + // --ngx-contextmenu-item-padding: 6px 20px; + --ngx-contextmenu-item-text-hover-color: var(--text-primary); +} +/* stylelint-enable scss/double-slash-comment-empty-line-before */ + +/* stylelint-disable-next-line selector-class-pattern */ +.ngx-contextmenu--item-content i { + margin-right: 5px; +} diff --git a/src/frontend/src/styles/color_picker_styles.scss b/src/frontend/src/styles/color_picker_styles.scss new file mode 100644 index 0000000000000000000000000000000000000000..1aed1f280e87a21d05602d330ac8fe18e5218aa0 --- /dev/null +++ b/src/frontend/src/styles/color_picker_styles.scss @@ -0,0 +1,25 @@ +/* Make the color picker looks more cortado-y */ + +.color-picker { + background-color: var(--box-background-color) !important; + z-index: 99999 !important; +} + +.color-picker .hex-text .box div, +.color-picker .cmyk-text .box div, +.color-picker .hsla-text .box div, +.color-picker .rgba-text .box div, +.color-picker .value-text .box div { + color: var(--text-secondary) !important; +} + +.color-picker .type-policy { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAgCAYAAAAffCjxAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEKSURBVEhL7ZXBDoIwDIaZJPoqEk6GBzHhyKtw5lU4En0YHoSjRsV16RY2WoqTi4lfQtqR7qddt5FINE0zwoNDFoWWJBSo65qN36GdoUUe6DqodxZWSJOinUK9M5CpSmtClTjLSIu80GWhYjyhPM/32iw2AFEY6/CEqqq6oSsSxrqvS+vCYdfLZLTUVgk715bGtnUFZq6KLSkkHYbhlGXZEcdRdF13RffPT6GKoriUZXnGcRTQ/s02pDlw34rBwbVn7Yk2BjN3s2vECQGfik3vbu+GbNv2gK5IGOsJ9X1/12ZNViPGOrzSLFKJ1O+IFAI4MUoE8EoLoLYEu03YjIAwKy6bVYCYvC2S5A27y2RrXIt7DgAAAABJRU5ErkJggg==") !important; +} + +.cp-button { + border: solid !important; + border-width: 1px !important; + border-radius: 5px; + color: var(--text-secondary); +} diff --git a/src/frontend/src/styles/custom_golden_layout_styles.scss b/src/frontend/src/styles/custom_golden_layout_styles.scss new file mode 100644 index 0000000000000000000000000000000000000000..f43373ec845589f72aa106d75d293f77589c2a5e --- /dev/null +++ b/src/frontend/src/styles/custom_golden_layout_styles.scss @@ -0,0 +1,75 @@ +/* stylelint-disable-next-line selector-class-pattern */ +.lm_goldenlayout{ + --bs-bg-opacity: 1; + + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity))!important; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.lm_tab { + background: var(--box-background-color)!important; + border-top-left-radius: .25rem; + border-top-right-radius: .25rem; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.lm_tab.lm_active { + background: rgb(119 117 117)!important; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.lm_header .lm_tab.lm_active { + border-bottom: none; + padding-bottom: 8.5px; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.lm_header .lm_tab{ + cursor: pointer; + float: left; + height: 10px; + padding: 0 18px 8.5px 5px; + position: relative; + touch-action: none; + -webkit-font-smoothing: subpixel-antialiased; + filter: blur(0); + backface-visibility: hidden; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.lm_header{ + background-color: rgb(var(--bs-dark-rgb) / var(--bs-bg-opacity)) !important; + border-bottom: 1px solid black; +} + + +.process-tree-editor-stack{ +/* stylelint-disable-next-line selector-class-pattern */ + .lm_tabs{ + margin-top : 1.5px; + } + +} + + +.variant-explorer-stack{ +/* stylelint-disable-next-line selector-class-pattern */ + .lm_header{ + margin-left: 20px; + } + +} + + +.info-box-stack{ +/* stylelint-disable-next-line selector-class-pattern */ + .lm_header{ + padding-left: 10px; + } + +} + + + + + diff --git a/src/frontend/src/styles/fonts.scss b/src/frontend/src/styles/fonts.scss new file mode 100644 index 0000000000000000000000000000000000000000..17cbe3799f6f5fca471644f4fbf06e30b7e2799c --- /dev/null +++ b/src/frontend/src/styles/fonts.scss @@ -0,0 +1,184 @@ +/* Roboto Thin */ +@font-face { + font-family: Roboto; + src: url('../assets/fonts/Roboto/Roboto-Thin.ttf') format('truetype'); + font-weight: 100; +} + +/* Roboto Thin Italic */ +@font-face { + font-family: Roboto; + src: url('../assets/fonts/Roboto/Roboto-ThinItalic.ttf') format('truetype'); + font-weight: 100; + font-style: italic; +} + +/* Roboto Light */ +@font-face { + font-family: Roboto; + src: url('../assets/fonts/Roboto/Roboto-Light.ttf') format('truetype'); + font-weight: 300; +} + +/* Roboto Light Italic */ +@font-face { + font-family: Roboto; + src: url('../assets/fonts/Roboto/Roboto-LightItalic.ttf') format('truetype'); + font-weight: 300; + font-style: italic; +} + +/* Roboto Regular */ +@font-face { + font-family: Roboto; + src: url('../assets/fonts/Roboto/Roboto-Regular.ttf') format('truetype'); +} + +/* Roboto Regular Italic */ +@font-face { + font-family: Roboto; + src: url('../assets/fonts/Roboto/Roboto-Italic.ttf') format('truetype'); + font-style: italic; +} + +/* Roboto Medium */ +@font-face { + font-family: Roboto; + src: url('../assets/fonts/Roboto/Roboto-Medium.ttf') format('truetype'); + font-weight: 500; +} + +/* Roboto Medium Italic */ +@font-face { + font-family: Roboto; + src: url('../assets/fonts/Roboto/Roboto-MediumItalic.ttf') format('truetype'); + font-weight: 500; + font-style: italic; +} + +/* Roboto Bold */ +@font-face { + font-family: Roboto; + src: url('../assets/fonts/Roboto/Roboto-Bold.ttf') format('truetype'); + font-weight: bold; +} + +/* Roboto Bold Italic */ +@font-face { + font-family: Roboto; + src: url('../assets/fonts/Roboto/Roboto-BoldItalic.ttf') format('truetype'); + font-weight: bold; + font-style: italic; +} + +/* Roboto Black */ +@font-face { + font-family: Roboto; + src: url('../assets/fonts/Roboto/Roboto-Black.ttf') format('truetype'); + font-weight: 900; +} + +/* Roboto Black */ +@font-face { + font-family: Roboto; + src: url('../assets/fonts/Roboto/Roboto-BlackItalic.ttf') format('truetype'); + font-weight: 900; + font-style: italic; +} + +/* Roboto Mono Regular */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-Regular.ttf') format('truetype'); +} + +/* Roboto Mono Bold */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-Bold.ttf') format('truetype'); + font-weight: bold; +} + +/* Roboto Mono Bold Italic */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-BoldItalic.ttf') format('truetype'); + font-weight: bold; + font-style: italic; +} + +/* Roboto Mono Extra Light */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-ExtraLight.ttf') format('truetype'); + font-weight: 200; /* Extra Light */ +} + +/* Roboto Mono Extra Light Italic */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-ExtraLightItalic.ttf') format('truetype'); + font-weight: 200; + font-style: italic; +} + +/* Roboto Mono Light */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-Light.ttf') format('truetype'); + font-weight: 300; /* Light */ +} + +/* Roboto Mono Light Italic */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-LightItalic.ttf') format('truetype'); + font-weight: 300; + font-style: italic; +} + +/* Roboto Mono Medium */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-Medium.ttf') format('truetype'); + font-weight: 500; /* Medium */ +} + +/* Roboto Mono Medium Italic */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-MediumItalic.ttf') format('truetype'); + font-weight: 500; + font-style: italic; +} + +/* Roboto Mono Semi Bold */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-SemiBold.ttf') format('truetype'); + font-weight: 600; /* Semi Bold */ +} + +/* Roboto Mono Semi Bold Italic */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-SemiBoldItalic.ttf') format('truetype'); + font-weight: 600; + font-style: italic; +} + +/* Roboto Mono Thin */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-Thin.ttf') format('truetype'); + font-weight: 100; /* Thin */ +} + +/* Roboto Mono Thin Italic */ +@font-face { + font-family: 'Roboto Mono'; + src: url('../assets/fonts/RobotoMono/RobotoMono-ThinItalic.ttf') format('truetype'); + font-weight: 100; + font-style: italic; +} + diff --git a/src/frontend/src/styles/svg_process_tree_styles.scss b/src/frontend/src/styles/svg_process_tree_styles.scss new file mode 100644 index 0000000000000000000000000000000000000000..2fa29be13b6d067022ab3844e84e357085d7e7ae --- /dev/null +++ b/src/frontend/src/styles/svg_process_tree_styles.scss @@ -0,0 +1,88 @@ +/* + Classes for the process tree SVG elements are used to easily differentiate the elements + and to add style that changes dynamically. Thus easier subtype specific selections can be made + and the styling can be stripped before tree export + + Used but Empty classes are: + + .node + .node-operator + .node-visible-activity + .node-invisible-activity + .node-text + +*/ + + +.frozen-node-operator { + fill: #25306a !important; +} + +.frozen-node-visible-activity { + fill: #425bbf !important; +} + +.frozen-node-invisible-activity { + fill: #161e40 !important; +} + +.frozen-edge{ + stroke : #425bbf !important; +} + +.selected-node{ + stroke : #dc3545 !important; +} + +.selected-edge{ + stroke : #dc3545 !important; +} + + +.performance-tooltip { + max-width: none; + white-space: nowrap !important; + + table { + margin: 0; + + td:first-child { + text-align: left; + padding-right: 10px; + } + + td:last-child { + text-align: right; + } + } +} + +.performance-tooltip-header-style { + margin-bottom: 0; + background-color: #f0f0f0; + border-bottom: 1px solid rgb(0 0 0 / 20%); + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); + padding: 6px 10px 0; +} + +.performance-tooltip-header { + color: white; + border-bottom: unset; +} + +.performance-tooltip.bs-tooltip-top .tooltip-arrow::before { + border-top-color: #373b3e; +} + +.performance-tooltip.bs-tooltip-bottom .tooltip-arrow::before { + border-bottom-color: #373b3e; +} + +.performance-tooltip.bs-tooltip-start .tooltip-arrow::before { + border-left-color: #373b3e; +} + +.performance-tooltip.bs-tooltip-end .tooltip-arrow::before { + border-right-color: #373b3e; +} diff --git a/src/frontend/src/styles/svg_variant_styles.scss b/src/frontend/src/styles/svg_variant_styles.scss new file mode 100644 index 0000000000000000000000000000000000000000..273424c16163887f10ffc8820f2df1f76807471d --- /dev/null +++ b/src/frontend/src/styles/svg_variant_styles.scss @@ -0,0 +1,25 @@ +.selected-polygon { + stroke: whitesmoke !important; + stroke-width: 3px; + stroke-dasharray: 4; +} + +svg * { + outline: none +} + +text { + stroke: none; +} + +.variant-element-group { + stroke: none; +} + +.cursor-pointer { + cursor: pointer; +} + +.variant-polygon { + cursor: pointer; +} diff --git a/src/frontend/src/test.ts b/src/frontend/src/test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5c6ddfb06d472dbb3bfcdf3c4d9497dcc4acdbd0 --- /dev/null +++ b/src/frontend/src/test.ts @@ -0,0 +1,32 @@ +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'zone.js/testing'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} from '@angular/platform-browser-dynamic/testing'; + +declare const require: { + context( + path: string, + deep?: boolean, + filter?: RegExp + ): { + keys(): string[]; + <T>(id: string): T; + }; +}; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting(), + { + teardown: { destroyAfterEach: false }, + } +); +// Then we find all the tests. +const context = require.context('./', true, /\.spec\.ts$/); +// And load the modules. +context.keys().map(context); diff --git a/src/frontend/tsconfig.app.json b/src/frontend/tsconfig.app.json new file mode 100644 index 0000000000000000000000000000000000000000..5747769899d8a6bcde4c9cd04024f329692fd7fc --- /dev/null +++ b/src/frontend/tsconfig.app.json @@ -0,0 +1,16 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "resolveJsonModule": true, + "outDir": "./out-tsc/app", + "types": [] + }, + "files": [ + "src/main.ts", + "src/polyfills.ts" + ], + "include": [ + "src/**/*.d.ts" + ] +} diff --git a/src/frontend/tsconfig.json b/src/frontend/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..a003609ff57b1c8a025625415c8efd763c83bfe6 --- /dev/null +++ b/src/frontend/tsconfig.json @@ -0,0 +1,24 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "compileOnSave": false, + "compilerOptions": { + "resolveJsonModule": true, + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "moduleResolution": "node", + "importHelpers": true, + "target": "ES2022", + "module": "es2020", + "lib": [ + "es2018", + "dom", + "ES2019.Array" + ], + "allowSyntheticDefaultImports": true, + "useDefineForClassFields": false + } +} diff --git a/src/frontend/tsconfig.spec.json b/src/frontend/tsconfig.spec.json new file mode 100644 index 0000000000000000000000000000000000000000..092345b02e807773164dba19f2b4d1f4ab869f67 --- /dev/null +++ b/src/frontend/tsconfig.spec.json @@ -0,0 +1,18 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/spec", + "types": [ + "jasmine" + ] + }, + "files": [ + "src/test.ts", + "src/polyfills.ts" + ], + "include": [ + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/src/frontend/util.js b/src/frontend/util.js new file mode 100644 index 0000000000000000000000000000000000000000..49f5b8de090ab024c430bd04309b4d7d88581e8d --- /dev/null +++ b/src/frontend/util.js @@ -0,0 +1,90 @@ +const fsPromise = require("node:fs/promises"); + +function decodeBase64Image(dataString) { + var matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/), + response = {}; + + if (matches.length !== 3) { + return new Error("Invalid input string"); + } + + response.type = matches[1]; + response.data = Buffer.from(matches[2], "base64"); + + return response; +} + +function fixPath(filePath, fileExtension) { + let splitted = filePath.split("/"); + let fileName = splitted[splitted.length - 1]; + let splittedFileName = fileName.split("."); + let hasFileExtension = splittedFileName.length == 2; + let hasCorrectFileExtension = + hasFileExtension && splittedFileName[1] == fileExtension; + + if (!hasFileExtension) { + filePath = filePath + "." + fileExtension; + } else if (!hasCorrectFileExtension) { + filePath = filePath.split(".")[0] + "." + fileExtension; + } + + return filePath; +} + +async function showSaveDialog( + downloadFolder, + dialog, + fs, + win, + fileName, + fileExtension, + base64File, + buttonLabel, + title +) { + let downloadPath = downloadFolder + `/${fileName}.${fileExtension}`; + + // define save dialog options + var options = { + title: title, + buttonLabel: buttonLabel, + defaultPath: downloadPath, + filters: [{ name: fileExtension, extensions: [fileExtension] }], + }; + + var imageBuffer = decodeBase64Image(base64File); + + const { canceled, filePath } = await dialog.showSaveDialog(win, options); + // fix file path if the path has no extension or a wrong extension + if (!canceled) { + fs.writeFileSync( + fixPath(filePath, fileExtension), + imageBuffer.data, + "base64" + ); + } + + return canceled ? undefined : filePath; +} + +function saveToUserFolder(userFolderPath, fileName, fileExtension, data) { + return fsPromise.writeFile( + `${userFolderPath}/${fileName}.${fileExtension}`, + data + ); +} + +function readFromUserFolder(userFolderPath, fileName, fileExtension) { + return fsPromise.readFile( + `${userFolderPath}/${fileName}.${fileExtension}`, + "utf8" + ); +} + +module.exports = { + decodeBase64Image, + fixPath, + showSaveDialog, + saveToUserFolder, + readFromUserFolder, +};