diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index fb1c815..a19545c 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -34,10 +34,10 @@ jobs:
pandas
numpy
intervaltree
- mummer=3.23
+ mummer4
glpk=5.0
snakemake=7.32.4
- plasnet=0.6.0
+ plasnet=0.7.0
dingII
init-shell: bash
cache-environment: true
diff --git a/.gitignore b/.gitignore
index 2e04171..4799eef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,44 @@
+.DS_Store
.idea
.snakemake
__pycache__
logs
/.venv/
+build/
+gurobi.log
+meta.yaml
+pling.egg-info/
+tests/gurobi.log
+tests/integration_test/gurobi.log
+tests/reuter_no_weights/
+tests/test1/
+tests/test2/
+tests/unimog_tests/test_cases/git_issues/containment_1/out/
+tests/unimog_tests/test_cases/git_issues/palindrome/out/
+tests/unimog_tests/test_cases/indel_tests/test_1/out/
+tests/unimog_tests/test_cases/indel_tests/test_10/out/
+tests/unimog_tests/test_cases/indel_tests/test_2/out/
+tests/unimog_tests/test_cases/indel_tests/test_3/out/
+tests/unimog_tests/test_cases/indel_tests/test_4/out/
+tests/unimog_tests/test_cases/indel_tests/test_4/truth/align/containment/containment_communities/objects/communities.pkl
+tests/unimog_tests/test_cases/indel_tests/test_4/truth/align/containment/containment_communities/objects/plasmid_graph.pkl
+tests/unimog_tests/test_cases/indel_tests/test_4/truth/align/containment/containment_communities/visualisations/
+tests/unimog_tests/test_cases/indel_tests/test_5/out/
+tests/unimog_tests/test_cases/indel_tests/test_6/out/
+tests/unimog_tests/test_cases/indel_tests/test_7/out/
+tests/unimog_tests/test_cases/indel_tests/test_8/out/
+tests/unimog_tests/test_cases/indel_tests/test_9/out/
+tests/unimog_tests/test_cases/toy_tests/test_1/out/
+tests/unimog_tests/test_cases/toy_tests/test_1/truth/align/containment/containment_communities/objects/communities.pkl
+tests/unimog_tests/test_cases/toy_tests/test_1/truth/align/containment/containment_communities/objects/plasmid_graph.pkl
+tests/unimog_tests/test_cases/toy_tests/test_1/truth/align/containment/containment_communities/visualisations/
+tests/unimog_tests/test_cases/toy_tests/test_1/truth/align/dcj_thresh_4_graph/objects/communities.pkl
+tests/unimog_tests/test_cases/toy_tests/test_1/truth/align/dcj_thresh_4_graph/objects/subcommunities.pkl
+tests/unimog_tests/test_cases/toy_tests/test_1/truth/align/dcj_thresh_4_graph/visualisations/
+tests/unimog_tests/test_cases/toy_tests/test_2/out/
+tests/unimog_tests/test_cases/toy_tests/test_2/truth/align/containment/containment_communities/objects/communities.pkl
+tests/unimog_tests/test_cases/toy_tests/test_2/truth/align/containment/containment_communities/objects/plasmid_graph.pkl
+tests/unimog_tests/test_cases/toy_tests/test_2/truth/align/containment/containment_communities/visualisations/
+tests/unimog_tests/test_cases/toy_tests/test_2/truth/align/dcj_thresh_4_graph/objects/communities.pkl
+tests/unimog_tests/test_cases/toy_tests/test_2/truth/align/dcj_thresh_4_graph/objects/subcommunities.pkl
+tests/unimog_tests/test_cases/toy_tests/test_2/truth/align/dcj_thresh_4_graph/visualisations/
diff --git a/MANIFEST.in b/MANIFEST.in
index 62bcbea..5751f22 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,3 +4,4 @@ include pling/batching/Snakefile
include pling/dcj_snakemake/Snakefile
include pling/common_rules/common_rules.smk
include pling/jac_network_snakemake/Snakefile
+include pling/submatrix_snakemake/Snakefile
\ No newline at end of file
diff --git a/docs/advanced.rst b/docs/advanced.rst
index 2a31b86..865c808 100644
--- a/docs/advanced.rst
+++ b/docs/advanced.rst
@@ -1,58 +1,19 @@
Advanced Usage
==============
-Overview
+Summary
--------
-.. code-block:: console
-
- usage: pling [-h] [--version] [--unimog UNIMOG] [--containment_distance CONTAINMENT_DISTANCE] [--dcj DCJ] [--regions] [--topology TOPOLOGY] [--batch_size BATCH_SIZE] [--sourmash] [--sourmash_threshold SOURMASH_THRESHOLD] [--identity IDENTITY]
- [--min_indel_size MIN_INDEL_SIZE] [--bh_connectivity BH_CONNECTIVITY] [--bh_neighbours_edge_density BH_NEIGHBOURS_EDGE_DENSITY] [--small_subcommunity_size_threshold SMALL_SUBCOMMUNITY_SIZE_THRESHOLD] [--output_type {html,json,both}]
- [--plasmid_metadata PLASMID_METADATA] [--ilp_solver {GLPK,gurobi}] [--timelimit TIMELIMIT] [--resources RESOURCES] [--cores CORES] [--profile PROFILE] [--forceall]
- genomes_list output_dir {align,skip}
-
- positional arguments:
- genomes_list Path to list of fasta file paths.
- output_dir Path to output directory.
- {align,skip} Integerisation method: "align" for alignment, "skip" to skip integerisation altogether. Make sure to input a unimog file if skipping integerisation.
-
- options:
- -h, --help show this help message and exit
- --version show program's version number and exit
- --unimog UNIMOG Path to unimog file. Required input if skipping integerisation. (default: None)
- --containment_distance CONTAINMENT_DISTANCE
- Threshold for initial containment network. (default: 0.5)
- --dcj DCJ Threshold for final DCJ-Indel network. (default: 4)
- --regions Cluster regions rather than complete genomes. Assumes regions are taken from circular plasmids. (default: False)
- --topology TOPOLOGY File stating whether plasmids are circular or linear. Must be a tsv with two columns, one with plasmid IDs under "plasmid" and one with "linear" or "circular" as entries under "topology". Without this file, pling will asume all plasmids are circular. (default: None)
- --batch_size BATCH_SIZE
- How many pairs of genomes to run together in one go (for integerisation from alignment and DCJ calculation steps). (default: 200)
- --sourmash Run sourmash as first filter on which pairs to calculate DCJ on. Recommended for large and very diverse datasets. (default: False)
- --sourmash_threshold SOURMASH_THRESHOLD
- Threshold for filtering with sourmash. (default: 0.85)
- --identity IDENTITY Threshold for percentage of shared sequence between blocks (for integerisation from alignment and for containment calculation). (default: 80)
- --min_indel_size MIN_INDEL_SIZE
- Minimum size for an indel to be treated as a block (for integerisation from alignment). (default: 200)
- --bh_connectivity BH_CONNECTIVITY
- Minimum number of connections a plasmid need to be considered a hub plasmid. (default: 10)
- --bh_neighbours_edge_density BH_NEIGHBOURS_EDGE_DENSITY
- Maximum number of edge density between hub plasmid neighbours to label the plasmid as hub. (default: 0.2)
- --small_subcommunity_size_threshold SMALL_SUBCOMMUNITY_SIZE_THRESHOLD
- Communities with size up to this parameter will be joined to neighbouring larger subcommunities. (default: 4)
- --output_type {html,json,both}
- Whether to output networks as html visualisations, cytoscape formatted json, or both. (default: html)
- --plasmid_metadata PLASMID_METADATA
- Metadata to add beside plasmid ID on the visualisation graph. Must be a tsv with a single column, with data in the same order as in genomes_list. (default: None)
- --ilp_solver {GLPK,gurobi}
- ILP solver to use. Default is GLPK, which is slower but is bundled with pling and is free. If using gurobi, make sure you have a valid license and gurobi_cl is in your PATH. (default: GLPK)
- --timelimit TIMELIMIT
- Time limit in seconds for ILP solver. (default: None)
- --resources RESOURCES
- tsv stating number of threads and memory to use for each rule. (default: None)
- --cores CORES Total number of cores/threads. Put the maximum number of threads you request in the resources tsv here. (This argument is passed on to snakemake's --cores argument.) (default: 1)
- --profile PROFILE To run on a cluster with corresponding snakemake profile. (default: None)
- --forceall Force snakemake to rerun everything. (default: False)
+pling consists of three subcommands: ``cluster``, ``add``, and ``submatrix``.
+
+**cluster:** This command includes all the standard clustering functionalities in pling. If you want to de novo cluster some genomes, this is what you want. It is further subdivided into ``align`` and ``skip`` -- ``align`` will run pling with integerisation, while ``skip`` allows you to provide your own custom integersiation and skip pling's built-in integerisation.
+
+**add:** This command is for adding novel plasmids to an existing pling clustering, or merging multiple prior clustering together. For more details, see below.
+**submatrix:** Provides some potentially useful outputs for downstream analysis, based on pling clustering results and DCJ-Indel distances.
+
+Options for pling cluster
+-------------------------
**Network thresholds:** ``--containment-distance`` and ``--dcj`` control the thresholds at which edges are added to the continament and DCJ-Indel networks. If looking for recent transmissions, we recommend trying threshold 0.3 for the containment distance. If you want to try different DCJ-Indel thresholds with the same containment threshold, you can run pling at different DCJ-Indel thresholds with the same output directory -- this will mean that only the DCJ-Indel network will be calculated anew, which will significantly reduce runtime. Changing the containment threshold will prompt pling to rerun the whole workflow though, and so you should change the output directory if you don't want to lose previous results.
@@ -74,16 +35,18 @@ You can also run pling on regions of genomes with the ``--regions`` flag.
**Clustering parameters:** ``--bh_connectivity`` and ``--bh_neighbour_density`` both determine how a hub plasmid is defined. ``--bh_connectivity`` determines to how many plasmids a hub should at least be connected to, while ``--bh_neighbour_density`` determines how interconnected a hub's neighbours should be.
-**Visualisation styles:** With ``--output_type`` you can opt to output cytoscpae compatible json files together with or instead of the default html visualisations. The json files can be loaded directly into cytoscape, and used in python together with networkx. There is also a cytoscape style file available, which provides a style similar to the default html visualisations. It can be downloaded from here: https://raw.githubusercontent.com/leoisl/plasnet/main/plasnet/ext/templates/plasnet_style.xml. You can also add additional metadata to node names with ``--plasmid_metadata``, e.g. Inc types.
+**Visualisation styles:** As of v3, by default only visualisations of results from ``dcj_thresh_4_graph`` are outputted, but you through ``--visualisation`` you can opt to output no visualisations, or all possible visualisation (this option will perform equivalently to pling v2). With ``--output_type`` you can opt to output cytoscpae compatible json files together with or instead of the default html visualisations. The json files can be loaded directly into cytoscape, and used in python together with networkx. There is also a cytoscape style file available, which provides a style similar to the default html visualisations. It can be downloaded from here: https://raw.githubusercontent.com/leoisl/plasnet/main/plasnet/ext/templates/plasnet_style.xml. You can also add additional metadata to node names with ``--plasmid_metadata``, e.g. Inc types.
**ILP solver:** Calculating the DCJ-Indel distances involves solving and integer linear problem (ILP), and pling allows a choice between two ILP solvers for this: GLPK or gurobi. GLPK is free and bundled with pling, but a bit slower. Gurobi is a commercial software, with a free academic license, and you must have a valid license and installed gurobi beforehand to run pling with it. Both solvers output the same final result. Generally calculating DCJ-Indel is an NP-hard problem, which means in its worst case calculation will take a very long time. The ``--timelimit`` variable sets a time limit for how long the ILP solver takes with a pair, before giving up and outputting the most optimal result it has at that point. However our experience is that when running with integers from alignment, the DCJ-Indel calculation is very quick.
**Snakemake arguments:** Arguments ``--cores``, ``--profile`` and ``--forceall`` are passed as are directly to snakemake. Please refer to snakemake documentation (https://snakemake.readthedocs.io/en/v7.0.0/) for further information. Through ``--resources`` you can pass a path to a ``resources.tsv`` file, which will define number of threads and memory allocated for each rule in pling's snakemake workflows. The format should be the same as the file found under ``pling/resources.tsv``. If you use more than one thread in any rule, remember to set ``--cores`` to the maximum number of threads you'd like to use.
+**Varying thresholds:** With ``--reuse_previous`` you can give a path to a previous clustering, and get a new clustering with different thresholds without recomputing all distances. This *only* works if the new containment threshold you choose is lower (i.e. stricter) than the previous threshold you ran pling with; therefore, if you are going to experiment with thresholds, make sure to start with the highest containment distance you will be considering (e.g. 0.5, the default).
+
Regions (e.g. integrons)
------------------------
-To run pling on a region of a genome, rather than full genomes, use the ``--regions`` flag. Make sure that your fasta files only contain the sequence of your region of interest. This option is intended for comparing specific regions in genomes that undergo rearrangement, e.g. comparing integrons across different genomes. The DCJ-Indel model is not inherently designed for regions of genomes, so pling uses the following assumptions to integerise regions for DCJ-Indel calculation:
+To cluster a region of a genome, rather than full genomes, use the ``--regions`` flag. Make sure that your fasta files only contain the sequence of your region of interest. This option is intended for comparing specific regions in genomes that undergo rearrangement, e.g. comparing integrons across different genomes. The DCJ-Indel model is not inherently designed for regions of genomes, so pling uses the following assumptions to integerise regions for DCJ-Indel calculation:
1. the sequence outside of the region of interest is identical across all genomes
2. the region of interest is embedded in a circular genome
@@ -131,8 +94,9 @@ You cannot use both the ``--topology`` and ``--regions`` options at the same tim
Skipping integerisation and unimog file format
----------------------------------------------
-There is the option to skip pling's integerisation and provide your own, by running pling with the ``skip`` option and providing a file path to a unimog formatted file with ``--unimog``. The unimog file will need to contain an integer sequence for each genome, where an integer always denotes the same block of sequence.
+There is the option to skip pling's integerisation and provide your own, by running pling with the ``cluster skip`` command and providing a file path to a unimog formatted file. The unimog file will need to contain an integer sequence for each genome, where an integer always denotes the same block of sequence.
Pling performs essentially the same workflow with this option: construction of a containment network, induction of a DCJ-Indel subnetwork from DCJ-Indel distances, and clustering. The only change is that alignment is only used to calculate the containment distances and network, *not* integer sequences, and DCJ-Indel distances are calculated from the user given integerisation, i.e. the unimog file.
+As of v3, when providing your own integerisation you can now construct the containment network just using containment distances computed from sourmash results, skipping alignment entirely, using the flag ``--sourmash_only``. This threshold given by ``containment_distance`` is used for the containment network construction.
The entries in a unimog file are formatted similar to fasta files - the first line begins with ">" and the entry name, and the second lines contains the integer sequence. In the sequence, integers are seperated by a space, and negative integers represent reverse complements. The end of a sequence is indicated by either ")" or "|", where ")" means the genome is circular, and "|" means the genome is linear. Here's an example of what it can look like:
@@ -179,6 +143,13 @@ for regions that are at the end.
For more information on the unimog file format, please refer to https://bibiserv.cebitec.uni-bielefeld.de/dcj?id=dcj_manual.
+Adding new plasmids to existing clustering, or merging multiple clusterings
+---------------------------------------------------------------------------
+
+With ``pling add`` you can add new plasmids to a previous pling clustering, or merge previous pling clusterings.
+When adding novel plasmids, there are two options, selected via ``reclustering_method`` : asynchronous label propagation (``asyn``, default) and nearest neighbour typing (``nearest_neighbour``).
+For nearest neighbour typing, the novel plasmids are typed according to which subcommunity they are closest to in terms of DCJ-Indel distance. If a new plasmid is close to none, it is labelled a singleton, even if there are other novel plasmids neighbouring it. This method does not provide a new typing scheme, it just types according to the previous pling typing.
+The ``asyn`` option can be used for both adding novel plasmids and merging previous clusterings, and is the default option. It performs the same asynchronous label propagation algorithm for clustering as ``pling cluster``, and therefore generates a completely new typing scheme (unlike ``nearest_neighbour``). It reuses previously computed distances to speed up the clustering workflow, and outputs a mapping between the old typing and new typing, as well as the rand index, mutual information score and split-join distance between each of the previous typing and the new typing.
Improving runtime
-----------------
diff --git a/docs/basic.rst b/docs/basic.rst
index 3395572..b282c02 100644
--- a/docs/basic.rst
+++ b/docs/basic.rst
@@ -11,6 +11,6 @@ Then usage is
.. code-block:: console
- pling input.txt output_dir align
+ pling cluster align input.txt output_dir
diff --git a/docs/citation.rst b/docs/citation.rst
index 5c95bb4..ce8e5f0 100644
--- a/docs/citation.rst
+++ b/docs/citation.rst
@@ -1,4 +1,4 @@
Citation
========
-Preprint: https://doi.org/10.1101/2024.06.12.598623
+Paper: https://doi.org/10.1099/mgen.0.001300
diff --git a/docs/conf.py b/docs/conf.py
index db9e6e5..1fc4e49 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -18,11 +18,11 @@
# -- Project information -----------------------------------------------------
project = "pling"
-copyright = "2024, Daria Frolova"
+copyright = "2026, Daria Frolova"
author = "Daria Frolova"
-release = '2.0'
-version = '2.0.0'
+release = '3.0'
+version = '3.0.0'
# -- General configuration ---------------------------------------------------
# -- General configuration
diff --git a/docs/output.rst b/docs/output.rst
index eead606..6583cee 100644
--- a/docs/output.rst
+++ b/docs/output.rst
@@ -7,5 +7,4 @@ Pling runs via the python script `run_pling.py`, which creates a config file and
- **Hub plasmids:** Pling identifies "hub plasmids", which are plasmids that are densely connected on the containment network, but their neighbours are not interconnected. In practice, these are usually relatively small plasmids that consist mostly of a large mobile genetic element, which has spread across many diverse, unrelated plasmids. They are listed in ``dcj_thresh_4_graph/objects/hub_plasmids.csv``
- **Integer sequences:** Pling outputs the integer sequences used to calculate DCJ-Indel distances. These are outputted in UniMoG-format (see https://bibiserv.cebitec.uni-bielefeld.de/dcj?id=dcj_manual for description), and also a mapping of integer to sequence coordinates, or a mapping of integer to gene name, is provided. The integer sequences are calculated in batches, so there is a unimog and a map file per batch, all found in the folder ``unimogs``.
- **DCJ-Indel subcommunities:** Pling identifies plasmid subcommunities by constructing a DCJ-Indel network, and then clustering on this network. The DCJ-Indel network is a subnetwork of the containment network initially built. Edges are kept if a pair of plasmids fulfil the DCJ-Indel distance threshold. Hub plasmids are isolated in the DCJ-Indel network, with no edges connecting to them (even if they fulfil the DCJ-Indel threshold). On this network pling clusters using asynchronous label propagation community detection algorithm. Plasmid clusters are labelled by containment community and DCJ-Indel subcommunity, e.g. ``community_2_subcommunity_13``, and plasmid to subcommunity assignments are found in ``dcj_thresh_4_graph/objects/typing.tsv``. The DCJ-Indel distances are in file ``all_plasmid_distances.tsv`` (note that the DCJ-Indel distance is only calculated between plasmids which fulfil the containment threshold, so not all pairs of plasmids will be in the file).
-- **Visualisations:** Alongside the distances and clustering, pling outputs network visualisations to aid in further analysis. These can be useful to look if you want to spot interesting relationships between plasmids, e.g. plasmid fusions. They include visualisations of the full containment network and each containment network individually, found under ``containment/containment_communities/visualisations``. All nodes are coloured black, but the edges are labelled by containment distance. Additionally, under ``dcj_thresh_4_graph/communities`` are visualisations of each plasmid community, where nodes are coloured by subcommunity assignment and edges are labelled with both containment distance and DCJ-Indel distance. Finally, under ``dcj_thresh_4_graph/subcommunities`` are visualisations of each plasmid subcommunity, where nodes all have the same colour, and edges are labelled by containment distance and DCJ-Indel distance. These subcommunity visualisations don't include edges that don't fulfil the DCJ-Indel threshold, but the others do. You can also optionally output json files of the networks, see Advanced Usage and General Advice for more information.
-
+- **Visualisations:** Alongside the distances and clustering, pling outputs network visualisations to aid in further analysis. These can be useful to look if you want to spot interesting relationships between plasmids, e.g. plasmid fusions. Under ``dcj_thresh_4_graph/communities`` are visualisations of each plasmid community, where nodes are coloured by subcommunity assignment and edges are labelled with both containment distance and DCJ-Indel distance. Then, under ``dcj_thresh_4_graph/subcommunities`` are visualisations of each plasmid subcommunity, where nodes all have the same colour, and edges are labelled by containment distance and DCJ-Indel distance. These subcommunity visualisations don't include edges that don't fulfil the DCJ-Indel threshold, but the others do. Optionally, you can also output visualisations of the full containment network and each containment network individually, found under ``containment/containment_communities/visualisations``. All nodes are coloured black, but the edges are labelled by containment distance. Also, you can optionally output json files of the networks, see Advanced Usage and General Advice for more information.
\ No newline at end of file
diff --git a/docs/tips.rst b/docs/tips.rst
index f44dff5..cf39709 100644
--- a/docs/tips.rst
+++ b/docs/tips.rst
@@ -63,3 +63,5 @@ Bacterial and other non-plasmid genomes
---------------------------------------
Pling was created with plasmids in mind, but in principle it can be used with other types of genomes (as long as they are complete and single chromosome). The only issue you may run into is with computational resources. The run time bottleneck for pling is generally the integerisation step, which requires doing pairwise alignment. This is reasonably cheap for plasmids as they have small genomes, but may be more of an issue with larger genomes like bacteria. If you think doing pairwise alignment is viable for your dataset, then pling will likely run just fine.
+
+A viable alternative for bacterial genomes might be to run ``pling cluster skip`` with your own integerisation. You can generate your own by running e.g. panaroo, or (my personal favourite) pangraph. Note that you will need to convert the output to UniMoG-format (see Advanced Usage).
diff --git a/docs/tutorial.rst b/docs/tutorial.rst
index 1de8a9d..d431c68 100644
--- a/docs/tutorial.rst
+++ b/docs/tutorial.rst
@@ -21,10 +21,10 @@ To reduce runtime, in this example you are going to run pling with the sourmash
Decide on a name for your output directory; in this tutorial we will use ``pling_out``.
Run pling with the following command::
- pling input.txt pling_out align --cores 8 --sourmash
+ pling cluster align input.txt pling_out --cores 8 --sourmash --visualisation all
The first two arguments are the file with the list of fasta filepaths, and the output directory, both of which are required inputs. The third argument is the type of integerisation; unless you want to skip integerisation entirely, this argument will always be ``align`` (for more information on skipping integerisation, see Advanced Usage).
-The remaining two arguments are optional -- ``--cores`` sets the amount of threads/cores to be used, and ``--sourmash`` is a flag that indicates pling should be run with sourmash prefiltering.
+The remaining three arguments are optional -- ``--cores`` sets the amount of threads/cores to be used, ``--sourmash`` is a flag that indicates pling should be run with sourmash prefiltering, and ``--visualisation`` toggles which network visualisations are outputted.
Pling will first calculate a containment network, the connected components of which define the *community* a plasmid is assigned to, after which the pling network is induced on the containment network from the DCJ-Indel distances. The *subcommunity* of a plasmid is its final type, and is found by clustering on the pling network.
@@ -52,6 +52,6 @@ It's similar to the community visualisations, except here plasmid pairs are join
Now try running::
- pling input.txt pling_out align --dcj 7
+ pling cluster align input.txt pling_out --dcj 7
this will recalculate the subcommunities with a DCJ-Indel threshold of 7. This should run quickly (if you *don't* change the output directory!) -- this is because pling reuses the already calculated DCJ-Indel distances and communities, and only recalculates the subcommunities. You should find a new folder in your output called ``dcj_thresh_7_graph``, which will contain the visualisations and typing for DCJ-Indel threshold of 7.
diff --git a/env.yaml b/env.yaml
index 580c7ed..09b8282 100644
--- a/env.yaml
+++ b/env.yaml
@@ -9,7 +9,7 @@ dependencies:
- pandas =1.5.3
- numpy =1.26.0
- intervaltree =3.0.2
- - mummer =3.23
+ - mummer4
- glpk =5.0
- - plasnet==0.6.0
+ - plasnet==0.7.0
- dingII
diff --git a/pling/.gitattributes b/pling/.gitattributes
new file mode 100644
index 0000000..bcb2859
--- /dev/null
+++ b/pling/.gitattributes
@@ -0,0 +1 @@
+tests/** linguist-vendored
\ No newline at end of file
diff --git a/pling/align_snakemake/integerise_plasmids.py b/pling/align_snakemake/integerise_plasmids.py
index ce09f23..a5aa37c 100644
--- a/pling/align_snakemake/integerise_plasmids.py
+++ b/pling/align_snakemake/integerise_plasmids.py
@@ -5,6 +5,7 @@
import pandas as pd
from matches import *
import warnings
+import sys
def make_interval_tree_w_dups(block_coords, length_threshold):
ref_to_block = IntervalTree()
@@ -28,21 +29,17 @@ def make_interval_tree_w_dups(block_coords, length_threshold):
return ref_to_block, query_to_block, max_id
def populate_interval_tree_with_unmatched_blocks(interval_tree, total_length, block_index, length_threshold):
- pos = 1
- while pos <= total_length:
- no_matches = len(interval_tree[pos])==0
- if no_matches:
- start_pos = pos
- while len(interval_tree[pos])==0 and pos<=total_length:
- pos+=1
- end_pos = pos
-
- too_short_unmatched_block = end_pos-start_pos <= length_threshold
- if not too_short_unmatched_block:
- interval_tree[start_pos:end_pos]=block_index
- block_index+=1
- else:
- pos+=1
+ sorted_intervals = sorted(interval_tree)
+ prev_block_end = 1
+ for start, end, block in sorted_intervals:
+ if prev_block_end < start and start-prev_block_end > length_threshold:
+ interval_tree[prev_block_end:start] = block_index
+ block_index += 1
+ prev_block_end = end
+
+ if prev_block_end < total_length and total_length+1-prev_block_end > length_threshold:
+ interval_tree[prev_block_end:total_length+1] = block_index
+
return block_index
def longest_block(interval_tree):
@@ -57,7 +54,7 @@ def check_rev_comp(ref_tree, query_tree, fake):
elif ref_block == -query_block:
return -fake
else:
- warning.warn("Longest block on reference does not equal longest block on query. Cannot decide orientation, so assume both regions are oriented the same way.")
+ warnings.warn("Longest block on reference does not equal longest block on query. Cannot decide orientation, so assume both regions are oriented the same way.")
return fake
def get_unimog(interval_tree, fake=None, topology="circular"):
@@ -134,7 +131,13 @@ def sort_and_update_indels(indels):
return updated_indels
def integerise_plasmids(plasmid_1: Path, plasmid_2: Path, prefix: str, plasmid_1_name, plasmid_2_name, containment_threshold, identity_threshold=80, topology_1="circular", topology_2="circular", length_threshold=200):
- subprocess.check_call(f"nucmer --diagdiff 20 --breaklen 500 --maxmatch -p {prefix} {plasmid_1} {plasmid_2} && delta-filter -qr {prefix}.delta > {prefix}.1delta", shell=True)
+ try:
+ subprocess.run(f"nucmer --diagdiff 20 --breaklen 500 --maxmatch -p {prefix} {plasmid_1} {plasmid_2} && delta-filter -qr {prefix}.delta > {prefix}.1delta", shell=True, check=True, capture_output=True)
+ except subprocess.CalledProcessError as e:
+ print(f"ERROR IN RULE:\n NUCMER FAILING WITH PAIR {plasmid_1_name} AND {plasmid_2_name}", file=sys.stderr)
+ print(e.stderr.decode(), file=sys.stderr)
+ print("END ERROR MSG", file=sys.stderr)
+ sys.exit(e.returncode)
show_coords_output = subprocess.check_output(f"show-coords -TrcldH -I {identity_threshold} {prefix}.1delta", shell=True).strip().split(b'\n') # TODO: what about this threshold?
show_snps_output = subprocess.check_output(f"show-snps -TrH {prefix}.1delta", shell=True).strip().split(b'\n')
@@ -222,7 +225,13 @@ def integerise_plasmids(plasmid_1: Path, plasmid_2: Path, prefix: str, plasmid_1
blocks_query = pd.DataFrame({"Plasmid":[], "Block_ID":[], "Start":[], "End":[]})
else:
overlap_threshold = 0
- matches.resolve_overlaps(overlap_threshold)
+ try:
+ matches.resolve_overlaps(overlap_threshold)
+ except Exception as e:
+ print(f"ERROR IN RULE:\n OVERLAP FIXING FAILED WITH PAIR {plasmid_1_name} AND {plasmid_2_name}", file=sys.stderr)
+ print(e.stderr.decode(), file=sys.stderr)
+ print("END ERROR MSG", file=sys.stderr)
+ sys.exit(e.returncode)
ref_to_block, query_to_block, max_id = make_interval_tree_w_dups(matches.list, length_threshold)
max_id = populate_interval_tree_with_unmatched_blocks(ref_to_block, len_ref, max_id+1, length_threshold)
max_id = populate_interval_tree_with_unmatched_blocks(query_to_block, len_query, len(ref_to_block)+1, length_threshold)
@@ -241,15 +250,3 @@ def integerise_plasmids(plasmid_1: Path, plasmid_2: Path, prefix: str, plasmid_1
return plasmid_1_unimogs, plasmid_2_unimogs, containment_distance, blocks_ref, blocks_query
-testing = False
-
-if testing == True:
- #plasmid1 = "NZ_LT985234.1"
- #plasmid2 = "NZ_CP062902.1"
- #plasmid1 = "NZ_LR999867.1"
- #plasmid2 = "NZ_CP032890.1"
- plasmid1 = "cpe041_12"
- plasmid2 = "cpe024_2"
- #path = "/home/daria/Documents/projects/INC-plasmids/samples/fastas/incy"
- path = "/home/daria/Documents/projects/addenbrookes/same_assembler"
- print(integerise_plasmids(f"{path}/{plasmid1}.fna", f"{path}/{plasmid2}.fna", f"{plasmid1}~{plasmid2}", plasmid1, plasmid2))
diff --git a/pling/align_snakemake/matches.py b/pling/align_snakemake/matches.py
index 56caa26..25bea21 100644
--- a/pling/align_snakemake/matches.py
+++ b/pling/align_snakemake/matches.py
@@ -393,7 +393,7 @@ def resolve_overlaps(self, overlap_threshold):
except MatchPointsError:
warnings.warn("An invalid match was created while fixing overlaps. Overlap fixing is broken off, and the last version prior to the error is used for integerisation.")
return
- except MatchOrderError:
+ except MatchesOrderError:
warnings.warn("The ordering of matches was broken. Overlap fixing is broken off, and the last version prior to the error is used for integerisation.")
return
if containment:
@@ -436,7 +436,7 @@ def resolve_overlaps(self, overlap_threshold):
except MatchPointsError:
warnings.warn("An invalid match was created while fixing overlaps. Overlap fixing is broken off, and the last version prior to the error is used for integerisation.")
return
- except MatchOrderError:
+ except MatchesOrderError:
warnings.warn("The ordering of matches was broken. Overlap fixing is broken off, and the last version prior to the error is used for integerisation.")
return
if containment:
@@ -452,26 +452,3 @@ def resolve_overlaps(self, overlap_threshold):
else:
old_version = self
-testing = False
-if testing == True:
- #plasmid1 = "NZ_LT985234.1"
- #plasmid2 = "NZ_CP062902.1"
- #plasmid2 = "NZ_LR999867.1"
- #plasmid1 = "NZ_CP032890.1"
- #path = "/home/daria/Documents/projects/INC-plasmids/samples/fastas/incy"
- #plasmid2 = "cpe105_contig_5_np1212"
- #plasmid1 = "cpe061_contig_3_np1212"
- plasmid1 = "2_dup_3_dup"
- plasmid2 = "3_dup"
- path = "/home/daria/Documents/projects/pling/tests/test1/fastas"
- #path = "/home/daria/Documents/projects/mobmessing/plasmids_leah"
- print(new_integerise_plasmids(f"{path}/{plasmid1}.fna", f"{path}/{plasmid2}.fna", f"{plasmid1}~{plasmid2}", plasmid1, plasmid2, length_threshold=200))
- '''matches = Matches([Match(100578,102034,64267,65708,1),Match(101858,101881,57736,57759,1),Match(101881,102188,57759,58867,1)])
- matches.resolve_overlaps(0)
- length_threshold=15
- ref_to_block, query_to_block, max_id = make_interval_tree_w_dups(matches.list, length_threshold)
- populate_interval_tree_with_unmatched_blocks(ref_to_block, 102034, max_id+1, length_threshold)
- populate_interval_tree_with_unmatched_blocks(query_to_block, 65708, len(ref_to_block)+1, length_threshold)
- plasmid_1_unimogs = get_unimog(ref_to_block)
- plasmid_2_unimogs = get_unimog(query_to_block)
- print(plasmid_1_unimogs, plasmid_2_unimogs)'''
diff --git a/pling/batching/Snakefile b/pling/batching/Snakefile
index e105b57..1876b84 100644
--- a/pling/batching/Snakefile
+++ b/pling/batching/Snakefile
@@ -1,10 +1,13 @@
from pling.utils import get_pling_root_dir
OUTPUTPATH = config["output_dir"]
+dcj_threshold = config["dcj_dist_threshold"]
def smash():
- if config.get("sourmash", False):
- return "--sourmash"
+ if config.get("sourmash_only", False):
+ return f"--sourmash_only --sourmash --smash_threshold " + str(config["seq_containment_distance"])
+ elif config.get("sourmash", False) and not config.get("sourmash_only", False):
+ return f"--sourmash --smash_threshold " + config.get("sourmash_threshold", "1")
else:
return ""
@@ -20,6 +23,20 @@ def get_batching_resources(type):
elif type == "mem":
return mem
+def get_containmentpath():
+ if config.get("sourmash_only", False):
+ return f"{OUTPUTPATH}/containment/all_pairs_containment_distance.tsv"
+ else:
+ f"{OUTPUTPATH}/containment/not_pairs_containment_distance.tsv"
+
+def get_prev_pling():
+ if config.get("previous_pling",False):
+ blub = config["previous_pling"].strip().split(",")
+ blah = " ".join([f"{bl}/dcj_thresh_{dcj_threshold}_graph/objects" for bl in blub])
+ return f"--prev_typing {blah}"
+ else:
+ return ""
+
rule all:
input:
f"{OUTPUTPATH}/batches"
@@ -32,9 +49,9 @@ rule get_batches:
genomes_list = config["genomes_list"],
batch_size = config["batch_size"],
sourmash = smash(),
- smash_threshold = config.get("sourmash_threshold", 1),
- containmentpath = f"{OUTPUTPATH}/containment/not_pairs_containment_distance.tsv",
- pling_root_dir = get_pling_root_dir()
+ containmentpath = get_containmentpath(),
+ pling_root_dir = get_pling_root_dir(),
+ prev_pling = get_prev_pling()
threads: get_batching_resources("threads")
resources:
mem_mb=lambda wildcards, attempt: get_batching_resources("mem")*attempt
@@ -45,6 +62,6 @@ rule get_batches:
--batch_size {params.batch_size} \
--outputpath {params.outputpath} \
{params.sourmash} \
- --smash_threshold {params.smash_threshold} \
- --containmentpath {params.containmentpath}
+ --containmentpath {params.containmentpath} \
+ {params.prev_pling}
"""
diff --git a/pling/batching/get_batches.py b/pling/batching/get_batches.py
index 3a63cbc..56d662f 100644
--- a/pling/batching/get_batches.py
+++ b/pling/batching/get_batches.py
@@ -2,10 +2,12 @@
import os
import math
import numpy as np
+import pandas as pd
import subprocess
from pathlib import Path
from pling.utils import get_fasta_file_info
import itertools
+import sys
def get_labels(filepath):
fastafiles, fastaext, fastapath = get_fasta_file_info(filepath)
@@ -17,30 +19,40 @@ def append_pair(smash, smash_threshold, smash_matrix, i, j):
return True
else:
return (1-smash_matrix[i][j]<=smash_threshold)
+
+def previous_pair(genome_1, genome_2, prev_genomes):
+ for genomes in prev_genomes:
+ if genome_1 in genomes and genome_2 in genomes:
+ return True
+ return False
-def get_pairs(genomes, batch_size, output_dir, containmentpath, smash, smash_matrix = None, smash_threshold = None):
+def get_pairs(genomes, batch_size, output_dir, containmentpath, smash, smash_only, smash_matrix = None, smash_threshold = None, prev_genomes = []):
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
n = len(genomes)
iter = 0
batch = -1
- if smash:
+ if smash or smash_only:
dir = Path(os.path.dirname(containmentpath))
dir.mkdir(parents=True, exist_ok=True)
contain_file = open(containmentpath, "w")
+ contain_file.write("plasmid_1\tplasmid_2\tdistance\n")
for i,j in itertools.combinations(range(n), 2):
- append = append_pair(smash, smash_threshold, smash_matrix, i, j)
- if append:
- if iter%batch_size==0:
- if iter!=0:
- batch_file.close()
- batch = batch+1
- batch_file = open(f"{output_dir}/batch_{batch}.txt","w")
- batch_file.write(str([genomes[i], genomes[j]])+"\n")
- iter = iter+1
- elif smash:
- contain_file.write(f"{genomes[i]}\t{genomes[j]}\t{1-smash_matrix[i][j]}\n")
- if smash:
+ if not previous_pair(genomes[i], genomes[j], prev_genomes):
+ append = append_pair(smash, smash_threshold, smash_matrix, i, j)
+ if append:
+ if iter%batch_size==0:
+ if iter!=0:
+ batch_file.close()
+ batch = batch+1
+ batch_file = open(f"{output_dir}/batch_{batch}.txt","w")
+ batch_file.write(str([genomes[i], genomes[j]])+"\n")
+ iter = iter+1
+ if smash_only:
+ contain_file.write(f"{genomes[i]}\t{genomes[j]}\t{1-smash_matrix[i][j]}\n")
+ elif smash:
+ contain_file.write(f"{genomes[i]}\t{genomes[j]}\t{1-smash_matrix[i][j]}\n")
+ if smash or smash_only:
contain_file.close()
batch_file.close()
return iter
@@ -58,14 +70,16 @@ def run_smash(genome_list, sig_path, matrixpath):
try:
subprocess.run(f"sourmash sketch dna --from-file {genome_list} -o {sig_path}", shell=True, check=True, capture_output=True)
except subprocess.CalledProcessError as e:
- print(e.stderr.decode())
- print(e)
+ print(f"ERROR IN RULE: SOURMASH FAILING WITH {genome_list}", file=sys.stderr)
+ print(e.stderr.decode(), file=sys.stderr)
+ print("END ERROR MSG", file=sys.stderr)
raise e
try:
subprocess.run(f"sourmash compare {sig_path} --max-containment -o {matrixpath}", shell=True, check=True, capture_output=True)
except subprocess.CalledProcessError as e:
- print(e.stderr.decode())
- print(e)
+ print(f"ERROR IN RULE: SOURMASH FAILING WITH {genome_list}", file=sys.stderr)
+ print(e.stderr.decode(), file=sys.stderr)
+ print("END ERROR MSG", file=sys.stderr)
raise e
def main():
@@ -75,13 +89,14 @@ def main():
parser.add_argument("--batch_size", type=int)
parser.add_argument("--outputpath")
parser.add_argument("--sourmash", action="store_true")
+ parser.add_argument("--sourmash_only", action="store_true")
parser.add_argument("--smash_threshold",type=float)
parser.add_argument("--containmentpath")
- parser.add_argument("--dcj_path")
+ parser.add_argument("--prev_typing", nargs="*")
args = parser.parse_args()
- if args.sourmash:
+ if args.sourmash or args.sourmash_only:
sig_dir = Path(f"{args.outputpath}/sourmash")
sig_dir.mkdir(parents=True, exist_ok=True)
sig_path = sig_dir/"all_plasmids.sig"
@@ -93,7 +108,14 @@ def main():
genomes = get_labels(args.genomes_list)
smash_matrix = None
- len_pairs = get_pairs(genomes, args.batch_size, f"{args.outputpath}/batches", args.containmentpath, args.sourmash, smash_matrix, args.smash_threshold)
+ if args.prev_typing:
+ prev_genomes = [pd.read_csv(f"{path}/typing.tsv", sep="\t")["plasmid"].to_list() for path in args.prev_typing]
+ prev_hubs = [pd.read_csv(f"{path}/hub_plasmids.csv", sep="\t")["hub_plasmids"].to_list() for path in args.prev_typing]
+ prev_genomes = [prev_genomes[i]+prev_hubs[i] for i in range(len(args.prev_typing))]
+ else:
+ prev_genomes=[]
+
+ len_pairs = get_pairs(genomes, args.batch_size, f"{args.outputpath}/batches", args.containmentpath, args.sourmash, args.sourmash_only, smash_matrix, args.smash_threshold,prev_genomes=prev_genomes)
number_of_batches = math.ceil(len_pairs/args.batch_size)
with open(f"{args.outputpath}/batches/batching_info.txt", "w") as f:
diff --git a/pling/common_rules/common_rules.smk b/pling/common_rules/common_rules.smk
index 416a58e..a73bb76 100644
--- a/pling/common_rules/common_rules.smk
+++ b/pling/common_rules/common_rules.smk
@@ -5,6 +5,21 @@
# GENOMES
from pling.utils import get_number_of_batches
+def get_prev_pling():
+ if config.get("previous_pling",False):
+ blub = config["previous_pling"].strip().split(",")
+ pickles = " ".join([f"{bl}/containment/containment_communities/objects/plasmid_graph.pkl" for bl in blub])
+ comms = " ".join([f"{bl}/containment/containment_communities/objects/communities.tsv" for bl in blub])
+ return f"--graph-pickle {pickles} --prev_typing {comms}"
+ else:
+ return ""
+
+def get_vis():
+ if config["visualisation"]=="none" or config["visualisation"]=="subcommunity":
+ return "--no-community-vis"
+ else:
+ return "--output-plasmid-graph"
+
rule create_genomes_tsv:
output:
genomes_tsv = f"{OUTPUTPATH}/tmp_files/genomes.tsv"
@@ -17,23 +32,24 @@ rule create_genomes_tsv:
f.write(f"{genome}\n")
localrules: create_genomes_tsv
-rule cat_containment:
- input:
- containments = expand(f"{OUTPUTPATH}/tmp_files/containment_batchwise/batch_{{batch}}_containment.tsv", batch=[str(i) for i in range(get_number_of_batches(OUTPUTPATH))])
- output:
- all_containment_distances = f"{OUTPUTPATH}/containment/all_pairs_containment_distance.tsv"
- threads: 1
- resources:
- mem_mb=lambda wildcards, attempt: 4000*attempt
- run:
- with open(output.all_containment_distances, "w") as contain_out:
- contain_out.write("plasmid_1\tplasmid_2\tdistance\n")
- for file in input.containments:
- with open(file, "r") as f:
- to_cat = f.read()
- contain_out.write(to_cat)
+if not config.get("sourmash_only", False):
+ rule cat_containment:
+ input:
+ containments = expand(f"{OUTPUTPATH}/tmp_files/containment_batchwise/batch_{{batch}}_containment.tsv", batch=[str(i) for i in range(get_number_of_batches(OUTPUTPATH))])
+ output:
+ all_containment_distances = f"{OUTPUTPATH}/containment/all_pairs_containment_distance.tsv"
+ threads: 1
+ resources:
+ mem_mb=lambda wildcards, attempt: 4000*attempt
+ run:
+ with open(output.all_containment_distances, "w") as contain_out:
+ contain_out.write("plasmid_1\tplasmid_2\tdistance\n")
+ for file in input.containments:
+ with open(file, "r") as f:
+ to_cat = f.read()
+ contain_out.write(to_cat)
-localrules: cat_containment
+ localrules: cat_containment
def get_metadata(metadata):
if metadata == "None":
@@ -55,16 +71,19 @@ rule get_communities:
bh_connectivity=config["bh_connectivity"],
bh_neighbours_edge_density=config["bh_neighbours_edge_density"],
metadata = get_metadata(config["metadata"]),
- output_type = config["output_type"]
+ output_type = config["output_type"],
+ vis = get_vis(),
+ prev_pling = get_prev_pling()
shell: """
plasnet split \
--distance-threshold {params.containment_distance} \
--bh-connectivity {params.bh_connectivity} \
--bh-neighbours-edge-density {params.bh_neighbours_edge_density} \
- --output-plasmid-graph \
--output-type {params.output_type} \
{params.metadata} \
{input.genomes} \
{input.containment} \
- {output.communities}
+ {output.communities} \
+ {params.prev_pling} \
+ {params.vis}
"""
diff --git a/pling/dcj_snakemake/Snakefile b/pling/dcj_snakemake/Snakefile
index 8998ba8..b145c62 100644
--- a/pling/dcj_snakemake/Snakefile
+++ b/pling/dcj_snakemake/Snakefile
@@ -28,13 +28,41 @@ def get_unimog():
else:
return ""
+def get_prev_pling():
+ if config.get("previous_pling",False):
+ blub = config["previous_pling"].strip().split(",")
+ blah = " ".join([f"{bl}/dcj_thresh_{dcj_threshold}_graph/objects/typing.tsv" for bl in blub])
+ recluster = config["reclustering_method"]
+ return f"--prev_typing {blah} --reclustering_method {recluster}"
+ else:
+ return ""
+
+def get_prev_dcj():
+ if config.get("previous_pling",False):
+ blub = config["previous_pling"]
+ return f"{blub}/all_plasmids_distances.tsv"
+ else:
+ return None
+
+def get_vis():
+ if config["visualisation"]=="none":
+ return "--no-vis"
+ else:
+ return ""
+
+def get_containmentpath(batch):
+ if config.get("sourmash_only", False):
+ return f"{OUTPUTPATH}/containment/all_pairs_containment_distance.tsv"
+ else:
+ return f"{OUTPUTPATH}/tmp_files/containment_batchwise/batch_{batch}_containment.tsv"
+
rule all:
input:
dcj_graph_outdir = f"{OUTPUTPATH}/dcj_thresh_{dcj_threshold}_graph"
rule ding:
input:
- containment_tsv = lambda wildcards: f"{OUTPUTPATH}/tmp_files/containment_batchwise/batch_{wildcards.batch}_containment.tsv",
+ containment_tsv = lambda wildcards: get_containmentpath(wildcards.batch),
batch_list = lambda wildcards: f"{OUTPUTPATH}/batches/batch_{wildcards.batch}.txt"
output:
f"{OUTPUTPATH}/tmp_files/dists_batchwise/batch_{{batch}}_dcj.tsv"
@@ -79,6 +107,8 @@ rule dcj_tsv:
threads: 1
resources:
mem_mb=lambda wildcards, attempt: 4000*attempt
+ params:
+ prev_dcj = get_prev_dcj()
run:
with open(output.tsv, "w") as dcj_out:
dcj_out.write("plasmid_1\tplasmid_2\tdistance\n")
@@ -86,6 +116,11 @@ rule dcj_tsv:
with open(file, "r") as f:
to_cat = f.read()
dcj_out.write(to_cat)
+ if params.prev_dcj:
+ with open(params.prev_dcj) as f:
+ next(f)
+ to_cat = f.read()
+ dcj_out.write(to_cat)
rule build_DCJ_graph:
input:
@@ -99,7 +134,9 @@ rule build_DCJ_graph:
params:
dcj_dist_threshold=config["dcj_dist_threshold"],
small_subcommunity_size_threshold = config["small_subcommunity_size_threshold"], #Communities with size up to this parameter will be joined to neighbouring larger subcommunities
- output_type = config["output_type"]
+ output_type = config["output_type"],
+ prev_pling = get_prev_pling(),
+ vis = get_vis()
shell: """
plasnet type \
--distance-threshold {params.dcj_dist_threshold} \
@@ -107,5 +144,7 @@ rule build_DCJ_graph:
{input.communities} \
{input.distances_tsv} \
{output.dcj_graph_outdir} \
- --output-type {params.output_type}
+ --output-type {params.output_type} \
+ {params.prev_pling} \
+ {params.vis}
"""
diff --git a/pling/dcj_snakemake/dcj.py b/pling/dcj_snakemake/dcj.py
index 34f1f0a..9a17f0e 100644
--- a/pling/dcj_snakemake/dcj.py
+++ b/pling/dcj_snakemake/dcj.py
@@ -26,8 +26,9 @@ def get_containment_distances_for_batch(containment_tsv):
with open(containment_tsv, "r") as f:
for line in f:
plasmid_1, plasmid_2, containment = line.strip().split("\t")
- containment = float(containment)
- containments[(plasmid_1,plasmid_2)] = containment
+ if containment!="distance":
+ containment = float(containment)
+ containments[(plasmid_1,plasmid_2)] = containment
return containments
def get_unimog(outputpath, integerisation, plasmid_to_community, batch, genome1, genome2, unimog_path=None):
@@ -65,7 +66,7 @@ def GLPK_flow(pairs, containment_distance, containments, integerisation, outputp
if timelimit == None:
timelimit=""
else:
- timelimit=f"--tmlim {args.timelimit}"
+ timelimit=f"--tmlim {timelimit}"
dists = []
for pair in pairs:
diff --git a/pling/dcj_snakemake/glpk_and_ding.py b/pling/dcj_snakemake/glpk_and_ding.py
index 7b6b492..70599c6 100644
--- a/pling/dcj_snakemake/glpk_and_ding.py
+++ b/pling/dcj_snakemake/glpk_and_ding.py
@@ -1,36 +1,41 @@
import subprocess
+import sys
+import logging
def unimog_to_ilp(unimog, lp, genome1, genome2):
try:
- print("Converting unimog to ILP...\n")
+ logging.info("Converting unimog to ILP...\n")
subprocess.run(f"dingII generate {unimog} -mm --writeilp {lp} -p {genome1} {genome2}", shell=True, check=True, capture_output=True)
- print("Completed.\n")
+ logging.info("Completed.\n")
except subprocess.CalledProcessError as e:
- print(e.stderr.decode())
- print(e)
+ print(f"ERROR IN RULE: dingII FAILING WITH {genome1} AND {genome2}", file=sys.stderr)
+ print(e.stderr.decode(), file=sys.stderr)
+ print("END ERROR MSG", file=sys.stderr)
raise e
def ilp_GLPK(lp, solution, snakefile_dir, timelimit):
try:
- print("Solving ILP with GLPK...\n")
+ logging.info("Solving ILP with GLPK...\n")
subprocess.run(f"glpsol --lp {lp} -o {solution}.tmp {timelimit}", shell=True, check=True, capture_output=True)
- print("Completed.\n Converting GLPK output to Gurobi output...\n")
+ logging.info("Completed.\n Converting GLPK output to Gurobi output...\n")
subprocess.run(f"python {snakefile_dir}/glpk_sol_to_gurobi_sol.py <{solution}.tmp >{solution}", shell=True, check=True, capture_output=True)
- print("Completed.\n")
+ logging.info("Completed.\n")
subprocess.run(f"rm {solution}.tmp", shell=True, check=True, capture_output=True)
except subprocess.CalledProcessError as e:
- print(e.stderr.decode())
- print(e)
+ print(f"ERROR IN RULE: GLPK FAILING WITH {lp}", file=sys.stderr)
+ print(e.stderr.decode(), file=sys.stderr)
+ print("END ERROR MSG", file=sys.stderr)
raise e
def dcj_dist(unimog, solution, genome1, genome2):
try:
- print("Parsing Gurobi output to get DCJ distances...\n")
+ logging.info("Parsing Gurobi output to get DCJ distances...\n")
dcj_out = subprocess.run(f"dingII parsesol {unimog} --solgur {solution} -p {genome1} {genome2}", shell=True, check=True, capture_output=True, text=True).stdout
dist = int(dcj_out.strip().split(" ")[2])
- print("Completed.\n")
+ logging.info("Completed.\n")
except subprocess.CalledProcessError as e:
- print(e.stderr.decode())
- print(e)
+ print(f"ERROR IN RULE: dingII FAILING WITH {genome1} AND {genome2}", file=sys.stderr)
+ print(e.stderr.decode(), file=sys.stderr)
+ print("END ERROR MSG", file=sys.stderr)
raise e
return dist
diff --git a/pling/jac_network_snakemake/Snakefile b/pling/jac_network_snakemake/Snakefile
index 8136474..2ca35f1 100644
--- a/pling/jac_network_snakemake/Snakefile
+++ b/pling/jac_network_snakemake/Snakefile
@@ -20,26 +20,27 @@ rule all:
input:
communities = f"{OUTPUTPATH}/containment/containment_communities"
-rule pairwise_seq_containment:
- input:
- batch_list=lambda wildcards: f"{OUTPUTPATH}/batches/batch_{wildcards.batch}.txt"
- output:
- containment=f"{OUTPUTPATH}/tmp_files/containment_batchwise/batch_{{batch}}_containment.tsv"
- threads: config["pairwise_seq_containment_threads"]
- resources:
- mem_mb=lambda wildcards, attempt: config["pairwise_seq_containment_mem"]*attempt
- params:
- genomes_list = config["genomes_list"],
- batch = lambda wildcards: wildcards.batch,
- outputpath = OUTPUTPATH,
- identity_threshold = config["identity_threshold"],
- pling_root_dir = get_pling_root_dir()
- shadow: "shallow"
- shell: """
- PYTHONPATH={params.pling_root_dir} python {params.pling_root_dir}/pling/jac_network_snakemake/seq_containment.py \
- --genomes_list {params.genomes_list} \
- --batch {params.batch} \
- --identity_threshold {params.identity_threshold} \
- --outputpath {params.outputpath} \
- --containment_output {output.containment} \
- """
+if not config.get("sourmash_only", False):
+ rule pairwise_seq_containment:
+ input:
+ batch_list=lambda wildcards: f"{OUTPUTPATH}/batches/batch_{wildcards.batch}.txt"
+ output:
+ containment=f"{OUTPUTPATH}/tmp_files/containment_batchwise/batch_{{batch}}_containment.tsv"
+ threads: config["pairwise_seq_containment_threads"]
+ resources:
+ mem_mb=lambda wildcards, attempt: config["pairwise_seq_containment_mem"]*attempt
+ params:
+ genomes_list = config["genomes_list"],
+ batch = lambda wildcards: wildcards.batch,
+ outputpath = OUTPUTPATH,
+ identity_threshold = config["identity_threshold"],
+ pling_root_dir = get_pling_root_dir()
+ shadow: "shallow"
+ shell: """
+ PYTHONPATH={params.pling_root_dir} python {params.pling_root_dir}/pling/jac_network_snakemake/seq_containment.py \
+ --genomes_list {params.genomes_list} \
+ --batch {params.batch} \
+ --identity_threshold {params.identity_threshold} \
+ --outputpath {params.outputpath} \
+ --containment_output {output.containment} \
+ """
diff --git a/pling/jac_network_snakemake/seq_containment.py b/pling/jac_network_snakemake/seq_containment.py
index 2b8a79c..80c2f24 100644
--- a/pling/jac_network_snakemake/seq_containment.py
+++ b/pling/jac_network_snakemake/seq_containment.py
@@ -4,6 +4,7 @@
from intervaltree import IntervalTree
import argparse
from pling.utils import read_in_batch_pairs, get_fasta_file_info
+import sys
def get_coverage(tree):
tree.merge_overlaps()
@@ -21,7 +22,13 @@ def get_coordinates(split_line, index):
return start, end
def get_sequence_containment_distance(plasmid_1: Path, plasmid_2: Path, prefix: str, identity_threshold=80) -> Tuple[str, str]:
- subprocess.check_call(f"nucmer --diagdiff 20 --breaklen 500 --maxmatch -p {prefix} {plasmid_1} {plasmid_2} && delta-filter -qr {prefix}.delta > {prefix}.1delta", shell=True)
+ try:
+ subprocess.check_call(f"nucmer --diagdiff 20 --breaklen 500 --maxmatch -p {prefix} {plasmid_1} {plasmid_2} && delta-filter -qr {prefix}.delta > {prefix}.1delta", shell=True)
+ except subprocess.CalledProcessError as e:
+ print(f"ERROR IN RULE:\n NUCMER FAILING WITH PAIR {plasmid_1} AND {plasmid_2}", file=sys.stderr)
+ print(e.stderr.decode(), file=sys.stderr)
+ print("END ERROR MSG", file=sys.stderr)
+ sys.exit(e.returncode)
show_coords_output = subprocess.check_output(f"show-coords -TrcldH -I {identity_threshold} {prefix}.1delta", shell=True).strip().split(b'\n')
assert(len(show_coords_output)>0)
diff --git a/pling/run_pling.py b/pling/run_pling.py
index 1250373..757c72f 100644
--- a/pling/run_pling.py
+++ b/pling/run_pling.py
@@ -5,92 +5,90 @@
"""
import subprocess
-import argparse
import shutil
import os
import pandas as pd
from pathlib import Path
-import subprocess
import yaml
import importlib
from pling import __version__
+import click
+import logging
+from plasnet.utils import PathlibPath
+import warnings
+import sys
-def parse_args():
- parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
- parser.add_argument('--version', action='version', version=__version__)
- parser.add_argument("genomes_list", help="Path to list of fasta file paths.")
- parser.add_argument("output_dir", help="Path to output directory.")
- parser.add_argument("integerisation", choices=["align", "skip"],
- help="Integerisation method: \"align\" for alignment, \"skip\" to skip integerisation altogether. Make sure to input a unimog file if skipping integerisation.")
- parser.add_argument("--unimog", help="Path to unimog file. Required input if skipping integerisation.")
- parser.add_argument("--containment_distance", default=0.5, help="Threshold for initial containment network.")
- parser.add_argument("--dcj", default=4, help="Threshold for final DCJ-Indel network.")
- parser.add_argument("--regions", action="store_true", help="Cluster regions rather than complete genomes. Assumes regions are taken from circular plasmids.")
- parser.add_argument("--topology", help="File stating whether plasmids are circular or linear. Must be a tsv with two columns, one with plasmid IDs under \"plasmid\" and one with \"linear\" or \"circular\" as entries under \"topology\". Without this file, pling will asume all plasmids are circular.")
- parser.add_argument("--batch_size", default = 200, help="How many pairs of genomes to run together in one go (for integerisation from alignment and DCJ calculation steps).")
- parser.add_argument("--sourmash", action="store_true", help="Run sourmash as first filter on which pairs to calculate DCJ on. Recommended for large and very diverse datasets.")
- parser.add_argument("--sourmash_threshold", default=0.85, help="Threshold for filtering with sourmash.")
- parser.add_argument("--identity", default=80, help="Threshold for percentage of shared sequence between blocks (for integerisation from alignment and for containment calculation).")
- parser.add_argument("--min_indel_size", default=200, help="Minimum size for an indel to be treated as a block (for integerisation from alignment).")
- parser.add_argument("--bh_connectivity", default=10, help="Minimum number of connections a plasmid need to be considered a hub plasmid.")
- parser.add_argument("--bh_neighbours_edge_density", default=0.2, help="Maximum number of edge density between hub plasmid neighbours to label the plasmid as hub.")
- parser.add_argument("--small_subcommunity_size_threshold", default=4, help="Communities with size up to this parameter will be joined to neighbouring larger subcommunities.")
- parser.add_argument("--output_type", choices=["html", "json", "both"], default="html", help="Whether to output networks as html visualisations, cytoscape formatted json, or both.")
- parser.add_argument("--plasmid_metadata", help="Metadata to add beside plasmid ID on the visualisation graph. Must be a tsv with a single column, with data in the same order as in genomes_list.")
- parser.add_argument("--ilp_solver", choices=["GLPK", "gurobi"], default="GLPK",
- help="ILP solver to use. Default is GLPK, which is slower but is bundled with pling and is free. "
- "If using gurobi, make sure you have a valid license and gurobi_cl is in your PATH.")
- parser.add_argument("--timelimit", help="Time limit in seconds for ILP solver.")
- parser.add_argument("--resources", help="tsv stating number of threads and memory to use for each rule.")
- parser.add_argument("--cores", default=1, help="Total number of cores/threads. Put the maximum number of threads you request in the resources tsv here. (This argument is passed on to snakemake's --cores argument.)")
- parser.add_argument("--profile", help="To run on a cluster with corresponding snakemake profile.")
- #parser.add_argument("--storetmp", action="store_true", help="Don't delete intermediate temporary files.")
- parser.add_argument("--forceall", action="store_true", help="Force snakemake to rerun everything.")
-
- args = parser.parse_args()
- return args
-
+logFormatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
+logger = logging.getLogger(__name__)
def get_pling_path():
plingpath = os.path.realpath(os.path.dirname(__file__))
return plingpath
+def read_log_file(path, config_dict={}):
+ with open(path) as f:
+ lines = f.readlines()
+ args_bool = True
+ i = 4
+ while args_bool:
+ if lines[i]=="\n":
+ args_bool = False
+ else:
+ arg, value = lines[i].replace(" ", "").strip().split(":")
+ config_dict[arg] = value
+ i = i + 1
+ return config_dict
+
def check_gurobi(ilp_solver):
if ilp_solver == "gurobi":
spec = importlib.util.find_spec("gurobi")
if spec is None:
+ logging.error("Missing optional dependency gurobi!")
raise Exception("Missing optional dependency gurobi!")
-
-def make_config_file(args):
- #make configfile
+
+def check_vis_trees(vis_trees):
+ if vis_trees:
+ spec = importlib.util.find_spec("ete3")
+ if spec is None:
+ logging.warning("Missing optional dependency ete3, will skip tree visualisation.")
+ return False
+ return True
+
+def make_snakemake_config(args, config_dict):
forceall = ""
- if args.forceall == True:
+ if args["forceall"] == True:
forceall = "--forceall"
- if args.timelimit==None:
- timelimit = "None"
- else:
- timelimit= args.timelimit
-
- if args.plasmid_metadata==None:
- metadata = "None"
- else:
- metadata= os.path.abspath(args.plasmid_metadata)
-
- if args.topology==None:
- topology = "None"
- else:
- topology= os.path.abspath(args.topology)
-
profile = ""
- if args.profile!=None:
- profile = f"--profile {args.profile}"
- if args.resources!=None:
- resources = pd.read_csv(args.resources, sep="\t")
+ if args["profile"]!=None:
+ profile = "--profile " + {args["profile"]}
+ if args["resources"]!=None:
+ resources = pd.read_csv(args["resources"], sep="\t")
else:
resources = pd.read_csv(f"{get_pling_path()}/resources.tsv", sep="\t")
+ for row in resources.index:
+ rule = resources.loc[row, "Rule"]
+ threads = resources.loc[row, "Threads"]
+ mem = resources.loc[row, "Mem"]
+ if not pd.isna(threads):
+ config_dict[f"{rule}_threads"] = int(threads)
+ config_dict[f"{rule}_mem"] = int(mem)
+
+ return config_dict, profile, forceall
+
+def set_up_logging(log_file, config_dict):
+ with open(log_file, "w") as log:
+ log.write(f"pling version {__version__}\n")
+ log.write("\n ARGUMENTS \n\n")
+ yaml.dump(config_dict,log)
+ log.write("\n\n LOG \n\n")
+ fileHandler = logging.FileHandler(log_file)
+ fileHandler.setFormatter(logFormatter)
+ logger.addHandler(fileHandler)
- output_dir = Path(os.path.abspath(args.output_dir))
+def make_config_file(args, integerisation):
+ #make configfile
+ output_dir = Path(os.path.abspath(args["output_dir"]))
output_dir.mkdir(parents=True, exist_ok=True)
tmp_dir = output_dir/"tmp_files"
@@ -98,89 +96,353 @@ def make_config_file(args):
configfile = f"{output_dir}/tmp_files/config.yaml"
- config_dict = {"genomes_list": str(os.path.abspath(args.genomes_list)), "output_dir": str(output_dir), "integerisation": str(args.integerisation), "seq_containment_distance": float(args.containment_distance), "dcj_dist_threshold": int(args.dcj), "prefix": "all_plasmids","communities": f"{output_dir}/containment/containment_communities", "identity_threshold": float(args.identity), "length_threshold": int(args.min_indel_size), "bh_connectivity": int(args.bh_connectivity), "bh_neighbours_edge_density": float(args.bh_neighbours_edge_density), "small_subcommunity_size_threshold": int(args.small_subcommunity_size_threshold), "output_type": str(args.output_type), "metadata": metadata, "ilp_solver": str(args.ilp_solver), "timelimit": timelimit, "batch_size": int(args.batch_size), "topology": topology}
-
- if args.sourmash:
- config_dict["sourmash"] = str(args.sourmash)
- config_dict["sourmash_threshold"] = str(args.sourmash_threshold)
- if args.regions:
- config_dict["regions"] = str(args.regions)
- if args.unimog!=None and args.integerisation=="skip":
- config_dict["unimog"] = os.path.abspath(args.unimog)
- elif args.unimog==None and args.integerisation=="skip":
- raise Exception("Selected to skip integerisation, but missing unimog file as input!")
- for row in resources.index:
- rule = resources.loc[row, "Rule"]
- threads = resources.loc[row, "Threads"]
- mem = resources.loc[row, "Mem"]
- if not pd.isna(threads):
- config_dict[f"{rule}_threads"] = int(threads)
- config_dict[f"{rule}_mem"] = int(mem)
+ config_dict = {"genomes_list": str(args["genomes_list"]), "output_dir": str(output_dir), "integerisation": integerisation,
+ "seq_containment_distance": float(args["containment_distance"]), "dcj_dist_threshold": int(args["dcj"]),
+ "prefix": "all_plasmids","communities": f"{output_dir}/containment/containment_communities",
+ "identity_threshold": float(args["identity"]), "bh_connectivity": int(args["bh_connectivity"]),
+ "bh_neighbours_edge_density": float(args["bh_neighbours_edge_density"]), "small_subcommunity_size_threshold": int(args["small_subcommunity_size_threshold"]),
+ "output_type": str(args["output_type"]), "ilp_solver": str(args["ilp_solver"]), "batch_size": int(args["batch_size"]), "visualisation":str(args["visualisation"])}
- with open(configfile, 'w') as config:
- yaml.dump(config_dict, config)
+ if integerisation=="align":
+ config_dict["length_threshold"] = int(args["min_indel_size"])
+ if args["topology"]==None:
+ config_dict["topology"] = "None"
+ else:
+ config_dict["topology"]= str(os.path.abspath(args["topology"]))
+ if args["regions"]:
+ config_dict["regions"] = str(args["regions"])
+
+ if integerisation=="skip":
+ config_dict["unimog"] = str(args["precomputed"])
+ config_dict["sourmash_only"] = str(args["sourmash_only"])
+
+ if args["sourmash"]:
+ config_dict["sourmash"] = str(args["sourmash"])
+ config_dict["sourmash_threshold"] = str(args["sourmash_threshold"])
+
+ if "previous_pling" in args.keys():
+ if args["reclustering_method"]=="asyn":
+ config_dict["reclustering_method"] = "unbiased"
+ else:
+ config_dict["reclustering_method"] = args["reclustering_method"]
+ config_dict["previous_pling"] = ",".join([str(os.path.abspath(path)) for path in args["previous_pling"]])
+ if config_dict["reclustering_method"]=="nearest_neighbour" and len(args["previous_pling"])>1:
+ raise Exception("Nearest neighbour typing does not support merging graphs.")
+ for path in args["previous_pling"]:
+ prev_thresholds = read_log_file(f"{path}/pling.log")
+ if prev_thresholds["dcj_dist_threshold"] != config_dict["dcj_dist_threshold"] or prev_thresholds["seq_containment_distance"] != config_dict["seq_containment_distance"]:
+ raise Exception(f"{path} was not constructed with the same containment or DCJ-Indel thresholds as given.")
+
+ set_up_logging(f"{output_dir}/pling.log", config_dict)
- return configfile, tmp_dir, forceall, profile
+ if args["timelimit"]==None:
+ config_dict["timelimit"] = "None"
+ else:
+ if args["ilp_solver"] == "gurobi":
+ config_dict["timelimit"]= args["timelimit"]
+ elif args["ilp_solver"] == "GLPK":
+ config_dict["timelimit"] = "None"
+ logger.warning("GLPK does not support a time limit; time limit parameter has been ignored.")
+
+ if args["plasmid_metadata"]==None:
+ config_dict["metadata"] = "None"
+ else:
+ config_dict["metadata"]= str(args["plasmid_metadata"])
-def pling(args):
+ config_dict, profile, forceall = make_snakemake_config(args, config_dict)
- check_gurobi(args.ilp_solver)
+ with open(configfile, 'w') as config:
+ yaml.dump(config_dict, config)
- configfile, tmp_dir, forceall, profile = make_config_file(args)
+ snakemake_args = f"--configfile {configfile} --cores " + str(args["cores"]) + f" --rerun-incomplete --nolock {profile} {forceall} --quiet all"
- snakemake_args = f"--configfile {configfile} --cores {args.cores} --rerun-incomplete --nolock {profile} {forceall}"
+ return tmp_dir, snakemake_args
- #batching
+def run_command(command):
try:
- print("Batching...\n")
- subprocess.run(f"snakemake --snakefile {get_pling_path()}/batching/Snakefile {snakemake_args}", shell=True, check=True, capture_output=True)
- print("Completed batching.\n")
+ subprocess.run(command, shell=True, check=True, capture_output=True)
except subprocess.CalledProcessError as e:
- print(e.stderr.decode())
- print(e)
+ logger.exception(e.stderr.decode())
raise e
- if args.integerisation == "align":
- try:
- print("Aligning, integerising, and building containment network...\n")
- subprocess.run(f"snakemake --snakefile {get_pling_path()}/align_snakemake/Snakefile {snakemake_args}", shell=True, check=True, capture_output=True)
- print("Completed integerisation and containment network.\n")
- except subprocess.CalledProcessError as e:
- print(e.stderr.decode())
- print(e)
- raise e
- elif args.integerisation == "skip":
- if args.unimog==None:
- raise Exception("Skipping integerisation but there is no unimog file provided!")
- try:
- print("Building containment network...\n")
- subprocess.run(f"snakemake --snakefile {get_pling_path()}/jac_network_snakemake/Snakefile {snakemake_args}", shell=True, check=True, capture_output=True)
- print("Completed containment network.\n")
- except subprocess.CalledProcessError as e:
- print(e.stderr.decode())
- print(e)
- raise e
+def batching(snakemake_args):
+ logger.info("Batching...")
+ run_command(f"snakemake --snakefile {get_pling_path()}/batching/Snakefile {snakemake_args}")
+ logger.info("Completed batching.")
+
+def alignment(snakemake_args):
+ logger.info("Aligning, integerising, and building containment network...")
+ run_command(f"snakemake --snakefile {get_pling_path()}/align_snakemake/Snakefile {snakemake_args}")
+ logger.info("Completed integerisation and containment network.")
+
+def ding_and_cluster(snakemake_args):
+ logger.info("Calculating DCJ-Indel distance and clustering...")
+ run_command(f"snakemake --snakefile {get_pling_path()}/dcj_snakemake/Snakefile {snakemake_args}")
+ logger.info("Completed distance calculations and clustering.")
+
+
+def thresholds(func):
+ options = [
+ click.option("--containment_distance", default=0.5, help="Threshold for initial containment network."),
+ click.option("--dcj", default=4, help="Threshold for final DCJ-Indel network."),
+ click.option("--identity", default=80, help="Threshold for percentage of shared sequence between blocks (for integerisation from alignment and for containment calculation)."),
+ click.option("--min_indel_size", default=200, help="Minimum size for an indel to be treated as a block (for integerisation from alignment)."),
+ click.option("--bh_connectivity", default=10, help="Minimum number of connections a plasmid need to be considered a hub plasmid."),
+ click.option("--bh_neighbours_edge_density", default=0.2, help="Maximum number of edge density between hub plasmid neighbours to label the plasmid as hub."),
+ click.option("--small_subcommunity_size_threshold", default=4, help="Communities with size up to this parameter will be joined to neighbouring larger subcommunities."),
+ ]
+ for option in reversed(options):
+ func = option(func)
+ return func
+
+def vis_paras(func):
+ options = [
+ click.option("--output_type", type=click.Choice(["html", "json", "both"]), default="html", help="Whether to output networks as html visualisations, cytoscape formatted json, or both."),
+ click.option("--plasmid_metadata", help="Metadata to add beside plasmid ID on the visualisation graph. Must be a tsv with a single column, with data in the same order as in genomes_list."),
+ click.option("--visualisation", type=click.Choice(["none", "all", "subcommunity"]), default="subcommunity", help="Which network visualisations to produce."),
+ ]
+ for option in reversed(options):
+ func = option(func)
+ return func
+
+def resource_paras(func):
+ options = [
+ click.option("--batch_size", default = 200, help="How many pairs of genomes to run together in one go (for integerisation from alignment and DCJ calculation steps)."),
+ click.option("--ilp_solver", type=click.Choice(["GLPK", "gurobi"]), default="GLPK",
+ help="ILP solver to use. Default is GLPK, which is slower but is bundled with pling and is free. "
+ "If using gurobi, make sure you have a valid license and gurobi_cl is in your PATH."),
+ click.option("--timelimit", help="Time limit in seconds for ILP solver."),
+ click.option("--resources", help="tsv stating number of threads and memory to use for each rule."),
+ click.option("--cores", default=1, help="Total number of cores/threads. Put the maximum number of threads you request in the resources tsv here. (This argument is passed on to snakemake's --cores argument.)"),
+ click.option("--profile", help="To run on a cluster with corresponding snakemake profile."),
+ #@click.option("--storetmp", is_flag=True, help="Don't delete intermediate temporary files.")
+ click.option("--forceall", is_flag=True, help="Force snakemake to rerun everything."),
+ ]
+ for option in reversed(options):
+ func = option(func)
+ return func
+
+@click.group(context_settings={"show_default": True})
+@click.version_option(version=__version__)
+@click.help_option()
+def cli() -> None:
+ pass
+
+
+@click.group(
+ help="Clusters genomes using containment and DCJ-Indel distances."
+)
+@click.help_option()
+def cluster() -> None:
+ pass
+
+@click.command(
+ help="""
+\b
+Intergerises genomes using alignment, calculates containment and DCJ-Indel distances, and clusters.
+\b
+First input is a path to list of fasta file paths.
+\b
+Second input is a path to an output directory.
+
+""", # noqa: E501
+)
+@click.argument("genomes_list", type=PathlibPath(exists=True))
+@click.argument("output_dir", type=PathlibPath(exists=False))
+@thresholds
+@click.option("--regions", is_flag=True, help="Cluster regions rather than complete genomes. Assumes regions are taken from circular plasmids.")
+@click.option("--topology", help="File stating whether plasmids are circular or linear. Must be a tsv with two columns, one with plasmid IDs under \"plasmid\" and one with \"linear\" or \"circular\" as entries under \"topology\". Without this file, pling will asume all plasmids are circular.")
+@click.option("--sourmash", is_flag=True, help="Run sourmash as first filter on which pairs to calculate DCJ on. Recommended for large and very diverse datasets.")
+@click.option("--sourmash_threshold", default=0.85, help="Threshold for filtering with sourmash.")
+@click.option("--reuse_previous", type=PathlibPath(exists=True), help="Recompute communities and subcommunities from previous containment and DCJ-Indel distances. Provide a path to a previous pling output folder. The containment threshold of previous output MUST have been higher than the current one.")
+@vis_paras
+@resource_paras
+@click.help_option()
+def align(
+ **args
+):
+ check_gurobi(args["ilp_solver"])
+
+ tmp_dir, snakemake_args = make_config_file(args, "align")
+
+ if not args["reuse_previous"]:
+ batching(snakemake_args)
else:
- raise Exception(f"\"{args.integerisation}\" is not a valid integerisation method!")
+ prev_thresholds = read_log_file(args["reuse_previous"]/ "pling.log")
+ if float(prev_thresholds["seq_containment_distance"]) >= args["containment_distance"]:
+ shutil.copy(args["reuse_previous"] / "containment/all_pairs_containment_distance.tsv", args["output_dir"] / "containment") #copy containment distances - should cause snakemake not to rerun everything, just communities
+ shutil.copy(args["reuse_previous"] / "all_plasmids_distances.tsv", args["output_dir"]) #copy DCJ-Indel distances - should cause snakemake not to rerun DCJ-Indel calculations
+ else:
+ logging.error("Previous containment distance threshold is not higher than current containment distance threshold!")
+ raise Exception("Previous containment distance threshold is not higher than current containment distance threshold!")
+
+ alignment(snakemake_args)
+
+ ding_and_cluster(snakemake_args)
+
+ #delete intermediary files
+ shutil.rmtree(tmp_dir)
- #ding and clustering
- try:
- print("Calculating DCJ-Indel distance and clustering...\n")
- subprocess.run(f"snakemake --snakefile {get_pling_path()}/dcj_snakemake/Snakefile {snakemake_args}", shell=True, check=True, capture_output=True)
- print("Completed distance calculations and clustering.\n")
- except subprocess.CalledProcessError as e:
- print(e.stderr.decode())
- print(e)
- raise e
+@click.command(
+ help="""
+\b
+Given a precomputed integerisation, calculates containment and DCJ-Indel distances, and clusters.
+\b
+First input is a path to list of fasta file paths.
+\b
+Second input is a path to an output directory.
+\b
+Third input is a path to a unimog file, or previous pling output folder. Required input when skipping integerisation. Unless run with \"reuse_previous\" flag, will assume is a unimog file.
+
+""", # noqa: E501
+)
+@click.argument("genomes_list", type=PathlibPath(exists=True))
+@click.argument("output_dir", type=PathlibPath(exists=False))
+@click.argument("precomputed", type=PathlibPath(exists=True))
+@thresholds
+@click.option("--sourmash", is_flag=True, help="Run sourmash as first filter on which pairs to calculate DCJ on. Recommended for large and very diverse datasets.")
+@click.option("--sourmash_threshold", default=0.85, help="Threshold for filtering with sourmash.")
+@click.option("--sourmash_only", is_flag=True, help="Run sourmash instead of aligning to get containment distances. Uses the threshold from \"containment_distance\" rather than \"sourmash_threshold\".")
+@click.option("--reuse_previous", type=PathlibPath(exists=True), help="Recompute communities and subcommunities from previous containment and DCJ-Indel distances. Provide a path to a previous pling output folder. The containment threshold of previous output MUST have been higher than the current one.")
+@vis_paras
+@resource_paras
+@click.help_option()
+def skip(
+ **args
+):
+ check_gurobi(args["ilp_solver"])
+
+ tmp_dir, snakemake_args = make_config_file(args, "skip")
+
+ if not args["reuse_previous"]:
+ batching(snakemake_args)
+ else:
+ prev_thresholds = read_log_file(args["reuse_previous"]/ "pling.log")
+ if float(prev_thresholds["seq_containment_distance"]) >= args["containment_distance"]:
+ shutil.copy(args["reuse_previous"] / "containment/all_pairs_containment_distance.tsv", args["output_dir"] / "containment") #copy containment distances - should cause snakemake not to rerun everything, just communities
+ shutil.copy(args["reuse_previous"] / "all_plasmids_distances.tsv", args["output_dir"]) #copy DCJ-Indel distances - should cause snakemake not to rerun DCJ-Indel calculations
+ else:
+ logging.error("Previous containment distance threshold is not higher than current containment distance threshold!")
+ raise Exception("Previous containment distance threshold is not higher than current containment distance threshold!")
+
+ logger.info("Building containment network...")
+ run_command(f"snakemake --snakefile {get_pling_path()}/jac_network_snakemake/Snakefile {snakemake_args}")
+ logger.info("Completed containment network.")
+
+ ding_and_cluster(snakemake_args)
+
#delete intermediary files
shutil.rmtree(tmp_dir)
+cluster.add_command(align)
+cluster.add_command(skip)
+cli.add_command(cluster)
+
+@click.command(
+ help="""
+\b
+Add new genomes to an existing pling clustering, and/or merge multiple previous clusterings into a single clustering.
+\b
+First input is a path to list of fasta file paths. This list must contain ALL genomes to be clustered, i.e. both genomes to add to previous clustering and genomes from previous clustering.
+\b
+Second input is a path to an output directory.
+\b
+Third input is a path to previous pling output directory (multiple are permitted).
+
+""", # noqa: E501
+)
+@click.argument("genomes_list", type=PathlibPath(exists=True))
+@click.argument("output_dir", type=PathlibPath(exists=False))
+@click.argument("previous_pling", required=True, nargs=-1)
+@click.option("--reclustering_method", type=click.Choice(["asyn", "nearest_neighbour"]), default="asyn")
+@thresholds
+@click.option("--regions", is_flag=True, help="Cluster regions rather than complete genomes. Assumes regions are taken from circular plasmids.")
+@click.option("--topology", help="File stating whether plasmids are circular or linear. Must be a tsv with two columns, one with plasmid IDs under \"plasmid\" and one with \"linear\" or \"circular\" as entries under \"topology\". Without this file, pling will asume all plasmids are circular.")
+@click.option("--sourmash", is_flag=True, help="Run sourmash as first filter on which pairs to calculate DCJ on. Recommended for large and very diverse datasets.")
+@click.option("--sourmash_threshold", default=0.85, help="Threshold for filtering with sourmash.")
+@vis_paras
+@resource_paras
+@click.help_option()
+def add(
+ **args
+):
+ check_gurobi(args["ilp_solver"])
+
+ tmp_dir, snakemake_args = make_config_file(args, "align")
+
+ batching(snakemake_args)
+
+ alignment(snakemake_args)
+
+ ding_and_cluster(snakemake_args)
+
+ #delete intermediary files
+ shutil.rmtree(tmp_dir)
+
+cli.add_command(add)
+
+@click.command(
+ help = "Output DCJ-Indel distances as matrices for each subcommunity, and calculate neighbour-joining trees."
+)
+@click.argument("output_dir", type=PathlibPath(exists=True))
+@click.option("--submatrices_dir", type=PathlibPath(exists=False), help="Directory to store results in. Defaults to output_dir/submatrices.")
+@click.option("--ignore_containment", is_flag=True, help="Calculate missing DCJ-Indel distances due to pairs not meeting the containment threshold previously. Interpret these with caution!")
+@click.option("--vis_trees", is_flag=True, help="Plot the DCJ-Indel NJ trees.")
+@resource_paras
+@click.help_option()
+def submatrix(**args):
+
+ output_dir = str(os.path.abspath(args["output_dir"]))
+
+ config_dict = {}
+ if args["submatrices_dir"]:
+ config_dict["submatrices_dir"] = str(os.path.abspath(args["submatrices_dir"]))
+ else:
+ config_dict["submatrices_dir"] = f"{output_dir}/submatrices"
+ submatrices_dir = config_dict["submatrices_dir"]
+ Path(submatrices_dir).mkdir(parents=True, exist_ok=True)
+
+ config_dict["vis_trees"] = check_vis_trees(args["vis_trees"])
+ config_dict["ignore_containment"] = args["ignore_containment"]
+
+ set_up_logging(f"{submatrices_dir}/submatrices.log", config_dict)
+
+ if args["timelimit"]==None:
+ config_dict["timelimit"] = "None"
+ else:
+ if args["ilp_solver"] == "gurobi":
+ config_dict["timelimit"]= args["timelimit"]
+ elif args["ilp_solver"] == "GLPK":
+ config_dict["timelimit"] = "None"
+ logger.warning("GLPK does not support a time limit; time limit parameter has been ignored.")
+
+ config_dict = read_log_file(f"{output_dir}/pling.log", config_dict)
+
+ config_dict, profile, forceall = make_snakemake_config(args, config_dict)
+
+ Path(config_dict["submatrices_dir"]).mkdir(parents=True, exist_ok=True)
+ configfile = config_dict["submatrices_dir"]+"/config.yaml"
+ with open(configfile, 'w') as config:
+ yaml.dump(config_dict, config)
+
+ command = "snakemake --cores " + str(args["cores"]) + f" --snakefile {get_pling_path()}/submatrix_snakemake/Snakefile --configfile {configfile} --rerun-incomplete --nolock {profile} {forceall} --quiet all"
+ logger.info("Creating distance matrices and trees...")
+ run_command(command)
+ logger.info("Completed!")
+
+ #delete intermediary files
+ os.remove(f"{submatrices_dir}/config.yaml")
+ if os.path.exists(f"{submatrices_dir}/incomplete"):
+ shutil.rmtree(f"{submatrices_dir}/incomplete")
+ if os.path.exists(f"{submatrices_dir}/missing"):
+ shutil.rmtree(f"{submatrices_dir}/missing")
+
+cli.add_command(submatrix)
def main():
- args = parse_args()
- pling(args)
+ cli()
if __name__ == "__main__":
- main()
+ main()
\ No newline at end of file
diff --git a/pling/submatrix_snakemake/Snakefile b/pling/submatrix_snakemake/Snakefile
new file mode 100755
index 0000000..8bd56ea
--- /dev/null
+++ b/pling/submatrix_snakemake/Snakefile
@@ -0,0 +1,201 @@
+from pathlib import Path
+import os
+import pandas as pd
+import subprocess
+import glob
+from pling.utils import get_pling_root_dir
+
+configfile: "config.yaml"
+
+INTEGERISATION="align"
+OUTPUTPATH = config["submatrices_dir"]
+dcj_threshold = config["dcj_dist_threshold"]
+old_dir = config["output_dir"]
+SUBCOMMUNITIESPATH = f"{old_dir}/dcj_thresh_{dcj_threshold}_graph/objects/typing.tsv"
+
+def get_subcomms(wildcards):
+ if not config["ignore_containment"]:
+ checkpoints.incomplete_submatrices.get(**wildcards).output[0]
+ subcomms = [os.path.basename(file).replace(".dist","") for file in glob.glob(f"{OUTPUTPATH}/dists/*")]
+ else:
+ subcommunities_list = pd.read_csv(SUBCOMMUNITIESPATH, sep='\t')["type"].to_list()
+ count = {subcommunity:subcommunities_list.count(subcommunity) for subcommunity in set(subcommunities_list)}
+ subcomms = [subcomm for subcomm in subcommunities_list if count[subcomm]>2]
+ return subcomms
+
+def get_regions():
+ if config.get("regions", False):
+ return "--regions"
+ else:
+ return ""
+
+def get_topology(topology):
+ if config["topology"]=="None":
+ return ""
+ else:
+ return f"--topology {topology}"
+
+def read_in_dists(filepath):
+ dists = {}
+ with open(filepath, "r") as f:
+ for line in f:
+ plasmid1, plasmid2, dist = line.strip("\n").split("\t")
+ dists[(plasmid1,plasmid2)] = int(dist)
+ dists[(plasmid2,plasmid1)] = int(dist)
+ return dists
+
+def get_final_outputs(wildcards):
+ if config["vis_trees"]:
+ return expand(f"{OUTPUTPATH}/vis/{{subcommunity}}.pdf", subcommunity=get_subcomms(wildcards))
+ else:
+ return expand(f"{OUTPUTPATH}/trees/{{subcommunity}}.tree", subcommunity=get_subcomms(wildcards))
+
+def get_input(wildcards):
+ checkpoints.incomplete_submatrices.get(subcommunity=wildcards.subcommunity).output[0]
+ return f"{OUTPUTPATH}/dists/{wildcards.subcommunity}.dist"
+
+rule all:
+ input:
+ get_final_outputs
+
+checkpoint incomplete_submatrices:
+ input:
+ subcom = SUBCOMMUNITIESPATH,
+ tsv = f"{old_dir}/all_plasmids_distances.tsv"
+ output:
+ outdir_1 = directory(f"{OUTPUTPATH}/incomplete"),
+ outdir_2 = directory(f"{OUTPUTPATH}/dists")
+ resources:
+ mem_mb = lambda wildcards, attempt: attempt * 1000
+ script:
+ "get_submatrices.py"
+
+rule missing_entries:
+ input:
+ incomplete_submatrix = lambda wildcards: f"{OUTPUTPATH}/incomplete/{wildcards.subcommunity}_incomplete.dist"
+ output:
+ missing_entries = f"{OUTPUTPATH}/missing/{{subcommunity}}_missing.txt"
+ resources:
+ mem_mb = lambda wildcards, attempt: attempt * 1000
+ run:
+ submatrix = pd.read_csv(input.incomplete_submatrix, sep="\t", index_col=0)
+ submatrix.columns = submatrix.index
+ missing_df = submatrix.isna()
+ with open(output.missing_entries, "w") as f:
+ for i in range(0, len(submatrix.index)):
+ plasmid1 = list(submatrix.index)[i]
+ for j in range(0,i):
+ if missing_df.iloc[i,j]==True:
+ plasmid2 = list(submatrix.columns)[j]
+ f.write(str([plasmid1,plasmid2])+"\n")
+
+rule make_unimogs:
+ input:
+ batch_list=lambda wildcards: f"{OUTPUTPATH}/missing/{wildcards.subcommunity}_missing.txt"
+ output:
+ containment=f"{OUTPUTPATH}/containment_missing/{{subcommunity}}_containment.tsv",
+ unimog = f"{OUTPUTPATH}/unimogs_missing/{{subcommunity}}_align.unimog",
+ map = f"{OUTPUTPATH}/unimogs_missing/{{subcommunity}}_map.txt"
+ threads: 1
+ resources:
+ mem_mb=lambda wildcards, attempt: 10000*attempt
+ params:
+ genomes_list = config["genomes_list"],
+ outputpath = OUTPUTPATH,
+ identity_threshold = 80,
+ containment_distance = 1,
+ pling_root_dir = get_pling_root_dir(),
+ regions = get_regions(),
+ topology = get_topology(config["topology"])
+ shadow: "shallow"
+ shell:
+ """
+ PYTHONPATH={params.pling_root_dir} python {params.pling_root_dir}/pling/align_snakemake/unimog.py \
+ --genomes_list {params.genomes_list} \
+ --batch {input.batch_list} \
+ --identity_threshold {params.identity_threshold} \
+ --containment_distance {params.containment_distance} \
+ --outputpath {params.outputpath} \
+ --containment_output {output.containment} \
+ --unimog_output {output.unimog} \
+ --map_output {output.map} \
+ {params.regions} \
+ {params.topology}
+ """
+
+rule ding:
+ input:
+ containment_tsv=f"{OUTPUTPATH}/containment_missing/{{subcommunity}}_containment.tsv",
+ unimog = f"{OUTPUTPATH}/unimogs_missing/{{subcommunity}}_align.unimog",
+ batch_list = lambda wildcards: f"{OUTPUTPATH}/missing/{wildcards.subcommunity}_missing.txt"
+ output:
+ f"{OUTPUTPATH}/dists_missing/{{subcommunity}}_dcj.tsv"
+ params:
+ containment_distance=1,
+ outputpath=OUTPUTPATH,
+ pling_root_dir = get_pling_root_dir(),
+ ilp_solver = config["ilp_solver"]
+ threads: 1
+ resources:
+ mem_mb = lambda wildcards, attempt: attempt * 16000
+ shadow: "shallow"
+ shell:
+ """
+ PYTHONPATH={params.pling_root_dir} python {params.pling_root_dir}/pling/dcj_snakemake/dcj.py \
+ --batch_file {input.batch_list} \
+ --batch 0 \
+ --containment_tsv {input.containment_tsv} \
+ --containment_distance {params.containment_distance} \
+ --outputpath {params.outputpath} \
+ --distpath {output} \
+ --communitypath NA \
+ --integerisation align \
+ --threads {threads} \
+ --snakefile_dir {params.pling_root_dir}/pling/dcj_snakemake \
+ --unimog {input.unimog} \
+ --ilp_solver {params.ilp_solver}
+ """
+
+rule dcj_submatrix:
+ input:
+ missing_dists = lambda wildcards: f"{OUTPUTPATH}/dists_missing/{wildcards.subcommunity}_dcj.tsv",
+ incomplete_submatrix = lambda wildcards: f"{OUTPUTPATH}/incomplete/{wildcards.subcommunity}_incomplete.dist"
+ output:
+ submatrix_tsv = f"{OUTPUTPATH}/dists/{{subcommunity}}.dist"
+ run:
+ submatrix = pd.read_csv(input.incomplete_submatrix, sep="\t", index_col=0)
+ submatrix.columns = submatrix.index
+ missing_dists = read_in_dists(input.missing_dists)
+ distances = submatrix.copy()
+ missing_df = submatrix.isna()
+ for i in range(0, len(submatrix.index)):
+ plasmid1 = list(submatrix.index)[i]
+ for j in range(0,i):
+ if missing_df.iloc[i,j]==True:
+ plasmid2 = list(submatrix.columns)[j]
+ distances.loc[plasmid1,plasmid2] = missing_dists[(plasmid1,plasmid2)]
+ distances.loc[plasmid2,plasmid1] = missing_dists[(plasmid1,plasmid2)]
+ new_row = pd.DataFrame({el:pd.NA for el in submatrix.columns}, index=[submatrix.index.name])
+ distances = pd.concat([new_row,distances.loc[:]])
+ distances.to_csv(output.submatrix_tsv, sep="\t", index=True, header=False)
+
+rule trees:
+ input:
+ get_input
+ output:
+ f"{OUTPUTPATH}/trees/{{subcommunity}}.tree"
+ resources:
+ mem_mb = lambda wildcards, attempt: attempt * 1000
+ shell:
+ "quicktree -in m {input} > {output}"
+
+
+rule vis:
+ input:
+ f"{OUTPUTPATH}/trees/{{subcommunity}}.tree"
+ output:
+ f"{OUTPUTPATH}/vis/{{subcommunity}}.pdf"
+ params:
+ pling_root_dir = get_pling_root_dir()
+ shell:
+ "PYTHONPATH={params.pling_root_dir} python {params.pling_root_dir}/pling/submatrix_snakemake/draw_trees.py {input} {output}"
\ No newline at end of file
diff --git a/pling/submatrix_snakemake/draw_trees.py b/pling/submatrix_snakemake/draw_trees.py
new file mode 100755
index 0000000..04b54b8
--- /dev/null
+++ b/pling/submatrix_snakemake/draw_trees.py
@@ -0,0 +1,36 @@
+from ete3 import Tree, TreeStyle, NodeStyle
+import argparse
+import pandas as pd
+import numpy as np
+import math
+
+parser = argparse.ArgumentParser()
+parser.add_argument('input')
+parser.add_argument('output')
+args = parser.parse_args()
+
+filepath = args.input
+t = Tree(filepath, format=0, quoted_node_names=True)
+
+ts = TreeStyle()
+ts.show_leaf_name = True
+ts.scale = 250
+ts.branch_vertical_margin = 5
+
+for n in t.traverse():
+ if n.is_leaf():
+ nstyle = NodeStyle()
+ nstyle['shape'] = 'circle'
+ nstyle['size'] = 4
+ nstyle['fgcolor'] = '#ff0000'
+ nstyle['hz_line_width'] = 2
+ nstyle['vt_line_width'] = 2
+ n.set_style(nstyle)
+ else:
+ nstyle=NodeStyle()
+ nstyle['size']=0
+ nstyle['hz_line_width'] = 2
+ nstyle['vt_line_width'] = 2
+ n.set_style(nstyle)
+
+t.render(str(args.output), tree_style=ts)
diff --git a/pling/submatrix_snakemake/get_submatrices.py b/pling/submatrix_snakemake/get_submatrices.py
new file mode 100755
index 0000000..1f14b2b
--- /dev/null
+++ b/pling/submatrix_snakemake/get_submatrices.py
@@ -0,0 +1,41 @@
+import pandas as pd
+import logging
+from pathlib import Path
+
+SUBCOMMUNITIESPATH = snakemake.input.subcom
+outdir_1 = snakemake.output.outdir_1
+outdir_2 = snakemake.output.outdir_2
+Path(outdir_1).mkdir(parents=True, exist_ok=True)
+Path(outdir_2).mkdir(parents=True, exist_ok=True)
+subcommunities_df = pd.read_csv(SUBCOMMUNITIESPATH, sep='\t')
+subcommunities_list = list(subcommunities_df['type'])
+count = {subcommunity:subcommunities_list.count(subcommunity) for subcommunity in set(subcommunities_list)}
+dcj_tsv = snakemake.input.tsv
+dcj_dists = {}
+with open(dcj_tsv) as f:
+ next(f)
+ for line in f:
+ plasmid1, plasmid2, dist = line.strip().split("\t")
+ dcj_dists[(plasmid1,plasmid2)] = int(dist)
+ dcj_dists[(plasmid2,plasmid1)] = int(dist)
+submatrices = {}
+
+for subcommunity in count.keys():
+ if count[subcommunity]>2:
+ plasmids = list(subcommunities_df[subcommunities_df['type']==subcommunity]['plasmid'])
+ distances = pd.DataFrame(index = [len(plasmids)] + plasmids, columns = plasmids)
+ complete = True
+ for plasmid1 in plasmids:
+ for plasmid2 in plasmids:
+ if (plasmid1,plasmid2) in dcj_dists.keys():
+ distances.loc[plasmid1,plasmid2]=dcj_dists[(plasmid1,plasmid2)]
+ elif plasmid1 == plasmid2:
+ distances.loc[plasmid1,plasmid2]=0
+ else:
+ distances.loc[plasmid1,plasmid2]=pd.NA
+ logging.warning(f"Plasmid pair {plasmid1}, {plasmid2} does not meet containment threshold")
+ complete = False
+ if complete:
+ distances.to_csv(f"{outdir_2}/{subcommunity}.dist", sep="\t", header=False)
+ else:
+ distances.to_csv(f"{outdir_1}/{subcommunity}_incomplete.dist", sep="\t", header=False)
diff --git a/pyproject.toml b/pyproject.toml
index ac55d5c..8d21d7e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "pling"
-version = "2.0.2"
+version = "3.0.0"
description = "Pling computes the rearrangement distance between plasmids"
authors = [{name = "Daria Frolova", email = "daria@ebi.ac.uk"}, {name = "Leandro Lima", email = "leandro@ebi.ac.uk"}]
license = {text = "MIT"}
diff --git a/tests/integration_test/test_integration_test.py b/tests/integration_test/test_integration_test.py
index 004084c..18a1e7a 100644
--- a/tests/integration_test/test_integration_test.py
+++ b/tests/integration_test/test_integration_test.py
@@ -2,7 +2,7 @@
from unittest import TestCase
from pling import run_pling
from tests.utils import *
-
+from click.testing import CliRunner
class Test_Pling_end_to_end(TestCase):
def read_file(self, path):
@@ -16,34 +16,23 @@ def assert_files_are_identical(self, path_to_first_file, path_to_second_file):
self.assertEqual(first_file_content, second_file_content)
def test_pling_align_end_to_end(self):
- args = Namespace(
- genomes_list='tests/integration_test/data/incy_list_4.txt',
- output_dir='tests/integration_test/data/out_align',
- integerisation='align',
- unimog=None,
- containment_distance=0.6,
- dcj=4,
- identity=80,
- min_indel_size=200,
- bh_connectivity=10,
- bh_neighbours_edge_density=0.2,
- small_subcommunity_size_threshold=4,
- plasmid_metadata=None,
- cores=2,
- storetmp=False,
- forceall=True,
- ilp_solver="GLPK",
- timelimit=None,
- resources=None,
- profile=None,
- batch_size=50,
- sourmash=False,
- sourmash_threshold=0.85,
- topology=None,
- regions=False,
- output_type="html"
+ runner = CliRunner()
+
+ result = runner.invoke(
+ run_pling.cli,
+ [
+ "cluster", "align",
+ "tests/integration_test/data/incy_list_4.txt",
+ "tests/integration_test/data/out_align",
+ "--containment_distance", "0.6",
+ "--dcj", "4",
+ "--cores", "2",
+ "--forceall",
+ "--batch_size", "50"
+ ],
)
- run_pling.pling(args)
+
+ assert result.exit_code == 0, result.output
assert_files_are_identical(
"tests/integration_test/data/out_align/all_plasmids_distances.tsv",
diff --git a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/batches/.snakemake_timestamp b/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/batches/.snakemake_timestamp
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/.snakemake_timestamp b/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/.snakemake_timestamp
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/graphs/community_0.html b/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/graphs/community_0.html
deleted file mode 100644
index e089cd6..0000000
--- a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/graphs/community_0.html
+++ /dev/null
@@ -1,297 +0,0 @@
-
-
-
-
-
- Roundhound visualisation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Legend
-
Node colours:
-
Each different colour represents a different plasmid community.
-
Due to the lack of enough colours, different plasmid communities will sometimes have same colours.
-
But hopefully they won't be connected, so we can infer they are still different communities.
-
Node shapes:
-
● Normal plasmids
-
★ Hub plasmids
-
-
-
- Filters:
- Hide hub plasmids (0 present)
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/index.html b/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/index.html
deleted file mode 100644
index 2888b31..0000000
--- a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/index.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
- Communities visualisation
-
-
-
-
-Communities visualisation
-
-View community_0 (11 nodes, 55 edges)
-
-
-
-
diff --git a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/bluebird.js b/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/bluebird.js
deleted file mode 100644
index 0b823f7..0000000
--- a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/bluebird.js
+++ /dev/null
@@ -1,5619 +0,0 @@
-/* @preserve
- * The MIT License (MIT)
- *
- * Copyright (c) 2013-2017 Petka Antonov
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-/**
- * bluebird build version 3.5.0
- * Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, using, timers, filter, any, each
-*/
-!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Promise=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof _dereq_=="function"&&_dereq_;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof _dereq_=="function"&&_dereq_;for(var o=0;o 0) {
- var fn = queue.shift();
- if (typeof fn !== "function") {
- fn._settlePromises();
- continue;
- }
- var receiver = queue.shift();
- var arg = queue.shift();
- fn.call(receiver, arg);
- }
-};
-
-Async.prototype._drainQueues = function () {
- this._drainQueue(this._normalQueue);
- this._reset();
- this._haveDrainedQueues = true;
- this._drainQueue(this._lateQueue);
-};
-
-Async.prototype._queueTick = function () {
- if (!this._isTickUsed) {
- this._isTickUsed = true;
- this._schedule(this.drainQueues);
- }
-};
-
-Async.prototype._reset = function () {
- this._isTickUsed = false;
-};
-
-module.exports = Async;
-module.exports.firstLineError = firstLineError;
-
-},{"./queue":26,"./schedule":29,"./util":36}],3:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise, INTERNAL, tryConvertToPromise, debug) {
-var calledBind = false;
-var rejectThis = function(_, e) {
- this._reject(e);
-};
-
-var targetRejected = function(e, context) {
- context.promiseRejectionQueued = true;
- context.bindingPromise._then(rejectThis, rejectThis, null, this, e);
-};
-
-var bindingResolved = function(thisArg, context) {
- if (((this._bitField & 50397184) === 0)) {
- this._resolveCallback(context.target);
- }
-};
-
-var bindingRejected = function(e, context) {
- if (!context.promiseRejectionQueued) this._reject(e);
-};
-
-Promise.prototype.bind = function (thisArg) {
- if (!calledBind) {
- calledBind = true;
- Promise.prototype._propagateFrom = debug.propagateFromFunction();
- Promise.prototype._boundValue = debug.boundValueFunction();
- }
- var maybePromise = tryConvertToPromise(thisArg);
- var ret = new Promise(INTERNAL);
- ret._propagateFrom(this, 1);
- var target = this._target();
- ret._setBoundTo(maybePromise);
- if (maybePromise instanceof Promise) {
- var context = {
- promiseRejectionQueued: false,
- promise: ret,
- target: target,
- bindingPromise: maybePromise
- };
- target._then(INTERNAL, targetRejected, undefined, ret, context);
- maybePromise._then(
- bindingResolved, bindingRejected, undefined, ret, context);
- ret._setOnCancel(maybePromise);
- } else {
- ret._resolveCallback(target);
- }
- return ret;
-};
-
-Promise.prototype._setBoundTo = function (obj) {
- if (obj !== undefined) {
- this._bitField = this._bitField | 2097152;
- this._boundTo = obj;
- } else {
- this._bitField = this._bitField & (~2097152);
- }
-};
-
-Promise.prototype._isBound = function () {
- return (this._bitField & 2097152) === 2097152;
-};
-
-Promise.bind = function (thisArg, value) {
- return Promise.resolve(value).bind(thisArg);
-};
-};
-
-},{}],4:[function(_dereq_,module,exports){
-"use strict";
-var old;
-if (typeof Promise !== "undefined") old = Promise;
-function noConflict() {
- try { if (Promise === bluebird) Promise = old; }
- catch (e) {}
- return bluebird;
-}
-var bluebird = _dereq_("./promise")();
-bluebird.noConflict = noConflict;
-module.exports = bluebird;
-
-},{"./promise":22}],5:[function(_dereq_,module,exports){
-"use strict";
-var cr = Object.create;
-if (cr) {
- var callerCache = cr(null);
- var getterCache = cr(null);
- callerCache[" size"] = getterCache[" size"] = 0;
-}
-
-module.exports = function(Promise) {
-var util = _dereq_("./util");
-var canEvaluate = util.canEvaluate;
-var isIdentifier = util.isIdentifier;
-
-var getMethodCaller;
-var getGetter;
-if (!true) {
-var makeMethodCaller = function (methodName) {
- return new Function("ensureMethod", " \n\
- return function(obj) { \n\
- 'use strict' \n\
- var len = this.length; \n\
- ensureMethod(obj, 'methodName'); \n\
- switch(len) { \n\
- case 1: return obj.methodName(this[0]); \n\
- case 2: return obj.methodName(this[0], this[1]); \n\
- case 3: return obj.methodName(this[0], this[1], this[2]); \n\
- case 0: return obj.methodName(); \n\
- default: \n\
- return obj.methodName.apply(obj, this); \n\
- } \n\
- }; \n\
- ".replace(/methodName/g, methodName))(ensureMethod);
-};
-
-var makeGetter = function (propertyName) {
- return new Function("obj", " \n\
- 'use strict'; \n\
- return obj.propertyName; \n\
- ".replace("propertyName", propertyName));
-};
-
-var getCompiled = function(name, compiler, cache) {
- var ret = cache[name];
- if (typeof ret !== "function") {
- if (!isIdentifier(name)) {
- return null;
- }
- ret = compiler(name);
- cache[name] = ret;
- cache[" size"]++;
- if (cache[" size"] > 512) {
- var keys = Object.keys(cache);
- for (var i = 0; i < 256; ++i) delete cache[keys[i]];
- cache[" size"] = keys.length - 256;
- }
- }
- return ret;
-};
-
-getMethodCaller = function(name) {
- return getCompiled(name, makeMethodCaller, callerCache);
-};
-
-getGetter = function(name) {
- return getCompiled(name, makeGetter, getterCache);
-};
-}
-
-function ensureMethod(obj, methodName) {
- var fn;
- if (obj != null) fn = obj[methodName];
- if (typeof fn !== "function") {
- var message = "Object " + util.classString(obj) + " has no method '" +
- util.toString(methodName) + "'";
- throw new Promise.TypeError(message);
- }
- return fn;
-}
-
-function caller(obj) {
- var methodName = this.pop();
- var fn = ensureMethod(obj, methodName);
- return fn.apply(obj, this);
-}
-Promise.prototype.call = function (methodName) {
- var args = [].slice.call(arguments, 1);;
- if (!true) {
- if (canEvaluate) {
- var maybeCaller = getMethodCaller(methodName);
- if (maybeCaller !== null) {
- return this._then(
- maybeCaller, undefined, undefined, args, undefined);
- }
- }
- }
- args.push(methodName);
- return this._then(caller, undefined, undefined, args, undefined);
-};
-
-function namedGetter(obj) {
- return obj[this];
-}
-function indexedGetter(obj) {
- var index = +this;
- if (index < 0) index = Math.max(0, index + obj.length);
- return obj[index];
-}
-Promise.prototype.get = function (propertyName) {
- var isIndex = (typeof propertyName === "number");
- var getter;
- if (!isIndex) {
- if (canEvaluate) {
- var maybeGetter = getGetter(propertyName);
- getter = maybeGetter !== null ? maybeGetter : namedGetter;
- } else {
- getter = namedGetter;
- }
- } else {
- getter = indexedGetter;
- }
- return this._then(getter, undefined, undefined, propertyName, undefined);
-};
-};
-
-},{"./util":36}],6:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise, PromiseArray, apiRejection, debug) {
-var util = _dereq_("./util");
-var tryCatch = util.tryCatch;
-var errorObj = util.errorObj;
-var async = Promise._async;
-
-Promise.prototype["break"] = Promise.prototype.cancel = function() {
- if (!debug.cancellation()) return this._warn("cancellation is disabled");
-
- var promise = this;
- var child = promise;
- while (promise._isCancellable()) {
- if (!promise._cancelBy(child)) {
- if (child._isFollowing()) {
- child._followee().cancel();
- } else {
- child._cancelBranched();
- }
- break;
- }
-
- var parent = promise._cancellationParent;
- if (parent == null || !parent._isCancellable()) {
- if (promise._isFollowing()) {
- promise._followee().cancel();
- } else {
- promise._cancelBranched();
- }
- break;
- } else {
- if (promise._isFollowing()) promise._followee().cancel();
- promise._setWillBeCancelled();
- child = promise;
- promise = parent;
- }
- }
-};
-
-Promise.prototype._branchHasCancelled = function() {
- this._branchesRemainingToCancel--;
-};
-
-Promise.prototype._enoughBranchesHaveCancelled = function() {
- return this._branchesRemainingToCancel === undefined ||
- this._branchesRemainingToCancel <= 0;
-};
-
-Promise.prototype._cancelBy = function(canceller) {
- if (canceller === this) {
- this._branchesRemainingToCancel = 0;
- this._invokeOnCancel();
- return true;
- } else {
- this._branchHasCancelled();
- if (this._enoughBranchesHaveCancelled()) {
- this._invokeOnCancel();
- return true;
- }
- }
- return false;
-};
-
-Promise.prototype._cancelBranched = function() {
- if (this._enoughBranchesHaveCancelled()) {
- this._cancel();
- }
-};
-
-Promise.prototype._cancel = function() {
- if (!this._isCancellable()) return;
- this._setCancelled();
- async.invoke(this._cancelPromises, this, undefined);
-};
-
-Promise.prototype._cancelPromises = function() {
- if (this._length() > 0) this._settlePromises();
-};
-
-Promise.prototype._unsetOnCancel = function() {
- this._onCancelField = undefined;
-};
-
-Promise.prototype._isCancellable = function() {
- return this.isPending() && !this._isCancelled();
-};
-
-Promise.prototype.isCancellable = function() {
- return this.isPending() && !this.isCancelled();
-};
-
-Promise.prototype._doInvokeOnCancel = function(onCancelCallback, internalOnly) {
- if (util.isArray(onCancelCallback)) {
- for (var i = 0; i < onCancelCallback.length; ++i) {
- this._doInvokeOnCancel(onCancelCallback[i], internalOnly);
- }
- } else if (onCancelCallback !== undefined) {
- if (typeof onCancelCallback === "function") {
- if (!internalOnly) {
- var e = tryCatch(onCancelCallback).call(this._boundValue());
- if (e === errorObj) {
- this._attachExtraTrace(e.e);
- async.throwLater(e.e);
- }
- }
- } else {
- onCancelCallback._resultCancelled(this);
- }
- }
-};
-
-Promise.prototype._invokeOnCancel = function() {
- var onCancelCallback = this._onCancel();
- this._unsetOnCancel();
- async.invoke(this._doInvokeOnCancel, this, onCancelCallback);
-};
-
-Promise.prototype._invokeInternalOnCancel = function() {
- if (this._isCancellable()) {
- this._doInvokeOnCancel(this._onCancel(), true);
- this._unsetOnCancel();
- }
-};
-
-Promise.prototype._resultCancelled = function() {
- this.cancel();
-};
-
-};
-
-},{"./util":36}],7:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(NEXT_FILTER) {
-var util = _dereq_("./util");
-var getKeys = _dereq_("./es5").keys;
-var tryCatch = util.tryCatch;
-var errorObj = util.errorObj;
-
-function catchFilter(instances, cb, promise) {
- return function(e) {
- var boundTo = promise._boundValue();
- predicateLoop: for (var i = 0; i < instances.length; ++i) {
- var item = instances[i];
-
- if (item === Error ||
- (item != null && item.prototype instanceof Error)) {
- if (e instanceof item) {
- return tryCatch(cb).call(boundTo, e);
- }
- } else if (typeof item === "function") {
- var matchesPredicate = tryCatch(item).call(boundTo, e);
- if (matchesPredicate === errorObj) {
- return matchesPredicate;
- } else if (matchesPredicate) {
- return tryCatch(cb).call(boundTo, e);
- }
- } else if (util.isObject(e)) {
- var keys = getKeys(item);
- for (var j = 0; j < keys.length; ++j) {
- var key = keys[j];
- if (item[key] != e[key]) {
- continue predicateLoop;
- }
- }
- return tryCatch(cb).call(boundTo, e);
- }
- }
- return NEXT_FILTER;
- };
-}
-
-return catchFilter;
-};
-
-},{"./es5":13,"./util":36}],8:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise) {
-var longStackTraces = false;
-var contextStack = [];
-
-Promise.prototype._promiseCreated = function() {};
-Promise.prototype._pushContext = function() {};
-Promise.prototype._popContext = function() {return null;};
-Promise._peekContext = Promise.prototype._peekContext = function() {};
-
-function Context() {
- this._trace = new Context.CapturedTrace(peekContext());
-}
-Context.prototype._pushContext = function () {
- if (this._trace !== undefined) {
- this._trace._promiseCreated = null;
- contextStack.push(this._trace);
- }
-};
-
-Context.prototype._popContext = function () {
- if (this._trace !== undefined) {
- var trace = contextStack.pop();
- var ret = trace._promiseCreated;
- trace._promiseCreated = null;
- return ret;
- }
- return null;
-};
-
-function createContext() {
- if (longStackTraces) return new Context();
-}
-
-function peekContext() {
- var lastIndex = contextStack.length - 1;
- if (lastIndex >= 0) {
- return contextStack[lastIndex];
- }
- return undefined;
-}
-Context.CapturedTrace = null;
-Context.create = createContext;
-Context.deactivateLongStackTraces = function() {};
-Context.activateLongStackTraces = function() {
- var Promise_pushContext = Promise.prototype._pushContext;
- var Promise_popContext = Promise.prototype._popContext;
- var Promise_PeekContext = Promise._peekContext;
- var Promise_peekContext = Promise.prototype._peekContext;
- var Promise_promiseCreated = Promise.prototype._promiseCreated;
- Context.deactivateLongStackTraces = function() {
- Promise.prototype._pushContext = Promise_pushContext;
- Promise.prototype._popContext = Promise_popContext;
- Promise._peekContext = Promise_PeekContext;
- Promise.prototype._peekContext = Promise_peekContext;
- Promise.prototype._promiseCreated = Promise_promiseCreated;
- longStackTraces = false;
- };
- longStackTraces = true;
- Promise.prototype._pushContext = Context.prototype._pushContext;
- Promise.prototype._popContext = Context.prototype._popContext;
- Promise._peekContext = Promise.prototype._peekContext = peekContext;
- Promise.prototype._promiseCreated = function() {
- var ctx = this._peekContext();
- if (ctx && ctx._promiseCreated == null) ctx._promiseCreated = this;
- };
-};
-return Context;
-};
-
-},{}],9:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise, Context) {
-var getDomain = Promise._getDomain;
-var async = Promise._async;
-var Warning = _dereq_("./errors").Warning;
-var util = _dereq_("./util");
-var canAttachTrace = util.canAttachTrace;
-var unhandledRejectionHandled;
-var possiblyUnhandledRejection;
-var bluebirdFramePattern =
- /[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/;
-var nodeFramePattern = /\((?:timers\.js):\d+:\d+\)/;
-var parseLinePattern = /[\/<\(](.+?):(\d+):(\d+)\)?\s*$/;
-var stackFramePattern = null;
-var formatStack = null;
-var indentStackFrames = false;
-var printWarning;
-var debugging = !!(util.env("BLUEBIRD_DEBUG") != 0 &&
- (true ||
- util.env("BLUEBIRD_DEBUG") ||
- util.env("NODE_ENV") === "development"));
-
-var warnings = !!(util.env("BLUEBIRD_WARNINGS") != 0 &&
- (debugging || util.env("BLUEBIRD_WARNINGS")));
-
-var longStackTraces = !!(util.env("BLUEBIRD_LONG_STACK_TRACES") != 0 &&
- (debugging || util.env("BLUEBIRD_LONG_STACK_TRACES")));
-
-var wForgottenReturn = util.env("BLUEBIRD_W_FORGOTTEN_RETURN") != 0 &&
- (warnings || !!util.env("BLUEBIRD_W_FORGOTTEN_RETURN"));
-
-Promise.prototype.suppressUnhandledRejections = function() {
- var target = this._target();
- target._bitField = ((target._bitField & (~1048576)) |
- 524288);
-};
-
-Promise.prototype._ensurePossibleRejectionHandled = function () {
- if ((this._bitField & 524288) !== 0) return;
- this._setRejectionIsUnhandled();
- async.invokeLater(this._notifyUnhandledRejection, this, undefined);
-};
-
-Promise.prototype._notifyUnhandledRejectionIsHandled = function () {
- fireRejectionEvent("rejectionHandled",
- unhandledRejectionHandled, undefined, this);
-};
-
-Promise.prototype._setReturnedNonUndefined = function() {
- this._bitField = this._bitField | 268435456;
-};
-
-Promise.prototype._returnedNonUndefined = function() {
- return (this._bitField & 268435456) !== 0;
-};
-
-Promise.prototype._notifyUnhandledRejection = function () {
- if (this._isRejectionUnhandled()) {
- var reason = this._settledValue();
- this._setUnhandledRejectionIsNotified();
- fireRejectionEvent("unhandledRejection",
- possiblyUnhandledRejection, reason, this);
- }
-};
-
-Promise.prototype._setUnhandledRejectionIsNotified = function () {
- this._bitField = this._bitField | 262144;
-};
-
-Promise.prototype._unsetUnhandledRejectionIsNotified = function () {
- this._bitField = this._bitField & (~262144);
-};
-
-Promise.prototype._isUnhandledRejectionNotified = function () {
- return (this._bitField & 262144) > 0;
-};
-
-Promise.prototype._setRejectionIsUnhandled = function () {
- this._bitField = this._bitField | 1048576;
-};
-
-Promise.prototype._unsetRejectionIsUnhandled = function () {
- this._bitField = this._bitField & (~1048576);
- if (this._isUnhandledRejectionNotified()) {
- this._unsetUnhandledRejectionIsNotified();
- this._notifyUnhandledRejectionIsHandled();
- }
-};
-
-Promise.prototype._isRejectionUnhandled = function () {
- return (this._bitField & 1048576) > 0;
-};
-
-Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) {
- return warn(message, shouldUseOwnTrace, promise || this);
-};
-
-Promise.onPossiblyUnhandledRejection = function (fn) {
- var domain = getDomain();
- possiblyUnhandledRejection =
- typeof fn === "function" ? (domain === null ?
- fn : util.domainBind(domain, fn))
- : undefined;
-};
-
-Promise.onUnhandledRejectionHandled = function (fn) {
- var domain = getDomain();
- unhandledRejectionHandled =
- typeof fn === "function" ? (domain === null ?
- fn : util.domainBind(domain, fn))
- : undefined;
-};
-
-var disableLongStackTraces = function() {};
-Promise.longStackTraces = function () {
- if (async.haveItemsQueued() && !config.longStackTraces) {
- throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a");
- }
- if (!config.longStackTraces && longStackTracesIsSupported()) {
- var Promise_captureStackTrace = Promise.prototype._captureStackTrace;
- var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace;
- config.longStackTraces = true;
- disableLongStackTraces = function() {
- if (async.haveItemsQueued() && !config.longStackTraces) {
- throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a");
- }
- Promise.prototype._captureStackTrace = Promise_captureStackTrace;
- Promise.prototype._attachExtraTrace = Promise_attachExtraTrace;
- Context.deactivateLongStackTraces();
- async.enableTrampoline();
- config.longStackTraces = false;
- };
- Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace;
- Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace;
- Context.activateLongStackTraces();
- async.disableTrampolineIfNecessary();
- }
-};
-
-Promise.hasLongStackTraces = function () {
- return config.longStackTraces && longStackTracesIsSupported();
-};
-
-var fireDomEvent = (function() {
- try {
- if (typeof CustomEvent === "function") {
- var event = new CustomEvent("CustomEvent");
- util.global.dispatchEvent(event);
- return function(name, event) {
- var domEvent = new CustomEvent(name.toLowerCase(), {
- detail: event,
- cancelable: true
- });
- return !util.global.dispatchEvent(domEvent);
- };
- } else if (typeof Event === "function") {
- var event = new Event("CustomEvent");
- util.global.dispatchEvent(event);
- return function(name, event) {
- var domEvent = new Event(name.toLowerCase(), {
- cancelable: true
- });
- domEvent.detail = event;
- return !util.global.dispatchEvent(domEvent);
- };
- } else {
- var event = document.createEvent("CustomEvent");
- event.initCustomEvent("testingtheevent", false, true, {});
- util.global.dispatchEvent(event);
- return function(name, event) {
- var domEvent = document.createEvent("CustomEvent");
- domEvent.initCustomEvent(name.toLowerCase(), false, true,
- event);
- return !util.global.dispatchEvent(domEvent);
- };
- }
- } catch (e) {}
- return function() {
- return false;
- };
-})();
-
-var fireGlobalEvent = (function() {
- if (util.isNode) {
- return function() {
- return process.emit.apply(process, arguments);
- };
- } else {
- if (!util.global) {
- return function() {
- return false;
- };
- }
- return function(name) {
- var methodName = "on" + name.toLowerCase();
- var method = util.global[methodName];
- if (!method) return false;
- method.apply(util.global, [].slice.call(arguments, 1));
- return true;
- };
- }
-})();
-
-function generatePromiseLifecycleEventObject(name, promise) {
- return {promise: promise};
-}
-
-var eventToObjectGenerator = {
- promiseCreated: generatePromiseLifecycleEventObject,
- promiseFulfilled: generatePromiseLifecycleEventObject,
- promiseRejected: generatePromiseLifecycleEventObject,
- promiseResolved: generatePromiseLifecycleEventObject,
- promiseCancelled: generatePromiseLifecycleEventObject,
- promiseChained: function(name, promise, child) {
- return {promise: promise, child: child};
- },
- warning: function(name, warning) {
- return {warning: warning};
- },
- unhandledRejection: function (name, reason, promise) {
- return {reason: reason, promise: promise};
- },
- rejectionHandled: generatePromiseLifecycleEventObject
-};
-
-var activeFireEvent = function (name) {
- var globalEventFired = false;
- try {
- globalEventFired = fireGlobalEvent.apply(null, arguments);
- } catch (e) {
- async.throwLater(e);
- globalEventFired = true;
- }
-
- var domEventFired = false;
- try {
- domEventFired = fireDomEvent(name,
- eventToObjectGenerator[name].apply(null, arguments));
- } catch (e) {
- async.throwLater(e);
- domEventFired = true;
- }
-
- return domEventFired || globalEventFired;
-};
-
-Promise.config = function(opts) {
- opts = Object(opts);
- if ("longStackTraces" in opts) {
- if (opts.longStackTraces) {
- Promise.longStackTraces();
- } else if (!opts.longStackTraces && Promise.hasLongStackTraces()) {
- disableLongStackTraces();
- }
- }
- if ("warnings" in opts) {
- var warningsOption = opts.warnings;
- config.warnings = !!warningsOption;
- wForgottenReturn = config.warnings;
-
- if (util.isObject(warningsOption)) {
- if ("wForgottenReturn" in warningsOption) {
- wForgottenReturn = !!warningsOption.wForgottenReturn;
- }
- }
- }
- if ("cancellation" in opts && opts.cancellation && !config.cancellation) {
- if (async.haveItemsQueued()) {
- throw new Error(
- "cannot enable cancellation after promises are in use");
- }
- Promise.prototype._clearCancellationData =
- cancellationClearCancellationData;
- Promise.prototype._propagateFrom = cancellationPropagateFrom;
- Promise.prototype._onCancel = cancellationOnCancel;
- Promise.prototype._setOnCancel = cancellationSetOnCancel;
- Promise.prototype._attachCancellationCallback =
- cancellationAttachCancellationCallback;
- Promise.prototype._execute = cancellationExecute;
- propagateFromFunction = cancellationPropagateFrom;
- config.cancellation = true;
- }
- if ("monitoring" in opts) {
- if (opts.monitoring && !config.monitoring) {
- config.monitoring = true;
- Promise.prototype._fireEvent = activeFireEvent;
- } else if (!opts.monitoring && config.monitoring) {
- config.monitoring = false;
- Promise.prototype._fireEvent = defaultFireEvent;
- }
- }
- return Promise;
-};
-
-function defaultFireEvent() { return false; }
-
-Promise.prototype._fireEvent = defaultFireEvent;
-Promise.prototype._execute = function(executor, resolve, reject) {
- try {
- executor(resolve, reject);
- } catch (e) {
- return e;
- }
-};
-Promise.prototype._onCancel = function () {};
-Promise.prototype._setOnCancel = function (handler) { ; };
-Promise.prototype._attachCancellationCallback = function(onCancel) {
- ;
-};
-Promise.prototype._captureStackTrace = function () {};
-Promise.prototype._attachExtraTrace = function () {};
-Promise.prototype._clearCancellationData = function() {};
-Promise.prototype._propagateFrom = function (parent, flags) {
- ;
- ;
-};
-
-function cancellationExecute(executor, resolve, reject) {
- var promise = this;
- try {
- executor(resolve, reject, function(onCancel) {
- if (typeof onCancel !== "function") {
- throw new TypeError("onCancel must be a function, got: " +
- util.toString(onCancel));
- }
- promise._attachCancellationCallback(onCancel);
- });
- } catch (e) {
- return e;
- }
-}
-
-function cancellationAttachCancellationCallback(onCancel) {
- if (!this._isCancellable()) return this;
-
- var previousOnCancel = this._onCancel();
- if (previousOnCancel !== undefined) {
- if (util.isArray(previousOnCancel)) {
- previousOnCancel.push(onCancel);
- } else {
- this._setOnCancel([previousOnCancel, onCancel]);
- }
- } else {
- this._setOnCancel(onCancel);
- }
-}
-
-function cancellationOnCancel() {
- return this._onCancelField;
-}
-
-function cancellationSetOnCancel(onCancel) {
- this._onCancelField = onCancel;
-}
-
-function cancellationClearCancellationData() {
- this._cancellationParent = undefined;
- this._onCancelField = undefined;
-}
-
-function cancellationPropagateFrom(parent, flags) {
- if ((flags & 1) !== 0) {
- this._cancellationParent = parent;
- var branchesRemainingToCancel = parent._branchesRemainingToCancel;
- if (branchesRemainingToCancel === undefined) {
- branchesRemainingToCancel = 0;
- }
- parent._branchesRemainingToCancel = branchesRemainingToCancel + 1;
- }
- if ((flags & 2) !== 0 && parent._isBound()) {
- this._setBoundTo(parent._boundTo);
- }
-}
-
-function bindingPropagateFrom(parent, flags) {
- if ((flags & 2) !== 0 && parent._isBound()) {
- this._setBoundTo(parent._boundTo);
- }
-}
-var propagateFromFunction = bindingPropagateFrom;
-
-function boundValueFunction() {
- var ret = this._boundTo;
- if (ret !== undefined) {
- if (ret instanceof Promise) {
- if (ret.isFulfilled()) {
- return ret.value();
- } else {
- return undefined;
- }
- }
- }
- return ret;
-}
-
-function longStackTracesCaptureStackTrace() {
- this._trace = new CapturedTrace(this._peekContext());
-}
-
-function longStackTracesAttachExtraTrace(error, ignoreSelf) {
- if (canAttachTrace(error)) {
- var trace = this._trace;
- if (trace !== undefined) {
- if (ignoreSelf) trace = trace._parent;
- }
- if (trace !== undefined) {
- trace.attachExtraTrace(error);
- } else if (!error.__stackCleaned__) {
- var parsed = parseStackAndMessage(error);
- util.notEnumerableProp(error, "stack",
- parsed.message + "\n" + parsed.stack.join("\n"));
- util.notEnumerableProp(error, "__stackCleaned__", true);
- }
- }
-}
-
-function checkForgottenReturns(returnValue, promiseCreated, name, promise,
- parent) {
- if (returnValue === undefined && promiseCreated !== null &&
- wForgottenReturn) {
- if (parent !== undefined && parent._returnedNonUndefined()) return;
- if ((promise._bitField & 65535) === 0) return;
-
- if (name) name = name + " ";
- var handlerLine = "";
- var creatorLine = "";
- if (promiseCreated._trace) {
- var traceLines = promiseCreated._trace.stack.split("\n");
- var stack = cleanStack(traceLines);
- for (var i = stack.length - 1; i >= 0; --i) {
- var line = stack[i];
- if (!nodeFramePattern.test(line)) {
- var lineMatches = line.match(parseLinePattern);
- if (lineMatches) {
- handlerLine = "at " + lineMatches[1] +
- ":" + lineMatches[2] + ":" + lineMatches[3] + " ";
- }
- break;
- }
- }
-
- if (stack.length > 0) {
- var firstUserLine = stack[0];
- for (var i = 0; i < traceLines.length; ++i) {
-
- if (traceLines[i] === firstUserLine) {
- if (i > 0) {
- creatorLine = "\n" + traceLines[i - 1];
- }
- break;
- }
- }
-
- }
- }
- var msg = "a promise was created in a " + name +
- "handler " + handlerLine + "but was not returned from it, " +
- "see http://goo.gl/rRqMUw" +
- creatorLine;
- promise._warn(msg, true, promiseCreated);
- }
-}
-
-function deprecated(name, replacement) {
- var message = name +
- " is deprecated and will be removed in a future version.";
- if (replacement) message += " Use " + replacement + " instead.";
- return warn(message);
-}
-
-function warn(message, shouldUseOwnTrace, promise) {
- if (!config.warnings) return;
- var warning = new Warning(message);
- var ctx;
- if (shouldUseOwnTrace) {
- promise._attachExtraTrace(warning);
- } else if (config.longStackTraces && (ctx = Promise._peekContext())) {
- ctx.attachExtraTrace(warning);
- } else {
- var parsed = parseStackAndMessage(warning);
- warning.stack = parsed.message + "\n" + parsed.stack.join("\n");
- }
-
- if (!activeFireEvent("warning", warning)) {
- formatAndLogError(warning, "", true);
- }
-}
-
-function reconstructStack(message, stacks) {
- for (var i = 0; i < stacks.length - 1; ++i) {
- stacks[i].push("From previous event:");
- stacks[i] = stacks[i].join("\n");
- }
- if (i < stacks.length) {
- stacks[i] = stacks[i].join("\n");
- }
- return message + "\n" + stacks.join("\n");
-}
-
-function removeDuplicateOrEmptyJumps(stacks) {
- for (var i = 0; i < stacks.length; ++i) {
- if (stacks[i].length === 0 ||
- ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) {
- stacks.splice(i, 1);
- i--;
- }
- }
-}
-
-function removeCommonRoots(stacks) {
- var current = stacks[0];
- for (var i = 1; i < stacks.length; ++i) {
- var prev = stacks[i];
- var currentLastIndex = current.length - 1;
- var currentLastLine = current[currentLastIndex];
- var commonRootMeetPoint = -1;
-
- for (var j = prev.length - 1; j >= 0; --j) {
- if (prev[j] === currentLastLine) {
- commonRootMeetPoint = j;
- break;
- }
- }
-
- for (var j = commonRootMeetPoint; j >= 0; --j) {
- var line = prev[j];
- if (current[currentLastIndex] === line) {
- current.pop();
- currentLastIndex--;
- } else {
- break;
- }
- }
- current = prev;
- }
-}
-
-function cleanStack(stack) {
- var ret = [];
- for (var i = 0; i < stack.length; ++i) {
- var line = stack[i];
- var isTraceLine = " (No stack trace)" === line ||
- stackFramePattern.test(line);
- var isInternalFrame = isTraceLine && shouldIgnore(line);
- if (isTraceLine && !isInternalFrame) {
- if (indentStackFrames && line.charAt(0) !== " ") {
- line = " " + line;
- }
- ret.push(line);
- }
- }
- return ret;
-}
-
-function stackFramesAsArray(error) {
- var stack = error.stack.replace(/\s+$/g, "").split("\n");
- for (var i = 0; i < stack.length; ++i) {
- var line = stack[i];
- if (" (No stack trace)" === line || stackFramePattern.test(line)) {
- break;
- }
- }
- if (i > 0 && error.name != "SyntaxError") {
- stack = stack.slice(i);
- }
- return stack;
-}
-
-function parseStackAndMessage(error) {
- var stack = error.stack;
- var message = error.toString();
- stack = typeof stack === "string" && stack.length > 0
- ? stackFramesAsArray(error) : [" (No stack trace)"];
- return {
- message: message,
- stack: error.name == "SyntaxError" ? stack : cleanStack(stack)
- };
-}
-
-function formatAndLogError(error, title, isSoft) {
- if (typeof console !== "undefined") {
- var message;
- if (util.isObject(error)) {
- var stack = error.stack;
- message = title + formatStack(stack, error);
- } else {
- message = title + String(error);
- }
- if (typeof printWarning === "function") {
- printWarning(message, isSoft);
- } else if (typeof console.log === "function" ||
- typeof console.log === "object") {
- console.log(message);
- }
- }
-}
-
-function fireRejectionEvent(name, localHandler, reason, promise) {
- var localEventFired = false;
- try {
- if (typeof localHandler === "function") {
- localEventFired = true;
- if (name === "rejectionHandled") {
- localHandler(promise);
- } else {
- localHandler(reason, promise);
- }
- }
- } catch (e) {
- async.throwLater(e);
- }
-
- if (name === "unhandledRejection") {
- if (!activeFireEvent(name, reason, promise) && !localEventFired) {
- formatAndLogError(reason, "Unhandled rejection ");
- }
- } else {
- activeFireEvent(name, promise);
- }
-}
-
-function formatNonError(obj) {
- var str;
- if (typeof obj === "function") {
- str = "[function " +
- (obj.name || "anonymous") +
- "]";
- } else {
- str = obj && typeof obj.toString === "function"
- ? obj.toString() : util.toString(obj);
- var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/;
- if (ruselessToString.test(str)) {
- try {
- var newStr = JSON.stringify(obj);
- str = newStr;
- }
- catch(e) {
-
- }
- }
- if (str.length === 0) {
- str = "(empty array)";
- }
- }
- return ("(<" + snip(str) + ">, no stack trace)");
-}
-
-function snip(str) {
- var maxChars = 41;
- if (str.length < maxChars) {
- return str;
- }
- return str.substr(0, maxChars - 3) + "...";
-}
-
-function longStackTracesIsSupported() {
- return typeof captureStackTrace === "function";
-}
-
-var shouldIgnore = function() { return false; };
-var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/;
-function parseLineInfo(line) {
- var matches = line.match(parseLineInfoRegex);
- if (matches) {
- return {
- fileName: matches[1],
- line: parseInt(matches[2], 10)
- };
- }
-}
-
-function setBounds(firstLineError, lastLineError) {
- if (!longStackTracesIsSupported()) return;
- var firstStackLines = firstLineError.stack.split("\n");
- var lastStackLines = lastLineError.stack.split("\n");
- var firstIndex = -1;
- var lastIndex = -1;
- var firstFileName;
- var lastFileName;
- for (var i = 0; i < firstStackLines.length; ++i) {
- var result = parseLineInfo(firstStackLines[i]);
- if (result) {
- firstFileName = result.fileName;
- firstIndex = result.line;
- break;
- }
- }
- for (var i = 0; i < lastStackLines.length; ++i) {
- var result = parseLineInfo(lastStackLines[i]);
- if (result) {
- lastFileName = result.fileName;
- lastIndex = result.line;
- break;
- }
- }
- if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName ||
- firstFileName !== lastFileName || firstIndex >= lastIndex) {
- return;
- }
-
- shouldIgnore = function(line) {
- if (bluebirdFramePattern.test(line)) return true;
- var info = parseLineInfo(line);
- if (info) {
- if (info.fileName === firstFileName &&
- (firstIndex <= info.line && info.line <= lastIndex)) {
- return true;
- }
- }
- return false;
- };
-}
-
-function CapturedTrace(parent) {
- this._parent = parent;
- this._promisesCreated = 0;
- var length = this._length = 1 + (parent === undefined ? 0 : parent._length);
- captureStackTrace(this, CapturedTrace);
- if (length > 32) this.uncycle();
-}
-util.inherits(CapturedTrace, Error);
-Context.CapturedTrace = CapturedTrace;
-
-CapturedTrace.prototype.uncycle = function() {
- var length = this._length;
- if (length < 2) return;
- var nodes = [];
- var stackToIndex = {};
-
- for (var i = 0, node = this; node !== undefined; ++i) {
- nodes.push(node);
- node = node._parent;
- }
- length = this._length = i;
- for (var i = length - 1; i >= 0; --i) {
- var stack = nodes[i].stack;
- if (stackToIndex[stack] === undefined) {
- stackToIndex[stack] = i;
- }
- }
- for (var i = 0; i < length; ++i) {
- var currentStack = nodes[i].stack;
- var index = stackToIndex[currentStack];
- if (index !== undefined && index !== i) {
- if (index > 0) {
- nodes[index - 1]._parent = undefined;
- nodes[index - 1]._length = 1;
- }
- nodes[i]._parent = undefined;
- nodes[i]._length = 1;
- var cycleEdgeNode = i > 0 ? nodes[i - 1] : this;
-
- if (index < length - 1) {
- cycleEdgeNode._parent = nodes[index + 1];
- cycleEdgeNode._parent.uncycle();
- cycleEdgeNode._length =
- cycleEdgeNode._parent._length + 1;
- } else {
- cycleEdgeNode._parent = undefined;
- cycleEdgeNode._length = 1;
- }
- var currentChildLength = cycleEdgeNode._length + 1;
- for (var j = i - 2; j >= 0; --j) {
- nodes[j]._length = currentChildLength;
- currentChildLength++;
- }
- return;
- }
- }
-};
-
-CapturedTrace.prototype.attachExtraTrace = function(error) {
- if (error.__stackCleaned__) return;
- this.uncycle();
- var parsed = parseStackAndMessage(error);
- var message = parsed.message;
- var stacks = [parsed.stack];
-
- var trace = this;
- while (trace !== undefined) {
- stacks.push(cleanStack(trace.stack.split("\n")));
- trace = trace._parent;
- }
- removeCommonRoots(stacks);
- removeDuplicateOrEmptyJumps(stacks);
- util.notEnumerableProp(error, "stack", reconstructStack(message, stacks));
- util.notEnumerableProp(error, "__stackCleaned__", true);
-};
-
-var captureStackTrace = (function stackDetection() {
- var v8stackFramePattern = /^\s*at\s*/;
- var v8stackFormatter = function(stack, error) {
- if (typeof stack === "string") return stack;
-
- if (error.name !== undefined &&
- error.message !== undefined) {
- return error.toString();
- }
- return formatNonError(error);
- };
-
- if (typeof Error.stackTraceLimit === "number" &&
- typeof Error.captureStackTrace === "function") {
- Error.stackTraceLimit += 6;
- stackFramePattern = v8stackFramePattern;
- formatStack = v8stackFormatter;
- var captureStackTrace = Error.captureStackTrace;
-
- shouldIgnore = function(line) {
- return bluebirdFramePattern.test(line);
- };
- return function(receiver, ignoreUntil) {
- Error.stackTraceLimit += 6;
- captureStackTrace(receiver, ignoreUntil);
- Error.stackTraceLimit -= 6;
- };
- }
- var err = new Error();
-
- if (typeof err.stack === "string" &&
- err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) {
- stackFramePattern = /@/;
- formatStack = v8stackFormatter;
- indentStackFrames = true;
- return function captureStackTrace(o) {
- o.stack = new Error().stack;
- };
- }
-
- var hasStackAfterThrow;
- try { throw new Error(); }
- catch(e) {
- hasStackAfterThrow = ("stack" in e);
- }
- if (!("stack" in err) && hasStackAfterThrow &&
- typeof Error.stackTraceLimit === "number") {
- stackFramePattern = v8stackFramePattern;
- formatStack = v8stackFormatter;
- return function captureStackTrace(o) {
- Error.stackTraceLimit += 6;
- try { throw new Error(); }
- catch(e) { o.stack = e.stack; }
- Error.stackTraceLimit -= 6;
- };
- }
-
- formatStack = function(stack, error) {
- if (typeof stack === "string") return stack;
-
- if ((typeof error === "object" ||
- typeof error === "function") &&
- error.name !== undefined &&
- error.message !== undefined) {
- return error.toString();
- }
- return formatNonError(error);
- };
-
- return null;
-
-})([]);
-
-if (typeof console !== "undefined" && typeof console.warn !== "undefined") {
- printWarning = function (message) {
- console.warn(message);
- };
- if (util.isNode && process.stderr.isTTY) {
- printWarning = function(message, isSoft) {
- var color = isSoft ? "\u001b[33m" : "\u001b[31m";
- console.warn(color + message + "\u001b[0m\n");
- };
- } else if (!util.isNode && typeof (new Error().stack) === "string") {
- printWarning = function(message, isSoft) {
- console.warn("%c" + message,
- isSoft ? "color: darkorange" : "color: red");
- };
- }
-}
-
-var config = {
- warnings: warnings,
- longStackTraces: false,
- cancellation: false,
- monitoring: false
-};
-
-if (longStackTraces) Promise.longStackTraces();
-
-return {
- longStackTraces: function() {
- return config.longStackTraces;
- },
- warnings: function() {
- return config.warnings;
- },
- cancellation: function() {
- return config.cancellation;
- },
- monitoring: function() {
- return config.monitoring;
- },
- propagateFromFunction: function() {
- return propagateFromFunction;
- },
- boundValueFunction: function() {
- return boundValueFunction;
- },
- checkForgottenReturns: checkForgottenReturns,
- setBounds: setBounds,
- warn: warn,
- deprecated: deprecated,
- CapturedTrace: CapturedTrace,
- fireDomEvent: fireDomEvent,
- fireGlobalEvent: fireGlobalEvent
-};
-};
-
-},{"./errors":12,"./util":36}],10:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise) {
-function returner() {
- return this.value;
-}
-function thrower() {
- throw this.reason;
-}
-
-Promise.prototype["return"] =
-Promise.prototype.thenReturn = function (value) {
- if (value instanceof Promise) value.suppressUnhandledRejections();
- return this._then(
- returner, undefined, undefined, {value: value}, undefined);
-};
-
-Promise.prototype["throw"] =
-Promise.prototype.thenThrow = function (reason) {
- return this._then(
- thrower, undefined, undefined, {reason: reason}, undefined);
-};
-
-Promise.prototype.catchThrow = function (reason) {
- if (arguments.length <= 1) {
- return this._then(
- undefined, thrower, undefined, {reason: reason}, undefined);
- } else {
- var _reason = arguments[1];
- var handler = function() {throw _reason;};
- return this.caught(reason, handler);
- }
-};
-
-Promise.prototype.catchReturn = function (value) {
- if (arguments.length <= 1) {
- if (value instanceof Promise) value.suppressUnhandledRejections();
- return this._then(
- undefined, returner, undefined, {value: value}, undefined);
- } else {
- var _value = arguments[1];
- if (_value instanceof Promise) _value.suppressUnhandledRejections();
- var handler = function() {return _value;};
- return this.caught(value, handler);
- }
-};
-};
-
-},{}],11:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise, INTERNAL) {
-var PromiseReduce = Promise.reduce;
-var PromiseAll = Promise.all;
-
-function promiseAllThis() {
- return PromiseAll(this);
-}
-
-function PromiseMapSeries(promises, fn) {
- return PromiseReduce(promises, fn, INTERNAL, INTERNAL);
-}
-
-Promise.prototype.each = function (fn) {
- return PromiseReduce(this, fn, INTERNAL, 0)
- ._then(promiseAllThis, undefined, undefined, this, undefined);
-};
-
-Promise.prototype.mapSeries = function (fn) {
- return PromiseReduce(this, fn, INTERNAL, INTERNAL);
-};
-
-Promise.each = function (promises, fn) {
- return PromiseReduce(promises, fn, INTERNAL, 0)
- ._then(promiseAllThis, undefined, undefined, promises, undefined);
-};
-
-Promise.mapSeries = PromiseMapSeries;
-};
-
-
-},{}],12:[function(_dereq_,module,exports){
-"use strict";
-var es5 = _dereq_("./es5");
-var Objectfreeze = es5.freeze;
-var util = _dereq_("./util");
-var inherits = util.inherits;
-var notEnumerableProp = util.notEnumerableProp;
-
-function subError(nameProperty, defaultMessage) {
- function SubError(message) {
- if (!(this instanceof SubError)) return new SubError(message);
- notEnumerableProp(this, "message",
- typeof message === "string" ? message : defaultMessage);
- notEnumerableProp(this, "name", nameProperty);
- if (Error.captureStackTrace) {
- Error.captureStackTrace(this, this.constructor);
- } else {
- Error.call(this);
- }
- }
- inherits(SubError, Error);
- return SubError;
-}
-
-var _TypeError, _RangeError;
-var Warning = subError("Warning", "warning");
-var CancellationError = subError("CancellationError", "cancellation error");
-var TimeoutError = subError("TimeoutError", "timeout error");
-var AggregateError = subError("AggregateError", "aggregate error");
-try {
- _TypeError = TypeError;
- _RangeError = RangeError;
-} catch(e) {
- _TypeError = subError("TypeError", "type error");
- _RangeError = subError("RangeError", "range error");
-}
-
-var methods = ("join pop push shift unshift slice filter forEach some " +
- "every map indexOf lastIndexOf reduce reduceRight sort reverse").split(" ");
-
-for (var i = 0; i < methods.length; ++i) {
- if (typeof Array.prototype[methods[i]] === "function") {
- AggregateError.prototype[methods[i]] = Array.prototype[methods[i]];
- }
-}
-
-es5.defineProperty(AggregateError.prototype, "length", {
- value: 0,
- configurable: false,
- writable: true,
- enumerable: true
-});
-AggregateError.prototype["isOperational"] = true;
-var level = 0;
-AggregateError.prototype.toString = function() {
- var indent = Array(level * 4 + 1).join(" ");
- var ret = "\n" + indent + "AggregateError of:" + "\n";
- level++;
- indent = Array(level * 4 + 1).join(" ");
- for (var i = 0; i < this.length; ++i) {
- var str = this[i] === this ? "[Circular AggregateError]" : this[i] + "";
- var lines = str.split("\n");
- for (var j = 0; j < lines.length; ++j) {
- lines[j] = indent + lines[j];
- }
- str = lines.join("\n");
- ret += str + "\n";
- }
- level--;
- return ret;
-};
-
-function OperationalError(message) {
- if (!(this instanceof OperationalError))
- return new OperationalError(message);
- notEnumerableProp(this, "name", "OperationalError");
- notEnumerableProp(this, "message", message);
- this.cause = message;
- this["isOperational"] = true;
-
- if (message instanceof Error) {
- notEnumerableProp(this, "message", message.message);
- notEnumerableProp(this, "stack", message.stack);
- } else if (Error.captureStackTrace) {
- Error.captureStackTrace(this, this.constructor);
- }
-
-}
-inherits(OperationalError, Error);
-
-var errorTypes = Error["__BluebirdErrorTypes__"];
-if (!errorTypes) {
- errorTypes = Objectfreeze({
- CancellationError: CancellationError,
- TimeoutError: TimeoutError,
- OperationalError: OperationalError,
- RejectionError: OperationalError,
- AggregateError: AggregateError
- });
- es5.defineProperty(Error, "__BluebirdErrorTypes__", {
- value: errorTypes,
- writable: false,
- enumerable: false,
- configurable: false
- });
-}
-
-module.exports = {
- Error: Error,
- TypeError: _TypeError,
- RangeError: _RangeError,
- CancellationError: errorTypes.CancellationError,
- OperationalError: errorTypes.OperationalError,
- TimeoutError: errorTypes.TimeoutError,
- AggregateError: errorTypes.AggregateError,
- Warning: Warning
-};
-
-},{"./es5":13,"./util":36}],13:[function(_dereq_,module,exports){
-var isES5 = (function(){
- "use strict";
- return this === undefined;
-})();
-
-if (isES5) {
- module.exports = {
- freeze: Object.freeze,
- defineProperty: Object.defineProperty,
- getDescriptor: Object.getOwnPropertyDescriptor,
- keys: Object.keys,
- names: Object.getOwnPropertyNames,
- getPrototypeOf: Object.getPrototypeOf,
- isArray: Array.isArray,
- isES5: isES5,
- propertyIsWritable: function(obj, prop) {
- var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
- return !!(!descriptor || descriptor.writable || descriptor.set);
- }
- };
-} else {
- var has = {}.hasOwnProperty;
- var str = {}.toString;
- var proto = {}.constructor.prototype;
-
- var ObjectKeys = function (o) {
- var ret = [];
- for (var key in o) {
- if (has.call(o, key)) {
- ret.push(key);
- }
- }
- return ret;
- };
-
- var ObjectGetDescriptor = function(o, key) {
- return {value: o[key]};
- };
-
- var ObjectDefineProperty = function (o, key, desc) {
- o[key] = desc.value;
- return o;
- };
-
- var ObjectFreeze = function (obj) {
- return obj;
- };
-
- var ObjectGetPrototypeOf = function (obj) {
- try {
- return Object(obj).constructor.prototype;
- }
- catch (e) {
- return proto;
- }
- };
-
- var ArrayIsArray = function (obj) {
- try {
- return str.call(obj) === "[object Array]";
- }
- catch(e) {
- return false;
- }
- };
-
- module.exports = {
- isArray: ArrayIsArray,
- keys: ObjectKeys,
- names: ObjectKeys,
- defineProperty: ObjectDefineProperty,
- getDescriptor: ObjectGetDescriptor,
- freeze: ObjectFreeze,
- getPrototypeOf: ObjectGetPrototypeOf,
- isES5: isES5,
- propertyIsWritable: function() {
- return true;
- }
- };
-}
-
-},{}],14:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise, INTERNAL) {
-var PromiseMap = Promise.map;
-
-Promise.prototype.filter = function (fn, options) {
- return PromiseMap(this, fn, options, INTERNAL);
-};
-
-Promise.filter = function (promises, fn, options) {
- return PromiseMap(promises, fn, options, INTERNAL);
-};
-};
-
-},{}],15:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise, tryConvertToPromise, NEXT_FILTER) {
-var util = _dereq_("./util");
-var CancellationError = Promise.CancellationError;
-var errorObj = util.errorObj;
-var catchFilter = _dereq_("./catch_filter")(NEXT_FILTER);
-
-function PassThroughHandlerContext(promise, type, handler) {
- this.promise = promise;
- this.type = type;
- this.handler = handler;
- this.called = false;
- this.cancelPromise = null;
-}
-
-PassThroughHandlerContext.prototype.isFinallyHandler = function() {
- return this.type === 0;
-};
-
-function FinallyHandlerCancelReaction(finallyHandler) {
- this.finallyHandler = finallyHandler;
-}
-
-FinallyHandlerCancelReaction.prototype._resultCancelled = function() {
- checkCancel(this.finallyHandler);
-};
-
-function checkCancel(ctx, reason) {
- if (ctx.cancelPromise != null) {
- if (arguments.length > 1) {
- ctx.cancelPromise._reject(reason);
- } else {
- ctx.cancelPromise._cancel();
- }
- ctx.cancelPromise = null;
- return true;
- }
- return false;
-}
-
-function succeed() {
- return finallyHandler.call(this, this.promise._target()._settledValue());
-}
-function fail(reason) {
- if (checkCancel(this, reason)) return;
- errorObj.e = reason;
- return errorObj;
-}
-function finallyHandler(reasonOrValue) {
- var promise = this.promise;
- var handler = this.handler;
-
- if (!this.called) {
- this.called = true;
- var ret = this.isFinallyHandler()
- ? handler.call(promise._boundValue())
- : handler.call(promise._boundValue(), reasonOrValue);
- if (ret === NEXT_FILTER) {
- return ret;
- } else if (ret !== undefined) {
- promise._setReturnedNonUndefined();
- var maybePromise = tryConvertToPromise(ret, promise);
- if (maybePromise instanceof Promise) {
- if (this.cancelPromise != null) {
- if (maybePromise._isCancelled()) {
- var reason =
- new CancellationError("late cancellation observer");
- promise._attachExtraTrace(reason);
- errorObj.e = reason;
- return errorObj;
- } else if (maybePromise.isPending()) {
- maybePromise._attachCancellationCallback(
- new FinallyHandlerCancelReaction(this));
- }
- }
- return maybePromise._then(
- succeed, fail, undefined, this, undefined);
- }
- }
- }
-
- if (promise.isRejected()) {
- checkCancel(this);
- errorObj.e = reasonOrValue;
- return errorObj;
- } else {
- checkCancel(this);
- return reasonOrValue;
- }
-}
-
-Promise.prototype._passThrough = function(handler, type, success, fail) {
- if (typeof handler !== "function") return this.then();
- return this._then(success,
- fail,
- undefined,
- new PassThroughHandlerContext(this, type, handler),
- undefined);
-};
-
-Promise.prototype.lastly =
-Promise.prototype["finally"] = function (handler) {
- return this._passThrough(handler,
- 0,
- finallyHandler,
- finallyHandler);
-};
-
-
-Promise.prototype.tap = function (handler) {
- return this._passThrough(handler, 1, finallyHandler);
-};
-
-Promise.prototype.tapCatch = function (handlerOrPredicate) {
- var len = arguments.length;
- if(len === 1) {
- return this._passThrough(handlerOrPredicate,
- 1,
- undefined,
- finallyHandler);
- } else {
- var catchInstances = new Array(len - 1),
- j = 0, i;
- for (i = 0; i < len - 1; ++i) {
- var item = arguments[i];
- if (util.isObject(item)) {
- catchInstances[j++] = item;
- } else {
- return Promise.reject(new TypeError(
- "tapCatch statement predicate: "
- + "expecting an object but got " + util.classString(item)
- ));
- }
- }
- catchInstances.length = j;
- var handler = arguments[i];
- return this._passThrough(catchFilter(catchInstances, handler, this),
- 1,
- undefined,
- finallyHandler);
- }
-
-};
-
-return PassThroughHandlerContext;
-};
-
-},{"./catch_filter":7,"./util":36}],16:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise,
- apiRejection,
- INTERNAL,
- tryConvertToPromise,
- Proxyable,
- debug) {
-var errors = _dereq_("./errors");
-var TypeError = errors.TypeError;
-var util = _dereq_("./util");
-var errorObj = util.errorObj;
-var tryCatch = util.tryCatch;
-var yieldHandlers = [];
-
-function promiseFromYieldHandler(value, yieldHandlers, traceParent) {
- for (var i = 0; i < yieldHandlers.length; ++i) {
- traceParent._pushContext();
- var result = tryCatch(yieldHandlers[i])(value);
- traceParent._popContext();
- if (result === errorObj) {
- traceParent._pushContext();
- var ret = Promise.reject(errorObj.e);
- traceParent._popContext();
- return ret;
- }
- var maybePromise = tryConvertToPromise(result, traceParent);
- if (maybePromise instanceof Promise) return maybePromise;
- }
- return null;
-}
-
-function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) {
- if (debug.cancellation()) {
- var internal = new Promise(INTERNAL);
- var _finallyPromise = this._finallyPromise = new Promise(INTERNAL);
- this._promise = internal.lastly(function() {
- return _finallyPromise;
- });
- internal._captureStackTrace();
- internal._setOnCancel(this);
- } else {
- var promise = this._promise = new Promise(INTERNAL);
- promise._captureStackTrace();
- }
- this._stack = stack;
- this._generatorFunction = generatorFunction;
- this._receiver = receiver;
- this._generator = undefined;
- this._yieldHandlers = typeof yieldHandler === "function"
- ? [yieldHandler].concat(yieldHandlers)
- : yieldHandlers;
- this._yieldedPromise = null;
- this._cancellationPhase = false;
-}
-util.inherits(PromiseSpawn, Proxyable);
-
-PromiseSpawn.prototype._isResolved = function() {
- return this._promise === null;
-};
-
-PromiseSpawn.prototype._cleanup = function() {
- this._promise = this._generator = null;
- if (debug.cancellation() && this._finallyPromise !== null) {
- this._finallyPromise._fulfill();
- this._finallyPromise = null;
- }
-};
-
-PromiseSpawn.prototype._promiseCancelled = function() {
- if (this._isResolved()) return;
- var implementsReturn = typeof this._generator["return"] !== "undefined";
-
- var result;
- if (!implementsReturn) {
- var reason = new Promise.CancellationError(
- "generator .return() sentinel");
- Promise.coroutine.returnSentinel = reason;
- this._promise._attachExtraTrace(reason);
- this._promise._pushContext();
- result = tryCatch(this._generator["throw"]).call(this._generator,
- reason);
- this._promise._popContext();
- } else {
- this._promise._pushContext();
- result = tryCatch(this._generator["return"]).call(this._generator,
- undefined);
- this._promise._popContext();
- }
- this._cancellationPhase = true;
- this._yieldedPromise = null;
- this._continue(result);
-};
-
-PromiseSpawn.prototype._promiseFulfilled = function(value) {
- this._yieldedPromise = null;
- this._promise._pushContext();
- var result = tryCatch(this._generator.next).call(this._generator, value);
- this._promise._popContext();
- this._continue(result);
-};
-
-PromiseSpawn.prototype._promiseRejected = function(reason) {
- this._yieldedPromise = null;
- this._promise._attachExtraTrace(reason);
- this._promise._pushContext();
- var result = tryCatch(this._generator["throw"])
- .call(this._generator, reason);
- this._promise._popContext();
- this._continue(result);
-};
-
-PromiseSpawn.prototype._resultCancelled = function() {
- if (this._yieldedPromise instanceof Promise) {
- var promise = this._yieldedPromise;
- this._yieldedPromise = null;
- promise.cancel();
- }
-};
-
-PromiseSpawn.prototype.promise = function () {
- return this._promise;
-};
-
-PromiseSpawn.prototype._run = function () {
- this._generator = this._generatorFunction.call(this._receiver);
- this._receiver =
- this._generatorFunction = undefined;
- this._promiseFulfilled(undefined);
-};
-
-PromiseSpawn.prototype._continue = function (result) {
- var promise = this._promise;
- if (result === errorObj) {
- this._cleanup();
- if (this._cancellationPhase) {
- return promise.cancel();
- } else {
- return promise._rejectCallback(result.e, false);
- }
- }
-
- var value = result.value;
- if (result.done === true) {
- this._cleanup();
- if (this._cancellationPhase) {
- return promise.cancel();
- } else {
- return promise._resolveCallback(value);
- }
- } else {
- var maybePromise = tryConvertToPromise(value, this._promise);
- if (!(maybePromise instanceof Promise)) {
- maybePromise =
- promiseFromYieldHandler(maybePromise,
- this._yieldHandlers,
- this._promise);
- if (maybePromise === null) {
- this._promiseRejected(
- new TypeError(
- "A value %s was yielded that could not be treated as a promise\u000a\u000a See http://goo.gl/MqrFmX\u000a\u000a".replace("%s", String(value)) +
- "From coroutine:\u000a" +
- this._stack.split("\n").slice(1, -7).join("\n")
- )
- );
- return;
- }
- }
- maybePromise = maybePromise._target();
- var bitField = maybePromise._bitField;
- ;
- if (((bitField & 50397184) === 0)) {
- this._yieldedPromise = maybePromise;
- maybePromise._proxy(this, null);
- } else if (((bitField & 33554432) !== 0)) {
- Promise._async.invoke(
- this._promiseFulfilled, this, maybePromise._value()
- );
- } else if (((bitField & 16777216) !== 0)) {
- Promise._async.invoke(
- this._promiseRejected, this, maybePromise._reason()
- );
- } else {
- this._promiseCancelled();
- }
- }
-};
-
-Promise.coroutine = function (generatorFunction, options) {
- if (typeof generatorFunction !== "function") {
- throw new TypeError("generatorFunction must be a function\u000a\u000a See http://goo.gl/MqrFmX\u000a");
- }
- var yieldHandler = Object(options).yieldHandler;
- var PromiseSpawn$ = PromiseSpawn;
- var stack = new Error().stack;
- return function () {
- var generator = generatorFunction.apply(this, arguments);
- var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler,
- stack);
- var ret = spawn.promise();
- spawn._generator = generator;
- spawn._promiseFulfilled(undefined);
- return ret;
- };
-};
-
-Promise.coroutine.addYieldHandler = function(fn) {
- if (typeof fn !== "function") {
- throw new TypeError("expecting a function but got " + util.classString(fn));
- }
- yieldHandlers.push(fn);
-};
-
-Promise.spawn = function (generatorFunction) {
- debug.deprecated("Promise.spawn()", "Promise.coroutine()");
- if (typeof generatorFunction !== "function") {
- return apiRejection("generatorFunction must be a function\u000a\u000a See http://goo.gl/MqrFmX\u000a");
- }
- var spawn = new PromiseSpawn(generatorFunction, this);
- var ret = spawn.promise();
- spawn._run(Promise.spawn);
- return ret;
-};
-};
-
-},{"./errors":12,"./util":36}],17:[function(_dereq_,module,exports){
-"use strict";
-module.exports =
-function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async,
- getDomain) {
-var util = _dereq_("./util");
-var canEvaluate = util.canEvaluate;
-var tryCatch = util.tryCatch;
-var errorObj = util.errorObj;
-var reject;
-
-if (!true) {
-if (canEvaluate) {
- var thenCallback = function(i) {
- return new Function("value", "holder", " \n\
- 'use strict'; \n\
- holder.pIndex = value; \n\
- holder.checkFulfillment(this); \n\
- ".replace(/Index/g, i));
- };
-
- var promiseSetter = function(i) {
- return new Function("promise", "holder", " \n\
- 'use strict'; \n\
- holder.pIndex = promise; \n\
- ".replace(/Index/g, i));
- };
-
- var generateHolderClass = function(total) {
- var props = new Array(total);
- for (var i = 0; i < props.length; ++i) {
- props[i] = "this.p" + (i+1);
- }
- var assignment = props.join(" = ") + " = null;";
- var cancellationCode= "var promise;\n" + props.map(function(prop) {
- return " \n\
- promise = " + prop + "; \n\
- if (promise instanceof Promise) { \n\
- promise.cancel(); \n\
- } \n\
- ";
- }).join("\n");
- var passedArguments = props.join(", ");
- var name = "Holder$" + total;
-
-
- var code = "return function(tryCatch, errorObj, Promise, async) { \n\
- 'use strict'; \n\
- function [TheName](fn) { \n\
- [TheProperties] \n\
- this.fn = fn; \n\
- this.asyncNeeded = true; \n\
- this.now = 0; \n\
- } \n\
- \n\
- [TheName].prototype._callFunction = function(promise) { \n\
- promise._pushContext(); \n\
- var ret = tryCatch(this.fn)([ThePassedArguments]); \n\
- promise._popContext(); \n\
- if (ret === errorObj) { \n\
- promise._rejectCallback(ret.e, false); \n\
- } else { \n\
- promise._resolveCallback(ret); \n\
- } \n\
- }; \n\
- \n\
- [TheName].prototype.checkFulfillment = function(promise) { \n\
- var now = ++this.now; \n\
- if (now === [TheTotal]) { \n\
- if (this.asyncNeeded) { \n\
- async.invoke(this._callFunction, this, promise); \n\
- } else { \n\
- this._callFunction(promise); \n\
- } \n\
- \n\
- } \n\
- }; \n\
- \n\
- [TheName].prototype._resultCancelled = function() { \n\
- [CancellationCode] \n\
- }; \n\
- \n\
- return [TheName]; \n\
- }(tryCatch, errorObj, Promise, async); \n\
- ";
-
- code = code.replace(/\[TheName\]/g, name)
- .replace(/\[TheTotal\]/g, total)
- .replace(/\[ThePassedArguments\]/g, passedArguments)
- .replace(/\[TheProperties\]/g, assignment)
- .replace(/\[CancellationCode\]/g, cancellationCode);
-
- return new Function("tryCatch", "errorObj", "Promise", "async", code)
- (tryCatch, errorObj, Promise, async);
- };
-
- var holderClasses = [];
- var thenCallbacks = [];
- var promiseSetters = [];
-
- for (var i = 0; i < 8; ++i) {
- holderClasses.push(generateHolderClass(i + 1));
- thenCallbacks.push(thenCallback(i + 1));
- promiseSetters.push(promiseSetter(i + 1));
- }
-
- reject = function (reason) {
- this._reject(reason);
- };
-}}
-
-Promise.join = function () {
- var last = arguments.length - 1;
- var fn;
- if (last > 0 && typeof arguments[last] === "function") {
- fn = arguments[last];
- if (!true) {
- if (last <= 8 && canEvaluate) {
- var ret = new Promise(INTERNAL);
- ret._captureStackTrace();
- var HolderClass = holderClasses[last - 1];
- var holder = new HolderClass(fn);
- var callbacks = thenCallbacks;
-
- for (var i = 0; i < last; ++i) {
- var maybePromise = tryConvertToPromise(arguments[i], ret);
- if (maybePromise instanceof Promise) {
- maybePromise = maybePromise._target();
- var bitField = maybePromise._bitField;
- ;
- if (((bitField & 50397184) === 0)) {
- maybePromise._then(callbacks[i], reject,
- undefined, ret, holder);
- promiseSetters[i](maybePromise, holder);
- holder.asyncNeeded = false;
- } else if (((bitField & 33554432) !== 0)) {
- callbacks[i].call(ret,
- maybePromise._value(), holder);
- } else if (((bitField & 16777216) !== 0)) {
- ret._reject(maybePromise._reason());
- } else {
- ret._cancel();
- }
- } else {
- callbacks[i].call(ret, maybePromise, holder);
- }
- }
-
- if (!ret._isFateSealed()) {
- if (holder.asyncNeeded) {
- var domain = getDomain();
- if (domain !== null) {
- holder.fn = util.domainBind(domain, holder.fn);
- }
- }
- ret._setAsyncGuaranteed();
- ret._setOnCancel(holder);
- }
- return ret;
- }
- }
- }
- var args = [].slice.call(arguments);;
- if (fn) args.pop();
- var ret = new PromiseArray(args).promise();
- return fn !== undefined ? ret.spread(fn) : ret;
-};
-
-};
-
-},{"./util":36}],18:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise,
- PromiseArray,
- apiRejection,
- tryConvertToPromise,
- INTERNAL,
- debug) {
-var getDomain = Promise._getDomain;
-var util = _dereq_("./util");
-var tryCatch = util.tryCatch;
-var errorObj = util.errorObj;
-var async = Promise._async;
-
-function MappingPromiseArray(promises, fn, limit, _filter) {
- this.constructor$(promises);
- this._promise._captureStackTrace();
- var domain = getDomain();
- this._callback = domain === null ? fn : util.domainBind(domain, fn);
- this._preservedValues = _filter === INTERNAL
- ? new Array(this.length())
- : null;
- this._limit = limit;
- this._inFlight = 0;
- this._queue = [];
- async.invoke(this._asyncInit, this, undefined);
-}
-util.inherits(MappingPromiseArray, PromiseArray);
-
-MappingPromiseArray.prototype._asyncInit = function() {
- this._init$(undefined, -2);
-};
-
-MappingPromiseArray.prototype._init = function () {};
-
-MappingPromiseArray.prototype._promiseFulfilled = function (value, index) {
- var values = this._values;
- var length = this.length();
- var preservedValues = this._preservedValues;
- var limit = this._limit;
-
- if (index < 0) {
- index = (index * -1) - 1;
- values[index] = value;
- if (limit >= 1) {
- this._inFlight--;
- this._drainQueue();
- if (this._isResolved()) return true;
- }
- } else {
- if (limit >= 1 && this._inFlight >= limit) {
- values[index] = value;
- this._queue.push(index);
- return false;
- }
- if (preservedValues !== null) preservedValues[index] = value;
-
- var promise = this._promise;
- var callback = this._callback;
- var receiver = promise._boundValue();
- promise._pushContext();
- var ret = tryCatch(callback).call(receiver, value, index, length);
- var promiseCreated = promise._popContext();
- debug.checkForgottenReturns(
- ret,
- promiseCreated,
- preservedValues !== null ? "Promise.filter" : "Promise.map",
- promise
- );
- if (ret === errorObj) {
- this._reject(ret.e);
- return true;
- }
-
- var maybePromise = tryConvertToPromise(ret, this._promise);
- if (maybePromise instanceof Promise) {
- maybePromise = maybePromise._target();
- var bitField = maybePromise._bitField;
- ;
- if (((bitField & 50397184) === 0)) {
- if (limit >= 1) this._inFlight++;
- values[index] = maybePromise;
- maybePromise._proxy(this, (index + 1) * -1);
- return false;
- } else if (((bitField & 33554432) !== 0)) {
- ret = maybePromise._value();
- } else if (((bitField & 16777216) !== 0)) {
- this._reject(maybePromise._reason());
- return true;
- } else {
- this._cancel();
- return true;
- }
- }
- values[index] = ret;
- }
- var totalResolved = ++this._totalResolved;
- if (totalResolved >= length) {
- if (preservedValues !== null) {
- this._filter(values, preservedValues);
- } else {
- this._resolve(values);
- }
- return true;
- }
- return false;
-};
-
-MappingPromiseArray.prototype._drainQueue = function () {
- var queue = this._queue;
- var limit = this._limit;
- var values = this._values;
- while (queue.length > 0 && this._inFlight < limit) {
- if (this._isResolved()) return;
- var index = queue.pop();
- this._promiseFulfilled(values[index], index);
- }
-};
-
-MappingPromiseArray.prototype._filter = function (booleans, values) {
- var len = values.length;
- var ret = new Array(len);
- var j = 0;
- for (var i = 0; i < len; ++i) {
- if (booleans[i]) ret[j++] = values[i];
- }
- ret.length = j;
- this._resolve(ret);
-};
-
-MappingPromiseArray.prototype.preservedValues = function () {
- return this._preservedValues;
-};
-
-function map(promises, fn, options, _filter) {
- if (typeof fn !== "function") {
- return apiRejection("expecting a function but got " + util.classString(fn));
- }
-
- var limit = 0;
- if (options !== undefined) {
- if (typeof options === "object" && options !== null) {
- if (typeof options.concurrency !== "number") {
- return Promise.reject(
- new TypeError("'concurrency' must be a number but it is " +
- util.classString(options.concurrency)));
- }
- limit = options.concurrency;
- } else {
- return Promise.reject(new TypeError(
- "options argument must be an object but it is " +
- util.classString(options)));
- }
- }
- limit = typeof limit === "number" &&
- isFinite(limit) && limit >= 1 ? limit : 0;
- return new MappingPromiseArray(promises, fn, limit, _filter).promise();
-}
-
-Promise.prototype.map = function (fn, options) {
- return map(this, fn, options, null);
-};
-
-Promise.map = function (promises, fn, options, _filter) {
- return map(promises, fn, options, _filter);
-};
-
-
-};
-
-},{"./util":36}],19:[function(_dereq_,module,exports){
-"use strict";
-module.exports =
-function(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug) {
-var util = _dereq_("./util");
-var tryCatch = util.tryCatch;
-
-Promise.method = function (fn) {
- if (typeof fn !== "function") {
- throw new Promise.TypeError("expecting a function but got " + util.classString(fn));
- }
- return function () {
- var ret = new Promise(INTERNAL);
- ret._captureStackTrace();
- ret._pushContext();
- var value = tryCatch(fn).apply(this, arguments);
- var promiseCreated = ret._popContext();
- debug.checkForgottenReturns(
- value, promiseCreated, "Promise.method", ret);
- ret._resolveFromSyncValue(value);
- return ret;
- };
-};
-
-Promise.attempt = Promise["try"] = function (fn) {
- if (typeof fn !== "function") {
- return apiRejection("expecting a function but got " + util.classString(fn));
- }
- var ret = new Promise(INTERNAL);
- ret._captureStackTrace();
- ret._pushContext();
- var value;
- if (arguments.length > 1) {
- debug.deprecated("calling Promise.try with more than 1 argument");
- var arg = arguments[1];
- var ctx = arguments[2];
- value = util.isArray(arg) ? tryCatch(fn).apply(ctx, arg)
- : tryCatch(fn).call(ctx, arg);
- } else {
- value = tryCatch(fn)();
- }
- var promiseCreated = ret._popContext();
- debug.checkForgottenReturns(
- value, promiseCreated, "Promise.try", ret);
- ret._resolveFromSyncValue(value);
- return ret;
-};
-
-Promise.prototype._resolveFromSyncValue = function (value) {
- if (value === util.errorObj) {
- this._rejectCallback(value.e, false);
- } else {
- this._resolveCallback(value, true);
- }
-};
-};
-
-},{"./util":36}],20:[function(_dereq_,module,exports){
-"use strict";
-var util = _dereq_("./util");
-var maybeWrapAsError = util.maybeWrapAsError;
-var errors = _dereq_("./errors");
-var OperationalError = errors.OperationalError;
-var es5 = _dereq_("./es5");
-
-function isUntypedError(obj) {
- return obj instanceof Error &&
- es5.getPrototypeOf(obj) === Error.prototype;
-}
-
-var rErrorKey = /^(?:name|message|stack|cause)$/;
-function wrapAsOperationalError(obj) {
- var ret;
- if (isUntypedError(obj)) {
- ret = new OperationalError(obj);
- ret.name = obj.name;
- ret.message = obj.message;
- ret.stack = obj.stack;
- var keys = es5.keys(obj);
- for (var i = 0; i < keys.length; ++i) {
- var key = keys[i];
- if (!rErrorKey.test(key)) {
- ret[key] = obj[key];
- }
- }
- return ret;
- }
- util.markAsOriginatingFromRejection(obj);
- return obj;
-}
-
-function nodebackForPromise(promise, multiArgs) {
- return function(err, value) {
- if (promise === null) return;
- if (err) {
- var wrapped = wrapAsOperationalError(maybeWrapAsError(err));
- promise._attachExtraTrace(wrapped);
- promise._reject(wrapped);
- } else if (!multiArgs) {
- promise._fulfill(value);
- } else {
- var args = [].slice.call(arguments, 1);;
- promise._fulfill(args);
- }
- promise = null;
- };
-}
-
-module.exports = nodebackForPromise;
-
-},{"./errors":12,"./es5":13,"./util":36}],21:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise) {
-var util = _dereq_("./util");
-var async = Promise._async;
-var tryCatch = util.tryCatch;
-var errorObj = util.errorObj;
-
-function spreadAdapter(val, nodeback) {
- var promise = this;
- if (!util.isArray(val)) return successAdapter.call(promise, val, nodeback);
- var ret =
- tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val));
- if (ret === errorObj) {
- async.throwLater(ret.e);
- }
-}
-
-function successAdapter(val, nodeback) {
- var promise = this;
- var receiver = promise._boundValue();
- var ret = val === undefined
- ? tryCatch(nodeback).call(receiver, null)
- : tryCatch(nodeback).call(receiver, null, val);
- if (ret === errorObj) {
- async.throwLater(ret.e);
- }
-}
-function errorAdapter(reason, nodeback) {
- var promise = this;
- if (!reason) {
- var newReason = new Error(reason + "");
- newReason.cause = reason;
- reason = newReason;
- }
- var ret = tryCatch(nodeback).call(promise._boundValue(), reason);
- if (ret === errorObj) {
- async.throwLater(ret.e);
- }
-}
-
-Promise.prototype.asCallback = Promise.prototype.nodeify = function (nodeback,
- options) {
- if (typeof nodeback == "function") {
- var adapter = successAdapter;
- if (options !== undefined && Object(options).spread) {
- adapter = spreadAdapter;
- }
- this._then(
- adapter,
- errorAdapter,
- undefined,
- this,
- nodeback
- );
- }
- return this;
-};
-};
-
-},{"./util":36}],22:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function() {
-var makeSelfResolutionError = function () {
- return new TypeError("circular promise resolution chain\u000a\u000a See http://goo.gl/MqrFmX\u000a");
-};
-var reflectHandler = function() {
- return new Promise.PromiseInspection(this._target());
-};
-var apiRejection = function(msg) {
- return Promise.reject(new TypeError(msg));
-};
-function Proxyable() {}
-var UNDEFINED_BINDING = {};
-var util = _dereq_("./util");
-
-var getDomain;
-if (util.isNode) {
- getDomain = function() {
- var ret = process.domain;
- if (ret === undefined) ret = null;
- return ret;
- };
-} else {
- getDomain = function() {
- return null;
- };
-}
-util.notEnumerableProp(Promise, "_getDomain", getDomain);
-
-var es5 = _dereq_("./es5");
-var Async = _dereq_("./async");
-var async = new Async();
-es5.defineProperty(Promise, "_async", {value: async});
-var errors = _dereq_("./errors");
-var TypeError = Promise.TypeError = errors.TypeError;
-Promise.RangeError = errors.RangeError;
-var CancellationError = Promise.CancellationError = errors.CancellationError;
-Promise.TimeoutError = errors.TimeoutError;
-Promise.OperationalError = errors.OperationalError;
-Promise.RejectionError = errors.OperationalError;
-Promise.AggregateError = errors.AggregateError;
-var INTERNAL = function(){};
-var APPLY = {};
-var NEXT_FILTER = {};
-var tryConvertToPromise = _dereq_("./thenables")(Promise, INTERNAL);
-var PromiseArray =
- _dereq_("./promise_array")(Promise, INTERNAL,
- tryConvertToPromise, apiRejection, Proxyable);
-var Context = _dereq_("./context")(Promise);
- /*jshint unused:false*/
-var createContext = Context.create;
-var debug = _dereq_("./debuggability")(Promise, Context);
-var CapturedTrace = debug.CapturedTrace;
-var PassThroughHandlerContext =
- _dereq_("./finally")(Promise, tryConvertToPromise, NEXT_FILTER);
-var catchFilter = _dereq_("./catch_filter")(NEXT_FILTER);
-var nodebackForPromise = _dereq_("./nodeback");
-var errorObj = util.errorObj;
-var tryCatch = util.tryCatch;
-function check(self, executor) {
- if (self == null || self.constructor !== Promise) {
- throw new TypeError("the promise constructor cannot be invoked directly\u000a\u000a See http://goo.gl/MqrFmX\u000a");
- }
- if (typeof executor !== "function") {
- throw new TypeError("expecting a function but got " + util.classString(executor));
- }
-
-}
-
-function Promise(executor) {
- if (executor !== INTERNAL) {
- check(this, executor);
- }
- this._bitField = 0;
- this._fulfillmentHandler0 = undefined;
- this._rejectionHandler0 = undefined;
- this._promise0 = undefined;
- this._receiver0 = undefined;
- this._resolveFromExecutor(executor);
- this._promiseCreated();
- this._fireEvent("promiseCreated", this);
-}
-
-Promise.prototype.toString = function () {
- return "[object Promise]";
-};
-
-Promise.prototype.caught = Promise.prototype["catch"] = function (fn) {
- var len = arguments.length;
- if (len > 1) {
- var catchInstances = new Array(len - 1),
- j = 0, i;
- for (i = 0; i < len - 1; ++i) {
- var item = arguments[i];
- if (util.isObject(item)) {
- catchInstances[j++] = item;
- } else {
- return apiRejection("Catch statement predicate: " +
- "expecting an object but got " + util.classString(item));
- }
- }
- catchInstances.length = j;
- fn = arguments[i];
- return this.then(undefined, catchFilter(catchInstances, fn, this));
- }
- return this.then(undefined, fn);
-};
-
-Promise.prototype.reflect = function () {
- return this._then(reflectHandler,
- reflectHandler, undefined, this, undefined);
-};
-
-Promise.prototype.then = function (didFulfill, didReject) {
- if (debug.warnings() && arguments.length > 0 &&
- typeof didFulfill !== "function" &&
- typeof didReject !== "function") {
- var msg = ".then() only accepts functions but was passed: " +
- util.classString(didFulfill);
- if (arguments.length > 1) {
- msg += ", " + util.classString(didReject);
- }
- this._warn(msg);
- }
- return this._then(didFulfill, didReject, undefined, undefined, undefined);
-};
-
-Promise.prototype.done = function (didFulfill, didReject) {
- var promise =
- this._then(didFulfill, didReject, undefined, undefined, undefined);
- promise._setIsFinal();
-};
-
-Promise.prototype.spread = function (fn) {
- if (typeof fn !== "function") {
- return apiRejection("expecting a function but got " + util.classString(fn));
- }
- return this.all()._then(fn, undefined, undefined, APPLY, undefined);
-};
-
-Promise.prototype.toJSON = function () {
- var ret = {
- isFulfilled: false,
- isRejected: false,
- fulfillmentValue: undefined,
- rejectionReason: undefined
- };
- if (this.isFulfilled()) {
- ret.fulfillmentValue = this.value();
- ret.isFulfilled = true;
- } else if (this.isRejected()) {
- ret.rejectionReason = this.reason();
- ret.isRejected = true;
- }
- return ret;
-};
-
-Promise.prototype.all = function () {
- if (arguments.length > 0) {
- this._warn(".all() was passed arguments but it does not take any");
- }
- return new PromiseArray(this).promise();
-};
-
-Promise.prototype.error = function (fn) {
- return this.caught(util.originatesFromRejection, fn);
-};
-
-Promise.getNewLibraryCopy = module.exports;
-
-Promise.is = function (val) {
- return val instanceof Promise;
-};
-
-Promise.fromNode = Promise.fromCallback = function(fn) {
- var ret = new Promise(INTERNAL);
- ret._captureStackTrace();
- var multiArgs = arguments.length > 1 ? !!Object(arguments[1]).multiArgs
- : false;
- var result = tryCatch(fn)(nodebackForPromise(ret, multiArgs));
- if (result === errorObj) {
- ret._rejectCallback(result.e, true);
- }
- if (!ret._isFateSealed()) ret._setAsyncGuaranteed();
- return ret;
-};
-
-Promise.all = function (promises) {
- return new PromiseArray(promises).promise();
-};
-
-Promise.cast = function (obj) {
- var ret = tryConvertToPromise(obj);
- if (!(ret instanceof Promise)) {
- ret = new Promise(INTERNAL);
- ret._captureStackTrace();
- ret._setFulfilled();
- ret._rejectionHandler0 = obj;
- }
- return ret;
-};
-
-Promise.resolve = Promise.fulfilled = Promise.cast;
-
-Promise.reject = Promise.rejected = function (reason) {
- var ret = new Promise(INTERNAL);
- ret._captureStackTrace();
- ret._rejectCallback(reason, true);
- return ret;
-};
-
-Promise.setScheduler = function(fn) {
- if (typeof fn !== "function") {
- throw new TypeError("expecting a function but got " + util.classString(fn));
- }
- return async.setScheduler(fn);
-};
-
-Promise.prototype._then = function (
- didFulfill,
- didReject,
- _, receiver,
- internalData
-) {
- var haveInternalData = internalData !== undefined;
- var promise = haveInternalData ? internalData : new Promise(INTERNAL);
- var target = this._target();
- var bitField = target._bitField;
-
- if (!haveInternalData) {
- promise._propagateFrom(this, 3);
- promise._captureStackTrace();
- if (receiver === undefined &&
- ((this._bitField & 2097152) !== 0)) {
- if (!((bitField & 50397184) === 0)) {
- receiver = this._boundValue();
- } else {
- receiver = target === this ? undefined : this._boundTo;
- }
- }
- this._fireEvent("promiseChained", this, promise);
- }
-
- var domain = getDomain();
- if (!((bitField & 50397184) === 0)) {
- var handler, value, settler = target._settlePromiseCtx;
- if (((bitField & 33554432) !== 0)) {
- value = target._rejectionHandler0;
- handler = didFulfill;
- } else if (((bitField & 16777216) !== 0)) {
- value = target._fulfillmentHandler0;
- handler = didReject;
- target._unsetRejectionIsUnhandled();
- } else {
- settler = target._settlePromiseLateCancellationObserver;
- value = new CancellationError("late cancellation observer");
- target._attachExtraTrace(value);
- handler = didReject;
- }
-
- async.invoke(settler, target, {
- handler: domain === null ? handler
- : (typeof handler === "function" &&
- util.domainBind(domain, handler)),
- promise: promise,
- receiver: receiver,
- value: value
- });
- } else {
- target._addCallbacks(didFulfill, didReject, promise, receiver, domain);
- }
-
- return promise;
-};
-
-Promise.prototype._length = function () {
- return this._bitField & 65535;
-};
-
-Promise.prototype._isFateSealed = function () {
- return (this._bitField & 117506048) !== 0;
-};
-
-Promise.prototype._isFollowing = function () {
- return (this._bitField & 67108864) === 67108864;
-};
-
-Promise.prototype._setLength = function (len) {
- this._bitField = (this._bitField & -65536) |
- (len & 65535);
-};
-
-Promise.prototype._setFulfilled = function () {
- this._bitField = this._bitField | 33554432;
- this._fireEvent("promiseFulfilled", this);
-};
-
-Promise.prototype._setRejected = function () {
- this._bitField = this._bitField | 16777216;
- this._fireEvent("promiseRejected", this);
-};
-
-Promise.prototype._setFollowing = function () {
- this._bitField = this._bitField | 67108864;
- this._fireEvent("promiseResolved", this);
-};
-
-Promise.prototype._setIsFinal = function () {
- this._bitField = this._bitField | 4194304;
-};
-
-Promise.prototype._isFinal = function () {
- return (this._bitField & 4194304) > 0;
-};
-
-Promise.prototype._unsetCancelled = function() {
- this._bitField = this._bitField & (~65536);
-};
-
-Promise.prototype._setCancelled = function() {
- this._bitField = this._bitField | 65536;
- this._fireEvent("promiseCancelled", this);
-};
-
-Promise.prototype._setWillBeCancelled = function() {
- this._bitField = this._bitField | 8388608;
-};
-
-Promise.prototype._setAsyncGuaranteed = function() {
- if (async.hasCustomScheduler()) return;
- this._bitField = this._bitField | 134217728;
-};
-
-Promise.prototype._receiverAt = function (index) {
- var ret = index === 0 ? this._receiver0 : this[
- index * 4 - 4 + 3];
- if (ret === UNDEFINED_BINDING) {
- return undefined;
- } else if (ret === undefined && this._isBound()) {
- return this._boundValue();
- }
- return ret;
-};
-
-Promise.prototype._promiseAt = function (index) {
- return this[
- index * 4 - 4 + 2];
-};
-
-Promise.prototype._fulfillmentHandlerAt = function (index) {
- return this[
- index * 4 - 4 + 0];
-};
-
-Promise.prototype._rejectionHandlerAt = function (index) {
- return this[
- index * 4 - 4 + 1];
-};
-
-Promise.prototype._boundValue = function() {};
-
-Promise.prototype._migrateCallback0 = function (follower) {
- var bitField = follower._bitField;
- var fulfill = follower._fulfillmentHandler0;
- var reject = follower._rejectionHandler0;
- var promise = follower._promise0;
- var receiver = follower._receiverAt(0);
- if (receiver === undefined) receiver = UNDEFINED_BINDING;
- this._addCallbacks(fulfill, reject, promise, receiver, null);
-};
-
-Promise.prototype._migrateCallbackAt = function (follower, index) {
- var fulfill = follower._fulfillmentHandlerAt(index);
- var reject = follower._rejectionHandlerAt(index);
- var promise = follower._promiseAt(index);
- var receiver = follower._receiverAt(index);
- if (receiver === undefined) receiver = UNDEFINED_BINDING;
- this._addCallbacks(fulfill, reject, promise, receiver, null);
-};
-
-Promise.prototype._addCallbacks = function (
- fulfill,
- reject,
- promise,
- receiver,
- domain
-) {
- var index = this._length();
-
- if (index >= 65535 - 4) {
- index = 0;
- this._setLength(0);
- }
-
- if (index === 0) {
- this._promise0 = promise;
- this._receiver0 = receiver;
- if (typeof fulfill === "function") {
- this._fulfillmentHandler0 =
- domain === null ? fulfill : util.domainBind(domain, fulfill);
- }
- if (typeof reject === "function") {
- this._rejectionHandler0 =
- domain === null ? reject : util.domainBind(domain, reject);
- }
- } else {
- var base = index * 4 - 4;
- this[base + 2] = promise;
- this[base + 3] = receiver;
- if (typeof fulfill === "function") {
- this[base + 0] =
- domain === null ? fulfill : util.domainBind(domain, fulfill);
- }
- if (typeof reject === "function") {
- this[base + 1] =
- domain === null ? reject : util.domainBind(domain, reject);
- }
- }
- this._setLength(index + 1);
- return index;
-};
-
-Promise.prototype._proxy = function (proxyable, arg) {
- this._addCallbacks(undefined, undefined, arg, proxyable, null);
-};
-
-Promise.prototype._resolveCallback = function(value, shouldBind) {
- if (((this._bitField & 117506048) !== 0)) return;
- if (value === this)
- return this._rejectCallback(makeSelfResolutionError(), false);
- var maybePromise = tryConvertToPromise(value, this);
- if (!(maybePromise instanceof Promise)) return this._fulfill(value);
-
- if (shouldBind) this._propagateFrom(maybePromise, 2);
-
- var promise = maybePromise._target();
-
- if (promise === this) {
- this._reject(makeSelfResolutionError());
- return;
- }
-
- var bitField = promise._bitField;
- if (((bitField & 50397184) === 0)) {
- var len = this._length();
- if (len > 0) promise._migrateCallback0(this);
- for (var i = 1; i < len; ++i) {
- promise._migrateCallbackAt(this, i);
- }
- this._setFollowing();
- this._setLength(0);
- this._setFollowee(promise);
- } else if (((bitField & 33554432) !== 0)) {
- this._fulfill(promise._value());
- } else if (((bitField & 16777216) !== 0)) {
- this._reject(promise._reason());
- } else {
- var reason = new CancellationError("late cancellation observer");
- promise._attachExtraTrace(reason);
- this._reject(reason);
- }
-};
-
-Promise.prototype._rejectCallback =
-function(reason, synchronous, ignoreNonErrorWarnings) {
- var trace = util.ensureErrorObject(reason);
- var hasStack = trace === reason;
- if (!hasStack && !ignoreNonErrorWarnings && debug.warnings()) {
- var message = "a promise was rejected with a non-error: " +
- util.classString(reason);
- this._warn(message, true);
- }
- this._attachExtraTrace(trace, synchronous ? hasStack : false);
- this._reject(reason);
-};
-
-Promise.prototype._resolveFromExecutor = function (executor) {
- if (executor === INTERNAL) return;
- var promise = this;
- this._captureStackTrace();
- this._pushContext();
- var synchronous = true;
- var r = this._execute(executor, function(value) {
- promise._resolveCallback(value);
- }, function (reason) {
- promise._rejectCallback(reason, synchronous);
- });
- synchronous = false;
- this._popContext();
-
- if (r !== undefined) {
- promise._rejectCallback(r, true);
- }
-};
-
-Promise.prototype._settlePromiseFromHandler = function (
- handler, receiver, value, promise
-) {
- var bitField = promise._bitField;
- if (((bitField & 65536) !== 0)) return;
- promise._pushContext();
- var x;
- if (receiver === APPLY) {
- if (!value || typeof value.length !== "number") {
- x = errorObj;
- x.e = new TypeError("cannot .spread() a non-array: " +
- util.classString(value));
- } else {
- x = tryCatch(handler).apply(this._boundValue(), value);
- }
- } else {
- x = tryCatch(handler).call(receiver, value);
- }
- var promiseCreated = promise._popContext();
- bitField = promise._bitField;
- if (((bitField & 65536) !== 0)) return;
-
- if (x === NEXT_FILTER) {
- promise._reject(value);
- } else if (x === errorObj) {
- promise._rejectCallback(x.e, false);
- } else {
- debug.checkForgottenReturns(x, promiseCreated, "", promise, this);
- promise._resolveCallback(x);
- }
-};
-
-Promise.prototype._target = function() {
- var ret = this;
- while (ret._isFollowing()) ret = ret._followee();
- return ret;
-};
-
-Promise.prototype._followee = function() {
- return this._rejectionHandler0;
-};
-
-Promise.prototype._setFollowee = function(promise) {
- this._rejectionHandler0 = promise;
-};
-
-Promise.prototype._settlePromise = function(promise, handler, receiver, value) {
- var isPromise = promise instanceof Promise;
- var bitField = this._bitField;
- var asyncGuaranteed = ((bitField & 134217728) !== 0);
- if (((bitField & 65536) !== 0)) {
- if (isPromise) promise._invokeInternalOnCancel();
-
- if (receiver instanceof PassThroughHandlerContext &&
- receiver.isFinallyHandler()) {
- receiver.cancelPromise = promise;
- if (tryCatch(handler).call(receiver, value) === errorObj) {
- promise._reject(errorObj.e);
- }
- } else if (handler === reflectHandler) {
- promise._fulfill(reflectHandler.call(receiver));
- } else if (receiver instanceof Proxyable) {
- receiver._promiseCancelled(promise);
- } else if (isPromise || promise instanceof PromiseArray) {
- promise._cancel();
- } else {
- receiver.cancel();
- }
- } else if (typeof handler === "function") {
- if (!isPromise) {
- handler.call(receiver, value, promise);
- } else {
- if (asyncGuaranteed) promise._setAsyncGuaranteed();
- this._settlePromiseFromHandler(handler, receiver, value, promise);
- }
- } else if (receiver instanceof Proxyable) {
- if (!receiver._isResolved()) {
- if (((bitField & 33554432) !== 0)) {
- receiver._promiseFulfilled(value, promise);
- } else {
- receiver._promiseRejected(value, promise);
- }
- }
- } else if (isPromise) {
- if (asyncGuaranteed) promise._setAsyncGuaranteed();
- if (((bitField & 33554432) !== 0)) {
- promise._fulfill(value);
- } else {
- promise._reject(value);
- }
- }
-};
-
-Promise.prototype._settlePromiseLateCancellationObserver = function(ctx) {
- var handler = ctx.handler;
- var promise = ctx.promise;
- var receiver = ctx.receiver;
- var value = ctx.value;
- if (typeof handler === "function") {
- if (!(promise instanceof Promise)) {
- handler.call(receiver, value, promise);
- } else {
- this._settlePromiseFromHandler(handler, receiver, value, promise);
- }
- } else if (promise instanceof Promise) {
- promise._reject(value);
- }
-};
-
-Promise.prototype._settlePromiseCtx = function(ctx) {
- this._settlePromise(ctx.promise, ctx.handler, ctx.receiver, ctx.value);
-};
-
-Promise.prototype._settlePromise0 = function(handler, value, bitField) {
- var promise = this._promise0;
- var receiver = this._receiverAt(0);
- this._promise0 = undefined;
- this._receiver0 = undefined;
- this._settlePromise(promise, handler, receiver, value);
-};
-
-Promise.prototype._clearCallbackDataAtIndex = function(index) {
- var base = index * 4 - 4;
- this[base + 2] =
- this[base + 3] =
- this[base + 0] =
- this[base + 1] = undefined;
-};
-
-Promise.prototype._fulfill = function (value) {
- var bitField = this._bitField;
- if (((bitField & 117506048) >>> 16)) return;
- if (value === this) {
- var err = makeSelfResolutionError();
- this._attachExtraTrace(err);
- return this._reject(err);
- }
- this._setFulfilled();
- this._rejectionHandler0 = value;
-
- if ((bitField & 65535) > 0) {
- if (((bitField & 134217728) !== 0)) {
- this._settlePromises();
- } else {
- async.settlePromises(this);
- }
- }
-};
-
-Promise.prototype._reject = function (reason) {
- var bitField = this._bitField;
- if (((bitField & 117506048) >>> 16)) return;
- this._setRejected();
- this._fulfillmentHandler0 = reason;
-
- if (this._isFinal()) {
- return async.fatalError(reason, util.isNode);
- }
-
- if ((bitField & 65535) > 0) {
- async.settlePromises(this);
- } else {
- this._ensurePossibleRejectionHandled();
- }
-};
-
-Promise.prototype._fulfillPromises = function (len, value) {
- for (var i = 1; i < len; i++) {
- var handler = this._fulfillmentHandlerAt(i);
- var promise = this._promiseAt(i);
- var receiver = this._receiverAt(i);
- this._clearCallbackDataAtIndex(i);
- this._settlePromise(promise, handler, receiver, value);
- }
-};
-
-Promise.prototype._rejectPromises = function (len, reason) {
- for (var i = 1; i < len; i++) {
- var handler = this._rejectionHandlerAt(i);
- var promise = this._promiseAt(i);
- var receiver = this._receiverAt(i);
- this._clearCallbackDataAtIndex(i);
- this._settlePromise(promise, handler, receiver, reason);
- }
-};
-
-Promise.prototype._settlePromises = function () {
- var bitField = this._bitField;
- var len = (bitField & 65535);
-
- if (len > 0) {
- if (((bitField & 16842752) !== 0)) {
- var reason = this._fulfillmentHandler0;
- this._settlePromise0(this._rejectionHandler0, reason, bitField);
- this._rejectPromises(len, reason);
- } else {
- var value = this._rejectionHandler0;
- this._settlePromise0(this._fulfillmentHandler0, value, bitField);
- this._fulfillPromises(len, value);
- }
- this._setLength(0);
- }
- this._clearCancellationData();
-};
-
-Promise.prototype._settledValue = function() {
- var bitField = this._bitField;
- if (((bitField & 33554432) !== 0)) {
- return this._rejectionHandler0;
- } else if (((bitField & 16777216) !== 0)) {
- return this._fulfillmentHandler0;
- }
-};
-
-function deferResolve(v) {this.promise._resolveCallback(v);}
-function deferReject(v) {this.promise._rejectCallback(v, false);}
-
-Promise.defer = Promise.pending = function() {
- debug.deprecated("Promise.defer", "new Promise");
- var promise = new Promise(INTERNAL);
- return {
- promise: promise,
- resolve: deferResolve,
- reject: deferReject
- };
-};
-
-util.notEnumerableProp(Promise,
- "_makeSelfResolutionError",
- makeSelfResolutionError);
-
-_dereq_("./method")(Promise, INTERNAL, tryConvertToPromise, apiRejection,
- debug);
-_dereq_("./bind")(Promise, INTERNAL, tryConvertToPromise, debug);
-_dereq_("./cancel")(Promise, PromiseArray, apiRejection, debug);
-_dereq_("./direct_resolve")(Promise);
-_dereq_("./synchronous_inspection")(Promise);
-_dereq_("./join")(
- Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, getDomain);
-Promise.Promise = Promise;
-Promise.version = "3.5.0";
-_dereq_('./map.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug);
-_dereq_('./call_get.js')(Promise);
-_dereq_('./using.js')(Promise, apiRejection, tryConvertToPromise, createContext, INTERNAL, debug);
-_dereq_('./timers.js')(Promise, INTERNAL, debug);
-_dereq_('./generators.js')(Promise, apiRejection, INTERNAL, tryConvertToPromise, Proxyable, debug);
-_dereq_('./nodeify.js')(Promise);
-_dereq_('./promisify.js')(Promise, INTERNAL);
-_dereq_('./props.js')(Promise, PromiseArray, tryConvertToPromise, apiRejection);
-_dereq_('./race.js')(Promise, INTERNAL, tryConvertToPromise, apiRejection);
-_dereq_('./reduce.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug);
-_dereq_('./settle.js')(Promise, PromiseArray, debug);
-_dereq_('./some.js')(Promise, PromiseArray, apiRejection);
-_dereq_('./filter.js')(Promise, INTERNAL);
-_dereq_('./each.js')(Promise, INTERNAL);
-_dereq_('./any.js')(Promise);
-
- util.toFastProperties(Promise);
- util.toFastProperties(Promise.prototype);
- function fillTypes(value) {
- var p = new Promise(INTERNAL);
- p._fulfillmentHandler0 = value;
- p._rejectionHandler0 = value;
- p._promise0 = value;
- p._receiver0 = value;
- }
- // Complete slack tracking, opt out of field-type tracking and
- // stabilize map
- fillTypes({a: 1});
- fillTypes({b: 2});
- fillTypes({c: 3});
- fillTypes(1);
- fillTypes(function(){});
- fillTypes(undefined);
- fillTypes(false);
- fillTypes(new Promise(INTERNAL));
- debug.setBounds(Async.firstLineError, util.lastLineError);
- return Promise;
-
-};
-
-},{"./any.js":1,"./async":2,"./bind":3,"./call_get.js":5,"./cancel":6,"./catch_filter":7,"./context":8,"./debuggability":9,"./direct_resolve":10,"./each.js":11,"./errors":12,"./es5":13,"./filter.js":14,"./finally":15,"./generators.js":16,"./join":17,"./map.js":18,"./method":19,"./nodeback":20,"./nodeify.js":21,"./promise_array":23,"./promisify.js":24,"./props.js":25,"./race.js":27,"./reduce.js":28,"./settle.js":30,"./some.js":31,"./synchronous_inspection":32,"./thenables":33,"./timers.js":34,"./using.js":35,"./util":36}],23:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise, INTERNAL, tryConvertToPromise,
- apiRejection, Proxyable) {
-var util = _dereq_("./util");
-var isArray = util.isArray;
-
-function toResolutionValue(val) {
- switch(val) {
- case -2: return [];
- case -3: return {};
- case -6: return new Map();
- }
-}
-
-function PromiseArray(values) {
- var promise = this._promise = new Promise(INTERNAL);
- if (values instanceof Promise) {
- promise._propagateFrom(values, 3);
- }
- promise._setOnCancel(this);
- this._values = values;
- this._length = 0;
- this._totalResolved = 0;
- this._init(undefined, -2);
-}
-util.inherits(PromiseArray, Proxyable);
-
-PromiseArray.prototype.length = function () {
- return this._length;
-};
-
-PromiseArray.prototype.promise = function () {
- return this._promise;
-};
-
-PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) {
- var values = tryConvertToPromise(this._values, this._promise);
- if (values instanceof Promise) {
- values = values._target();
- var bitField = values._bitField;
- ;
- this._values = values;
-
- if (((bitField & 50397184) === 0)) {
- this._promise._setAsyncGuaranteed();
- return values._then(
- init,
- this._reject,
- undefined,
- this,
- resolveValueIfEmpty
- );
- } else if (((bitField & 33554432) !== 0)) {
- values = values._value();
- } else if (((bitField & 16777216) !== 0)) {
- return this._reject(values._reason());
- } else {
- return this._cancel();
- }
- }
- values = util.asArray(values);
- if (values === null) {
- var err = apiRejection(
- "expecting an array or an iterable object but got " + util.classString(values)).reason();
- this._promise._rejectCallback(err, false);
- return;
- }
-
- if (values.length === 0) {
- if (resolveValueIfEmpty === -5) {
- this._resolveEmptyArray();
- }
- else {
- this._resolve(toResolutionValue(resolveValueIfEmpty));
- }
- return;
- }
- this._iterate(values);
-};
-
-PromiseArray.prototype._iterate = function(values) {
- var len = this.getActualLength(values.length);
- this._length = len;
- this._values = this.shouldCopyValues() ? new Array(len) : this._values;
- var result = this._promise;
- var isResolved = false;
- var bitField = null;
- for (var i = 0; i < len; ++i) {
- var maybePromise = tryConvertToPromise(values[i], result);
-
- if (maybePromise instanceof Promise) {
- maybePromise = maybePromise._target();
- bitField = maybePromise._bitField;
- } else {
- bitField = null;
- }
-
- if (isResolved) {
- if (bitField !== null) {
- maybePromise.suppressUnhandledRejections();
- }
- } else if (bitField !== null) {
- if (((bitField & 50397184) === 0)) {
- maybePromise._proxy(this, i);
- this._values[i] = maybePromise;
- } else if (((bitField & 33554432) !== 0)) {
- isResolved = this._promiseFulfilled(maybePromise._value(), i);
- } else if (((bitField & 16777216) !== 0)) {
- isResolved = this._promiseRejected(maybePromise._reason(), i);
- } else {
- isResolved = this._promiseCancelled(i);
- }
- } else {
- isResolved = this._promiseFulfilled(maybePromise, i);
- }
- }
- if (!isResolved) result._setAsyncGuaranteed();
-};
-
-PromiseArray.prototype._isResolved = function () {
- return this._values === null;
-};
-
-PromiseArray.prototype._resolve = function (value) {
- this._values = null;
- this._promise._fulfill(value);
-};
-
-PromiseArray.prototype._cancel = function() {
- if (this._isResolved() || !this._promise._isCancellable()) return;
- this._values = null;
- this._promise._cancel();
-};
-
-PromiseArray.prototype._reject = function (reason) {
- this._values = null;
- this._promise._rejectCallback(reason, false);
-};
-
-PromiseArray.prototype._promiseFulfilled = function (value, index) {
- this._values[index] = value;
- var totalResolved = ++this._totalResolved;
- if (totalResolved >= this._length) {
- this._resolve(this._values);
- return true;
- }
- return false;
-};
-
-PromiseArray.prototype._promiseCancelled = function() {
- this._cancel();
- return true;
-};
-
-PromiseArray.prototype._promiseRejected = function (reason) {
- this._totalResolved++;
- this._reject(reason);
- return true;
-};
-
-PromiseArray.prototype._resultCancelled = function() {
- if (this._isResolved()) return;
- var values = this._values;
- this._cancel();
- if (values instanceof Promise) {
- values.cancel();
- } else {
- for (var i = 0; i < values.length; ++i) {
- if (values[i] instanceof Promise) {
- values[i].cancel();
- }
- }
- }
-};
-
-PromiseArray.prototype.shouldCopyValues = function () {
- return true;
-};
-
-PromiseArray.prototype.getActualLength = function (len) {
- return len;
-};
-
-return PromiseArray;
-};
-
-},{"./util":36}],24:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise, INTERNAL) {
-var THIS = {};
-var util = _dereq_("./util");
-var nodebackForPromise = _dereq_("./nodeback");
-var withAppended = util.withAppended;
-var maybeWrapAsError = util.maybeWrapAsError;
-var canEvaluate = util.canEvaluate;
-var TypeError = _dereq_("./errors").TypeError;
-var defaultSuffix = "Async";
-var defaultPromisified = {__isPromisified__: true};
-var noCopyProps = [
- "arity", "length",
- "name",
- "arguments",
- "caller",
- "callee",
- "prototype",
- "__isPromisified__"
-];
-var noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$");
-
-var defaultFilter = function(name) {
- return util.isIdentifier(name) &&
- name.charAt(0) !== "_" &&
- name !== "constructor";
-};
-
-function propsFilter(key) {
- return !noCopyPropsPattern.test(key);
-}
-
-function isPromisified(fn) {
- try {
- return fn.__isPromisified__ === true;
- }
- catch (e) {
- return false;
- }
-}
-
-function hasPromisified(obj, key, suffix) {
- var val = util.getDataPropertyOrDefault(obj, key + suffix,
- defaultPromisified);
- return val ? isPromisified(val) : false;
-}
-function checkValid(ret, suffix, suffixRegexp) {
- for (var i = 0; i < ret.length; i += 2) {
- var key = ret[i];
- if (suffixRegexp.test(key)) {
- var keyWithoutAsyncSuffix = key.replace(suffixRegexp, "");
- for (var j = 0; j < ret.length; j += 2) {
- if (ret[j] === keyWithoutAsyncSuffix) {
- throw new TypeError("Cannot promisify an API that has normal methods with '%s'-suffix\u000a\u000a See http://goo.gl/MqrFmX\u000a"
- .replace("%s", suffix));
- }
- }
- }
- }
-}
-
-function promisifiableMethods(obj, suffix, suffixRegexp, filter) {
- var keys = util.inheritedDataKeys(obj);
- var ret = [];
- for (var i = 0; i < keys.length; ++i) {
- var key = keys[i];
- var value = obj[key];
- var passesDefaultFilter = filter === defaultFilter
- ? true : defaultFilter(key, value, obj);
- if (typeof value === "function" &&
- !isPromisified(value) &&
- !hasPromisified(obj, key, suffix) &&
- filter(key, value, obj, passesDefaultFilter)) {
- ret.push(key, value);
- }
- }
- checkValid(ret, suffix, suffixRegexp);
- return ret;
-}
-
-var escapeIdentRegex = function(str) {
- return str.replace(/([$])/, "\\$");
-};
-
-var makeNodePromisifiedEval;
-if (!true) {
-var switchCaseArgumentOrder = function(likelyArgumentCount) {
- var ret = [likelyArgumentCount];
- var min = Math.max(0, likelyArgumentCount - 1 - 3);
- for(var i = likelyArgumentCount - 1; i >= min; --i) {
- ret.push(i);
- }
- for(var i = likelyArgumentCount + 1; i <= 3; ++i) {
- ret.push(i);
- }
- return ret;
-};
-
-var argumentSequence = function(argumentCount) {
- return util.filledRange(argumentCount, "_arg", "");
-};
-
-var parameterDeclaration = function(parameterCount) {
- return util.filledRange(
- Math.max(parameterCount, 3), "_arg", "");
-};
-
-var parameterCount = function(fn) {
- if (typeof fn.length === "number") {
- return Math.max(Math.min(fn.length, 1023 + 1), 0);
- }
- return 0;
-};
-
-makeNodePromisifiedEval =
-function(callback, receiver, originalName, fn, _, multiArgs) {
- var newParameterCount = Math.max(0, parameterCount(fn) - 1);
- var argumentOrder = switchCaseArgumentOrder(newParameterCount);
- var shouldProxyThis = typeof callback === "string" || receiver === THIS;
-
- function generateCallForArgumentCount(count) {
- var args = argumentSequence(count).join(", ");
- var comma = count > 0 ? ", " : "";
- var ret;
- if (shouldProxyThis) {
- ret = "ret = callback.call(this, {{args}}, nodeback); break;\n";
- } else {
- ret = receiver === undefined
- ? "ret = callback({{args}}, nodeback); break;\n"
- : "ret = callback.call(receiver, {{args}}, nodeback); break;\n";
- }
- return ret.replace("{{args}}", args).replace(", ", comma);
- }
-
- function generateArgumentSwitchCase() {
- var ret = "";
- for (var i = 0; i < argumentOrder.length; ++i) {
- ret += "case " + argumentOrder[i] +":" +
- generateCallForArgumentCount(argumentOrder[i]);
- }
-
- ret += " \n\
- default: \n\
- var args = new Array(len + 1); \n\
- var i = 0; \n\
- for (var i = 0; i < len; ++i) { \n\
- args[i] = arguments[i]; \n\
- } \n\
- args[i] = nodeback; \n\
- [CodeForCall] \n\
- break; \n\
- ".replace("[CodeForCall]", (shouldProxyThis
- ? "ret = callback.apply(this, args);\n"
- : "ret = callback.apply(receiver, args);\n"));
- return ret;
- }
-
- var getFunctionCode = typeof callback === "string"
- ? ("this != null ? this['"+callback+"'] : fn")
- : "fn";
- var body = "'use strict'; \n\
- var ret = function (Parameters) { \n\
- 'use strict'; \n\
- var len = arguments.length; \n\
- var promise = new Promise(INTERNAL); \n\
- promise._captureStackTrace(); \n\
- var nodeback = nodebackForPromise(promise, " + multiArgs + "); \n\
- var ret; \n\
- var callback = tryCatch([GetFunctionCode]); \n\
- switch(len) { \n\
- [CodeForSwitchCase] \n\
- } \n\
- if (ret === errorObj) { \n\
- promise._rejectCallback(maybeWrapAsError(ret.e), true, true);\n\
- } \n\
- if (!promise._isFateSealed()) promise._setAsyncGuaranteed(); \n\
- return promise; \n\
- }; \n\
- notEnumerableProp(ret, '__isPromisified__', true); \n\
- return ret; \n\
- ".replace("[CodeForSwitchCase]", generateArgumentSwitchCase())
- .replace("[GetFunctionCode]", getFunctionCode);
- body = body.replace("Parameters", parameterDeclaration(newParameterCount));
- return new Function("Promise",
- "fn",
- "receiver",
- "withAppended",
- "maybeWrapAsError",
- "nodebackForPromise",
- "tryCatch",
- "errorObj",
- "notEnumerableProp",
- "INTERNAL",
- body)(
- Promise,
- fn,
- receiver,
- withAppended,
- maybeWrapAsError,
- nodebackForPromise,
- util.tryCatch,
- util.errorObj,
- util.notEnumerableProp,
- INTERNAL);
-};
-}
-
-function makeNodePromisifiedClosure(callback, receiver, _, fn, __, multiArgs) {
- var defaultThis = (function() {return this;})();
- var method = callback;
- if (typeof method === "string") {
- callback = fn;
- }
- function promisified() {
- var _receiver = receiver;
- if (receiver === THIS) _receiver = this;
- var promise = new Promise(INTERNAL);
- promise._captureStackTrace();
- var cb = typeof method === "string" && this !== defaultThis
- ? this[method] : callback;
- var fn = nodebackForPromise(promise, multiArgs);
- try {
- cb.apply(_receiver, withAppended(arguments, fn));
- } catch(e) {
- promise._rejectCallback(maybeWrapAsError(e), true, true);
- }
- if (!promise._isFateSealed()) promise._setAsyncGuaranteed();
- return promise;
- }
- util.notEnumerableProp(promisified, "__isPromisified__", true);
- return promisified;
-}
-
-var makeNodePromisified = canEvaluate
- ? makeNodePromisifiedEval
- : makeNodePromisifiedClosure;
-
-function promisifyAll(obj, suffix, filter, promisifier, multiArgs) {
- var suffixRegexp = new RegExp(escapeIdentRegex(suffix) + "$");
- var methods =
- promisifiableMethods(obj, suffix, suffixRegexp, filter);
-
- for (var i = 0, len = methods.length; i < len; i+= 2) {
- var key = methods[i];
- var fn = methods[i+1];
- var promisifiedKey = key + suffix;
- if (promisifier === makeNodePromisified) {
- obj[promisifiedKey] =
- makeNodePromisified(key, THIS, key, fn, suffix, multiArgs);
- } else {
- var promisified = promisifier(fn, function() {
- return makeNodePromisified(key, THIS, key,
- fn, suffix, multiArgs);
- });
- util.notEnumerableProp(promisified, "__isPromisified__", true);
- obj[promisifiedKey] = promisified;
- }
- }
- util.toFastProperties(obj);
- return obj;
-}
-
-function promisify(callback, receiver, multiArgs) {
- return makeNodePromisified(callback, receiver, undefined,
- callback, null, multiArgs);
-}
-
-Promise.promisify = function (fn, options) {
- if (typeof fn !== "function") {
- throw new TypeError("expecting a function but got " + util.classString(fn));
- }
- if (isPromisified(fn)) {
- return fn;
- }
- options = Object(options);
- var receiver = options.context === undefined ? THIS : options.context;
- var multiArgs = !!options.multiArgs;
- var ret = promisify(fn, receiver, multiArgs);
- util.copyDescriptors(fn, ret, propsFilter);
- return ret;
-};
-
-Promise.promisifyAll = function (target, options) {
- if (typeof target !== "function" && typeof target !== "object") {
- throw new TypeError("the target of promisifyAll must be an object or a function\u000a\u000a See http://goo.gl/MqrFmX\u000a");
- }
- options = Object(options);
- var multiArgs = !!options.multiArgs;
- var suffix = options.suffix;
- if (typeof suffix !== "string") suffix = defaultSuffix;
- var filter = options.filter;
- if (typeof filter !== "function") filter = defaultFilter;
- var promisifier = options.promisifier;
- if (typeof promisifier !== "function") promisifier = makeNodePromisified;
-
- if (!util.isIdentifier(suffix)) {
- throw new RangeError("suffix must be a valid identifier\u000a\u000a See http://goo.gl/MqrFmX\u000a");
- }
-
- var keys = util.inheritedDataKeys(target);
- for (var i = 0; i < keys.length; ++i) {
- var value = target[keys[i]];
- if (keys[i] !== "constructor" &&
- util.isClass(value)) {
- promisifyAll(value.prototype, suffix, filter, promisifier,
- multiArgs);
- promisifyAll(value, suffix, filter, promisifier, multiArgs);
- }
- }
-
- return promisifyAll(target, suffix, filter, promisifier, multiArgs);
-};
-};
-
-
-},{"./errors":12,"./nodeback":20,"./util":36}],25:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(
- Promise, PromiseArray, tryConvertToPromise, apiRejection) {
-var util = _dereq_("./util");
-var isObject = util.isObject;
-var es5 = _dereq_("./es5");
-var Es6Map;
-if (typeof Map === "function") Es6Map = Map;
-
-var mapToEntries = (function() {
- var index = 0;
- var size = 0;
-
- function extractEntry(value, key) {
- this[index] = value;
- this[index + size] = key;
- index++;
- }
-
- return function mapToEntries(map) {
- size = map.size;
- index = 0;
- var ret = new Array(map.size * 2);
- map.forEach(extractEntry, ret);
- return ret;
- };
-})();
-
-var entriesToMap = function(entries) {
- var ret = new Es6Map();
- var length = entries.length / 2 | 0;
- for (var i = 0; i < length; ++i) {
- var key = entries[length + i];
- var value = entries[i];
- ret.set(key, value);
- }
- return ret;
-};
-
-function PropertiesPromiseArray(obj) {
- var isMap = false;
- var entries;
- if (Es6Map !== undefined && obj instanceof Es6Map) {
- entries = mapToEntries(obj);
- isMap = true;
- } else {
- var keys = es5.keys(obj);
- var len = keys.length;
- entries = new Array(len * 2);
- for (var i = 0; i < len; ++i) {
- var key = keys[i];
- entries[i] = obj[key];
- entries[i + len] = key;
- }
- }
- this.constructor$(entries);
- this._isMap = isMap;
- this._init$(undefined, isMap ? -6 : -3);
-}
-util.inherits(PropertiesPromiseArray, PromiseArray);
-
-PropertiesPromiseArray.prototype._init = function () {};
-
-PropertiesPromiseArray.prototype._promiseFulfilled = function (value, index) {
- this._values[index] = value;
- var totalResolved = ++this._totalResolved;
- if (totalResolved >= this._length) {
- var val;
- if (this._isMap) {
- val = entriesToMap(this._values);
- } else {
- val = {};
- var keyOffset = this.length();
- for (var i = 0, len = this.length(); i < len; ++i) {
- val[this._values[i + keyOffset]] = this._values[i];
- }
- }
- this._resolve(val);
- return true;
- }
- return false;
-};
-
-PropertiesPromiseArray.prototype.shouldCopyValues = function () {
- return false;
-};
-
-PropertiesPromiseArray.prototype.getActualLength = function (len) {
- return len >> 1;
-};
-
-function props(promises) {
- var ret;
- var castValue = tryConvertToPromise(promises);
-
- if (!isObject(castValue)) {
- return apiRejection("cannot await properties of a non-object\u000a\u000a See http://goo.gl/MqrFmX\u000a");
- } else if (castValue instanceof Promise) {
- ret = castValue._then(
- Promise.props, undefined, undefined, undefined, undefined);
- } else {
- ret = new PropertiesPromiseArray(castValue).promise();
- }
-
- if (castValue instanceof Promise) {
- ret._propagateFrom(castValue, 2);
- }
- return ret;
-}
-
-Promise.prototype.props = function () {
- return props(this);
-};
-
-Promise.props = function (promises) {
- return props(promises);
-};
-};
-
-},{"./es5":13,"./util":36}],26:[function(_dereq_,module,exports){
-"use strict";
-function arrayMove(src, srcIndex, dst, dstIndex, len) {
- for (var j = 0; j < len; ++j) {
- dst[j + dstIndex] = src[j + srcIndex];
- src[j + srcIndex] = void 0;
- }
-}
-
-function Queue(capacity) {
- this._capacity = capacity;
- this._length = 0;
- this._front = 0;
-}
-
-Queue.prototype._willBeOverCapacity = function (size) {
- return this._capacity < size;
-};
-
-Queue.prototype._pushOne = function (arg) {
- var length = this.length();
- this._checkCapacity(length + 1);
- var i = (this._front + length) & (this._capacity - 1);
- this[i] = arg;
- this._length = length + 1;
-};
-
-Queue.prototype.push = function (fn, receiver, arg) {
- var length = this.length() + 3;
- if (this._willBeOverCapacity(length)) {
- this._pushOne(fn);
- this._pushOne(receiver);
- this._pushOne(arg);
- return;
- }
- var j = this._front + length - 3;
- this._checkCapacity(length);
- var wrapMask = this._capacity - 1;
- this[(j + 0) & wrapMask] = fn;
- this[(j + 1) & wrapMask] = receiver;
- this[(j + 2) & wrapMask] = arg;
- this._length = length;
-};
-
-Queue.prototype.shift = function () {
- var front = this._front,
- ret = this[front];
-
- this[front] = undefined;
- this._front = (front + 1) & (this._capacity - 1);
- this._length--;
- return ret;
-};
-
-Queue.prototype.length = function () {
- return this._length;
-};
-
-Queue.prototype._checkCapacity = function (size) {
- if (this._capacity < size) {
- this._resizeTo(this._capacity << 1);
- }
-};
-
-Queue.prototype._resizeTo = function (capacity) {
- var oldCapacity = this._capacity;
- this._capacity = capacity;
- var front = this._front;
- var length = this._length;
- var moveItemsCount = (front + length) & (oldCapacity - 1);
- arrayMove(this, 0, this, oldCapacity, moveItemsCount);
-};
-
-module.exports = Queue;
-
-},{}],27:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(
- Promise, INTERNAL, tryConvertToPromise, apiRejection) {
-var util = _dereq_("./util");
-
-var raceLater = function (promise) {
- return promise.then(function(array) {
- return race(array, promise);
- });
-};
-
-function race(promises, parent) {
- var maybePromise = tryConvertToPromise(promises);
-
- if (maybePromise instanceof Promise) {
- return raceLater(maybePromise);
- } else {
- promises = util.asArray(promises);
- if (promises === null)
- return apiRejection("expecting an array or an iterable object but got " + util.classString(promises));
- }
-
- var ret = new Promise(INTERNAL);
- if (parent !== undefined) {
- ret._propagateFrom(parent, 3);
- }
- var fulfill = ret._fulfill;
- var reject = ret._reject;
- for (var i = 0, len = promises.length; i < len; ++i) {
- var val = promises[i];
-
- if (val === undefined && !(i in promises)) {
- continue;
- }
-
- Promise.cast(val)._then(fulfill, reject, undefined, ret, null);
- }
- return ret;
-}
-
-Promise.race = function (promises) {
- return race(promises, undefined);
-};
-
-Promise.prototype.race = function () {
- return race(this, undefined);
-};
-
-};
-
-},{"./util":36}],28:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise,
- PromiseArray,
- apiRejection,
- tryConvertToPromise,
- INTERNAL,
- debug) {
-var getDomain = Promise._getDomain;
-var util = _dereq_("./util");
-var tryCatch = util.tryCatch;
-
-function ReductionPromiseArray(promises, fn, initialValue, _each) {
- this.constructor$(promises);
- var domain = getDomain();
- this._fn = domain === null ? fn : util.domainBind(domain, fn);
- if (initialValue !== undefined) {
- initialValue = Promise.resolve(initialValue);
- initialValue._attachCancellationCallback(this);
- }
- this._initialValue = initialValue;
- this._currentCancellable = null;
- if(_each === INTERNAL) {
- this._eachValues = Array(this._length);
- } else if (_each === 0) {
- this._eachValues = null;
- } else {
- this._eachValues = undefined;
- }
- this._promise._captureStackTrace();
- this._init$(undefined, -5);
-}
-util.inherits(ReductionPromiseArray, PromiseArray);
-
-ReductionPromiseArray.prototype._gotAccum = function(accum) {
- if (this._eachValues !== undefined &&
- this._eachValues !== null &&
- accum !== INTERNAL) {
- this._eachValues.push(accum);
- }
-};
-
-ReductionPromiseArray.prototype._eachComplete = function(value) {
- if (this._eachValues !== null) {
- this._eachValues.push(value);
- }
- return this._eachValues;
-};
-
-ReductionPromiseArray.prototype._init = function() {};
-
-ReductionPromiseArray.prototype._resolveEmptyArray = function() {
- this._resolve(this._eachValues !== undefined ? this._eachValues
- : this._initialValue);
-};
-
-ReductionPromiseArray.prototype.shouldCopyValues = function () {
- return false;
-};
-
-ReductionPromiseArray.prototype._resolve = function(value) {
- this._promise._resolveCallback(value);
- this._values = null;
-};
-
-ReductionPromiseArray.prototype._resultCancelled = function(sender) {
- if (sender === this._initialValue) return this._cancel();
- if (this._isResolved()) return;
- this._resultCancelled$();
- if (this._currentCancellable instanceof Promise) {
- this._currentCancellable.cancel();
- }
- if (this._initialValue instanceof Promise) {
- this._initialValue.cancel();
- }
-};
-
-ReductionPromiseArray.prototype._iterate = function (values) {
- this._values = values;
- var value;
- var i;
- var length = values.length;
- if (this._initialValue !== undefined) {
- value = this._initialValue;
- i = 0;
- } else {
- value = Promise.resolve(values[0]);
- i = 1;
- }
-
- this._currentCancellable = value;
-
- if (!value.isRejected()) {
- for (; i < length; ++i) {
- var ctx = {
- accum: null,
- value: values[i],
- index: i,
- length: length,
- array: this
- };
- value = value._then(gotAccum, undefined, undefined, ctx, undefined);
- }
- }
-
- if (this._eachValues !== undefined) {
- value = value
- ._then(this._eachComplete, undefined, undefined, this, undefined);
- }
- value._then(completed, completed, undefined, value, this);
-};
-
-Promise.prototype.reduce = function (fn, initialValue) {
- return reduce(this, fn, initialValue, null);
-};
-
-Promise.reduce = function (promises, fn, initialValue, _each) {
- return reduce(promises, fn, initialValue, _each);
-};
-
-function completed(valueOrReason, array) {
- if (this.isFulfilled()) {
- array._resolve(valueOrReason);
- } else {
- array._reject(valueOrReason);
- }
-}
-
-function reduce(promises, fn, initialValue, _each) {
- if (typeof fn !== "function") {
- return apiRejection("expecting a function but got " + util.classString(fn));
- }
- var array = new ReductionPromiseArray(promises, fn, initialValue, _each);
- return array.promise();
-}
-
-function gotAccum(accum) {
- this.accum = accum;
- this.array._gotAccum(accum);
- var value = tryConvertToPromise(this.value, this.array._promise);
- if (value instanceof Promise) {
- this.array._currentCancellable = value;
- return value._then(gotValue, undefined, undefined, this, undefined);
- } else {
- return gotValue.call(this, value);
- }
-}
-
-function gotValue(value) {
- var array = this.array;
- var promise = array._promise;
- var fn = tryCatch(array._fn);
- promise._pushContext();
- var ret;
- if (array._eachValues !== undefined) {
- ret = fn.call(promise._boundValue(), value, this.index, this.length);
- } else {
- ret = fn.call(promise._boundValue(),
- this.accum, value, this.index, this.length);
- }
- if (ret instanceof Promise) {
- array._currentCancellable = ret;
- }
- var promiseCreated = promise._popContext();
- debug.checkForgottenReturns(
- ret,
- promiseCreated,
- array._eachValues !== undefined ? "Promise.each" : "Promise.reduce",
- promise
- );
- return ret;
-}
-};
-
-},{"./util":36}],29:[function(_dereq_,module,exports){
-"use strict";
-var util = _dereq_("./util");
-var schedule;
-var noAsyncScheduler = function() {
- throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/MqrFmX\u000a");
-};
-var NativePromise = util.getNativePromise();
-if (util.isNode && typeof MutationObserver === "undefined") {
- var GlobalSetImmediate = global.setImmediate;
- var ProcessNextTick = process.nextTick;
- schedule = util.isRecentNode
- ? function(fn) { GlobalSetImmediate.call(global, fn); }
- : function(fn) { ProcessNextTick.call(process, fn); };
-} else if (typeof NativePromise === "function" &&
- typeof NativePromise.resolve === "function") {
- var nativePromise = NativePromise.resolve();
- schedule = function(fn) {
- nativePromise.then(fn);
- };
-} else if ((typeof MutationObserver !== "undefined") &&
- !(typeof window !== "undefined" &&
- window.navigator &&
- (window.navigator.standalone || window.cordova))) {
- schedule = (function() {
- var div = document.createElement("div");
- var opts = {attributes: true};
- var toggleScheduled = false;
- var div2 = document.createElement("div");
- var o2 = new MutationObserver(function() {
- div.classList.toggle("foo");
- toggleScheduled = false;
- });
- o2.observe(div2, opts);
-
- var scheduleToggle = function() {
- if (toggleScheduled) return;
- toggleScheduled = true;
- div2.classList.toggle("foo");
- };
-
- return function schedule(fn) {
- var o = new MutationObserver(function() {
- o.disconnect();
- fn();
- });
- o.observe(div, opts);
- scheduleToggle();
- };
- })();
-} else if (typeof setImmediate !== "undefined") {
- schedule = function (fn) {
- setImmediate(fn);
- };
-} else if (typeof setTimeout !== "undefined") {
- schedule = function (fn) {
- setTimeout(fn, 0);
- };
-} else {
- schedule = noAsyncScheduler;
-}
-module.exports = schedule;
-
-},{"./util":36}],30:[function(_dereq_,module,exports){
-"use strict";
-module.exports =
- function(Promise, PromiseArray, debug) {
-var PromiseInspection = Promise.PromiseInspection;
-var util = _dereq_("./util");
-
-function SettledPromiseArray(values) {
- this.constructor$(values);
-}
-util.inherits(SettledPromiseArray, PromiseArray);
-
-SettledPromiseArray.prototype._promiseResolved = function (index, inspection) {
- this._values[index] = inspection;
- var totalResolved = ++this._totalResolved;
- if (totalResolved >= this._length) {
- this._resolve(this._values);
- return true;
- }
- return false;
-};
-
-SettledPromiseArray.prototype._promiseFulfilled = function (value, index) {
- var ret = new PromiseInspection();
- ret._bitField = 33554432;
- ret._settledValueField = value;
- return this._promiseResolved(index, ret);
-};
-SettledPromiseArray.prototype._promiseRejected = function (reason, index) {
- var ret = new PromiseInspection();
- ret._bitField = 16777216;
- ret._settledValueField = reason;
- return this._promiseResolved(index, ret);
-};
-
-Promise.settle = function (promises) {
- debug.deprecated(".settle()", ".reflect()");
- return new SettledPromiseArray(promises).promise();
-};
-
-Promise.prototype.settle = function () {
- return Promise.settle(this);
-};
-};
-
-},{"./util":36}],31:[function(_dereq_,module,exports){
-"use strict";
-module.exports =
-function(Promise, PromiseArray, apiRejection) {
-var util = _dereq_("./util");
-var RangeError = _dereq_("./errors").RangeError;
-var AggregateError = _dereq_("./errors").AggregateError;
-var isArray = util.isArray;
-var CANCELLATION = {};
-
-
-function SomePromiseArray(values) {
- this.constructor$(values);
- this._howMany = 0;
- this._unwrap = false;
- this._initialized = false;
-}
-util.inherits(SomePromiseArray, PromiseArray);
-
-SomePromiseArray.prototype._init = function () {
- if (!this._initialized) {
- return;
- }
- if (this._howMany === 0) {
- this._resolve([]);
- return;
- }
- this._init$(undefined, -5);
- var isArrayResolved = isArray(this._values);
- if (!this._isResolved() &&
- isArrayResolved &&
- this._howMany > this._canPossiblyFulfill()) {
- this._reject(this._getRangeError(this.length()));
- }
-};
-
-SomePromiseArray.prototype.init = function () {
- this._initialized = true;
- this._init();
-};
-
-SomePromiseArray.prototype.setUnwrap = function () {
- this._unwrap = true;
-};
-
-SomePromiseArray.prototype.howMany = function () {
- return this._howMany;
-};
-
-SomePromiseArray.prototype.setHowMany = function (count) {
- this._howMany = count;
-};
-
-SomePromiseArray.prototype._promiseFulfilled = function (value) {
- this._addFulfilled(value);
- if (this._fulfilled() === this.howMany()) {
- this._values.length = this.howMany();
- if (this.howMany() === 1 && this._unwrap) {
- this._resolve(this._values[0]);
- } else {
- this._resolve(this._values);
- }
- return true;
- }
- return false;
-
-};
-SomePromiseArray.prototype._promiseRejected = function (reason) {
- this._addRejected(reason);
- return this._checkOutcome();
-};
-
-SomePromiseArray.prototype._promiseCancelled = function () {
- if (this._values instanceof Promise || this._values == null) {
- return this._cancel();
- }
- this._addRejected(CANCELLATION);
- return this._checkOutcome();
-};
-
-SomePromiseArray.prototype._checkOutcome = function() {
- if (this.howMany() > this._canPossiblyFulfill()) {
- var e = new AggregateError();
- for (var i = this.length(); i < this._values.length; ++i) {
- if (this._values[i] !== CANCELLATION) {
- e.push(this._values[i]);
- }
- }
- if (e.length > 0) {
- this._reject(e);
- } else {
- this._cancel();
- }
- return true;
- }
- return false;
-};
-
-SomePromiseArray.prototype._fulfilled = function () {
- return this._totalResolved;
-};
-
-SomePromiseArray.prototype._rejected = function () {
- return this._values.length - this.length();
-};
-
-SomePromiseArray.prototype._addRejected = function (reason) {
- this._values.push(reason);
-};
-
-SomePromiseArray.prototype._addFulfilled = function (value) {
- this._values[this._totalResolved++] = value;
-};
-
-SomePromiseArray.prototype._canPossiblyFulfill = function () {
- return this.length() - this._rejected();
-};
-
-SomePromiseArray.prototype._getRangeError = function (count) {
- var message = "Input array must contain at least " +
- this._howMany + " items but contains only " + count + " items";
- return new RangeError(message);
-};
-
-SomePromiseArray.prototype._resolveEmptyArray = function () {
- this._reject(this._getRangeError(0));
-};
-
-function some(promises, howMany) {
- if ((howMany | 0) !== howMany || howMany < 0) {
- return apiRejection("expecting a positive integer\u000a\u000a See http://goo.gl/MqrFmX\u000a");
- }
- var ret = new SomePromiseArray(promises);
- var promise = ret.promise();
- ret.setHowMany(howMany);
- ret.init();
- return promise;
-}
-
-Promise.some = function (promises, howMany) {
- return some(promises, howMany);
-};
-
-Promise.prototype.some = function (howMany) {
- return some(this, howMany);
-};
-
-Promise._SomePromiseArray = SomePromiseArray;
-};
-
-},{"./errors":12,"./util":36}],32:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise) {
-function PromiseInspection(promise) {
- if (promise !== undefined) {
- promise = promise._target();
- this._bitField = promise._bitField;
- this._settledValueField = promise._isFateSealed()
- ? promise._settledValue() : undefined;
- }
- else {
- this._bitField = 0;
- this._settledValueField = undefined;
- }
-}
-
-PromiseInspection.prototype._settledValue = function() {
- return this._settledValueField;
-};
-
-var value = PromiseInspection.prototype.value = function () {
- if (!this.isFulfilled()) {
- throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/MqrFmX\u000a");
- }
- return this._settledValue();
-};
-
-var reason = PromiseInspection.prototype.error =
-PromiseInspection.prototype.reason = function () {
- if (!this.isRejected()) {
- throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/MqrFmX\u000a");
- }
- return this._settledValue();
-};
-
-var isFulfilled = PromiseInspection.prototype.isFulfilled = function() {
- return (this._bitField & 33554432) !== 0;
-};
-
-var isRejected = PromiseInspection.prototype.isRejected = function () {
- return (this._bitField & 16777216) !== 0;
-};
-
-var isPending = PromiseInspection.prototype.isPending = function () {
- return (this._bitField & 50397184) === 0;
-};
-
-var isResolved = PromiseInspection.prototype.isResolved = function () {
- return (this._bitField & 50331648) !== 0;
-};
-
-PromiseInspection.prototype.isCancelled = function() {
- return (this._bitField & 8454144) !== 0;
-};
-
-Promise.prototype.__isCancelled = function() {
- return (this._bitField & 65536) === 65536;
-};
-
-Promise.prototype._isCancelled = function() {
- return this._target().__isCancelled();
-};
-
-Promise.prototype.isCancelled = function() {
- return (this._target()._bitField & 8454144) !== 0;
-};
-
-Promise.prototype.isPending = function() {
- return isPending.call(this._target());
-};
-
-Promise.prototype.isRejected = function() {
- return isRejected.call(this._target());
-};
-
-Promise.prototype.isFulfilled = function() {
- return isFulfilled.call(this._target());
-};
-
-Promise.prototype.isResolved = function() {
- return isResolved.call(this._target());
-};
-
-Promise.prototype.value = function() {
- return value.call(this._target());
-};
-
-Promise.prototype.reason = function() {
- var target = this._target();
- target._unsetRejectionIsUnhandled();
- return reason.call(target);
-};
-
-Promise.prototype._value = function() {
- return this._settledValue();
-};
-
-Promise.prototype._reason = function() {
- this._unsetRejectionIsUnhandled();
- return this._settledValue();
-};
-
-Promise.PromiseInspection = PromiseInspection;
-};
-
-},{}],33:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise, INTERNAL) {
-var util = _dereq_("./util");
-var errorObj = util.errorObj;
-var isObject = util.isObject;
-
-function tryConvertToPromise(obj, context) {
- if (isObject(obj)) {
- if (obj instanceof Promise) return obj;
- var then = getThen(obj);
- if (then === errorObj) {
- if (context) context._pushContext();
- var ret = Promise.reject(then.e);
- if (context) context._popContext();
- return ret;
- } else if (typeof then === "function") {
- if (isAnyBluebirdPromise(obj)) {
- var ret = new Promise(INTERNAL);
- obj._then(
- ret._fulfill,
- ret._reject,
- undefined,
- ret,
- null
- );
- return ret;
- }
- return doThenable(obj, then, context);
- }
- }
- return obj;
-}
-
-function doGetThen(obj) {
- return obj.then;
-}
-
-function getThen(obj) {
- try {
- return doGetThen(obj);
- } catch (e) {
- errorObj.e = e;
- return errorObj;
- }
-}
-
-var hasProp = {}.hasOwnProperty;
-function isAnyBluebirdPromise(obj) {
- try {
- return hasProp.call(obj, "_promise0");
- } catch (e) {
- return false;
- }
-}
-
-function doThenable(x, then, context) {
- var promise = new Promise(INTERNAL);
- var ret = promise;
- if (context) context._pushContext();
- promise._captureStackTrace();
- if (context) context._popContext();
- var synchronous = true;
- var result = util.tryCatch(then).call(x, resolve, reject);
- synchronous = false;
-
- if (promise && result === errorObj) {
- promise._rejectCallback(result.e, true, true);
- promise = null;
- }
-
- function resolve(value) {
- if (!promise) return;
- promise._resolveCallback(value);
- promise = null;
- }
-
- function reject(reason) {
- if (!promise) return;
- promise._rejectCallback(reason, synchronous, true);
- promise = null;
- }
- return ret;
-}
-
-return tryConvertToPromise;
-};
-
-},{"./util":36}],34:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function(Promise, INTERNAL, debug) {
-var util = _dereq_("./util");
-var TimeoutError = Promise.TimeoutError;
-
-function HandleWrapper(handle) {
- this.handle = handle;
-}
-
-HandleWrapper.prototype._resultCancelled = function() {
- clearTimeout(this.handle);
-};
-
-var afterValue = function(value) { return delay(+this).thenReturn(value); };
-var delay = Promise.delay = function (ms, value) {
- var ret;
- var handle;
- if (value !== undefined) {
- ret = Promise.resolve(value)
- ._then(afterValue, null, null, ms, undefined);
- if (debug.cancellation() && value instanceof Promise) {
- ret._setOnCancel(value);
- }
- } else {
- ret = new Promise(INTERNAL);
- handle = setTimeout(function() { ret._fulfill(); }, +ms);
- if (debug.cancellation()) {
- ret._setOnCancel(new HandleWrapper(handle));
- }
- ret._captureStackTrace();
- }
- ret._setAsyncGuaranteed();
- return ret;
-};
-
-Promise.prototype.delay = function (ms) {
- return delay(ms, this);
-};
-
-var afterTimeout = function (promise, message, parent) {
- var err;
- if (typeof message !== "string") {
- if (message instanceof Error) {
- err = message;
- } else {
- err = new TimeoutError("operation timed out");
- }
- } else {
- err = new TimeoutError(message);
- }
- util.markAsOriginatingFromRejection(err);
- promise._attachExtraTrace(err);
- promise._reject(err);
-
- if (parent != null) {
- parent.cancel();
- }
-};
-
-function successClear(value) {
- clearTimeout(this.handle);
- return value;
-}
-
-function failureClear(reason) {
- clearTimeout(this.handle);
- throw reason;
-}
-
-Promise.prototype.timeout = function (ms, message) {
- ms = +ms;
- var ret, parent;
-
- var handleWrapper = new HandleWrapper(setTimeout(function timeoutTimeout() {
- if (ret.isPending()) {
- afterTimeout(ret, message, parent);
- }
- }, ms));
-
- if (debug.cancellation()) {
- parent = this.then();
- ret = parent._then(successClear, failureClear,
- undefined, handleWrapper, undefined);
- ret._setOnCancel(handleWrapper);
- } else {
- ret = this._then(successClear, failureClear,
- undefined, handleWrapper, undefined);
- }
-
- return ret;
-};
-
-};
-
-},{"./util":36}],35:[function(_dereq_,module,exports){
-"use strict";
-module.exports = function (Promise, apiRejection, tryConvertToPromise,
- createContext, INTERNAL, debug) {
- var util = _dereq_("./util");
- var TypeError = _dereq_("./errors").TypeError;
- var inherits = _dereq_("./util").inherits;
- var errorObj = util.errorObj;
- var tryCatch = util.tryCatch;
- var NULL = {};
-
- function thrower(e) {
- setTimeout(function(){throw e;}, 0);
- }
-
- function castPreservingDisposable(thenable) {
- var maybePromise = tryConvertToPromise(thenable);
- if (maybePromise !== thenable &&
- typeof thenable._isDisposable === "function" &&
- typeof thenable._getDisposer === "function" &&
- thenable._isDisposable()) {
- maybePromise._setDisposable(thenable._getDisposer());
- }
- return maybePromise;
- }
- function dispose(resources, inspection) {
- var i = 0;
- var len = resources.length;
- var ret = new Promise(INTERNAL);
- function iterator() {
- if (i >= len) return ret._fulfill();
- var maybePromise = castPreservingDisposable(resources[i++]);
- if (maybePromise instanceof Promise &&
- maybePromise._isDisposable()) {
- try {
- maybePromise = tryConvertToPromise(
- maybePromise._getDisposer().tryDispose(inspection),
- resources.promise);
- } catch (e) {
- return thrower(e);
- }
- if (maybePromise instanceof Promise) {
- return maybePromise._then(iterator, thrower,
- null, null, null);
- }
- }
- iterator();
- }
- iterator();
- return ret;
- }
-
- function Disposer(data, promise, context) {
- this._data = data;
- this._promise = promise;
- this._context = context;
- }
-
- Disposer.prototype.data = function () {
- return this._data;
- };
-
- Disposer.prototype.promise = function () {
- return this._promise;
- };
-
- Disposer.prototype.resource = function () {
- if (this.promise().isFulfilled()) {
- return this.promise().value();
- }
- return NULL;
- };
-
- Disposer.prototype.tryDispose = function(inspection) {
- var resource = this.resource();
- var context = this._context;
- if (context !== undefined) context._pushContext();
- var ret = resource !== NULL
- ? this.doDispose(resource, inspection) : null;
- if (context !== undefined) context._popContext();
- this._promise._unsetDisposable();
- this._data = null;
- return ret;
- };
-
- Disposer.isDisposer = function (d) {
- return (d != null &&
- typeof d.resource === "function" &&
- typeof d.tryDispose === "function");
- };
-
- function FunctionDisposer(fn, promise, context) {
- this.constructor$(fn, promise, context);
- }
- inherits(FunctionDisposer, Disposer);
-
- FunctionDisposer.prototype.doDispose = function (resource, inspection) {
- var fn = this.data();
- return fn.call(resource, resource, inspection);
- };
-
- function maybeUnwrapDisposer(value) {
- if (Disposer.isDisposer(value)) {
- this.resources[this.index]._setDisposable(value);
- return value.promise();
- }
- return value;
- }
-
- function ResourceList(length) {
- this.length = length;
- this.promise = null;
- this[length-1] = null;
- }
-
- ResourceList.prototype._resultCancelled = function() {
- var len = this.length;
- for (var i = 0; i < len; ++i) {
- var item = this[i];
- if (item instanceof Promise) {
- item.cancel();
- }
- }
- };
-
- Promise.using = function () {
- var len = arguments.length;
- if (len < 2) return apiRejection(
- "you must pass at least 2 arguments to Promise.using");
- var fn = arguments[len - 1];
- if (typeof fn !== "function") {
- return apiRejection("expecting a function but got " + util.classString(fn));
- }
- var input;
- var spreadArgs = true;
- if (len === 2 && Array.isArray(arguments[0])) {
- input = arguments[0];
- len = input.length;
- spreadArgs = false;
- } else {
- input = arguments;
- len--;
- }
- var resources = new ResourceList(len);
- for (var i = 0; i < len; ++i) {
- var resource = input[i];
- if (Disposer.isDisposer(resource)) {
- var disposer = resource;
- resource = resource.promise();
- resource._setDisposable(disposer);
- } else {
- var maybePromise = tryConvertToPromise(resource);
- if (maybePromise instanceof Promise) {
- resource =
- maybePromise._then(maybeUnwrapDisposer, null, null, {
- resources: resources,
- index: i
- }, undefined);
- }
- }
- resources[i] = resource;
- }
-
- var reflectedResources = new Array(resources.length);
- for (var i = 0; i < reflectedResources.length; ++i) {
- reflectedResources[i] = Promise.resolve(resources[i]).reflect();
- }
-
- var resultPromise = Promise.all(reflectedResources)
- .then(function(inspections) {
- for (var i = 0; i < inspections.length; ++i) {
- var inspection = inspections[i];
- if (inspection.isRejected()) {
- errorObj.e = inspection.error();
- return errorObj;
- } else if (!inspection.isFulfilled()) {
- resultPromise.cancel();
- return;
- }
- inspections[i] = inspection.value();
- }
- promise._pushContext();
-
- fn = tryCatch(fn);
- var ret = spreadArgs
- ? fn.apply(undefined, inspections) : fn(inspections);
- var promiseCreated = promise._popContext();
- debug.checkForgottenReturns(
- ret, promiseCreated, "Promise.using", promise);
- return ret;
- });
-
- var promise = resultPromise.lastly(function() {
- var inspection = new Promise.PromiseInspection(resultPromise);
- return dispose(resources, inspection);
- });
- resources.promise = promise;
- promise._setOnCancel(resources);
- return promise;
- };
-
- Promise.prototype._setDisposable = function (disposer) {
- this._bitField = this._bitField | 131072;
- this._disposer = disposer;
- };
-
- Promise.prototype._isDisposable = function () {
- return (this._bitField & 131072) > 0;
- };
-
- Promise.prototype._getDisposer = function () {
- return this._disposer;
- };
-
- Promise.prototype._unsetDisposable = function () {
- this._bitField = this._bitField & (~131072);
- this._disposer = undefined;
- };
-
- Promise.prototype.disposer = function (fn) {
- if (typeof fn === "function") {
- return new FunctionDisposer(fn, this, createContext());
- }
- throw new TypeError();
- };
-
-};
-
-},{"./errors":12,"./util":36}],36:[function(_dereq_,module,exports){
-"use strict";
-var es5 = _dereq_("./es5");
-var canEvaluate = typeof navigator == "undefined";
-
-var errorObj = {e: {}};
-var tryCatchTarget;
-var globalObject = typeof self !== "undefined" ? self :
- typeof window !== "undefined" ? window :
- typeof global !== "undefined" ? global :
- this !== undefined ? this : null;
-
-function tryCatcher() {
- try {
- var target = tryCatchTarget;
- tryCatchTarget = null;
- return target.apply(this, arguments);
- } catch (e) {
- errorObj.e = e;
- return errorObj;
- }
-}
-function tryCatch(fn) {
- tryCatchTarget = fn;
- return tryCatcher;
-}
-
-var inherits = function(Child, Parent) {
- var hasProp = {}.hasOwnProperty;
-
- function T() {
- this.constructor = Child;
- this.constructor$ = Parent;
- for (var propertyName in Parent.prototype) {
- if (hasProp.call(Parent.prototype, propertyName) &&
- propertyName.charAt(propertyName.length-1) !== "$"
- ) {
- this[propertyName + "$"] = Parent.prototype[propertyName];
- }
- }
- }
- T.prototype = Parent.prototype;
- Child.prototype = new T();
- return Child.prototype;
-};
-
-
-function isPrimitive(val) {
- return val == null || val === true || val === false ||
- typeof val === "string" || typeof val === "number";
-
-}
-
-function isObject(value) {
- return typeof value === "function" ||
- typeof value === "object" && value !== null;
-}
-
-function maybeWrapAsError(maybeError) {
- if (!isPrimitive(maybeError)) return maybeError;
-
- return new Error(safeToString(maybeError));
-}
-
-function withAppended(target, appendee) {
- var len = target.length;
- var ret = new Array(len + 1);
- var i;
- for (i = 0; i < len; ++i) {
- ret[i] = target[i];
- }
- ret[i] = appendee;
- return ret;
-}
-
-function getDataPropertyOrDefault(obj, key, defaultValue) {
- if (es5.isES5) {
- var desc = Object.getOwnPropertyDescriptor(obj, key);
-
- if (desc != null) {
- return desc.get == null && desc.set == null
- ? desc.value
- : defaultValue;
- }
- } else {
- return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined;
- }
-}
-
-function notEnumerableProp(obj, name, value) {
- if (isPrimitive(obj)) return obj;
- var descriptor = {
- value: value,
- configurable: true,
- enumerable: false,
- writable: true
- };
- es5.defineProperty(obj, name, descriptor);
- return obj;
-}
-
-function thrower(r) {
- throw r;
-}
-
-var inheritedDataKeys = (function() {
- var excludedPrototypes = [
- Array.prototype,
- Object.prototype,
- Function.prototype
- ];
-
- var isExcludedProto = function(val) {
- for (var i = 0; i < excludedPrototypes.length; ++i) {
- if (excludedPrototypes[i] === val) {
- return true;
- }
- }
- return false;
- };
-
- if (es5.isES5) {
- var getKeys = Object.getOwnPropertyNames;
- return function(obj) {
- var ret = [];
- var visitedKeys = Object.create(null);
- while (obj != null && !isExcludedProto(obj)) {
- var keys;
- try {
- keys = getKeys(obj);
- } catch (e) {
- return ret;
- }
- for (var i = 0; i < keys.length; ++i) {
- var key = keys[i];
- if (visitedKeys[key]) continue;
- visitedKeys[key] = true;
- var desc = Object.getOwnPropertyDescriptor(obj, key);
- if (desc != null && desc.get == null && desc.set == null) {
- ret.push(key);
- }
- }
- obj = es5.getPrototypeOf(obj);
- }
- return ret;
- };
- } else {
- var hasProp = {}.hasOwnProperty;
- return function(obj) {
- if (isExcludedProto(obj)) return [];
- var ret = [];
-
- /*jshint forin:false */
- enumeration: for (var key in obj) {
- if (hasProp.call(obj, key)) {
- ret.push(key);
- } else {
- for (var i = 0; i < excludedPrototypes.length; ++i) {
- if (hasProp.call(excludedPrototypes[i], key)) {
- continue enumeration;
- }
- }
- ret.push(key);
- }
- }
- return ret;
- };
- }
-
-})();
-
-var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/;
-function isClass(fn) {
- try {
- if (typeof fn === "function") {
- var keys = es5.names(fn.prototype);
-
- var hasMethods = es5.isES5 && keys.length > 1;
- var hasMethodsOtherThanConstructor = keys.length > 0 &&
- !(keys.length === 1 && keys[0] === "constructor");
- var hasThisAssignmentAndStaticMethods =
- thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0;
-
- if (hasMethods || hasMethodsOtherThanConstructor ||
- hasThisAssignmentAndStaticMethods) {
- return true;
- }
- }
- return false;
- } catch (e) {
- return false;
- }
-}
-
-function toFastProperties(obj) {
- /*jshint -W027,-W055,-W031*/
- function FakeConstructor() {}
- FakeConstructor.prototype = obj;
- var l = 8;
- while (l--) new FakeConstructor();
- return obj;
- eval(obj);
-}
-
-var rident = /^[a-z$_][a-z$_0-9]*$/i;
-function isIdentifier(str) {
- return rident.test(str);
-}
-
-function filledRange(count, prefix, suffix) {
- var ret = new Array(count);
- for(var i = 0; i < count; ++i) {
- ret[i] = prefix + i + suffix;
- }
- return ret;
-}
-
-function safeToString(obj) {
- try {
- return obj + "";
- } catch (e) {
- return "[no string representation]";
- }
-}
-
-function isError(obj) {
- return obj !== null &&
- typeof obj === "object" &&
- typeof obj.message === "string" &&
- typeof obj.name === "string";
-}
-
-function markAsOriginatingFromRejection(e) {
- try {
- notEnumerableProp(e, "isOperational", true);
- }
- catch(ignore) {}
-}
-
-function originatesFromRejection(e) {
- if (e == null) return false;
- return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) ||
- e["isOperational"] === true);
-}
-
-function canAttachTrace(obj) {
- return isError(obj) && es5.propertyIsWritable(obj, "stack");
-}
-
-var ensureErrorObject = (function() {
- if (!("stack" in new Error())) {
- return function(value) {
- if (canAttachTrace(value)) return value;
- try {throw new Error(safeToString(value));}
- catch(err) {return err;}
- };
- } else {
- return function(value) {
- if (canAttachTrace(value)) return value;
- return new Error(safeToString(value));
- };
- }
-})();
-
-function classString(obj) {
- return {}.toString.call(obj);
-}
-
-function copyDescriptors(from, to, filter) {
- var keys = es5.names(from);
- for (var i = 0; i < keys.length; ++i) {
- var key = keys[i];
- if (filter(key)) {
- try {
- es5.defineProperty(to, key, es5.getDescriptor(from, key));
- } catch (ignore) {}
- }
- }
-}
-
-var asArray = function(v) {
- if (es5.isArray(v)) {
- return v;
- }
- return null;
-};
-
-if (typeof Symbol !== "undefined" && Symbol.iterator) {
- var ArrayFrom = typeof Array.from === "function" ? function(v) {
- return Array.from(v);
- } : function(v) {
- var ret = [];
- var it = v[Symbol.iterator]();
- var itResult;
- while (!((itResult = it.next()).done)) {
- ret.push(itResult.value);
- }
- return ret;
- };
-
- asArray = function(v) {
- if (es5.isArray(v)) {
- return v;
- } else if (v != null && typeof v[Symbol.iterator] === "function") {
- return ArrayFrom(v);
- }
- return null;
- };
-}
-
-var isNode = typeof process !== "undefined" &&
- classString(process).toLowerCase() === "[object process]";
-
-var hasEnvVariables = typeof process !== "undefined" &&
- typeof process.env !== "undefined";
-
-function env(key) {
- return hasEnvVariables ? process.env[key] : undefined;
-}
-
-function getNativePromise() {
- if (typeof Promise === "function") {
- try {
- var promise = new Promise(function(){});
- if ({}.toString.call(promise) === "[object Promise]") {
- return Promise;
- }
- } catch (e) {}
- }
-}
-
-function domainBind(self, cb) {
- return self.bind(cb);
-}
-
-var ret = {
- isClass: isClass,
- isIdentifier: isIdentifier,
- inheritedDataKeys: inheritedDataKeys,
- getDataPropertyOrDefault: getDataPropertyOrDefault,
- thrower: thrower,
- isArray: es5.isArray,
- asArray: asArray,
- notEnumerableProp: notEnumerableProp,
- isPrimitive: isPrimitive,
- isObject: isObject,
- isError: isError,
- canEvaluate: canEvaluate,
- errorObj: errorObj,
- tryCatch: tryCatch,
- inherits: inherits,
- withAppended: withAppended,
- maybeWrapAsError: maybeWrapAsError,
- toFastProperties: toFastProperties,
- filledRange: filledRange,
- toString: safeToString,
- canAttachTrace: canAttachTrace,
- ensureErrorObject: ensureErrorObject,
- originatesFromRejection: originatesFromRejection,
- markAsOriginatingFromRejection: markAsOriginatingFromRejection,
- classString: classString,
- copyDescriptors: copyDescriptors,
- hasDevTools: typeof chrome !== "undefined" && chrome &&
- typeof chrome.loadTimes === "function",
- isNode: isNode,
- hasEnvVariables: hasEnvVariables,
- env: env,
- global: globalObject,
- getNativePromise: getNativePromise,
- domainBind: domainBind
-};
-ret.isRecentNode = ret.isNode && (function() {
- var version = process.versions.node.split(".").map(Number);
- return (version[0] === 0 && version[1] > 10) || (version[0] > 0);
-})();
-
-if (ret.isNode) ret.toFastProperties(process);
-
-try {throw new Error(); } catch (e) {ret.lastLineError = e;}
-module.exports = ret;
-
-},{"./es5":13}]},{},[4])(4)
-}); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; }
\ No newline at end of file
diff --git a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/cytoscape-bubblesets.js b/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/cytoscape-bubblesets.js
deleted file mode 100644
index 2f7089e..0000000
--- a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/cytoscape-bubblesets.js
+++ /dev/null
@@ -1,2 +0,0 @@
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("cytoscape-layers")):"function"==typeof define&&define.amd?define(["exports","cytoscape-layers"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).CytoscapeBubbleSets={},t.CytoscapeLayers)}(this,(function(t,e){"use strict";function i(t,e,i,s){if("a"===i&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?s:"a"===i?s.call(t):s?s.value:e.get(t)}function s(t,e,i,s,n){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!n)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===s?n.call(t,i):n?n.value=i:e.set(t,i),i}function n(t,e,i,s,n,r){const h=i-t,o=s-e;let a=n-t,c=r-e,u=a*h+c*o,l=0;u<=0?l=0:(a=h-a,c=o-c,u=a*h+c*o,l=u<=0?0:u*u/(h*h+o*o));const f=a*a+c*c-l;return f<0?0:f}function r(t,e,i,s){return(t-i)*(t-i)+(e-s)*(e-s)}function h(t,e,i,s,n){return r(t,e,i,s)this.y1&&e>=this.y2)return!1;if(t>this.x1&&t>=this.x2)return!1;if(tthis.x2+i)return!1}else if(tthis.x1+i)return!1;if(this.y1this.y2+i)return!1}else if(ethis.y1+i)return!1;return!0}}var a,c;!function(t){t[t.POINT=1]="POINT",t[t.PARALLEL=2]="PARALLEL",t[t.COINCIDENT=3]="COINCIDENT",t[t.NONE=4]="NONE"}(a||(a={}));class u{constructor(t,e=0,i=0){this.state=t,this.x=e,this.y=i}}function l(t,e){const i=(e.x2-e.x1)*(t.y1-e.y1)-(e.y2-e.y1)*(t.x1-e.x1),s=(t.x2-t.x1)*(t.y1-e.y1)-(t.y2-t.y1)*(t.x1-e.x1),n=(e.y2-e.y1)*(t.x2-t.x1)-(e.x2-e.x1)*(t.y2-t.y1);if(n){const e=i/n,r=s/n;return 0<=e&&e<=1&&0<=r&&r<=1?new u(a.POINT,t.x1+e*(t.x2-t.x1),t.y1+e*(t.y2-t.y1)):new u(a.NONE)}return new u(0===i||0===s?a.COINCIDENT:a.PARALLEL)}function f(t,e){const i=(e.x2-e.x1)*(t.y1-e.y1)-(e.y2-e.y1)*(t.x1-e.x1),s=(t.x2-t.x1)*(t.y1-e.y1)-(t.y2-t.y1)*(t.x1-e.x1),n=(e.y2-e.y1)*(t.x2-t.x1)-(e.x2-e.x1)*(t.y2-t.y1);if(n){const t=i/n,e=s/n;if(0<=t&&t<=1&&0<=e&&e<=1)return t}return Number.POSITIVE_INFINITY}function x(t,e,i){const s=new Set;return t.width<=0?(s.add(c.LEFT),s.add(c.RIGHT)):et.x+t.width&&s.add(c.RIGHT),t.height<=0?(s.add(c.TOP),s.add(c.BOTTOM)):it.y+t.height&&s.add(c.BOTTOM),s}function y(t,e){let i=e.x1,s=e.y1;const n=e.x2,r=e.y2,h=Array.from(x(t,n,r));if(0===h.length)return!0;let o=x(t,i,s);for(;0!==o.size;){for(const t of h)if(o.has(t))return!1;if(o.has(c.RIGHT)||o.has(c.LEFT)){let e=t.x;o.has(c.RIGHT)&&(e+=t.width),s+=(e-i)*(r-s)/(n-i),i=e}else{let e=t.y;o.has(c.BOTTOM)&&(e+=t.height),i+=(e-s)*(n-i)/(r-s),s=e}o=x(t,i,s)}return!0}function d(t,e){let i=Number.POSITIVE_INFINITY,s=0;function n(t,n,r,h){let a=f(e,new o(t,n,r,h));a=Math.abs(a-.5),a>=0&&a<=1&&(s++,a1?i:(n(t.x,t.y2,t.x2,t.y2),s>1?i:(n(t.x2,t.y,t.x2,t.y2),0===s?-1:i))}function p(t,e){let i=0;const s=l(t,new o(e.x,e.y,e.x2,e.y));i+=s.state===a.POINT?1:0;const n=l(t,new o(e.x,e.y,e.x,e.y2));i+=n.state===a.POINT?1:0;const r=l(t,new o(e.x,e.y2,e.x2,e.y2));i+=r.state===a.POINT?1:0;const h=l(t,new o(e.x2,e.y,e.x2,e.y2));return i+=h.state===a.POINT?1:0,{top:s,left:n,bottom:r,right:h,count:i}}!function(t){t[t.LEFT=0]="LEFT",t[t.TOP=1]="TOP",t[t.RIGHT=2]="RIGHT",t[t.BOTTOM=3]="BOTTOM"}(c||(c={}));class g{constructor(t,e,i,s){this.x=t,this.y=e,this.width=i,this.height=s}get x2(){return this.x+this.width}get y2(){return this.y+this.height}get cx(){return this.x+this.width/2}get cy(){return this.y+this.height/2}get radius(){return Math.max(this.width,this.height)/2}static from(t){return new g(t.x,t.y,t.width,t.height)}equals(t){return this.x===t.x&&this.y===t.y&&this.width===t.width&&this.height===t.height}clone(){return new g(this.x,this.y,this.width,this.height)}add(t){const e=Math.min(this.x,t.x),i=Math.min(this.y,t.y),s=Math.max(this.x2,t.x+t.width),n=Math.max(this.y2,t.y+t.height);this.x=e,this.y=i,this.width=s-e,this.height=n-i}addPoint(t){const e=Math.min(this.x,t.x),i=Math.min(this.y,t.y),s=Math.max(this.x2,t.x),n=Math.max(this.y2,t.y);this.x=e,this.y=i,this.width=s-e,this.height=n-i}toString(){return`Rectangle[x=${this.x}, y=${this.y}, w=${this.width}, h=${this.height}]`}draw(t){t.rect(this.x,this.y,this.width,this.height)}containsPt(t,e){return t>=this.x&&t<=this.x2&&e>=this.y&&e<=this.y2}get area(){return this.width*this.height}intersects(t){return!(this.area<=0||t.width<=0||t.height<=0)&&(t.x+t.width>this.x&&t.y+t.height>this.y&&t.x=this.width?this.width-1:t}boundY(t){return t=this.height?this.height-1:t}scaleX(t){return this.boundX(Math.floor((t-this.pixelX)/this.pixelGroup))}scaleY(t){return this.boundY(Math.floor((t-this.pixelY)/this.pixelGroup))}scale(t){const e=this.scaleX(t.x),i=this.scaleY(t.y),s=this.boundX(Math.ceil((t.x+t.width-this.pixelX)/this.pixelGroup)),n=this.boundY(Math.ceil((t.y+t.height-this.pixelY)/this.pixelGroup));return new g(e,i,s-e,n-i)}invertScaleX(t){return Math.round(t*this.pixelGroup+this.pixelX)}invertScaleY(t){return Math.round(t*this.pixelGroup+this.pixelY)}addPadding(t,e){const i=Math.ceil(e/this.pixelGroup),s=this.boundX(t.x-i),n=this.boundY(t.y-i),r=this.boundX(t.x2+i),h=this.boundY(t.y2+i);return new g(s,n,r-s,h-n)}get(t,e){return t<0||e<0||t>=this.width||e>=this.height?Number.NaN:this.area[t+e*this.width]}inc(t,e,i){t<0||e<0||t>=this.width||e>=this.height||(this.area[t+e*this.width]+=i)}set(t,e,i){t<0||e<0||t>=this.width||e>=this.height||(this.area[t+e*this.width]=i)}incArea(t,e){if(t.width<=0||t.height<=0||0===e)return;const i=this.width,s=t.width,n=Math.max(0,t.i),r=Math.max(0,t.j),h=Math.min(t.i+t.width,i),o=Math.min(t.j+t.height,this.height);if(!(o<=0||h<=0||n>=i||o>=this.height))for(let a=r;aMath.min(t,e)),Number.POSITIVE_INFINITY),s=this.area.reduce(((t,e)=>Math.max(t,e)),Number.NEGATIVE_INFINITY),n=t=>(t-i)/(s-i);t.scale(this.pixelGroup,this.pixelGroup);for(let e=0;ee?"black":"white",t.fillRect(i,s,1,1)}t.restore()}}}function b(t,e,i){return v(Object.assign(function(t){const e=Math.min(t.x1,t.x2),i=Math.max(t.x1,t.x2),s=Math.min(t.y1,t.y2),n=Math.max(t.y1,t.y2);return{x:e,y:s,x2:i,y2:n,width:i-e,height:n-s}}(t),{distSquare:(e,i)=>n(t.x1,t.y1,t.x2,t.y2,e,i)}),e,i)}function v(t,e,i){const s=function(t,e){const i=t=>({x:t.x-e,y:t.y-e,width:t.width+2*e,height:t.height+2*e});return Array.isArray(t)?t.map(i):i(t)}(t,i),n=e.scale(s),r=e.createSub(n,s);return function(t,e,i,s){const n=i*i;for(let r=0;rt.distSquare(e,i))),r}function M(t,e){return{x:t,y:e}}function T(t,e,i,s){if(0===t.length)return[];const n=function(t){if(t.length<2)return t;let e=0,i=0;return t.forEach((t=>{e+=t.cx,i+=t.cy})),e/=t.length,i/=t.length,t.map((t=>{const s=e-t.cx,n=i-t.cy;return[t,s*s+n*n]})).sort(((t,e)=>t[1]-e[1])).map((t=>t[0]))}(t);return n.map(((t,h)=>{const a=n.slice(0,h);return function(t,e,i,s,n){const h=M(e.cx,e.cy),a=function(t,e,i){let s=Number.POSITIVE_INFINITY;return e.reduce(((e,n)=>{const h=r(t.x,t.y,n.cx,n.cy);if(h>s)return e;const a=new o(t.x,t.y,n.cx,n.cy),c=function(t,e){return t.reduce(((t,i)=>y(i,e)&&function(t,e){function i(t,i,s,n){let r=f(e,new o(t,i,s,n));return r=Math.abs(r-.5),r>=0&&r<=1?1:0}let s=i(t.x,t.y,t.x2,t.y);return s+=i(t.x,t.y,t.x,t.y2),s>1||(s+=i(t.x,t.y2,t.x2,t.y2),s>1||(s+=i(t.x2,t.y,t.x2,t.y2),s>0))}(i,e)?t+1:t),0)}(i,a);return h*(c+1)*(c+1)0;){const s=t.pop();if(0===t.length){i.push(s);break}const n=t.pop(),r=new o(s.x1,s.y1,n.x2,n.y2);E(e,r)?(i.push(s),t.push(n)):t.push(r)}return i}(function(t,e,i,s){const n=[],r=[];r.push(t);let h=!0;for(let t=0;t0;){const t=r.pop(),i=E(e,t),a=i?p(t,i):null;if(!i||!a||2!==a.count){h||n.push(t);continue}let c=s,u=O(i,c,a,!0),l=I(u,r)||I(u,n),f=N(u,e);for(;!l&&f&&c>=1;)c/=1.5,u=O(i,c,a,!0),l=I(u,r)||I(u,n),f=N(u,e);if(!u||l||f||(r.push(new o(t.x1,t.y1,u.x,u.y)),r.push(new o(u.x,u.y,t.x2,t.y2)),h=!0),h)continue;c=s,u=O(i,c,a,!1);let x=I(u,r)||I(u,n);for(f=N(u,e);!x&&f&&c>=1;)c/=1.5,u=O(i,c,a,!1),x=I(u,r)||I(u,n),f=N(u,e);u&&!x&&(r.push(new o(t.x1,t.y1,u.x,u.y)),r.push(new o(u.x,u.y,t.x2,t.y2)),h=!0),h||n.push(t)}for(;r.length>0;)n.push(r.pop());return n}(c,t,s,n),t)}(e,t,a,i,s)})).flat()}function N(t,e){return e.some((e=>e.containsPt(t.x,t.y)))}function I(t,e){return e.some((e=>!!h(e.x1,e.y1,t.x,t.y,.001)||!!h(e.x2,e.y2,t.x,t.y,.001)))}function E(t,e){let i=Number.POSITIVE_INFINITY,s=null;for(const n of t){if(!y(n,e))continue;const t=d(n,e);t>=0&&to.y?M(t.x-e,t.y-e):M(t.x2+e,t.y-e):r.yh.x?M(t.x-e,t.y-e):M(t.x-e,t.y2+e):n.xo.y?M(t.x2+e,t.y2+e):M(t.x-e,t.y2+e):r.yh.x?M(t.x2+e,t.y2+e):M(t.x2+e,t.y-e):n.xs)return!1}return!0}function S(t,e){switch(t){case-2:return(((3-e)*e-3)*e+1)/6;case-1:return((3*e-6)*e*e+4)/6;case 0:return(((-3*e+3)*e+3)*e+1)/6;case 1:return e*e*e/6;default:throw new Error("unknown error")}}class R{constructor(t=[],e=!0){this.points=t,this.closed=e}get(t){const e=t,i=this.points.length;return t<0?this.closed?this.get(t+i):this.points[0]:t>=i?this.closed?this.get(t-i):this.points[i-1]:this.points[e]}get length(){return this.points.length}toString(t=1/0){const e=this.points;if(0===e.length)return"";const i="function"==typeof t?t:function(t){if(!Number.isFinite(t))return t=>t;if(0===t)return Math.round;const e=Math.pow(10,t);return t=>Math.round(t*e)/e}(t);let s="M";for(const t of e)s+=`${i(t.x)},${i(t.y)} L`;return s=s.slice(0,-1),this.closed&&(s+=" Z"),s}draw(t){const e=this.points;if(0!==e.length){t.beginPath(),t.moveTo(e[0].x,e[0].y);for(const i of e)t.lineTo(i.x,i.y);this.closed&&t.closePath()}}sample(t){return function(t=8){return e=>{let i=t,s=e.length;if(i>1)for(s=Math.floor(e.length/i);s<3&&i>1;)i-=1,s=Math.floor(e.length/i);const n=[];for(let t=0,r=0;r{if(t<0||e.length<3)return e;const i=[];let s=0;const n=t*t;for(;s{if(i.length<3)return i;const s=[],n=i.closed,r=i.length+3-1+(n?0:2);s.push(e(i,2-(n?0:2),0));for(let h=2-(n?0:2);he.containsPt(t.cx,t.cy)&&this.withinArea(t.cx,t.cy)))}withinArea(t,e){if(0===this.length)return!1;let i=0;const s=this.points[0],n=new o(s.x,s.y,s.x,s.y);for(let s=1;se?n+r:n}function r(t,e){let i=0;return i=n(t,e,i,1),i=n(t+1,e,i,2),i=n(t,e+1,i,4),i=n(t+1,e+1,i,8),Number.isNaN(i)?-1:i}let h=1;function o(e,i){let n=e,o=i,a=t.invertScaleX(n),c=t.invertScaleY(o);for(let e=0;e=e||i<0||l&&t-c>=r}function p(){var t=z();if(d(t))return g(t);o=setTimeout(p,function(t){var i=e-(t-a);return l?D(i,r-(t-c)):i}(t))}function g(t){return o=void 0,f&&s?x(t):(s=n=void 0,h)}function w(){var t=z(),i=d(t);if(s=arguments,n=this,a=t,i){if(void 0===o)return y(a);if(l)return o=setTimeout(p,e),x(a)}return void 0===o&&(o=setTimeout(p,e)),h}return e=K(e)||0,J(i)&&(u=!!i.leading,r=(l="maxWait"in i)?V(K(i.maxWait)||0,e):r,f="trailing"in i?!!i.trailing:f),w.cancel=function(){void 0!==o&&clearTimeout(o),c=0,s=a=n=o=void 0},w.flush=function(){return void 0===o?h:g(z())},w}function J(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function K(t){if("number"==typeof t)return t;if(function(t){return"symbol"==typeof t||function(t){return!!t&&"object"==typeof t}(t)&&"[object Symbol]"==_.call(t)}(t))return NaN;if(J(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=J(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(j,"");var i=B.test(t);return i||X.test(t)?q(t.slice(2),i?2:8):A.test(t)?NaN:+t}var Q,U,tt,et,it,st,nt,rt,ht=function(t,e,i){var s=!0,n=!0;if("function"!=typeof t)throw new TypeError(Y);return J(i)&&(s="leading"in i?!!i.leading:s,n="trailing"in i?!!i.trailing:n),Z(t,e,{leading:s,maxWait:e,trailing:n})};function ot(t){return Math.round(100*t)/100}const at="bubbleSets",ct=["ellipse","diamond","diamond","pentagon","diamond","hexagon","heptagon","octagon","star"],ut=new Set(ct.concat(ct.map((t=>`round-${t}`))));function lt(t){return`${ot(t.shape.width)}x${ot(t.shape.height)}x${t.isCircle}`}function ft(t){return`${ot(t.x1)}x${ot(t.y1)}x${ot(t.x2)}x${ot(t.y2)}`}function xt(t,e){return t?new w(e.x1+e.w/2,e.y1+e.h/2,Math.max(e.w,e.h)/2):new g(e.x1,e.y1,e.w,e.h)}class yt{constructor(t,e,n,r,h,a={}){this.node=e,this.nodes=n,this.edges=r,this.avoidNodes=h,Q.set(this,{x:0,y:0,width:0,height:0}),U.set(this,new m(4,0,0,0,0,0,0)),tt.set(this,void 0),et.set(this,new Map),it.set(this,void 0),st.set(this,void 0),nt.set(this,void 0),rt.set(this,void 0),this.update=(t=!1)=>{const e=this.nodes.union(this.edges).boundingBox(i(this,tt,"f"));let n=!1;const r=Math.max(i(this,tt,"f").edgeR1,i(this,tt,"f").nodeR1)+i(this,tt,"f").morphBuffer,h={x:e.x1-r,y:e.y1-r,width:e.w+2*r,height:e.h+2*r};t||i(this,Q,"f").x!==h.x||i(this,Q,"f").y!==h.y?(n=!0,s(this,U,m.fromPixelRegion(h,i(this,tt,"f").pixelGroup),"f")):i(this,Q,"f").width===h.width&&i(this,Q,"f").height===h.height||s(this,U,m.fromPixelRegion(h,i(this,tt,"f").pixelGroup),"f"),s(this,Q,h,"f");const a=i(this,U,"f"),c=new Map;n||this.nodes.forEach((t=>{var e;const i=null!==(e=t.scratch(at))&&void 0!==e?e:null;i&&i.area&&c.set(lt(i),i.area)}));let u=!1;const l=t=>{var e;const s=t.boundingBox(i(this,tt,"f"));let r=null!==(e=t.scratch(at))&&void 0!==e?e:null;const h=(o=t.style("shape"),ut.has(o));var o;if(r&&!n&&r.area&&r.isCircle===h&&r.shape.width===s.w&&r.shape.height===s.h)r.shape.x===s.x1&&r.shape.y===s.y1||(u=!0,r.shape=xt(h,s),r.area=i(this,U,"f").copy(r.area,{x:s.x1-i(this,tt,"f").nodeR1,y:s.y1-i(this,tt,"f").nodeR1}));else{u=!0,r={isCircle:h,shape:xt(h,s)};const e=lt(r),n=c.get(e);null!=n?r.area=i(this,U,"f").copy(n,{x:s.x1-i(this,tt,"f").nodeR1,y:s.y1-i(this,tt,"f").nodeR1}):(r.area=r.isCircle?v(r.shape,a,i(this,tt,"f").nodeR1):function(t,e,i){const s=e.scale(t),n=e.addPadding(s,i),r=e.createSub(n,{x:t.x-i,y:t.y-i}),h=s.x-n.x,o=s.y-n.y,a=n.x2-s.x2,c=n.y2-s.y2,u=n.width-h-a,l=n.height-o-c,f=i*i;r.fillArea({x:h,y:o,width:u+1,height:l+1},f);const x=[0],y=Math.max(o,h,a,c);{const n=e.invertScaleX(s.x+s.width/2);for(let r=1;ry.set(e,t))),this.edges.forEach((t=>{var e;const i=null!==(e=t.scratch(at))&&void 0!==e?e:null;i&&i.lines&&i.lines.forEach(((t,e)=>{const s=i.areas[e];s&&c.set(ft(t),s)}))})));const d=t=>{const e=ft(t),s=y.get(e);if(null!=s)return s;const n=b(t,i(this,U,"f"),i(this,tt,"f").edgeR1);return y.set(e,n),n},p=[];this.edges.forEach((t=>{var e,i;const s=(null!==(e=t.segmentPoints())&&void 0!==e?e:[t.sourceEndpoint(),t.targetEndpoint()]).map((t=>({...t})));if(0===s.length)return;const r=s.slice(1).map(((t,e)=>{const i=s[e];return o.from({x1:i.x,y1:i.y,x2:t.x,y2:t.y})}));let h=null!==(i=t.scratch(at))&&void 0!==i?i:null;var a,c;h&&!n&&(a=h.lines,c=r,a.length===c.length&&a.every(((t,e)=>ft(t)===ft(c[e]))))||(h={lines:r,areas:r.map(d)},t.scratch(at,h)),p.push(...h.areas)}));const g=f.map((t=>t.shape));if(i(this,tt,"f").virtualEdges)if(u){const t=x.map((t=>t.shape)),e=T(g,t,i(this,tt,"f").maxRoutingIterations,i(this,tt,"f").morphBuffer);i(this,et,"f").clear(),e.forEach((t=>{const e=d(t),s=ft(t);i(this,et,"f").set(s,e),p.push(e)}))}else i(this,et,"f").forEach((t=>p.push(t)));const w=f.filter((t=>null!=t.area)).map((t=>t.area)),M=x.filter((t=>null!=t.area)).map((t=>t.area)),N=function(t,e,i,s,n,r={}){const h=Object.assign({},k,r);let o=h.threshold,a=h.memberInfluenceFactor,c=h.edgeInfluenceFactor,u=h.nonMemberInfluenceFactor;const l=(h.nodeR0-h.nodeR1)*(h.nodeR0-h.nodeR1),f=(h.edgeR0-h.edgeR1)*(h.edgeR0-h.edgeR1);for(let r=0;r0))break;u*=.8}}return new R([])}(a,w,p,M,(t=>t.containsElements(g)),i(this,tt,"f"));this.node.setAttribute("d",N.sample(8).simplify(0).bSplines().simplify(0).toString(2))},s(this,rt,t,"f"),s(this,tt,{...k,style:{stroke:"black",fill:"black",fillOpacity:"0.25"},className:"",throttle:100,virtualEdges:!1,interactive:!1,includeLabels:!1,includeMainLabels:!1,includeOverlays:!1,includeSourceLabels:!1,includeTargetLabels:!1,...a},"f"),Object.assign(this.node.style,i(this,tt,"f").style),i(this,tt,"f").className&&this.node.classList.add(i(this,tt,"f").className),i(this,tt,"f").interactive&&this.node.addEventListener("dblclick",(()=>{this.nodes.select()})),s(this,it,ht((()=>{this.update()}),i(this,tt,"f").throttle),"f"),s(this,st,(t=>{t.target.on("add",i(this,st,"f")),t.target.on("remove",i(this,nt,"f")),i(this,it,"f").call(this)}),"f"),s(this,nt,(t=>{t.target.off("add",void 0,i(this,st,"f")),t.target.off("remove",void 0,i(this,nt,"f")),i(this,it,"f").call(this)}),"f"),n.on("position",i(this,it,"f")),n.on("add",i(this,st,"f")),n.on("remove",i(this,nt,"f")),h.on("position",i(this,it,"f")),h.on("add",i(this,st,"f")),h.on("remove",i(this,nt,"f")),r.on("move position",i(this,it,"f")),r.on("add",i(this,st,"f")),r.on("remove",i(this,nt,"f"))}remove(){for(const t of[this.nodes,this.edges,this.avoidNodes])t.off("move position",void 0,i(this,it,"f")),t.off("add",void 0,i(this,st,"f")),t.off("remove",void 0,i(this,nt,"f")),t.forEach((t=>{t.scratch(at,{})}));return this.node.remove(),i(this,rt,"f").remove(this)}}var dt,pt,gt,wt;Q=new WeakMap,U=new WeakMap,tt=new WeakMap,et=new WeakMap,it=new WeakMap,st=new WeakMap,nt=new WeakMap,rt=new WeakMap;class mt{constructor(t,n={}){var r;dt.set(this,[]),pt.set(this,{remove:t=>{const e=i(this,dt,"f").indexOf(t);return!(e<0)&&(i(this,dt,"f").splice(e,1),!0)}}),gt.set(this,void 0),wt.set(this,void 0),s(this,gt,t,"f"),s(this,wt,n,"f"),this.layer=null!==(r=n.layer)&&void 0!==r?r:e.layers(t).nodeLayer.insertBefore("svg")}destroy(){for(const t of i(this,dt,"f"))t.remove();this.layer.remove()}addPath(t,e=i(this,gt,"f").collection(),s=i(this,gt,"f").collection(),n={}){const r=this.layer.node.ownerDocument.createElementNS("http://www.w3.org/2000/svg","path");this.layer.node.appendChild(r);const h=new yt(i(this,pt,"f"),r,t,null!=e?e:i(this,gt,"f").collection(),null!=s?s:i(this,gt,"f").collection(),{...i(this,wt,"f"),...n});return i(this,dt,"f").push(h),h.update(),h}getPaths(){return i(this,dt,"f").slice()}removePath(t){return!(i(this,dt,"f").indexOf(t)<0)&&t.remove()}update(t=!1){i(this,dt,"f").forEach((e=>e.update(t)))}}function bt(t={}){return new mt(this,t)}function vt(t){t("core","bubbleSets",bt)}dt=new WeakMap,pt=new WeakMap,gt=new WeakMap,wt=new WeakMap,"function"==typeof window.cytoscape&&vt(window.cytoscape),t.BubbleSetPath=yt,t.BubbleSetsPlugin=mt,t.bubbleSets=bt,t.default=vt,Object.defineProperty(t,"__esModule",{value:!0})}));
-//# sourceMappingURL=index.umd.min.js.map
diff --git a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/cytoscape-euler.js b/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/cytoscape-euler.js
deleted file mode 100644
index b9a6585..0000000
--- a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/cytoscape-euler.js
+++ /dev/null
@@ -1,1412 +0,0 @@
-(function webpackUniversalModuleDefinition(root, factory) {
- if(typeof exports === 'object' && typeof module === 'object')
- module.exports = factory();
- else if(typeof define === 'function' && define.amd)
- define([], factory);
- else if(typeof exports === 'object')
- exports["cytoscapeEuler"] = factory();
- else
- root["cytoscapeEuler"] = factory();
-})(this, function() {
-return /******/ (function(modules) { // webpackBootstrap
-/******/ // The module cache
-/******/ var installedModules = {};
-/******/
-/******/ // The require function
-/******/ function __webpack_require__(moduleId) {
-/******/
-/******/ // Check if module is in cache
-/******/ if(installedModules[moduleId]) {
-/******/ return installedModules[moduleId].exports;
-/******/ }
-/******/ // Create a new module (and put it into the cache)
-/******/ var module = installedModules[moduleId] = {
-/******/ i: moduleId,
-/******/ l: false,
-/******/ exports: {}
-/******/ };
-/******/
-/******/ // Execute the module function
-/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
-/******/
-/******/ // Flag the module as loaded
-/******/ module.l = true;
-/******/
-/******/ // Return the exports of the module
-/******/ return module.exports;
-/******/ }
-/******/
-/******/
-/******/ // expose the modules object (__webpack_modules__)
-/******/ __webpack_require__.m = modules;
-/******/
-/******/ // expose the module cache
-/******/ __webpack_require__.c = installedModules;
-/******/
-/******/ // identity function for calling harmony imports with the correct context
-/******/ __webpack_require__.i = function(value) { return value; };
-/******/
-/******/ // define getter function for harmony exports
-/******/ __webpack_require__.d = function(exports, name, getter) {
-/******/ if(!__webpack_require__.o(exports, name)) {
-/******/ Object.defineProperty(exports, name, {
-/******/ configurable: false,
-/******/ enumerable: true,
-/******/ get: getter
-/******/ });
-/******/ }
-/******/ };
-/******/
-/******/ // getDefaultExport function for compatibility with non-harmony modules
-/******/ __webpack_require__.n = function(module) {
-/******/ var getter = module && module.__esModule ?
-/******/ function getDefault() { return module['default']; } :
-/******/ function getModuleExports() { return module; };
-/******/ __webpack_require__.d(getter, 'a', getter);
-/******/ return getter;
-/******/ };
-/******/
-/******/ // Object.prototype.hasOwnProperty.call
-/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
-/******/
-/******/ // __webpack_public_path__
-/******/ __webpack_require__.p = "";
-/******/
-/******/ // Load entry module and return exports
-/******/ return __webpack_require__(__webpack_require__.s = 11);
-/******/ })
-/************************************************************************/
-/******/ ([
-/* 0 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-module.exports = Object.assign != null ? Object.assign.bind(Object) : function (tgt) {
- for (var _len = arguments.length, srcs = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
- srcs[_key - 1] = arguments[_key];
- }
-
- srcs.forEach(function (src) {
- Object.keys(src).forEach(function (k) {
- return tgt[k] = src[k];
- });
- });
-
- return tgt;
-};
-
-/***/ }),
-/* 1 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-var assign = __webpack_require__(0);
-
-var defaults = Object.freeze({
- source: null,
- target: null,
- length: 80,
- coeff: 0.0002,
- weight: 1
-});
-
-function makeSpring(spring) {
- return assign({}, defaults, spring);
-}
-
-function applySpring(spring) {
- var body1 = spring.source,
- body2 = spring.target,
- length = spring.length < 0 ? defaults.length : spring.length,
- dx = body2.pos.x - body1.pos.x,
- dy = body2.pos.y - body1.pos.y,
- r = Math.sqrt(dx * dx + dy * dy);
-
- if (r === 0) {
- dx = (Math.random() - 0.5) / 50;
- dy = (Math.random() - 0.5) / 50;
- r = Math.sqrt(dx * dx + dy * dy);
- }
-
- var d = r - length;
- var coeff = (!spring.coeff || spring.coeff < 0 ? defaults.springCoeff : spring.coeff) * d / r * spring.weight;
-
- body1.force.x += coeff * dx;
- body1.force.y += coeff * dy;
-
- body2.force.x -= coeff * dx;
- body2.force.y -= coeff * dy;
-}
-
-module.exports = { makeSpring: makeSpring, applySpring: applySpring };
-
-/***/ }),
-/* 2 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-/**
-The implementation of the Euler layout algorithm
-*/
-
-var Layout = __webpack_require__(13);
-var assign = __webpack_require__(0);
-var defaults = __webpack_require__(4);
-
-var _require = __webpack_require__(10),
- _tick = _require.tick;
-
-var _require2 = __webpack_require__(7),
- makeQuadtree = _require2.makeQuadtree;
-
-var _require3 = __webpack_require__(3),
- makeBody = _require3.makeBody;
-
-var _require4 = __webpack_require__(1),
- makeSpring = _require4.makeSpring;
-
-var isFn = function isFn(fn) {
- return typeof fn === 'function';
-};
-var isParent = function isParent(n) {
- return n.isParent();
-};
-var notIsParent = function notIsParent(n) {
- return !isParent(n);
-};
-var isLocked = function isLocked(n) {
- return n.locked();
-};
-var notIsLocked = function notIsLocked(n) {
- return !isLocked(n);
-};
-var isParentEdge = function isParentEdge(e) {
- return isParent(e.source()) || isParent(e.target());
-};
-var notIsParentEdge = function notIsParentEdge(e) {
- return !isParentEdge(e);
-};
-var getBody = function getBody(n) {
- return n.scratch('euler').body;
-};
-var getNonParentDescendants = function getNonParentDescendants(n) {
- return isParent(n) ? n.descendants().filter(notIsParent) : n;
-};
-
-var getScratch = function getScratch(el) {
- var scratch = el.scratch('euler');
-
- if (!scratch) {
- scratch = {};
-
- el.scratch('euler', scratch);
- }
-
- return scratch;
-};
-
-var optFn = function optFn(opt, ele) {
- if (isFn(opt)) {
- return opt(ele);
- } else {
- return opt;
- }
-};
-
-var Euler = function (_Layout) {
- _inherits(Euler, _Layout);
-
- function Euler(options) {
- _classCallCheck(this, Euler);
-
- return _possibleConstructorReturn(this, (Euler.__proto__ || Object.getPrototypeOf(Euler)).call(this, assign({}, defaults, options)));
- }
-
- _createClass(Euler, [{
- key: 'prerun',
- value: function prerun(state) {
- var s = state;
-
- s.quadtree = makeQuadtree();
-
- var bodies = s.bodies = [];
-
- // regular nodes
- s.nodes.filter(function (n) {
- return notIsParent(n);
- }).forEach(function (n) {
- var scratch = getScratch(n);
-
- var body = makeBody({
- pos: { x: scratch.x, y: scratch.y },
- mass: optFn(s.mass, n),
- locked: scratch.locked
- });
-
- body._cyNode = n;
-
- scratch.body = body;
-
- body._scratch = scratch;
-
- bodies.push(body);
- });
-
- var springs = s.springs = [];
-
- // regular edge springs
- s.edges.filter(notIsParentEdge).forEach(function (e) {
- var spring = makeSpring({
- source: getBody(e.source()),
- target: getBody(e.target()),
- length: optFn(s.springLength, e),
- coeff: optFn(s.springCoeff, e)
- });
-
- spring._cyEdge = e;
-
- var scratch = getScratch(e);
-
- spring._scratch = scratch;
-
- scratch.spring = spring;
-
- springs.push(spring);
- });
-
- // compound edge springs
- s.edges.filter(isParentEdge).forEach(function (e) {
- var sources = getNonParentDescendants(e.source());
- var targets = getNonParentDescendants(e.target());
-
- // just add one spring for perf
- sources = [sources[0]];
- targets = [targets[0]];
-
- sources.forEach(function (src) {
- targets.forEach(function (tgt) {
- springs.push(makeSpring({
- source: getBody(src),
- target: getBody(tgt),
- length: optFn(s.springLength, e),
- coeff: optFn(s.springCoeff, e)
- }));
- });
- });
- });
- }
- }, {
- key: 'tick',
- value: function tick(state) {
- var movement = _tick(state);
-
- var isDone = movement <= state.movementThreshold;
-
- return isDone;
- }
- }]);
-
- return Euler;
-}(Layout);
-
-module.exports = Euler;
-
-/***/ }),
-/* 3 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-var defaults = Object.freeze({
- pos: { x: 0, y: 0 },
- prevPos: { x: 0, y: 0 },
- force: { x: 0, y: 0 },
- velocity: { x: 0, y: 0 },
- mass: 1
-});
-
-var copyVec = function copyVec(v) {
- return { x: v.x, y: v.y };
-};
-var getValue = function getValue(val, def) {
- return val != null ? val : def;
-};
-var getVec = function getVec(vec, def) {
- return copyVec(getValue(vec, def));
-};
-
-function makeBody(opts) {
- var b = {};
-
- b.pos = getVec(opts.pos, defaults.pos);
- b.prevPos = getVec(opts.prevPos, b.pos);
- b.force = getVec(opts.force, defaults.force);
- b.velocity = getVec(opts.velocity, defaults.velocity);
- b.mass = opts.mass != null ? opts.mass : defaults.mass;
- b.locked = opts.locked;
-
- return b;
-}
-
-module.exports = { makeBody: makeBody };
-
-/***/ }),
-/* 4 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-var defaults = Object.freeze({
- // The ideal legth of a spring
- // - This acts as a hint for the edge length
- // - The edge length can be longer or shorter if the forces are set to extreme values
- springLength: function springLength(edge) {
- return 80;
- },
-
- // Hooke's law coefficient
- // - The value ranges on [0, 1]
- // - Lower values give looser springs
- // - Higher values give tighter springs
- springCoeff: function springCoeff(edge) {
- return 0.0008;
- },
-
- // The mass of the node in the physics simulation
- // - The mass affects the gravity node repulsion/attraction
- mass: function mass(node) {
- return 4;
- },
-
- // Coulomb's law coefficient
- // - Makes the nodes repel each other for negative values
- // - Makes the nodes attract each other for positive values
- gravity: -1.2,
-
- // A force that pulls nodes towards the origin (0, 0)
- // Higher values keep the components less spread out
- pull: 0.001,
-
- // Theta coefficient from Barnes-Hut simulation
- // - Value ranges on [0, 1]
- // - Performance is better with smaller values
- // - Very small values may not create enough force to give a good result
- theta: 0.666,
-
- // Friction / drag coefficient to make the system stabilise over time
- dragCoeff: 0.02,
-
- // When the total of the squared position deltas is less than this value, the simulation ends
- movementThreshold: 1,
-
- // The amount of time passed per tick
- // - Larger values result in faster runtimes but might spread things out too far
- // - Smaller values produce more accurate results
- timeStep: 20
-});
-
-module.exports = defaults;
-
-/***/ }),
-/* 5 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-var defaultCoeff = 0.02;
-
-function applyDrag(body, manualDragCoeff) {
- var dragCoeff = void 0;
-
- if (manualDragCoeff != null) {
- dragCoeff = manualDragCoeff;
- } else if (body.dragCoeff != null) {
- dragCoeff = body.dragCoeff;
- } else {
- dragCoeff = defaultCoeff;
- }
-
- body.force.x -= dragCoeff * body.velocity.x;
- body.force.y -= dragCoeff * body.velocity.y;
-}
-
-module.exports = { applyDrag: applyDrag };
-
-/***/ }),
-/* 6 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-// use euler method for force integration http://en.wikipedia.org/wiki/Euler_method
-// return sum of squared position deltas
-function integrate(bodies, timeStep) {
- var dx = 0,
- tx = 0,
- dy = 0,
- ty = 0,
- i,
- max = bodies.length;
-
- if (max === 0) {
- return 0;
- }
-
- for (i = 0; i < max; ++i) {
- var body = bodies[i],
- coeff = timeStep / body.mass;
-
- if (body.grabbed) {
- continue;
- }
-
- if (body.locked) {
- body.velocity.x = 0;
- body.velocity.y = 0;
- } else {
- body.velocity.x += coeff * body.force.x;
- body.velocity.y += coeff * body.force.y;
- }
-
- var vx = body.velocity.x,
- vy = body.velocity.y,
- v = Math.sqrt(vx * vx + vy * vy);
-
- if (v > 1) {
- body.velocity.x = vx / v;
- body.velocity.y = vy / v;
- }
-
- dx = timeStep * body.velocity.x;
- dy = timeStep * body.velocity.y;
-
- body.pos.x += dx;
- body.pos.y += dy;
-
- tx += Math.abs(dx);ty += Math.abs(dy);
- }
-
- return (tx * tx + ty * ty) / max;
-}
-
-module.exports = { integrate: integrate };
-
-/***/ }),
-/* 7 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-// impl of barnes hut
-// http://www.eecs.berkeley.edu/~demmel/cs267/lecture26/lecture26.html
-// http://en.wikipedia.org/wiki/Barnes%E2%80%93Hut_simulation
-
-var Node = __webpack_require__(9);
-var InsertStack = __webpack_require__(8);
-
-var resetVec = function resetVec(v) {
- v.x = 0;v.y = 0;
-};
-
-var isSamePosition = function isSamePosition(p1, p2) {
- var threshold = 1e-8;
- var dx = Math.abs(p1.x - p2.x);
- var dy = Math.abs(p1.y - p2.y);
-
- return dx < threshold && dy < threshold;
-};
-
-function makeQuadtree() {
- var updateQueue = [],
- insertStack = new InsertStack(),
- nodesCache = [],
- currentInCache = 0,
- root = newNode();
-
- function newNode() {
- // To avoid pressure on GC we reuse nodes.
- var node = nodesCache[currentInCache];
- if (node) {
- node.quad0 = null;
- node.quad1 = null;
- node.quad2 = null;
- node.quad3 = null;
- node.body = null;
- node.mass = node.massX = node.massY = 0;
- node.left = node.right = node.top = node.bottom = 0;
- } else {
- node = new Node();
- nodesCache[currentInCache] = node;
- }
-
- ++currentInCache;
- return node;
- }
-
- function update(sourceBody, gravity, theta, pull) {
- var queue = updateQueue,
- v = void 0,
- dx = void 0,
- dy = void 0,
- r = void 0,
- fx = 0,
- fy = 0,
- queueLength = 1,
- shiftIdx = 0,
- pushIdx = 1;
-
- queue[0] = root;
-
- resetVec(sourceBody.force);
-
- var px = -sourceBody.pos.x;
- var py = -sourceBody.pos.y;
- var pr = Math.sqrt(px * px + py * py);
- var pv = sourceBody.mass * pull / pr;
-
- fx += pv * px;
- fy += pv * py;
-
- while (queueLength) {
- var node = queue[shiftIdx],
- body = node.body;
-
- queueLength -= 1;
- shiftIdx += 1;
- var differentBody = body !== sourceBody;
- if (body && differentBody) {
- // If the current node is a leaf node (and it is not source body),
- // calculate the force exerted by the current node on body, and add this
- // amount to body's net force.
- dx = body.pos.x - sourceBody.pos.x;
- dy = body.pos.y - sourceBody.pos.y;
- r = Math.sqrt(dx * dx + dy * dy);
-
- if (r === 0) {
- // Poor man's protection against zero distance.
- dx = (Math.random() - 0.5) / 50;
- dy = (Math.random() - 0.5) / 50;
- r = Math.sqrt(dx * dx + dy * dy);
- }
-
- // This is standard gravition force calculation but we divide
- // by r^3 to save two operations when normalizing force vector.
- v = gravity * body.mass * sourceBody.mass / (r * r * r);
- fx += v * dx;
- fy += v * dy;
- } else if (differentBody) {
- // Otherwise, calculate the ratio s / r, where s is the width of the region
- // represented by the internal node, and r is the distance between the body
- // and the node's center-of-mass
- dx = node.massX / node.mass - sourceBody.pos.x;
- dy = node.massY / node.mass - sourceBody.pos.y;
- r = Math.sqrt(dx * dx + dy * dy);
-
- if (r === 0) {
- // Sorry about code duplucation. I don't want to create many functions
- // right away. Just want to see performance first.
- dx = (Math.random() - 0.5) / 50;
- dy = (Math.random() - 0.5) / 50;
- r = Math.sqrt(dx * dx + dy * dy);
- }
- // If s / r < θ, treat this internal node as a single body, and calculate the
- // force it exerts on sourceBody, and add this amount to sourceBody's net force.
- if ((node.right - node.left) / r < theta) {
- // in the if statement above we consider node's width only
- // because the region was squarified during tree creation.
- // Thus there is no difference between using width or height.
- v = gravity * node.mass * sourceBody.mass / (r * r * r);
- fx += v * dx;
- fy += v * dy;
- } else {
- // Otherwise, run the procedure recursively on each of the current node's children.
-
- // I intentionally unfolded this loop, to save several CPU cycles.
- if (node.quad0) {
- queue[pushIdx] = node.quad0;
- queueLength += 1;
- pushIdx += 1;
- }
- if (node.quad1) {
- queue[pushIdx] = node.quad1;
- queueLength += 1;
- pushIdx += 1;
- }
- if (node.quad2) {
- queue[pushIdx] = node.quad2;
- queueLength += 1;
- pushIdx += 1;
- }
- if (node.quad3) {
- queue[pushIdx] = node.quad3;
- queueLength += 1;
- pushIdx += 1;
- }
- }
- }
- }
-
- sourceBody.force.x += fx;
- sourceBody.force.y += fy;
- }
-
- function insertBodies(bodies) {
- if (bodies.length === 0) {
- return;
- }
-
- var x1 = Number.MAX_VALUE,
- y1 = Number.MAX_VALUE,
- x2 = Number.MIN_VALUE,
- y2 = Number.MIN_VALUE,
- i = void 0,
- max = bodies.length;
-
- // To reduce quad tree depth we are looking for exact bounding box of all particles.
- i = max;
- while (i--) {
- var x = bodies[i].pos.x;
- var y = bodies[i].pos.y;
- if (x < x1) {
- x1 = x;
- }
- if (x > x2) {
- x2 = x;
- }
- if (y < y1) {
- y1 = y;
- }
- if (y > y2) {
- y2 = y;
- }
- }
-
- // Squarify the bounds.
- var dx = x2 - x1,
- dy = y2 - y1;
- if (dx > dy) {
- y2 = y1 + dx;
- } else {
- x2 = x1 + dy;
- }
-
- currentInCache = 0;
- root = newNode();
- root.left = x1;
- root.right = x2;
- root.top = y1;
- root.bottom = y2;
-
- i = max - 1;
- if (i >= 0) {
- root.body = bodies[i];
- }
- while (i--) {
- insert(bodies[i], root);
- }
- }
-
- function insert(newBody) {
- insertStack.reset();
- insertStack.push(root, newBody);
-
- while (!insertStack.isEmpty()) {
- var stackItem = insertStack.pop(),
- node = stackItem.node,
- body = stackItem.body;
-
- if (!node.body) {
- // This is internal node. Update the total mass of the node and center-of-mass.
- var x = body.pos.x;
- var y = body.pos.y;
- node.mass = node.mass + body.mass;
- node.massX = node.massX + body.mass * x;
- node.massY = node.massY + body.mass * y;
-
- // Recursively insert the body in the appropriate quadrant.
- // But first find the appropriate quadrant.
- var quadIdx = 0,
- // Assume we are in the 0's quad.
- left = node.left,
- right = (node.right + left) / 2,
- top = node.top,
- bottom = (node.bottom + top) / 2;
-
- if (x > right) {
- // somewhere in the eastern part.
- quadIdx = quadIdx + 1;
- left = right;
- right = node.right;
- }
- if (y > bottom) {
- // and in south.
- quadIdx = quadIdx + 2;
- top = bottom;
- bottom = node.bottom;
- }
-
- var child = getChild(node, quadIdx);
- if (!child) {
- // The node is internal but this quadrant is not taken. Add
- // subnode to it.
- child = newNode();
- child.left = left;
- child.top = top;
- child.right = right;
- child.bottom = bottom;
- child.body = body;
-
- setChild(node, quadIdx, child);
- } else {
- // continue searching in this quadrant.
- insertStack.push(child, body);
- }
- } else {
- // We are trying to add to the leaf node.
- // We have to convert current leaf into internal node
- // and continue adding two nodes.
- var oldBody = node.body;
- node.body = null; // internal nodes do not cary bodies
-
- if (isSamePosition(oldBody.pos, body.pos)) {
- // Prevent infinite subdivision by bumping one node
- // anywhere in this quadrant
- var retriesCount = 3;
- do {
- var offset = Math.random();
- var dx = (node.right - node.left) * offset;
- var dy = (node.bottom - node.top) * offset;
-
- oldBody.pos.x = node.left + dx;
- oldBody.pos.y = node.top + dy;
- retriesCount -= 1;
- // Make sure we don't bump it out of the box. If we do, next iteration should fix it
- } while (retriesCount > 0 && isSamePosition(oldBody.pos, body.pos));
-
- if (retriesCount === 0 && isSamePosition(oldBody.pos, body.pos)) {
- // This is very bad, we ran out of precision.
- // if we do not return from the method we'll get into
- // infinite loop here. So we sacrifice correctness of layout, and keep the app running
- // Next layout iteration should get larger bounding box in the first step and fix this
- return;
- }
- }
- // Next iteration should subdivide node further.
- insertStack.push(node, oldBody);
- insertStack.push(node, body);
- }
- }
- }
-
- return {
- insertBodies: insertBodies,
- updateBodyForce: update
- };
-}
-
-function getChild(node, idx) {
- if (idx === 0) return node.quad0;
- if (idx === 1) return node.quad1;
- if (idx === 2) return node.quad2;
- if (idx === 3) return node.quad3;
- return null;
-}
-
-function setChild(node, idx, child) {
- if (idx === 0) node.quad0 = child;else if (idx === 1) node.quad1 = child;else if (idx === 2) node.quad2 = child;else if (idx === 3) node.quad3 = child;
-}
-
-module.exports = { makeQuadtree: makeQuadtree };
-
-/***/ }),
-/* 8 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-module.exports = InsertStack;
-
-/**
- * Our implmentation of QuadTree is non-recursive to avoid GC hit
- * This data structure represent stack of elements
- * which we are trying to insert into quad tree.
- */
-function InsertStack() {
- this.stack = [];
- this.popIdx = 0;
-}
-
-InsertStack.prototype = {
- isEmpty: function isEmpty() {
- return this.popIdx === 0;
- },
- push: function push(node, body) {
- var item = this.stack[this.popIdx];
- if (!item) {
- // we are trying to avoid memory pressue: create new element
- // only when absolutely necessary
- this.stack[this.popIdx] = new InsertStackElement(node, body);
- } else {
- item.node = node;
- item.body = body;
- }
- ++this.popIdx;
- },
- pop: function pop() {
- if (this.popIdx > 0) {
- return this.stack[--this.popIdx];
- }
- },
- reset: function reset() {
- this.popIdx = 0;
- }
-};
-
-function InsertStackElement(node, body) {
- this.node = node; // QuadTree node
- this.body = body; // physical body which needs to be inserted to node
-}
-
-/***/ }),
-/* 9 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-/**
- * Internal data structure to represent 2D QuadTree node
- */
-module.exports = function Node() {
- // body stored inside this node. In quad tree only leaf nodes (by construction)
- // contain boides:
- this.body = null;
-
- // Child nodes are stored in quads. Each quad is presented by number:
- // 0 | 1
- // -----
- // 2 | 3
- this.quad0 = null;
- this.quad1 = null;
- this.quad2 = null;
- this.quad3 = null;
-
- // Total mass of current node
- this.mass = 0;
-
- // Center of mass coordinates
- this.massX = 0;
- this.massY = 0;
-
- // bounding box coordinates
- this.left = 0;
- this.top = 0;
- this.bottom = 0;
- this.right = 0;
-};
-
-/***/ }),
-/* 10 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-var _require = __webpack_require__(6),
- integrate = _require.integrate;
-
-var _require2 = __webpack_require__(5),
- applyDrag = _require2.applyDrag;
-
-var _require3 = __webpack_require__(1),
- applySpring = _require3.applySpring;
-
-function tick(_ref) {
- var bodies = _ref.bodies,
- springs = _ref.springs,
- quadtree = _ref.quadtree,
- timeStep = _ref.timeStep,
- gravity = _ref.gravity,
- theta = _ref.theta,
- dragCoeff = _ref.dragCoeff,
- pull = _ref.pull;
-
- // update body from scratch in case of any changes
- bodies.forEach(function (body) {
- var p = body._scratch;
-
- if (!p) {
- return;
- }
-
- body.locked = p.locked;
- body.grabbed = p.grabbed;
- body.pos.x = p.x;
- body.pos.y = p.y;
- });
-
- quadtree.insertBodies(bodies);
-
- for (var i = 0; i < bodies.length; i++) {
- var body = bodies[i];
-
- quadtree.updateBodyForce(body, gravity, theta, pull);
- applyDrag(body, dragCoeff);
- }
-
- for (var _i = 0; _i < springs.length; _i++) {
- var spring = springs[_i];
-
- applySpring(spring);
- }
-
- var movement = integrate(bodies, timeStep);
-
- // update scratch positions from body positions
- bodies.forEach(function (body) {
- var p = body._scratch;
-
- if (!p) {
- return;
- }
-
- p.x = body.pos.x;
- p.y = body.pos.y;
- });
-
- return movement;
-}
-
-module.exports = { tick: tick };
-
-/***/ }),
-/* 11 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-var Euler = __webpack_require__(2);
-
-// registers the extension on a cytoscape lib ref
-var register = function register(cytoscape) {
- if (!cytoscape) {
- return;
- } // can't register if cytoscape unspecified
-
- cytoscape('layout', 'euler', Euler); // register with cytoscape.js
-};
-
-if (typeof cytoscape !== 'undefined') {
- // expose to global cytoscape (i.e. window.cytoscape)
- register(cytoscape);
-}
-
-module.exports = register;
-
-/***/ }),
-/* 12 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-// general default options for force-directed layout
-
-module.exports = Object.freeze({
- animate: true, // whether to show the layout as it's running; special 'end' value makes the layout animate like a discrete layout
- refresh: 10, // number of ticks per frame; higher is faster but more jerky
- maxIterations: 1000, // max iterations before the layout will bail out
- maxSimulationTime: 4000, // max length in ms to run the layout
- ungrabifyWhileSimulating: false, // so you can't drag nodes during layout
- fit: true, // on every layout reposition of nodes, fit the viewport
- padding: 30, // padding around the simulation
- boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
-
- // layout event callbacks
- ready: function ready() {}, // on layoutready
- stop: function stop() {}, // on layoutstop
-
- // positioning options
- randomize: false, // use random node positions at beginning of layout
-
- // infinite layout options
- infinite: false // overrides all other options for a forces-all-the-time mode
-});
-
-/***/ }),
-/* 13 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-/**
-A generic continuous layout class
-*/
-
-var assign = __webpack_require__(0);
-var defaults = __webpack_require__(12);
-var makeBoundingBox = __webpack_require__(14);
-
-var _require = __webpack_require__(15),
- setInitialPositionState = _require.setInitialPositionState,
- refreshPositions = _require.refreshPositions,
- getNodePositionData = _require.getNodePositionData;
-
-var _require2 = __webpack_require__(16),
- multitick = _require2.multitick;
-
-var Layout = function () {
- function Layout(options) {
- _classCallCheck(this, Layout);
-
- var o = this.options = assign({}, defaults, options);
-
- var s = this.state = assign({}, o, {
- layout: this,
- nodes: o.eles.nodes(),
- edges: o.eles.edges(),
- tickIndex: 0,
- firstUpdate: true
- });
-
- s.animateEnd = o.animate && o.animate === 'end';
- s.animateContinuously = o.animate && !s.animateEnd;
- }
-
- _createClass(Layout, [{
- key: 'run',
- value: function run() {
- var l = this;
- var s = this.state;
-
- s.tickIndex = 0;
- s.firstUpdate = true;
- s.startTime = Date.now();
- s.running = true;
-
- s.currentBoundingBox = makeBoundingBox(s.boundingBox, s.cy);
-
- if (s.ready) {
- l.one('ready', s.ready);
- }
- if (s.stop) {
- l.one('stop', s.stop);
- }
-
- s.nodes.forEach(function (n) {
- return setInitialPositionState(n, s);
- });
-
- l.prerun(s);
-
- if (s.animateContinuously) {
- var ungrabify = function ungrabify(node) {
- if (!s.ungrabifyWhileSimulating) {
- return;
- }
-
- var grabbable = getNodePositionData(node, s).grabbable = node.grabbable();
-
- if (grabbable) {
- node.ungrabify();
- }
- };
-
- var regrabify = function regrabify(node) {
- if (!s.ungrabifyWhileSimulating) {
- return;
- }
-
- var grabbable = getNodePositionData(node, s).grabbable;
-
- if (grabbable) {
- node.grabify();
- }
- };
-
- var updateGrabState = function updateGrabState(node) {
- return getNodePositionData(node, s).grabbed = node.grabbed();
- };
-
- var onGrab = function onGrab(_ref) {
- var target = _ref.target;
-
- updateGrabState(target);
- };
-
- var onFree = onGrab;
-
- var onDrag = function onDrag(_ref2) {
- var target = _ref2.target;
-
- var p = getNodePositionData(target, s);
- var tp = target.position();
-
- p.x = tp.x;
- p.y = tp.y;
- };
-
- var listenToGrab = function listenToGrab(node) {
- node.on('grab', onGrab);
- node.on('free', onFree);
- node.on('drag', onDrag);
- };
-
- var unlistenToGrab = function unlistenToGrab(node) {
- node.removeListener('grab', onGrab);
- node.removeListener('free', onFree);
- node.removeListener('drag', onDrag);
- };
-
- var fit = function fit() {
- if (s.fit && s.animateContinuously) {
- s.cy.fit(s.padding);
- }
- };
-
- var onNotDone = function onNotDone() {
- refreshPositions(s.nodes, s);
- fit();
-
- requestAnimationFrame(_frame);
- };
-
- var _frame = function _frame() {
- multitick(s, onNotDone, _onDone);
- };
-
- var _onDone = function _onDone() {
- refreshPositions(s.nodes, s);
- fit();
-
- s.nodes.forEach(function (n) {
- regrabify(n);
- unlistenToGrab(n);
- });
-
- s.running = false;
-
- l.emit('layoutstop');
- };
-
- l.emit('layoutstart');
-
- s.nodes.forEach(function (n) {
- ungrabify(n);
- listenToGrab(n);
- });
-
- _frame(); // kick off
- } else {
- var done = false;
- var _onNotDone = function _onNotDone() {};
- var _onDone2 = function _onDone2() {
- return done = true;
- };
-
- while (!done) {
- multitick(s, _onNotDone, _onDone2);
- }
-
- s.eles.layoutPositions(this, s, function (node) {
- var pd = getNodePositionData(node, s);
-
- return { x: pd.x, y: pd.y };
- });
- }
-
- l.postrun(s);
-
- return this; // chaining
- }
- }, {
- key: 'prerun',
- value: function prerun() {}
- }, {
- key: 'postrun',
- value: function postrun() {}
- }, {
- key: 'tick',
- value: function tick() {}
- }, {
- key: 'stop',
- value: function stop() {
- this.state.running = false;
-
- return this; // chaining
- }
- }, {
- key: 'destroy',
- value: function destroy() {
- return this; // chaining
- }
- }]);
-
- return Layout;
-}();
-
-module.exports = Layout;
-
-/***/ }),
-/* 14 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-module.exports = function (bb, cy) {
- if (bb == null) {
- bb = { x1: 0, y1: 0, w: cy.width(), h: cy.height() };
- } else {
- // copy
- bb = { x1: bb.x1, x2: bb.x2, y1: bb.y1, y2: bb.y2, w: bb.w, h: bb.h };
- }
-
- if (bb.x2 == null) {
- bb.x2 = bb.x1 + bb.w;
- }
- if (bb.w == null) {
- bb.w = bb.x2 - bb.x1;
- }
- if (bb.y2 == null) {
- bb.y2 = bb.y1 + bb.h;
- }
- if (bb.h == null) {
- bb.h = bb.y2 - bb.y1;
- }
-
- return bb;
-};
-
-/***/ }),
-/* 15 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-var assign = __webpack_require__(0);
-
-var setInitialPositionState = function setInitialPositionState(node, state) {
- var p = node.position();
- var bb = state.currentBoundingBox;
- var scratch = node.scratch(state.name);
-
- if (scratch == null) {
- scratch = {};
-
- node.scratch(state.name, scratch);
- }
-
- assign(scratch, state.randomize ? {
- x: bb.x1 + Math.random() * bb.w,
- y: bb.y1 + Math.random() * bb.h
- } : {
- x: p.x,
- y: p.y
- });
-
- scratch.locked = node.locked();
-};
-
-var getNodePositionData = function getNodePositionData(node, state) {
- return node.scratch(state.name);
-};
-
-var refreshPositions = function refreshPositions(nodes, state) {
- nodes.positions(function (node) {
- var scratch = node.scratch(state.name);
-
- return {
- x: scratch.x,
- y: scratch.y
- };
- });
-};
-
-module.exports = { setInitialPositionState: setInitialPositionState, getNodePositionData: getNodePositionData, refreshPositions: refreshPositions };
-
-/***/ }),
-/* 16 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-var nop = function nop() {};
-
-var tick = function tick(state) {
- var s = state;
- var l = state.layout;
-
- var tickIndicatesDone = l.tick(s);
-
- if (s.firstUpdate) {
- if (s.animateContinuously) {
- // indicate the initial positions have been set
- s.layout.emit('layoutready');
- }
- s.firstUpdate = false;
- }
-
- s.tickIndex++;
-
- var duration = Date.now() - s.startTime;
-
- return !s.infinite && (tickIndicatesDone || s.tickIndex >= s.maxIterations || duration >= s.maxSimulationTime);
-};
-
-var multitick = function multitick(state) {
- var onNotDone = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : nop;
- var onDone = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : nop;
-
- var done = false;
- var s = state;
-
- for (var i = 0; i < s.refresh; i++) {
- done = !s.running || tick(s);
-
- if (done) {
- break;
- }
- }
-
- if (!done) {
- onNotDone();
- } else {
- onDone();
- }
-};
-
-module.exports = { tick: tick, multitick: multitick };
-
-/***/ })
-/******/ ]);
-});
-//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uIiwid2VicGFjazovLy93ZWJwYWNrL2Jvb3RzdHJhcCA2MGFhNzhlOTI4NDc1MThmZDBmMyIsIndlYnBhY2s6Ly8vLi9zcmMvYXNzaWduLmpzIiwid2VicGFjazovLy8uL3NyYy9ldWxlci9zcHJpbmcuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2V1bGVyL2luZGV4LmpzIiwid2VicGFjazovLy8uL3NyYy9ldWxlci9ib2R5LmpzIiwid2VicGFjazovLy8uL3NyYy9ldWxlci9kZWZhdWx0cy5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvZXVsZXIvZHJhZy5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvZXVsZXIvaW50ZWdyYXRlLmpzIiwid2VicGFjazovLy8uL3NyYy9ldWxlci9xdWFkdHJlZS9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvZXVsZXIvcXVhZHRyZWUvaW5zZXJ0U3RhY2suanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2V1bGVyL3F1YWR0cmVlL25vZGUuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2V1bGVyL3RpY2suanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2luZGV4LmpzIiwid2VicGFjazovLy8uL3NyYy9sYXlvdXQvZGVmYXVsdHMuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2xheW91dC9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvbGF5b3V0L21ha2UtYmIuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2xheW91dC9wb3NpdGlvbi5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvbGF5b3V0L3RpY2suanMiXSwibmFtZXMiOlsibW9kdWxlIiwiZXhwb3J0cyIsIk9iamVjdCIsImFzc2lnbiIsImJpbmQiLCJ0Z3QiLCJzcmNzIiwiZm9yRWFjaCIsImtleXMiLCJzcmMiLCJrIiwicmVxdWlyZSIsImRlZmF1bHRzIiwiZnJlZXplIiwic291cmNlIiwidGFyZ2V0IiwibGVuZ3RoIiwiY29lZmYiLCJ3ZWlnaHQiLCJtYWtlU3ByaW5nIiwic3ByaW5nIiwiYXBwbHlTcHJpbmciLCJib2R5MSIsImJvZHkyIiwiZHgiLCJwb3MiLCJ4IiwiZHkiLCJ5IiwiciIsIk1hdGgiLCJzcXJ0IiwicmFuZG9tIiwiZCIsInNwcmluZ0NvZWZmIiwiZm9yY2UiLCJMYXlvdXQiLCJ0aWNrIiwibWFrZVF1YWR0cmVlIiwibWFrZUJvZHkiLCJpc0ZuIiwiZm4iLCJpc1BhcmVudCIsIm4iLCJub3RJc1BhcmVudCIsImlzTG9ja2VkIiwibG9ja2VkIiwibm90SXNMb2NrZWQiLCJpc1BhcmVudEVkZ2UiLCJlIiwibm90SXNQYXJlbnRFZGdlIiwiZ2V0Qm9keSIsInNjcmF0Y2giLCJib2R5IiwiZ2V0Tm9uUGFyZW50RGVzY2VuZGFudHMiLCJkZXNjZW5kYW50cyIsImZpbHRlciIsImdldFNjcmF0Y2giLCJlbCIsIm9wdEZuIiwib3B0IiwiZWxlIiwiRXVsZXIiLCJvcHRpb25zIiwic3RhdGUiLCJzIiwicXVhZHRyZWUiLCJib2RpZXMiLCJub2RlcyIsIm1hc3MiLCJfY3lOb2RlIiwiX3NjcmF0Y2giLCJwdXNoIiwic3ByaW5ncyIsImVkZ2VzIiwic3ByaW5nTGVuZ3RoIiwiX2N5RWRnZSIsInNvdXJjZXMiLCJ0YXJnZXRzIiwibW92ZW1lbnQiLCJpc0RvbmUiLCJtb3ZlbWVudFRocmVzaG9sZCIsInByZXZQb3MiLCJ2ZWxvY2l0eSIsImNvcHlWZWMiLCJ2IiwiZ2V0VmFsdWUiLCJ2YWwiLCJkZWYiLCJnZXRWZWMiLCJ2ZWMiLCJvcHRzIiwiYiIsImdyYXZpdHkiLCJwdWxsIiwidGhldGEiLCJkcmFnQ29lZmYiLCJ0aW1lU3RlcCIsImRlZmF1bHRDb2VmZiIsImFwcGx5RHJhZyIsIm1hbnVhbERyYWdDb2VmZiIsImludGVncmF0ZSIsInR4IiwidHkiLCJpIiwibWF4IiwiZ3JhYmJlZCIsInZ4IiwidnkiLCJhYnMiLCJOb2RlIiwiSW5zZXJ0U3RhY2siLCJyZXNldFZlYyIsImlzU2FtZVBvc2l0aW9uIiwicDEiLCJwMiIsInRocmVzaG9sZCIsInVwZGF0ZVF1ZXVlIiwiaW5zZXJ0U3RhY2siLCJub2Rlc0NhY2hlIiwiY3VycmVudEluQ2FjaGUiLCJyb290IiwibmV3Tm9kZSIsIm5vZGUiLCJxdWFkMCIsInF1YWQxIiwicXVhZDIiLCJxdWFkMyIsIm1hc3NYIiwibWFzc1kiLCJsZWZ0IiwicmlnaHQiLCJ0b3AiLCJib3R0b20iLCJ1cGRhdGUiLCJzb3VyY2VCb2R5IiwicXVldWUiLCJmeCIsImZ5IiwicXVldWVMZW5ndGgiLCJzaGlmdElkeCIsInB1c2hJZHgiLCJweCIsInB5IiwicHIiLCJwdiIsImRpZmZlcmVudEJvZHkiLCJpbnNlcnRCb2RpZXMiLCJ4MSIsIk51bWJlciIsIk1BWF9WQUxVRSIsInkxIiwieDIiLCJNSU5fVkFMVUUiLCJ5MiIsImluc2VydCIsIm5ld0JvZHkiLCJyZXNldCIsImlzRW1wdHkiLCJzdGFja0l0ZW0iLCJwb3AiLCJxdWFkSWR4IiwiY2hpbGQiLCJnZXRDaGlsZCIsInNldENoaWxkIiwib2xkQm9keSIsInJldHJpZXNDb3VudCIsIm9mZnNldCIsInVwZGF0ZUJvZHlGb3JjZSIsImlkeCIsInN0YWNrIiwicG9wSWR4IiwicHJvdG90eXBlIiwiaXRlbSIsIkluc2VydFN0YWNrRWxlbWVudCIsInAiLCJyZWdpc3RlciIsImN5dG9zY2FwZSIsImFuaW1hdGUiLCJyZWZyZXNoIiwibWF4SXRlcmF0aW9ucyIsIm1heFNpbXVsYXRpb25UaW1lIiwidW5ncmFiaWZ5V2hpbGVTaW11bGF0aW5nIiwiZml0IiwicGFkZGluZyIsImJvdW5kaW5nQm94IiwidW5kZWZpbmVkIiwicmVhZHkiLCJzdG9wIiwicmFuZG9taXplIiwiaW5maW5pdGUiLCJtYWtlQm91bmRpbmdCb3giLCJzZXRJbml0aWFsUG9zaXRpb25TdGF0ZSIsInJlZnJlc2hQb3NpdGlvbnMiLCJnZXROb2RlUG9zaXRpb25EYXRhIiwibXVsdGl0aWNrIiwibyIsImxheW91dCIsImVsZXMiLCJ0aWNrSW5kZXgiLCJmaXJzdFVwZGF0ZSIsImFuaW1hdGVFbmQiLCJhbmltYXRlQ29udGludW91c2x5IiwibCIsInN0YXJ0VGltZSIsIkRhdGUiLCJub3ciLCJydW5uaW5nIiwiY3VycmVudEJvdW5kaW5nQm94IiwiY3kiLCJvbmUiLCJwcmVydW4iLCJ1bmdyYWJpZnkiLCJncmFiYmFibGUiLCJyZWdyYWJpZnkiLCJncmFiaWZ5IiwidXBkYXRlR3JhYlN0YXRlIiwib25HcmFiIiwib25GcmVlIiwib25EcmFnIiwidHAiLCJwb3NpdGlvbiIsImxpc3RlblRvR3JhYiIsIm9uIiwidW5saXN0ZW5Ub0dyYWIiLCJyZW1vdmVMaXN0ZW5lciIsIm9uTm90RG9uZSIsInJlcXVlc3RBbmltYXRpb25GcmFtZSIsImZyYW1lIiwib25Eb25lIiwiZW1pdCIsImRvbmUiLCJsYXlvdXRQb3NpdGlvbnMiLCJwZCIsInBvc3RydW4iLCJiYiIsInciLCJ3aWR0aCIsImgiLCJoZWlnaHQiLCJuYW1lIiwicG9zaXRpb25zIiwibm9wIiwidGlja0luZGljYXRlc0RvbmUiLCJkdXJhdGlvbiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNELE87QUNWQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsbURBQTJDLGNBQWM7O0FBRXpEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUNBQTJCLDBCQUEwQixFQUFFO0FBQ3ZELHlDQUFpQyxlQUFlO0FBQ2hEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhEQUFzRCwrREFBK0Q7O0FBRXJIO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7Ozs7OztBQ2hFQUEsT0FBT0MsT0FBUCxHQUFpQkMsT0FBT0Ms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bkJnQixHQUFtQjtBQUFBLE1BQWRiLE1BQWMsdUVBQUxhLEdBQUs7O0FBQzlELE1BQUlYLE9BQU8sS0FBWDtBQUNBLE1BQUl0SyxJQUFJRCxLQUFSOztBQUVBLE9BQUssSUFBSXdDLElBQUksQ0FBYixFQUFnQkEsSUFBSXZDLEVBQUVrSCxPQUF0QixFQUErQjNFLEdBQS9CLEVBQW9DO0FBQ2xDK0gsV0FBTyxDQUFDdEssRUFBRThJLE9BQUgsSUFBYzFLLEtBQU00QixDQUFOLENBQXJCOztBQUVBLFFBQUlzSyxJQUFKLEVBQVU7QUFBRTtBQUFRO0FBQ3JCOztBQUVELE1BQUksQ0FBQ0EsSUFBTCxFQUFXO0FBQ1RMO0FBQ0QsR0FGRCxNQUVPO0FBQ0xHO0FBQ0Q7QUFDRixDQWZEOztBQWlCQXJPLE9BQU9DLE9BQVAsR0FBaUIsRUFBRW9DLFVBQUYsRUFBUThKLG9CQUFSLEVBQWpCLEMiLCJmaWxlIjoiY3l0b3NjYXBlLWV1bGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIHdlYnBhY2tVbml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnKVxuXHRcdG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpO1xuXHRlbHNlIGlmKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZClcblx0XHRkZWZpbmUoW10sIGZhY3RvcnkpO1xuXHRlbHNlIGlmKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0Jylcblx0XHRleHBvcnRzW1wiY3l0b3NjYXBlRXVsZXJcIl0gPSBmYWN0b3J5KCk7XG5cdGVsc2Vcblx0XHRyb290W1wiY3l0b3NjYXBlRXVsZXJcIl0gPSBmYWN0b3J5KCk7XG59KSh0aGlzLCBmdW5jdGlvbigpIHtcbnJldHVybiBcblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uIiwiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHtcbiBcdFx0XHRyZXR1cm4gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0uZXhwb3J0cztcbiBcdFx0fVxuIFx0XHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuIFx0XHR2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gXHRcdFx0aTogbW9kdWxlSWQsXG4gXHRcdFx0bDogZmFsc2UsXG4gXHRcdFx0ZXhwb3J0czoge31cbiBcdFx0fTtcblxuIFx0XHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cbiBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cbiBcdFx0Ly8gRmxhZyB0aGUgbW9kdWxlIGFzIGxvYWRlZFxuIFx0XHRtb2R1bGUubCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gaWRlbnRpdHkgZnVuY3Rpb24gZm9yIGNhbGxpbmcgaGFybW9ueSBpbXBvcnRzIHdpdGggdGhlIGNvcnJlY3QgY29udGV4dFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5pID0gZnVuY3Rpb24odmFsdWUpIHsgcmV0dXJuIHZhbHVlOyB9O1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHtcbiBcdFx0XHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuIFx0XHRcdFx0Z2V0OiBnZXR0ZXJcbiBcdFx0XHR9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbiBcdFx0XHRmdW5jdGlvbiBnZXREZWZhdWx0KCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuIFx0XHRcdGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7IHJldHVybiBtb2R1bGU7IH07XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbiBcdFx0cmV0dXJuIGdldHRlcjtcbiBcdH07XG5cbiBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpOyB9O1xuXG4gXHQvLyBfX3dlYnBhY2tfcHVibGljX3BhdGhfX1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCJcIjtcblxuIFx0Ly8gTG9hZCBlbnRyeSBtb2R1bGUgYW5kIHJldHVybiBleHBvcnRzXG4gXHRyZXR1cm4gX193ZWJwYWNrX3JlcXVpcmVfXyhfX3dlYnBhY2tfcmVxdWlyZV9fLnMgPSAxMSk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gd2VicGFjay9ib290c3RyYXAgNjBhYTc4ZTkyODQ3NTE4ZmQwZjMiLCJtb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5hc3NpZ24gIT0gbnVsbCA/IE9iamVjdC5hc3NpZ24uYmluZCggT2JqZWN0ICkgOiBmdW5jdGlvbiggdGd0LCAuLi5zcmNzICl7XG4gIHNyY3MuZm9yRWFjaCggc3JjID0+IHtcbiAgICBPYmplY3Qua2V5cyggc3JjICkuZm9yRWFjaCggayA9PiB0Z3Rba10gPSBzcmNba10gKTtcbiAgfSApO1xuXG4gIHJldHVybiB0Z3Q7XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2Fzc2lnbi5qcyIsImNvbnN0IGFzc2lnbiA9IHJlcXVpcmUoJy4uL2Fzc2lnbicpO1xuXG5jb25zdCBkZWZhdWx0cyA9IE9iamVjdC5mcmVlemUoe1xuICBzb3VyY2U6IG51bGwsXG4gIHRhcmdldDogbnVsbCxcbiAgbGVuZ3RoOiA4MCxcbiAgY29lZmY6IDAuMDAwMixcbiAgd2VpZ2h0OiAxXG59KTtcblxuZnVuY3Rpb24gbWFrZVNwcmluZyggc3ByaW5nICl7XG4gIHJldHVybiBhc3NpZ24oIHt9LCBkZWZhdWx0cywgc3ByaW5nICk7XG59XG5cbmZ1bmN0aW9uIGFwcGx5U3ByaW5nKCBzcHJpbmcgKXtcbiAgbGV0IGJvZHkxID0gc3ByaW5nLnNvdXJjZSxcbiAgICAgIGJvZHkyID0gc3ByaW5nLnRhcmdldCxcbiAgICAgIGxlbmd0aCA9IHNwcmluZy5sZW5ndGggPCAwID8gZGVmYXVsdHMubGVuZ3RoIDogc3ByaW5nLmxlbmd0aCxcbiAgICAgIGR4ID0gYm9keTIucG9zLnggLSBib2R5MS5wb3MueCxcbiAgICAgIGR5ID0gYm9keTIucG9zLnkgLSBib2R5MS5wb3MueSxcbiAgICAgIHIgPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xuXG4gIGlmIChyID09PSAwKSB7XG4gICAgICBkeCA9IChNYXRoLnJhbmRvbSgpIC0gMC41KSAvIDUwO1xuICAgICAgZHkgPSAoTWF0aC5yYW5kb20oKSAtIDAuNSkgLyA1MDtcbiAgICAgIHIgPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xuICB9XG5cbiAgbGV0IGQgPSByIC0gbGVuZ3RoO1xuICBsZXQgY29lZmYgPSAoKCFzcHJpbmcuY29lZmYgfHwgc3ByaW5nLmNvZWZmIDwgMCkgPyBkZWZhdWx0cy5zcHJpbmdDb2VmZiA6IHNwcmluZy5jb2VmZikgKiBkIC8gciAqIHNwcmluZy53ZWlnaHQ7XG5cbiAgYm9keTEuZm9yY2UueCArPSBjb2VmZiAqIGR4O1xuICBib2R5MS5mb3JjZS55ICs9IGNvZWZmICogZHk7XG5cbiAgYm9keTIuZm9yY2UueCAtPSBjb2VmZiAqIGR4O1xuICBib2R5Mi5mb3JjZS55IC09IGNvZWZmICogZHk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0geyBtYWtlU3ByaW5nLCBhcHBseVNwcmluZyB9O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2V1bGVyL3NwcmluZy5qcyIsIi8qKlxuVGhlIGltcGxlbWVudGF0aW9uIG9mIHRoZSBFdWxlciBsYXlvdXQgYWxnb3JpdGhtXG4qL1xuXG5jb25zdCBMYXlvdXQgPSByZXF1aXJlKCcuLi9sYXlvdXQnKTtcbmNvbnN0IGFzc2lnbiA9IHJlcXVpcmUoJy4uL2Fzc2lnbicpO1xuY29uc3QgZGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5jb25zdCB7IHRpY2sgfSA9IHJlcXVpcmUoJy4vdGljaycpO1xuY29uc3QgeyBtYWtlUXVhZHRyZWUgfSA9IHJlcXVpcmUoJy4vcXVhZHRyZWUnKTtcbmNvbnN0IHsgbWFrZUJvZHkgfSA9IHJlcXVpcmUoJy4vYm9keScpO1xuY29uc3QgeyBtYWtlU3ByaW5nIH0gPSByZXF1aXJlKCcuL3NwcmluZycpO1xuY29uc3QgaXNGbiA9IGZuID0+IHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJztcbmNvbnN0IGlzUGFyZW50ID0gbiA9PiBuLmlzUGFyZW50KCk7XG5jb25zdCBub3RJc1BhcmVudCA9IG4gPT4gIWlzUGFyZW50KG4pO1xuY29uc3QgaXNMb2NrZWQgPSBuID0+IG4ubG9ja2VkKCk7XG5jb25zdCBub3RJc0xvY2tlZCA9IG4gPT4gIWlzTG9ja2VkKG4pO1xuY29uc3QgaXNQYXJlbnRFZGdlID0gZSA9PiBpc1BhcmVudCggZS5zb3VyY2UoKSApIHx8IGlzUGFyZW50KCBlLnRhcmdldCgpICk7XG5jb25zdCBub3RJc1BhcmVudEVkZ2UgPSBlID0+ICFpc1BhcmVudEVkZ2UoZSk7XG5jb25zdCBnZXRCb2R5ID0gbiA9PiBuLnNjcmF0Y2goJ2V1bGVyJykuYm9keTtcbmNvbnN0IGdldE5vblBhcmVudERlc2NlbmRhbnRzID0gbiA9PiBpc1BhcmVudChuKSA/IG4uZGVzY2VuZGFudHMoKS5maWx0ZXIoIG5vdElzUGFyZW50ICkgOiBuO1xuXG5jb25zdCBnZXRTY3JhdGNoID0gZWwgPT4ge1xuICBsZXQgc2NyYXRjaCA9IGVsLnNjcmF0Y2goJ2V1bGVyJyk7XG5cbiAgaWYoICFzY3JhdGNoICl7XG4gICAgc2NyYXRjaCA9IHt9O1xuXG4gICAgZWwuc2NyYXRjaCgnZXVsZXInLCBzY3JhdGNoKTtcbiAgfVxuXG4gIHJldHVybiBzY3JhdGNoO1xufTtcblxuY29uc3Qgb3B0Rm4gPSAoIG9wdCwgZWxlICkgPT4ge1xuICBpZiggaXNGbiggb3B0ICkgKXtcbiAgICByZXR1cm4gb3B0KCBlbGUgKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gb3B0O1xuICB9XG59O1xuXG5jbGFzcyBFdWxlciBleHRlbmRzIExheW91dCB7XG4gIGNvbnN0cnVjdG9yKCBvcHRpb25zICl7XG4gICAgc3VwZXIoIGFzc2lnbigge30sIGRlZmF1bHRzLCBvcHRpb25zICkgKTtcbiAgfVxuXG4gIHByZXJ1biggc3RhdGUgKXtcbiAgICBsZXQgcyA9IHN0YXRlO1xuXG4gICAgcy5xdWFkdHJlZSA9IG1ha2VRdWFkdHJlZSgpO1xuXG4gICAgbGV0IGJvZGllcyA9IHMuYm9kaWVzID0gW107XG5cbiAgICAvLyByZWd1bGFyIG5vZGVzXG4gICAgcy5ub2Rlcy5maWx0ZXIoIG4gPT4gbm90SXNQYXJlbnQobikgKS5mb3JFYWNoKCBuID0+IHtcbiAgICAgIGxldCBzY3JhdGNoID0gZ2V0U2NyYXRjaCggbiApO1xuXG4gICAgICBsZXQgYm9keSA9IG1ha2VCb2R5KHtcbiAgICAgICAgcG9zOiB7IHg6IHNjcmF0Y2gueCwgeTogc2NyYXRjaC55IH0sXG4gICAgICAgIG1hc3M6IG9wdEZuKCBzLm1hc3MsIG4gKSxcbiAgICAgICAgbG9ja2VkOiBzY3JhdGNoLmxvY2tlZFxuICAgICAgfSk7XG5cbiAgICAgIGJvZHkuX2N5Tm9kZSA9IG47XG5cbiAgICAgIHNjcmF0Y2guYm9keSA9IGJvZHk7XG5cbiAgICAgIGJvZHkuX3NjcmF0Y2ggPSBzY3JhdGNoO1xuXG4gICAgICBib2RpZXMucHVzaCggYm9keSApO1xuICAgIH0gKTtcblxuICAgIGxldCBzcHJpbmdzID0gcy5zcHJpbmdzID0gW107XG5cbiAgICAvLyByZWd1bGFyIGVkZ2Ugc3ByaW5nc1xuICAgIHMuZWRnZXMuZmlsdGVyKCBub3RJc1BhcmVudEVkZ2UgKS5mb3JFYWNoKCBlID0+IHtcbiAgICAgIGxldCBzcHJpbmcgPSBtYWtlU3ByaW5nKHtcbiAgICAgICAgc291cmNlOiBnZXRCb2R5KCBlLnNvdXJjZSgpICksXG4gICAgICAgIHRhcmdldDogZ2V0Qm9keSggZS50YXJnZXQoKSApLFxuICAgICAgICBsZW5ndGg6IG9wdEZuKCBzLnNwcmluZ0xlbmd0aCwgZSApLFxuICAgICAgICBjb2VmZjogb3B0Rm4oIHMuc3ByaW5nQ29lZmYsIGUgKVxuICAgICAgfSk7XG5cbiAgICAgIHNwcmluZy5fY3lFZGdlID0gZTtcblxuICAgICAgbGV0IHNjcmF0Y2ggPSBnZXRTY3JhdGNoKCBlICk7XG5cbiAgICAgIHNwcmluZy5fc2NyYXRjaCA9IHNjcmF0Y2g7XG5cbiAgICAgIHNjcmF0Y2guc3ByaW5nID0gc3ByaW5nO1xuXG4gICAgICBzcHJpbmdzLnB1c2goIHNwcmluZyApO1xuICAgIH0gKTtcblxuICAgIC8vIGNvbXBvdW5kIGVkZ2Ugc3ByaW5nc1xuICAgIHMuZWRnZXMuZmlsdGVyKCBpc1BhcmVudEVkZ2UgKS5mb3JFYWNoKCBlID0+IHtcbiAgICAgIGxldCBzb3VyY2VzID0gZ2V0Tm9uUGFyZW50RGVzY2VuZGFudHMoIGUuc291cmNlKCkgKTtcbiAgICAgIGxldCB0YXJnZXRzID0gZ2V0Tm9uUGFyZW50RGVzY2VuZGFudHMoIGUudGFyZ2V0KCkgKTtcblxuICAgICAgLy8ganVzdCBhZGQgb25lIHNwcmluZyBmb3IgcGVyZlxuICAgICAgc291cmNlcyA9IFsgc291cmNlc1swXSBdO1xuICAgICAgdGFyZ2V0cyA9IFsgdGFyZ2V0c1swXSBdO1xuXG4gICAgICBzb3VyY2VzLmZvckVhY2goIHNyYyA9PiB7XG4gICAgICAgIHRhcmdldHMuZm9yRWFjaCggdGd0ID0+IHtcbiAgICAgICAgICBzcHJpbmdzLnB1c2goIG1ha2VTcHJpbmcoe1xuICAgICAgICAgICAgc291cmNlOiBnZXRCb2R5KCBzcmMgKSxcbiAgICAgICAgICAgIHRhcmdldDogZ2V0Qm9keSggdGd0ICksXG4gICAgICAgICAgICBsZW5ndGg6IG9wdEZuKCBzLnNwcmluZ0xlbmd0aCwgZSApLFxuICAgICAgICAgICAgY29lZmY6IG9wdEZuKCBzLnNwcmluZ0NvZWZmLCBlIClcbiAgICAgICAgICB9KSApO1xuICAgICAgICB9ICk7XG4gICAgICB9ICk7XG4gICAgfSApO1xuICB9XG5cbiAgdGljayggc3RhdGUgKXtcbiAgICBsZXQgbW92ZW1lbnQgPSB0aWNrKCBzdGF0ZSApO1xuXG4gICAgbGV0IGlzRG9uZSA9IG1vdmVtZW50IDw9IHN0YXRlLm1vdmVtZW50VGhyZXNob2xkO1xuXG4gICAgcmV0dXJuIGlzRG9uZTtcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IEV1bGVyO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2V1bGVyL2luZGV4LmpzIiwiY29uc3QgZGVmYXVsdHMgPSBPYmplY3QuZnJlZXplKHtcbiAgcG9zOiB7IHg6IDAsIHk6IDAgfSxcbiAgcHJldlBvczogeyB4OiAwLCB5OiAwIH0sXG4gIGZvcmNlOiB7IHg6IDAsIHk6IDAgfSxcbiAgdmVsb2NpdHk6IHsgeDogMCwgeTogMCB9LFxuICBtYXNzOiAxXG59KTtcblxuY29uc3QgY29weVZlYyA9IHYgPT4gKHsgeDogdi54LCB5OiB2LnkgfSk7XG5jb25zdCBnZXRWYWx1ZSA9ICggdmFsLCBkZWYgKSA9PiB2YWwgIT0gbnVsbCA/IHZhbCA6IGRlZjtcbmNvbnN0IGdldFZlYyA9ICggdmVjLCBkZWYgKSA9PiBjb3B5VmVjKCBnZXRWYWx1ZSggdmVjLCBkZWYgKSApO1xuXG5mdW5jdGlvbiBtYWtlQm9keSggb3B0cyApe1xuICBsZXQgYiA9IHt9O1xuXG4gIGIucG9zID0gZ2V0VmVjKCBvcHRzLnBvcywgZGVmYXVsdHMucG9zICk7XG4gIGIucHJldlBvcyA9IGdldFZlYyggb3B0cy5wcmV2UG9zLCBiLnBvcyApO1xuICBiLmZvcmNlID0gZ2V0VmVjKCBvcHRzLmZvcmNlLCBkZWZhdWx0cy5mb3JjZSApO1xuICBiLnZlbG9jaXR5ID0gZ2V0VmVjKCBvcHRzLnZlbG9jaXR5LCBkZWZhdWx0cy52ZWxvY2l0eSApO1xuICBiLm1hc3MgPSBvcHRzLm1hc3MgIT0gbnVsbCA/IG9wdHMubWFzcyA6IGRlZmF1bHRzLm1hc3M7XG4gIGIubG9ja2VkID0gb3B0cy5sb2NrZWQ7XG5cbiAgcmV0dXJuIGI7XG59XG5cbm1vZHVsZS5leHBvcnRzID0geyBtYWtlQm9keSB9O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2V1bGVyL2JvZHkuanMiLCJjb25zdCBkZWZhdWx0cyA9IE9iamVjdC5mcmVlemUoe1xuICAvLyBUaGUgaWRlYWwgbGVndGggb2YgYSBzcHJpbmdcbiAgLy8gLSBUaGlzIGFjdHMgYXMgYSBoaW50IGZvciB0aGUgZWRnZSBsZW5ndGhcbiAgLy8gLSBUaGUgZWRnZSBsZW5ndGggY2FuIGJlIGxvbmdlciBvciBzaG9ydGVyIGlmIHRoZSBmb3JjZXMgYXJlIHNldCB0byBleHRyZW1lIHZhbHVlc1xuICBzcHJpbmdMZW5ndGg6IGVkZ2UgPT4gODAsXG5cbiAgLy8gSG9va2UncyBsYXcgY29lZmZpY2llbnRcbiAgLy8gLSBUaGUgdmFsdWUgcmFuZ2VzIG9uIFswLCAxXVxuICAvLyAtIExvd2VyIHZhbHVlcyBnaXZlIGxvb3NlciBzcHJpbmdzXG4gIC8vIC0gSGlnaGVyIHZhbHVlcyBnaXZlIHRpZ2h0ZXIgc3ByaW5nc1xuICBzcHJpbmdDb2VmZjogZWRnZSA9PiAwLjAwMDgsXG5cbiAgLy8gVGhlIG1hc3Mgb2YgdGhlIG5vZGUgaW4gdGhlIHBoeXNpY3Mgc2ltdWxhdGlvblxuICAvLyAtIFRoZSBtYXNzIGFmZmVjdHMgdGhlIGdyYXZpdHkgbm9kZSByZXB1bHNpb24vYXR0cmFjdGlvblxuICBtYXNzOiBub2RlID0+IDQsXG5cbiAgLy8gQ291bG9tYidzIGxhdyBjb2VmZmljaWVudFxuICAvLyAtIE1ha2VzIHRoZSBub2RlcyByZXBlbCBlYWNoIG90aGVyIGZvciBuZWdhdGl2ZSB2YWx1ZXNcbiAgLy8gLSBNYWtlcyB0aGUgbm9kZXMgYXR0cmFjdCBlYWNoIG90aGVyIGZvciBwb3NpdGl2ZSB2YWx1ZXNcbiAgZ3Jhdml0eTogLTEuMixcblxuICAvLyBBIGZvcmNlIHRoYXQgcHVsbHMgbm9kZXMgdG93YXJkcyB0aGUgb3JpZ2luICgwLCAwKVxuICAvLyBIaWdoZXIgdmFsdWVzIGtlZXAgdGhlIGNvbXBvbmVudHMgbGVzcyBzcHJlYWQgb3V0XG4gIHB1bGw6IDAuMDAxLFxuXG4gIC8vIFRoZXRhIGNvZWZmaWNpZW50IGZyb20gQmFybmVzLUh1dCBzaW11bGF0aW9uXG4gIC8vIC0gVmFsdWUgcmFuZ2VzIG9uIFswLCAxXVxuICAvLyAtIFBlcmZvcm1hbmNlIGlzIGJldHRlciB3aXRoIHNtYWxsZXIgdmFsdWVzXG4gIC8vIC0gVmVyeSBzbWFsbCB2YWx1ZXMgbWF5IG5vdCBjcmVhdGUgZW5vdWdoIGZvcmNlIHRvIGdpdmUgYSBnb29kIHJlc3VsdFxuICB0aGV0YTogMC42NjYsXG5cbiAgLy8gRnJpY3Rpb24gLyBkcmFnIGNvZWZmaWNpZW50IHRvIG1ha2UgdGhlIHN5c3RlbSBzdGFiaWxpc2Ugb3ZlciB0aW1lXG4gIGRyYWdDb2VmZjogMC4wMixcblxuICAvLyBXaGVuIHRoZSB0b3RhbCBvZiB0aGUgc3F1YXJlZCBwb3NpdGlvbiBkZWx0YXMgaXMgbGVzcyB0aGFuIHRoaXMgdmFsdWUsIHRoZSBzaW11bGF0aW9uIGVuZHNcbiAgbW92ZW1lbnRUaHJlc2hvbGQ6IDEsXG5cbiAgLy8gVGhlIGFtb3VudCBvZiB0aW1lIHBhc3NlZCBwZXIgdGlja1xuICAvLyAtIExhcmdlciB2YWx1ZXMgcmVzdWx0IGluIGZhc3RlciBydW50aW1lcyBidXQgbWlnaHQgc3ByZWFkIHRoaW5ncyBvdXQgdG9vIGZhclxuICAvLyAtIFNtYWxsZXIgdmFsdWVzIHByb2R1Y2UgbW9yZSBhY2N1cmF0ZSByZXN1bHRzXG4gIHRpbWVTdGVwOiAyMFxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gZGVmYXVsdHM7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvZXVsZXIvZGVmYXVsdHMuanMiLCJjb25zdCBkZWZhdWx0Q29lZmYgPSAwLjAyO1xuXG5mdW5jdGlvbiBhcHBseURyYWcoIGJvZHksIG1hbnVhbERyYWdDb2VmZiApe1xuICBsZXQgZHJhZ0NvZWZmO1xuXG4gIGlmKCBtYW51YWxEcmFnQ29lZmYgIT0gbnVsbCApe1xuICAgIGRyYWdDb2VmZiA9IG1hbnVhbERyYWdDb2VmZjtcbiAgfSBlbHNlIGlmKCBib2R5LmRyYWdDb2VmZiAhPSBudWxsICl7XG4gICAgZHJhZ0NvZWZmID0gYm9keS5kcmFnQ29lZmY7XG4gIH0gZWxzZSB7XG4gICAgZHJhZ0NvZWZmID0gZGVmYXVsdENvZWZmO1xuICB9XG5cbiAgYm9keS5mb3JjZS54IC09IGRyYWdDb2VmZiAqIGJvZHkudmVsb2NpdHkueDtcbiAgYm9keS5mb3JjZS55IC09IGRyYWdDb2VmZiAqIGJvZHkudmVsb2NpdHkueTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7IGFwcGx5RHJhZyB9O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2V1bGVyL2RyYWcuanMiLCIvLyB1c2UgZXVsZXIgbWV0aG9kIGZvciBmb3JjZSBpbnRlZ3JhdGlvbiBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0V1bGVyX21ldGhvZFxuLy8gcmV0dXJuIHN1bSBvZiBzcXVhcmVkIHBvc2l0aW9uIGRlbHRhc1xuZnVuY3Rpb24gaW50ZWdyYXRlKCBib2RpZXMsIHRpbWVTdGVwICl7XG4gIHZhciBkeCA9IDAsIHR4ID0gMCxcbiAgICAgIGR5ID0gMCwgdHkgPSAwLFxuICAgICAgaSxcbiAgICAgIG1heCA9IGJvZGllcy5sZW5ndGg7XG5cbiAgaWYgKG1heCA9PT0gMCkge1xuICAgIHJldHVybiAwO1xuICB9XG5cbiAgZm9yIChpID0gMDsgaSA8IG1heDsgKytpKSB7XG4gICAgdmFyIGJvZHkgPSBib2RpZXNbaV0sXG4gICAgICAgIGNvZWZmID0gdGltZVN0ZXAgLyBib2R5Lm1hc3M7XG5cbiAgICBpZiggYm9keS5ncmFiYmVkICl7IGNvbnRpbnVlOyB9XG5cbiAgICBpZiggYm9keS5sb2NrZWQgKXtcbiAgICAgIGJvZHkudmVsb2NpdHkueCA9IDA7XG4gICAgICBib2R5LnZlbG9jaXR5LnkgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBib2R5LnZlbG9jaXR5LnggKz0gY29lZmYgKiBib2R5LmZvcmNlLng7XG4gICAgICBib2R5LnZlbG9jaXR5LnkgKz0gY29lZmYgKiBib2R5LmZvcmNlLnk7XG4gICAgfVxuXG4gICAgdmFyIHZ4ID0gYm9keS52ZWxvY2l0eS54LFxuICAgICAgICB2eSA9IGJvZHkudmVsb2NpdHkueSxcbiAgICAgICAgdiA9IE1hdGguc3FydCh2eCAqIHZ4ICsgdnkgKiB2eSk7XG5cbiAgICBpZiAodiA+IDEpIHtcbiAgICAgIGJvZHkudmVsb2NpdHkueCA9IHZ4IC8gdjtcbiAgICAgIGJvZHkudmVsb2NpdHkueSA9IHZ5IC8gdjtcbiAgICB9XG5cbiAgICBkeCA9IHRpbWVTdGVwICogYm9keS52ZWxvY2l0eS54O1xuICAgIGR5ID0gdGltZVN0ZXAgKiBib2R5LnZlbG9jaXR5Lnk7XG5cbiAgICBib2R5LnBvcy54ICs9IGR4O1xuICAgIGJvZHkucG9zLnkgKz0gZHk7XG5cbiAgICB0eCArPSBNYXRoLmFicyhkeCk7IHR5ICs9IE1hdGguYWJzKGR5KTtcbiAgfVxuXG4gIHJldHVybiAodHggKiB0eCArIHR5ICogdHkpL21heDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7IGludGVncmF0ZSB9O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2V1bGVyL2ludGVncmF0ZS5qcyIsIi8vIGltcGwgb2YgYmFybmVzIGh1dFxuLy8gaHR0cDovL3d3dy5lZWNzLmJlcmtlbGV5LmVkdS9+ZGVtbWVsL2NzMjY3L2xlY3R1cmUyNi9sZWN0dXJlMjYuaHRtbFxuLy8gaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9CYXJuZXMlRTIlODAlOTNIdXRfc2ltdWxhdGlvblxuXG5jb25zdCBOb2RlID0gcmVxdWlyZSgnLi9ub2RlJyk7XG5jb25zdCBJbnNlcnRTdGFjayA9IHJlcXVpcmUoJy4vaW5zZXJ0U3RhY2snKTtcblxuY29uc3QgcmVzZXRWZWMgPSB2ID0+IHsgdi54ID0gMDsgdi55ID0gMDsgfTtcblxuY29uc3QgaXNTYW1lUG9zaXRpb24gPSAocDEsIHAyKSA9PiB7XG4gIGxldCB0aHJlc2hvbGQgPSAxZS04O1xuICBsZXQgZHggPSBNYXRoLmFicyhwMS54IC0gcDIueCk7XG4gIGxldCBkeSA9IE1hdGguYWJzKHAxLnkgLSBwMi55KTtcblxuICByZXR1cm4gZHggPCB0aHJlc2hvbGQgJiYgZHkgPCB0aHJlc2hvbGQ7XG59O1xuXG5mdW5jdGlvbiBtYWtlUXVhZHRyZWUoKXtcbiAgbGV0IHVwZGF0ZVF1ZXVlID0gW10sXG4gICAgaW5zZXJ0U3RhY2sgPSBuZXcgSW5zZXJ0U3RhY2soKSxcbiAgICBub2Rlc0NhY2hlID0gW10sXG4gICAgY3VycmVudEluQ2FjaGUgPSAwLFxuICAgIHJvb3QgPSBuZXdOb2RlKCk7XG5cbiAgZnVuY3Rpb24gbmV3Tm9kZSgpIHtcbiAgICAvLyBUbyBhdm9pZCBwcmVzc3VyZSBvbiBHQyB3ZSByZXVzZSBub2Rlcy5cbiAgICBsZXQgbm9kZSA9IG5vZGVzQ2FjaGVbY3VycmVudEluQ2FjaGVdO1xuICAgIGlmIChub2RlKSB7XG4gICAgICBub2RlLnF1YWQwID0gbnVsbDtcbiAgICAgIG5vZGUucXVhZDEgPSBudWxsO1xuICAgICAgbm9kZS5xdWFkMiA9IG51bGw7XG4gICAgICBub2RlLnF1YWQzID0gbnVsbDtcbiAgICAgIG5vZGUuYm9keSA9IG51bGw7XG4gICAgICBub2RlLm1hc3MgPSBub2RlLm1hc3NYID0gbm9kZS5tYXNzWSA9IDA7XG4gICAgICBub2RlLmxlZnQgPSBub2RlLnJpZ2h0ID0gbm9kZS50b3AgPSBub2RlLmJvdHRvbSA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5vZGUgPSBuZXcgTm9kZSgpO1xuICAgICAgbm9kZXNDYWNoZVtjdXJyZW50SW5DYWNoZV0gPSBub2RlO1xuICAgIH1cblxuICAgICsrY3VycmVudEluQ2FjaGU7XG4gICAgcmV0dXJuIG5vZGU7XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGUoIHNvdXJjZUJvZHksIGdyYXZpdHksIHRoZXRhLCBwdWxsICkge1xuICAgIGxldCBxdWV1ZSA9IHVwZGF0ZVF1ZXVlLFxuICAgICAgdixcbiAgICAgIGR4LFxuICAgICAgZHksXG4gICAgICByLCBmeCA9IDAsXG4gICAgICBmeSA9IDAsXG4gICAgICBxdWV1ZUxlbmd0aCA9IDEsXG4gICAgICBzaGlmdElkeCA9IDAsXG4gICAgICBwdXNoSWR4ID0gMTtcblxuICAgIHF1ZXVlWzBdID0gcm9vdDtcblxuICAgIHJlc2V0VmVjKCBzb3VyY2VCb2R5LmZvcmNlICk7XG5cbiAgICBsZXQgcHggPSAtc291cmNlQm9keS5wb3MueDtcbiAgICBsZXQgcHkgPSAtc291cmNlQm9keS5wb3MueTtcbiAgICBsZXQgcHIgPSBNYXRoLnNxcnQocHggKiBweCArIHB5ICogcHkpO1xuICAgIGxldCBwdiA9IHNvdXJjZUJvZHkubWFzcyAqIHB1bGwgLyBwcjtcblxuICAgIGZ4ICs9IHB2ICogcHg7XG4gICAgZnkgKz0gcHYgKiBweTtcblxuICAgIHdoaWxlIChxdWV1ZUxlbmd0aCkge1xuICAgICAgbGV0IG5vZGUgPSBxdWV1ZVtzaGlmdElkeF0sXG4gICAgICAgIGJvZHkgPSBub2RlLmJvZHk7XG5cbiAgICAgIHF1ZXVlTGVuZ3RoIC09IDE7XG4gICAgICBzaGlmdElkeCArPSAxO1xuICAgICAgbGV0IGRpZmZlcmVudEJvZHkgPSAoYm9keSAhPT0gc291cmNlQm9keSk7XG4gICAgICBpZiAoYm9keSAmJiBkaWZmZXJlbnRCb2R5KSB7XG4gICAgICAgIC8vIElmIHRoZSBjdXJyZW50IG5vZGUgaXMgYSBsZWFmIG5vZGUgKGFuZCBpdCBpcyBub3Qgc291cmNlIGJvZHkpLFxuICAgICAgICAvLyBjYWxjdWxhdGUgdGhlIGZvcmNlIGV4ZXJ0ZWQgYnkgdGhlIGN1cnJlbnQgbm9kZSBvbiBib2R5LCBhbmQgYWRkIHRoaXNcbiAgICAgICAgLy8gYW1vdW50IHRvIGJvZHkncyBuZXQgZm9yY2UuXG4gICAgICAgIGR4ID0gYm9keS5wb3MueCAtIHNvdXJjZUJvZHkucG9zLng7XG4gICAgICAgIGR5ID0gYm9keS5wb3MueSAtIHNvdXJjZUJvZHkucG9zLnk7XG4gICAgICAgIHIgPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xuXG4gICAgICAgIGlmIChyID09PSAwKSB7XG4gICAgICAgICAgLy8gUG9vciBtYW4ncyBwcm90ZWN0aW9uIGFnYWluc3QgemVybyBkaXN0YW5jZS5cbiAgICAgICAgICBkeCA9IChNYXRoLnJhbmRvbSgpIC0gMC41KSAvIDUwO1xuICAgICAgICAgIGR5ID0gKE1hdGgucmFuZG9tKCkgLSAwLjUpIC8gNTA7XG4gICAgICAgICAgciA9IE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGlzIGlzIHN0YW5kYXJkIGdyYXZpdGlvbiBmb3JjZSBjYWxjdWxhdGlvbiBidXQgd2UgZGl2aWRlXG4gICAgICAgIC8vIGJ5IHJeMyB0byBzYXZlIHR3byBvcGVyYXRpb25zIHdoZW4gbm9ybWFsaXppbmcgZm9yY2UgdmVjdG9yLlxuICAgICAgICB2ID0gZ3Jhdml0eSAqIGJvZHkubWFzcyAqIHNvdXJjZUJvZHkubWFzcyAvIChyICogciAqIHIpO1xuICAgICAgICBmeCArPSB2ICogZHg7XG4gICAgICAgIGZ5ICs9IHYgKiBkeTtcbiAgICAgIH0gZWxzZSBpZiAoZGlmZmVyZW50Qm9keSkge1xuICAgICAgICAvLyBPdGhlcndpc2UsIGNhbGN1bGF0ZSB0aGUgcmF0aW8gcyAvIHIsICB3aGVyZSBzIGlzIHRoZSB3aWR0aCBvZiB0aGUgcmVnaW9uXG4gICAgICAgIC8vIHJlcHJlc2VudGVkIGJ5IHRoZSBpbnRlcm5hbCBub2RlLCBhbmQgciBpcyB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0aGUgYm9keVxuICAgICAgICAvLyBhbmQgdGhlIG5vZGUncyBjZW50ZXItb2YtbWFzc1xuICAgICAgICBkeCA9IG5vZGUubWFzc1ggLyBub2RlLm1hc3MgLSBzb3VyY2VCb2R5LnBvcy54O1xuICAgICAgICBkeSA9IG5vZGUubWFzc1kgLyBub2RlLm1hc3MgLSBzb3VyY2VCb2R5LnBvcy55O1xuICAgICAgICByID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcblxuICAgICAgICBpZiAociA9PT0gMCkge1xuICAgICAgICAgIC8vIFNvcnJ5IGFib3V0IGNvZGUgZHVwbHVjYXRpb24uIEkgZG9uJ3Qgd2FudCB0byBjcmVhdGUgbWFueSBmdW5jdGlvbnNcbiAgICAgICAgICAvLyByaWdodCBhd2F5LiBKdXN0IHdhbnQgdG8gc2VlIHBlcmZvcm1hbmNlIGZpcnN0LlxuICAgICAgICAgIGR4ID0gKE1hdGgucmFuZG9tKCkgLSAwLjUpIC8gNTA7XG4gICAgICAgICAgZHkgPSAoTWF0aC5yYW5kb20oKSAtIDAuNSkgLyA1MDtcbiAgICAgICAgICByID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBJZiBzIC8gciA8IM64LCB0cmVhdCB0aGlzIGludGVybmFsIG5vZGUgYXMgYSBzaW5nbGUgYm9keSwgYW5kIGNhbGN1bGF0ZSB0aGVcbiAgICAgICAgLy8gZm9yY2UgaXQgZXhlcnRzIG9uIHNvdXJjZUJvZHksIGFuZCBhZGQgdGhpcyBhbW91bnQgdG8gc291cmNlQm9keSdzIG5ldCBmb3JjZS5cbiAgICAgICAgaWYgKChub2RlLnJpZ2h0IC0gbm9kZS5sZWZ0KSAvIHIgPCB0aGV0YSkge1xuICAgICAgICAgIC8vIGluIHRoZSBpZiBzdGF0ZW1lbnQgYWJvdmUgd2UgY29uc2lkZXIgbm9kZSdzIHdpZHRoIG9ubHlcbiAgICAgICAgICAvLyBiZWNhdXNlIHRoZSByZWdpb24gd2FzIHNxdWFyaWZpZWQgZHVyaW5nIHRyZWUgY3JlYXRpb24uXG4gICAgICAgICAgLy8gVGh1cyB0aGVyZSBpcyBubyBkaWZmZXJlbmNlIGJldHdlZW4gdXNpbmcgd2lkdGggb3IgaGVpZ2h0LlxuICAgICAgICAgIHYgPSBncmF2aXR5ICogbm9kZS5tYXNzICogc291cmNlQm9keS5tYXNzIC8gKHIgKiByICogcik7XG4gICAgICAgICAgZnggKz0gdiAqIGR4O1xuICAgICAgICAgIGZ5ICs9IHYgKiBkeTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBPdGhlcndpc2UsIHJ1biB0aGUgcHJvY2VkdXJlIHJlY3Vyc2l2ZWx5IG9uIGVhY2ggb2YgdGhlIGN1cnJlbnQgbm9kZSdzIGNoaWxkcmVuLlxuXG4gICAgICAgICAgLy8gSSBpbnRlbnRpb25hbGx5IHVuZm9sZGVkIHRoaXMgbG9vcCwgdG8gc2F2ZSBzZXZlcmFsIENQVSBjeWNsZXMuXG4gICAgICAgICAgaWYgKG5vZGUucXVhZDApIHtcbiAgICAgICAgICAgIHF1ZXVlW3B1c2hJZHhdID0gbm9kZS5xdWFkMDtcbiAgICAgICAgICAgIHF1ZXVlTGVuZ3RoICs9IDE7XG4gICAgICAgICAgICBwdXNoSWR4ICs9IDE7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChub2RlLnF1YWQxKSB7XG4gICAgICAgICAgICBxdWV1ZVtwdXNoSWR4XSA9IG5vZGUucXVhZDE7XG4gICAgICAgICAgICBxdWV1ZUxlbmd0aCArPSAxO1xuICAgICAgICAgICAgcHVzaElkeCArPSAxO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAobm9kZS5xdWFkMikge1xuICAgICAgICAgICAgcXVldWVbcHVzaElkeF0gPSBub2RlLnF1YWQyO1xuICAgICAgICAgICAgcXVldWVMZW5ndGggKz0gMTtcbiAgICAgICAgICAgIHB1c2hJZHggKz0gMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKG5vZGUucXVhZDMpIHtcbiAgICAgICAgICAgIHF1ZXVlW3B1c2hJZHhdID0gbm9kZS5xdWFkMztcbiAgICAgICAgICAgIHF1ZXVlTGVuZ3RoICs9IDE7XG4gICAgICAgICAgICBwdXNoSWR4ICs9IDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgc291cmNlQm9keS5mb3JjZS54ICs9IGZ4O1xuICAgIHNvdXJjZUJvZHkuZm9yY2UueSArPSBmeTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluc2VydEJvZGllcyhib2RpZXMpIHtcbiAgICBpZiggYm9kaWVzLmxlbmd0aCA9PT0gMCApeyByZXR1cm47IH1cblxuICAgIGxldCB4MSA9IE51bWJlci5NQVhfVkFMVUUsXG4gICAgICB5MSA9IE51bWJlci5NQVhfVkFMVUUsXG4gICAgICB4MiA9IE51bWJlci5NSU5fVkFMVUUsXG4gICAgICB5MiA9IE51bWJlci5NSU5fVkFMVUUsXG4gICAgICBpLFxuICAgICAgbWF4ID0gYm9kaWVzLmxlbmd0aDtcblxuICAgIC8vIFRvIHJlZHVjZSBxdWFkIHRyZWUgZGVwdGggd2UgYXJlIGxvb2tpbmcgZm9yIGV4YWN0IGJvdW5kaW5nIGJveCBvZiBhbGwgcGFydGljbGVzLlxuICAgIGkgPSBtYXg7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgbGV0IHggPSBib2RpZXNbaV0ucG9zLng7XG4gICAgICBsZXQgeSA9IGJvZGllc1tpXS5wb3MueTtcbiAgICAgIGlmICh4IDwgeDEpIHtcbiAgICAgICAgeDEgPSB4O1xuICAgICAgfVxuICAgICAgaWYgKHggPiB4Mikge1xuICAgICAgICB4MiA9IHg7XG4gICAgICB9XG4gICAgICBpZiAoeSA8IHkxKSB7XG4gICAgICAgIHkxID0geTtcbiAgICAgIH1cbiAgICAgIGlmICh5ID4geTIpIHtcbiAgICAgICAgeTIgPSB5O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFNxdWFyaWZ5IHRoZSBib3VuZHMuXG4gICAgbGV0IGR4ID0geDIgLSB4MSxcbiAgICAgIGR5ID0geTIgLSB5MTtcbiAgICBpZiAoZHggPiBkeSkge1xuICAgICAgeTIgPSB5MSArIGR4O1xuICAgIH0gZWxzZSB7XG4gICAgICB4MiA9IHgxICsgZHk7XG4gICAgfVxuXG4gICAgY3VycmVudEluQ2FjaGUgPSAwO1xuICAgIHJvb3QgPSBuZXdOb2RlKCk7XG4gICAgcm9vdC5sZWZ0ID0geDE7XG4gICAgcm9vdC5yaWdodCA9IHgyO1xuICAgIHJvb3QudG9wID0geTE7XG4gICAgcm9vdC5ib3R0b20gPSB5MjtcblxuICAgIGkgPSBtYXggLSAxO1xuICAgIGlmIChpID49IDApIHtcbiAgICAgIHJvb3QuYm9keSA9IGJvZGllc1tpXTtcbiAgICB9XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgaW5zZXJ0KGJvZGllc1tpXSwgcm9vdCk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5zZXJ0KG5ld0JvZHkpIHtcbiAgICBpbnNlcnRTdGFjay5yZXNldCgpO1xuICAgIGluc2VydFN0YWNrLnB1c2gocm9vdCwgbmV3Qm9keSk7XG5cbiAgICB3aGlsZSAoIWluc2VydFN0YWNrLmlzRW1wdHkoKSkge1xuICAgICAgbGV0IHN0YWNrSXRlbSA9IGluc2VydFN0YWNrLnBvcCgpLFxuICAgICAgICBub2RlID0gc3RhY2tJdGVtLm5vZGUsXG4gICAgICAgIGJvZHkgPSBzdGFja0l0ZW0uYm9keTtcblxuICAgICAgaWYgKCFub2RlLmJvZHkpIHtcbiAgICAgICAgLy8gVGhpcyBpcyBpbnRlcm5hbCBub2RlLiBVcGRhdGUgdGhlIHRvdGFsIG1hc3Mgb2YgdGhlIG5vZGUgYW5kIGNlbnRlci1vZi1tYXNzLlxuICAgICAgICBsZXQgeCA9IGJvZHkucG9zLng7XG4gICAgICAgIGxldCB5ID0gYm9keS5wb3MueTtcbiAgICAgICAgbm9kZS5tYXNzID0gbm9kZS5tYXNzICsgYm9keS5tYXNzO1xuICAgICAgICBub2RlLm1hc3NYID0gbm9kZS5tYXNzWCArIGJvZHkubWFzcyAqIHg7XG4gICAgICAgIG5vZGUubWFzc1kgPSBub2RlLm1hc3NZICsgYm9keS5tYXNzICogeTtcblxuICAgICAgICAvLyBSZWN1cnNpdmVseSBpbnNlcnQgdGhlIGJvZHkgaW4gdGhlIGFwcHJvcHJpYXRlIHF1YWRyYW50LlxuICAgICAgICAvLyBCdXQgZmlyc3QgZmluZCB0aGUgYXBwcm9wcmlhdGUgcXVhZHJhbnQuXG4gICAgICAgIGxldCBxdWFkSWR4ID0gMCwgLy8gQXNzdW1lIHdlIGFyZSBpbiB0aGUgMCdzIHF1YWQuXG4gICAgICAgICAgbGVmdCA9IG5vZGUubGVmdCxcbiAgICAgICAgICByaWdodCA9IChub2RlLnJpZ2h0ICsgbGVmdCkgLyAyLFxuICAgICAgICAgIHRvcCA9IG5vZGUudG9wLFxuICAgICAgICAgIGJvdHRvbSA9IChub2RlLmJvdHRvbSArIHRvcCkgLyAyO1xuXG4gICAgICAgIGlmICh4ID4gcmlnaHQpIHsgLy8gc29tZXdoZXJlIGluIHRoZSBlYXN0ZXJuIHBhcnQuXG4gICAgICAgICAgcXVhZElkeCA9IHF1YWRJZHggKyAxO1xuICAgICAgICAgIGxlZnQgPSByaWdodDtcbiAgICAgICAgICByaWdodCA9IG5vZGUucmlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHkgPiBib3R0b20pIHsgLy8gYW5kIGluIHNvdXRoLlxuICAgICAgICAgIHF1YWRJZHggPSBxdWFkSWR4ICsgMjtcbiAgICAgICAgICB0b3AgPSBib3R0b207XG4gICAgICAgICAgYm90dG9tID0gbm9kZS5ib3R0b207XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgY2hpbGQgPSBnZXRDaGlsZChub2RlLCBxdWFkSWR4KTtcbiAgICAgICAgaWYgKCFjaGlsZCkge1xuICAgICAgICAgIC8vIFRoZSBub2RlIGlzIGludGVybmFsIGJ1dCB0aGlzIHF1YWRyYW50IGlzIG5vdCB0YWtlbi4gQWRkXG4gICAgICAgICAgLy8gc3Vibm9kZSB0byBpdC5cbiAgICAgICAgICBjaGlsZCA9IG5ld05vZGUoKTtcbiAgICAgICAgICBjaGlsZC5sZWZ0ID0gbGVmdDtcbiAgICAgICAgICBjaGlsZC50b3AgPSB0b3A7XG4gICAgICAgICAgY2hpbGQucmlnaHQgPSByaWdodDtcbiAgICAgICAgICBjaGlsZC5ib3R0b20gPSBib3R0b207XG4gICAgICAgICAgY2hpbGQuYm9keSA9IGJvZHk7XG5cbiAgICAgICAgICBzZXRDaGlsZChub2RlLCBxdWFkSWR4LCBjaGlsZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gY29udGludWUgc2VhcmNoaW5nIGluIHRoaXMgcXVhZHJhbnQuXG4gICAgICAgICAgaW5zZXJ0U3RhY2sucHVzaChjaGlsZCwgYm9keSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFdlIGFyZSB0cnlpbmcgdG8gYWRkIHRvIHRoZSBsZWFmIG5vZGUuXG4gICAgICAgIC8vIFdlIGhhdmUgdG8gY29udmVydCBjdXJyZW50IGxlYWYgaW50byBpbnRlcm5hbCBub2RlXG4gICAgICAgIC8vIGFuZCBjb250aW51ZSBhZGRpbmcgdHdvIG5vZGVzLlxuICAgICAgICBsZXQgb2xkQm9keSA9IG5vZGUuYm9keTtcbiAgICAgICAgbm9kZS5ib2R5ID0gbnVsbDsgLy8gaW50ZXJuYWwgbm9kZXMgZG8gbm90IGNhcnkgYm9kaWVzXG5cbiAgICAgICAgaWYgKGlzU2FtZVBvc2l0aW9uKG9sZEJvZHkucG9zLCBib2R5LnBvcykpIHtcbiAgICAgICAgICAvLyBQcmV2ZW50IGluZmluaXRlIHN1YmRpdmlzaW9uIGJ5IGJ1bXBpbmcgb25lIG5vZGVcbiAgICAgICAgICAvLyBhbnl3aGVyZSBpbiB0aGlzIHF1YWRyYW50XG4gICAgICAgICAgbGV0IHJldHJpZXNDb3VudCA9IDM7XG4gICAgICAgICAgZG8ge1xuICAgICAgICAgICAgbGV0IG9mZnNldCA9IE1hdGgucmFuZG9tKCk7XG4gICAgICAgICAgICBsZXQgZHggPSAobm9kZS5yaWdodCAtIG5vZGUubGVmdCkgKiBvZmZzZXQ7XG4gICAgICAgICAgICBsZXQgZHkgPSAobm9kZS5ib3R0b20gLSBub2RlLnRvcCkgKiBvZmZzZXQ7XG5cbiAgICAgICAgICAgIG9sZEJvZHkucG9zLnggPSBub2RlLmxlZnQgKyBkeDtcbiAgICAgICAgICAgIG9sZEJvZHkucG9zLnkgPSBub2RlLnRvcCArIGR5O1xuICAgICAgICAgICAgcmV0cmllc0NvdW50IC09IDE7XG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgd2UgZG9uJ3QgYnVtcCBpdCBvdXQgb2YgdGhlIGJveC4gSWYgd2UgZG8sIG5leHQgaXRlcmF0aW9uIHNob3VsZCBmaXggaXRcbiAgICAgICAgICB9IHdoaWxlIChyZXRyaWVzQ291bnQgPiAwICYmIGlzU2FtZVBvc2l0aW9uKG9sZEJvZHkucG9zLCBib2R5LnBvcykpO1xuXG4gICAgICAgICAgaWYgKHJldHJpZXNDb3VudCA9PT0gMCAmJiBpc1NhbWVQb3NpdGlvbihvbGRCb2R5LnBvcywgYm9keS5wb3MpKSB7XG4gICAgICAgICAgICAvLyBUaGlzIGlzIHZlcnkgYmFkLCB3ZSByYW4gb3V0IG9mIHByZWNpc2lvbi5cbiAgICAgICAgICAgIC8vIGlmIHdlIGRvIG5vdCByZXR1cm4gZnJvbSB0aGUgbWV0aG9kIHdlJ2xsIGdldCBpbnRvXG4gICAgICAgICAgICAvLyBpbmZpbml0ZSBsb29wIGhlcmUuIFNvIHdlIHNhY3JpZmljZSBjb3JyZWN0bmVzcyBvZiBsYXlvdXQsIGFuZCBrZWVwIHRoZSBhcHAgcnVubmluZ1xuICAgICAgICAgICAgLy8gTmV4dCBsYXlvdXQgaXRlcmF0aW9uIHNob3VsZCBnZXQgbGFyZ2VyIGJvdW5kaW5nIGJveCBpbiB0aGUgZmlyc3Qgc3RlcCBhbmQgZml4IHRoaXNcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gTmV4dCBpdGVyYXRpb24gc2hvdWxkIHN1YmRpdmlkZSBub2RlIGZ1cnRoZXIuXG4gICAgICAgIGluc2VydFN0YWNrLnB1c2gobm9kZSwgb2xkQm9keSk7XG4gICAgICAgIGluc2VydFN0YWNrLnB1c2gobm9kZSwgYm9keSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBpbnNlcnRCb2RpZXM6IGluc2VydEJvZGllcyxcbiAgICB1cGRhdGVCb2R5Rm9yY2U6IHVwZGF0ZVxuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRDaGlsZChub2RlLCBpZHgpIHtcbiAgaWYgKGlkeCA9PT0gMCkgcmV0dXJuIG5vZGUucXVhZDA7XG4gIGlmIChpZHggPT09IDEpIHJldHVybiBub2RlLnF1YWQxO1xuICBpZiAoaWR4ID09PSAyKSByZXR1cm4gbm9kZS5xdWFkMjtcbiAgaWYgKGlkeCA9PT0gMykgcmV0dXJuIG5vZGUucXVhZDM7XG4gIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiBzZXRDaGlsZChub2RlLCBpZHgsIGNoaWxkKSB7XG4gIGlmIChpZHggPT09IDApIG5vZGUucXVhZDAgPSBjaGlsZDtcbiAgZWxzZSBpZiAoaWR4ID09PSAxKSBub2RlLnF1YWQxID0gY2hpbGQ7XG4gIGVsc2UgaWYgKGlkeCA9PT0gMikgbm9kZS5xdWFkMiA9IGNoaWxkO1xuICBlbHNlIGlmIChpZHggPT09IDMpIG5vZGUucXVhZDMgPSBjaGlsZDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7IG1ha2VRdWFkdHJlZSB9O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2V1bGVyL3F1YWR0cmVlL2luZGV4LmpzIiwibW9kdWxlLmV4cG9ydHMgPSBJbnNlcnRTdGFjaztcblxuLyoqXG4gKiBPdXIgaW1wbG1lbnRhdGlvbiBvZiBRdWFkVHJlZSBpcyBub24tcmVjdXJzaXZlIHRvIGF2b2lkIEdDIGhpdFxuICogVGhpcyBkYXRhIHN0cnVjdHVyZSByZXByZXNlbnQgc3RhY2sgb2YgZWxlbWVudHNcbiAqIHdoaWNoIHdlIGFyZSB0cnlpbmcgdG8gaW5zZXJ0IGludG8gcXVhZCB0cmVlLlxuICovXG5mdW5jdGlvbiBJbnNlcnRTdGFjayAoKSB7XG4gICAgdGhpcy5zdGFjayA9IFtdO1xuICAgIHRoaXMucG9wSWR4ID0gMDtcbn1cblxuSW5zZXJ0U3RhY2sucHJvdG90eXBlID0ge1xuICAgIGlzRW1wdHk6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wb3BJZHggPT09IDA7XG4gICAgfSxcbiAgICBwdXNoOiBmdW5jdGlvbiAobm9kZSwgYm9keSkge1xuICAgICAgICBsZXQgaXRlbSA9IHRoaXMuc3RhY2tbdGhpcy5wb3BJZHhdO1xuICAgICAgICBpZiAoIWl0ZW0pIHtcbiAgICAgICAgICAgIC8vIHdlIGFyZSB0cnlpbmcgdG8gYXZvaWQgbWVtb3J5IHByZXNzdWU6IGNyZWF0ZSBuZXcgZWxlbWVudFxuICAgICAgICAgICAgLy8gb25seSB3aGVuIGFic29sdXRlbHkgbmVjZXNzYXJ5XG4gICAgICAgICAgICB0aGlzLnN0YWNrW3RoaXMucG9wSWR4XSA9IG5ldyBJbnNlcnRTdGFja0VsZW1lbnQobm9kZSwgYm9keSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpdGVtLm5vZGUgPSBub2RlO1xuICAgICAgICAgICAgaXRlbS5ib2R5ID0gYm9keTtcbiAgICAgICAgfVxuICAgICAgICArK3RoaXMucG9wSWR4O1xuICAgIH0sXG4gICAgcG9wOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnBvcElkeCA+IDApIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0YWNrWy0tdGhpcy5wb3BJZHhdO1xuICAgICAgICB9XG4gICAgfSxcbiAgICByZXNldDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnBvcElkeCA9IDA7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gSW5zZXJ0U3RhY2tFbGVtZW50KG5vZGUsIGJvZHkpIHtcbiAgICB0aGlzLm5vZGUgPSBub2RlOyAvLyBRdWFkVHJlZSBub2RlXG4gICAgdGhpcy5ib2R5ID0gYm9keTsgLy8gcGh5c2ljYWwgYm9keSB3aGljaCBuZWVkcyB0byBiZSBpbnNlcnRlZCB0byBub2RlXG59XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvZXVsZXIvcXVhZHRyZWUvaW5zZXJ0U3RhY2suanMiLCIvKipcbiAqIEludGVybmFsIGRhdGEgc3RydWN0dXJlIHRvIHJlcHJlc2VudCAyRCBRdWFkVHJlZSBub2RlXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gTm9kZSgpIHtcbiAgLy8gYm9keSBzdG9yZWQgaW5zaWRlIHRoaXMgbm9kZS4gSW4gcXVhZCB0cmVlIG9ubHkgbGVhZiBub2RlcyAoYnkgY29uc3RydWN0aW9uKVxuICAvLyBjb250YWluIGJvaWRlczpcbiAgdGhpcy5ib2R5ID0gbnVsbDtcblxuICAvLyBDaGlsZCBub2RlcyBhcmUgc3RvcmVkIGluIHF1YWRzLiBFYWNoIHF1YWQgaXMgcHJlc2VudGVkIGJ5IG51bWJlcjpcbiAgLy8gMCB8IDFcbiAgLy8gLS0tLS1cbiAgLy8gMiB8IDNcbiAgdGhpcy5xdWFkMCA9IG51bGw7XG4gIHRoaXMucXVhZDEgPSBudWxsO1xuICB0aGlzLnF1YWQyID0gbnVsbDtcbiAgdGhpcy5xdWFkMyA9IG51bGw7XG5cbiAgLy8gVG90YWwgbWFzcyBvZiBjdXJyZW50IG5vZGVcbiAgdGhpcy5tYXNzID0gMDtcblxuICAvLyBDZW50ZXIgb2YgbWFzcyBjb29yZGluYXRlc1xuICB0aGlzLm1hc3NYID0gMDtcbiAgdGhpcy5tYXNzWSA9IDA7XG5cbiAgLy8gYm91bmRpbmcgYm94IGNvb3JkaW5hdGVzXG4gIHRoaXMubGVmdCA9IDA7XG4gIHRoaXMudG9wID0gMDtcbiAgdGhpcy5ib3R0b20gPSAwO1xuICB0aGlzLnJpZ2h0ID0gMDtcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvZXVsZXIvcXVhZHRyZWUvbm9kZS5qcyIsImNvbnN0IHsgaW50ZWdyYXRlIH0gPSByZXF1aXJlKCcuL2ludGVncmF0ZScpO1xuY29uc3QgeyBhcHBseURyYWcgfSA9IHJlcXVpcmUoJy4vZHJhZycpO1xuY29uc3QgeyBhcHBseVNwcmluZyB9ID0gcmVxdWlyZSgnLi9zcHJpbmcnKTtcblxuZnVuY3Rpb24gdGljayh7IGJvZGllcywgc3ByaW5ncywgcXVhZHRyZWUsIHRpbWVTdGVwLCBncmF2aXR5LCB0aGV0YSwgZHJhZ0NvZWZmLCBwdWxsIH0pe1xuICAvLyB1cGRhdGUgYm9keSBmcm9tIHNjcmF0Y2ggaW4gY2FzZSBvZiBhbnkgY2hhbmdlc1xuICBib2RpZXMuZm9yRWFjaCggYm9keSA9PiB7XG4gICAgbGV0IHAgPSBib2R5Ll9zY3JhdGNoO1xuXG4gICAgaWYoICFwICl7IHJldHVybjsgfVxuXG4gICAgYm9keS5sb2NrZWQgPSBwLmxvY2tlZDtcbiAgICBib2R5LmdyYWJiZWQgPSBwLmdyYWJiZWQ7XG4gICAgYm9keS5wb3MueCA9IHAueDtcbiAgICBib2R5LnBvcy55ID0gcC55O1xuICB9ICk7XG5cbiAgcXVhZHRyZWUuaW5zZXJ0Qm9kaWVzKCBib2RpZXMgKTtcblxuICBmb3IoIGxldCBpID0gMDsgaSA8IGJvZGllcy5sZW5ndGg7IGkrKyApe1xuICAgIGxldCBib2R5ID0gYm9kaWVzW2ldO1xuXG4gICAgcXVhZHRyZWUudXBkYXRlQm9keUZvcmNlKCBib2R5LCBncmF2aXR5LCB0aGV0YSwgcHVsbCApO1xuICAgIGFwcGx5RHJhZyggYm9keSwgZHJhZ0NvZWZmICk7XG4gIH1cblxuICBmb3IoIGxldCBpID0gMDsgaSA8IHNwcmluZ3MubGVuZ3RoOyBpKysgKXtcbiAgICBsZXQgc3ByaW5nID0gc3ByaW5nc1tpXTtcblxuICAgIGFwcGx5U3ByaW5nKCBzcHJpbmcgKTtcbiAgfVxuXG4gIGxldCBtb3ZlbWVudCA9IGludGVncmF0ZSggYm9kaWVzLCB0aW1lU3RlcCApO1xuXG4gIC8vIHVwZGF0ZSBzY3JhdGNoIHBvc2l0aW9ucyBmcm9tIGJvZHkgcG9zaXRpb25zXG4gIGJvZGllcy5mb3JFYWNoKCBib2R5ID0+IHtcbiAgICBsZXQgcCA9IGJvZHkuX3NjcmF0Y2g7XG5cbiAgICBpZiggIXAgKXsgcmV0dXJuOyB9XG5cbiAgICBwLnggPSBib2R5LnBvcy54O1xuICAgIHAueSA9IGJvZHkucG9zLnk7XG4gIH0gKTtcblxuICByZXR1cm4gbW92ZW1lbnQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0geyB0aWNrIH07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvZXVsZXIvdGljay5qcyIsImNvbnN0IEV1bGVyID0gcmVxdWlyZSgnLi9ldWxlcicpO1xuXG4vLyByZWdpc3RlcnMgdGhlIGV4dGVuc2lvbiBvbiBhIGN5dG9zY2FwZSBsaWIgcmVmXG5sZXQgcmVnaXN0ZXIgPSBmdW5jdGlvbiggY3l0b3NjYXBlICl7XG4gIGlmKCAhY3l0b3NjYXBlICl7IHJldHVybjsgfSAvLyBjYW4ndCByZWdpc3RlciBpZiBjeXRvc2NhcGUgdW5zcGVjaWZpZWRcblxuICBjeXRvc2NhcGUoICdsYXlvdXQnLCAnZXVsZXInLCBFdWxlciApOyAvLyByZWdpc3RlciB3aXRoIGN5dG9zY2FwZS5qc1xufTtcblxuaWYoIHR5cGVvZiBjeXRvc2NhcGUgIT09ICd1bmRlZmluZWQnICl7IC8vIGV4cG9zZSB0byBnbG9iYWwgY3l0b3NjYXBlIChpLmUuIHdpbmRvdy5jeXRvc2NhcGUpXG4gIHJlZ2lzdGVyKCBjeXRvc2NhcGUgKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSByZWdpc3RlcjtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9pbmRleC5qcyIsIi8vIGdlbmVyYWwgZGVmYXVsdCBvcHRpb25zIGZvciBmb3JjZS1kaXJlY3RlZCBsYXlvdXRcblxubW9kdWxlLmV4cG9ydHMgPSBPYmplY3QuZnJlZXplKHtcbiAgYW5pbWF0ZTogdHJ1ZSwgLy8gd2hldGhlciB0byBzaG93IHRoZSBsYXlvdXQgYXMgaXQncyBydW5uaW5nOyBzcGVjaWFsICdlbmQnIHZhbHVlIG1ha2VzIHRoZSBsYXlvdXQgYW5pbWF0ZSBsaWtlIGEgZGlzY3JldGUgbGF5b3V0XG4gIHJlZnJlc2g6IDEwLCAvLyBudW1iZXIgb2YgdGlja3MgcGVyIGZyYW1lOyBoaWdoZXIgaXMgZmFzdGVyIGJ1dCBtb3JlIGplcmt5XG4gIG1heEl0ZXJhdGlvbnM6IDEwMDAsIC8vIG1heCBpdGVyYXRpb25zIGJlZm9yZSB0aGUgbGF5b3V0IHdpbGwgYmFpbCBvdXRcbiAgbWF4U2ltdWxhdGlvblRpbWU6IDQwMDAsIC8vIG1heCBsZW5ndGggaW4gbXMgdG8gcnVuIHRoZSBsYXlvdXRcbiAgdW5ncmFiaWZ5V2hpbGVTaW11bGF0aW5nOiBmYWxzZSwgLy8gc28geW91IGNhbid0IGRyYWcgbm9kZXMgZHVyaW5nIGxheW91dFxuICBmaXQ6IHRydWUsIC8vIG9uIGV2ZXJ5IGxheW91dCByZXBvc2l0aW9uIG9mIG5vZGVzLCBmaXQgdGhlIHZpZXdwb3J0XG4gIHBhZGRpbmc6IDMwLCAvLyBwYWRkaW5nIGFyb3VuZCB0aGUgc2ltdWxhdGlvblxuICBib3VuZGluZ0JveDogdW5kZWZpbmVkLCAvLyBjb25zdHJhaW4gbGF5b3V0IGJvdW5kczsgeyB4MSwgeTEsIHgyLCB5MiB9IG9yIHsgeDEsIHkxLCB3LCBoIH1cblxuICAvLyBsYXlvdXQgZXZlbnQgY2FsbGJhY2tzXG4gIHJlYWR5OiBmdW5jdGlvbigpe30sIC8vIG9uIGxheW91dHJlYWR5XG4gIHN0b3A6IGZ1bmN0aW9uKCl7fSwgLy8gb24gbGF5b3V0c3RvcFxuXG4gIC8vIHBvc2l0aW9uaW5nIG9wdGlvbnNcbiAgcmFuZG9taXplOiBmYWxzZSwgLy8gdXNlIHJhbmRvbSBub2RlIHBvc2l0aW9ucyBhdCBiZWdpbm5pbmcgb2YgbGF5b3V0XG4gIFxuICAvLyBpbmZpbml0ZSBsYXlvdXQgb3B0aW9uc1xuICBpbmZpbml0ZTogZmFsc2UgLy8gb3ZlcnJpZGVzIGFsbCBvdGhlciBvcHRpb25zIGZvciBhIGZvcmNlcy1hbGwtdGhlLXRpbWUgbW9kZVxufSk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvbGF5b3V0L2RlZmF1bHRzLmpzIiwiLyoqXG5BIGdlbmVyaWMgY29udGludW91cyBsYXlvdXQgY2xhc3NcbiovXG5cbmNvbnN0IGFzc2lnbiA9IHJlcXVpcmUoJy4uL2Fzc2lnbicpO1xuY29uc3QgZGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5jb25zdCBtYWtlQm91bmRpbmdCb3ggPSByZXF1aXJlKCcuL21ha2UtYmInKTtcbmNvbnN0IHsgc2V0SW5pdGlhbFBvc2l0aW9uU3RhdGUsIHJlZnJlc2hQb3NpdGlvbnMsIGdldE5vZGVQb3NpdGlvbkRhdGEgfSA9IHJlcXVpcmUoJy4vcG9zaXRpb24nKTtcbmNvbnN0IHsgbXVsdGl0aWNrIH0gPSByZXF1aXJlKCcuL3RpY2snKTtcblxuY2xhc3MgTGF5b3V0IHtcbiAgY29uc3RydWN0b3IoIG9wdGlvbnMgKXtcbiAgICBsZXQgbyA9IHRoaXMub3B0aW9ucyA9IGFzc2lnbigge30sIGRlZmF1bHRzLCBvcHRpb25zICk7XG5cbiAgICBsZXQgcyA9IHRoaXMuc3RhdGUgPSBhc3NpZ24oIHt9LCBvLCB7XG4gICAgICBsYXlvdXQ6IHRoaXMsXG4gICAgICBub2Rlczogby5lbGVzLm5vZGVzKCksXG4gICAgICBlZGdlczogby5lbGVzLmVkZ2VzKCksXG4gICAgICB0aWNrSW5kZXg6IDAsXG4gICAgICBmaXJzdFVwZGF0ZTogdHJ1ZVxuICAgIH0gKTtcblxuICAgIHMuYW5pbWF0ZUVuZCA9IG8uYW5pbWF0ZSAmJiBvLmFuaW1hdGUgPT09ICdlbmQnO1xuICAgIHMuYW5pbWF0ZUNvbnRpbnVvdXNseSA9IG8uYW5pbWF0ZSAmJiAhcy5hbmltYXRlRW5kO1xuICB9XG5cbiAgcnVuKCl7XG4gICAgbGV0IGwgPSB0aGlzO1xuICAgIGxldCBzID0gdGhpcy5zdGF0ZTtcblxuICAgIHMudGlja0luZGV4ID0gMDtcbiAgICBzLmZpcnN0VXBkYXRlID0gdHJ1ZTtcbiAgICBzLnN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgcy5ydW5uaW5nID0gdHJ1ZTtcblxuICAgIHMuY3VycmVudEJvdW5kaW5nQm94ID0gbWFrZUJvdW5kaW5nQm94KCBzLmJvdW5kaW5nQm94LCBzLmN5ICk7XG5cbiAgICBpZiggcy5yZWFkeSApeyBsLm9uZSggJ3JlYWR5Jywgcy5yZWFkeSApOyB9XG4gICAgaWYoIHMuc3RvcCApeyBsLm9uZSggJ3N0b3AnLCBzLnN0b3AgKTsgfVxuXG4gICAgcy5ub2Rlcy5mb3JFYWNoKCBuID0+IHNldEluaXRpYWxQb3NpdGlvblN0YXRlKCBuLCBzICkgKTtcblxuICAgIGwucHJlcnVuKCBzICk7XG5cbiAgICBpZiggcy5hbmltYXRlQ29udGludW91c2x5ICl7XG4gICAgICBsZXQgdW5ncmFiaWZ5ID0gbm9kZSA9PiB7XG4gICAgICAgIGlmKCAhcy51bmdyYWJpZnlXaGlsZVNpbXVsYXRpbmcgKXsgcmV0dXJuOyB9XG5cbiAgICAgICAgbGV0IGdyYWJiYWJsZSA9IGdldE5vZGVQb3NpdGlvbkRhdGEoIG5vZGUsIHMgKS5ncmFiYmFibGUgPSBub2RlLmdyYWJiYWJsZSgpO1xuXG4gICAgICAgIGlmKCBncmFiYmFibGUgKXtcbiAgICAgICAgICBub2RlLnVuZ3JhYmlmeSgpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBsZXQgcmVncmFiaWZ5ID0gbm9kZSA9PiB7XG4gICAgICAgIGlmKCAhcy51bmdyYWJpZnlXaGlsZVNpbXVsYXRpbmcgKXsgcmV0dXJuOyB9XG5cbiAgICAgICAgbGV0IGdyYWJiYWJsZSA9IGdldE5vZGVQb3NpdGlvbkRhdGEoIG5vZGUsIHMgKS5ncmFiYmFibGU7XG5cbiAgICAgICAgaWYoIGdyYWJiYWJsZSApe1xuICAgICAgICAgIG5vZGUuZ3JhYmlmeSgpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBsZXQgdXBkYXRlR3JhYlN0YXRlID0gbm9kZSA9PiBnZXROb2RlUG9zaXRpb25EYXRhKCBub2RlLCBzICkuZ3JhYmJlZCA9IG5vZGUuZ3JhYmJlZCgpO1xuXG4gICAgICBsZXQgb25HcmFiID0gZnVuY3Rpb24oeyB0YXJnZXQgfSl7XG4gICAgICAgIHVwZGF0ZUdyYWJTdGF0ZSggdGFyZ2V0ICk7XG4gICAgICB9O1xuXG4gICAgICBsZXQgb25GcmVlID0gb25HcmFiO1xuXG4gICAgICBsZXQgb25EcmFnID0gZnVuY3Rpb24oeyB0YXJnZXQgfSl7XG4gICAgICAgIGxldCBwID0gZ2V0Tm9kZVBvc2l0aW9uRGF0YSggdGFyZ2V0LCBzICk7XG4gICAgICAgIGxldCB0cCA9IHRhcmdldC5wb3NpdGlvbigpO1xuXG4gICAgICAgIHAueCA9IHRwLng7XG4gICAgICAgIHAueSA9IHRwLnk7XG4gICAgICB9O1xuXG4gICAgICBsZXQgbGlzdGVuVG9HcmFiID0gbm9kZSA9PiB7XG4gICAgICAgIG5vZGUub24oJ2dyYWInLCBvbkdyYWIpO1xuICAgICAgICBub2RlLm9uKCdmcmVlJywgb25GcmVlKTtcbiAgICAgICAgbm9kZS5vbignZHJhZycsIG9uRHJhZyk7XG4gICAgICB9O1xuXG4gICAgICBsZXQgdW5saXN0ZW5Ub0dyYWIgPSBub2RlID0+IHtcbiAgICAgICAgbm9kZS5yZW1vdmVMaXN0ZW5lcignZ3JhYicsIG9uR3JhYik7XG4gICAgICAgIG5vZGUucmVtb3ZlTGlzdGVuZXIoJ2ZyZWUnLCBvbkZyZWUpO1xuICAgICAgICBub2RlLnJlbW92ZUxpc3RlbmVyKCdkcmFnJywgb25EcmFnKTtcbiAgICAgIH07XG5cbiAgICAgIGxldCBmaXQgPSAoKSA9PiB7XG4gICAgICAgIGlmKCBzLmZpdCAmJiBzLmFuaW1hdGVDb250aW51b3VzbHkgKXtcbiAgICAgICAgICBzLmN5LmZpdCggcy5wYWRkaW5nICk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGxldCBvbk5vdERvbmUgPSAoKSA9PiB7XG4gICAgICAgIHJlZnJlc2hQb3NpdGlvbnMoIHMubm9kZXMsIHMgKTtcbiAgICAgICAgZml0KCk7XG5cbiAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCBmcmFtZSApO1xuICAgICAgfTtcblxuICAgICAgbGV0IGZyYW1lID0gZnVuY3Rpb24oKXtcbiAgICAgICAgbXVsdGl0aWNrKCBzLCBvbk5vdERvbmUsIG9uRG9uZSApO1xuICAgICAgfTtcblxuICAgICAgbGV0IG9uRG9uZSA9ICgpID0+IHtcbiAgICAgICAgcmVmcmVzaFBvc2l0aW9ucyggcy5ub2RlcywgcyApO1xuICAgICAgICBmaXQoKTtcblxuICAgICAgICBzLm5vZGVzLmZvckVhY2goIG4gPT4ge1xuICAgICAgICAgIHJlZ3JhYmlmeSggbiApO1xuICAgICAgICAgIHVubGlzdGVuVG9HcmFiKCBuICk7XG4gICAgICAgIH0gKTtcblxuICAgICAgICBzLnJ1bm5pbmcgPSBmYWxzZTtcblxuICAgICAgICBsLmVtaXQoJ2xheW91dHN0b3AnKTtcbiAgICAgIH07XG5cbiAgICAgIGwuZW1pdCgnbGF5b3V0c3RhcnQnKTtcblxuICAgICAgcy5ub2Rlcy5mb3JFYWNoKCBuID0+IHtcbiAgICAgICAgdW5ncmFiaWZ5KCBuICk7XG4gICAgICAgIGxpc3RlblRvR3JhYiggbiApO1xuICAgICAgfSApO1xuXG4gICAgICBmcmFtZSgpOyAvLyBraWNrIG9mZlxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgZG9uZSA9IGZhbHNlO1xuICAgICAgbGV0IG9uTm90RG9uZSA9ICgpID0+IHt9O1xuICAgICAgbGV0IG9uRG9uZSA9ICgpID0+IGRvbmUgPSB0cnVlO1xuXG4gICAgICB3aGlsZSggIWRvbmUgKXtcbiAgICAgICAgbXVsdGl0aWNrKCBzLCBvbk5vdERvbmUsIG9uRG9uZSApO1xuICAgICAgfVxuXG4gICAgICBzLmVsZXMubGF5b3V0UG9zaXRpb25zKCB0aGlzLCBzLCBub2RlID0+IHtcbiAgICAgICAgbGV0IHBkID0gZ2V0Tm9kZVBvc2l0aW9uRGF0YSggbm9kZSwgcyApO1xuXG4gICAgICAgIHJldHVybiB7IHg6IHBkLngsIHk6IHBkLnkgfTtcbiAgICAgIH0gKTtcbiAgICB9XG5cbiAgICBsLnBvc3RydW4oIHMgKTtcblxuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9XG5cbiAgcHJlcnVuKCl7fVxuICBwb3N0cnVuKCl7fVxuICB0aWNrKCl7fVxuXG4gIHN0b3AoKXtcbiAgICB0aGlzLnN0YXRlLnJ1bm5pbmcgPSBmYWxzZTtcblxuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9XG5cbiAgZGVzdHJveSgpe1xuICAgIHJldHVybiB0aGlzOyAvLyBjaGFpbmluZ1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gTGF5b3V0O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2xheW91dC9pbmRleC5qcyIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oIGJiLCBjeSApe1xuICBpZiggYmIgPT0gbnVsbCApe1xuICAgIGJiID0geyB4MTogMCwgeTE6IDAsIHc6IGN5LndpZHRoKCksIGg6IGN5LmhlaWdodCgpIH07XG4gIH0gZWxzZSB7IC8vIGNvcHlcbiAgICBiYiA9IHsgeDE6IGJiLngxLCB4MjogYmIueDIsIHkxOiBiYi55MSwgeTI6IGJiLnkyLCB3OiBiYi53LCBoOiBiYi5oIH07XG4gIH1cblxuICBpZiggYmIueDIgPT0gbnVsbCApeyBiYi54MiA9IGJiLngxICsgYmIudzsgfVxuICBpZiggYmIudyA9PSBudWxsICl7IGJiLncgPSBiYi54MiAtIGJiLngxOyB9XG4gIGlmKCBiYi55MiA9PSBudWxsICl7IGJiLnkyID0gYmIueTEgKyBiYi5oOyB9XG4gIGlmKCBiYi5oID09IG51bGwgKXsgYmIuaCA9IGJiLnkyIC0gYmIueTE7IH1cblxuICByZXR1cm4gYmI7XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2xheW91dC9tYWtlLWJiLmpzIiwiY29uc3QgYXNzaWduID0gcmVxdWlyZSgnLi4vYXNzaWduJyk7XG5cbmxldCBzZXRJbml0aWFsUG9zaXRpb25TdGF0ZSA9IGZ1bmN0aW9uKCBub2RlLCBzdGF0ZSApe1xuICBsZXQgcCA9IG5vZGUucG9zaXRpb24oKTtcbiAgbGV0IGJiID0gc3RhdGUuY3VycmVudEJvdW5kaW5nQm94O1xuICBsZXQgc2NyYXRjaCA9IG5vZGUuc2NyYXRjaCggc3RhdGUubmFtZSApO1xuXG4gIGlmKCBzY3JhdGNoID09IG51bGwgKXtcbiAgICBzY3JhdGNoID0ge307XG5cbiAgICBub2RlLnNjcmF0Y2goIHN0YXRlLm5hbWUsIHNjcmF0Y2ggKTtcbiAgfVxuXG4gIGFzc2lnbiggc2NyYXRjaCwgc3RhdGUucmFuZG9taXplID8ge1xuICAgIHg6IGJiLngxICsgTWF0aC5yYW5kb20oKSAqIGJiLncsXG4gICAgeTogYmIueTEgKyBNYXRoLnJhbmRvbSgpICogYmIuaFxuICB9IDoge1xuICAgIHg6IHAueCxcbiAgICB5OiBwLnlcbiAgfSApO1xuXG4gIHNjcmF0Y2gubG9ja2VkID0gbm9kZS5sb2NrZWQoKTtcbn07XG5cbmxldCBnZXROb2RlUG9zaXRpb25EYXRhID0gZnVuY3Rpb24oIG5vZGUsIHN0YXRlICl7XG4gIHJldHVybiBub2RlLnNjcmF0Y2goIHN0YXRlLm5hbWUgKTtcbn07XG5cbmxldCByZWZyZXNoUG9zaXRpb25zID0gZnVuY3Rpb24oIG5vZGVzLCBzdGF0ZSApe1xuICBub2Rlcy5wb3NpdGlvbnMoZnVuY3Rpb24oIG5vZGUgKXtcbiAgICBsZXQgc2NyYXRjaCA9IG5vZGUuc2NyYXRjaCggc3RhdGUubmFtZSApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IHNjcmF0Y2gueCxcbiAgICAgIHk6IHNjcmF0Y2gueVxuICAgIH07XG4gIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSB7IHNldEluaXRpYWxQb3NpdGlvblN0YXRlLCBnZXROb2RlUG9zaXRpb25EYXRhLCByZWZyZXNoUG9zaXRpb25zIH07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvbGF5b3V0L3Bvc2l0aW9uLmpzIiwiY29uc3Qgbm9wID0gZnVuY3Rpb24oKXt9O1xuXG5sZXQgdGljayA9IGZ1bmN0aW9uKCBzdGF0ZSApe1xuICBsZXQgcyA9IHN0YXRlO1xuICBsZXQgbCA9IHN0YXRlLmxheW91dDtcblxuICBsZXQgdGlja0luZGljYXRlc0RvbmUgPSBsLnRpY2soIHMgKTtcblxuICBpZiggcy5maXJzdFVwZGF0ZSApe1xuICAgIGlmKCBzLmFuaW1hdGVDb250aW51b3VzbHkgKXsgLy8gaW5kaWNhdGUgdGhlIGluaXRpYWwgcG9zaXRpb25zIGhhdmUgYmVlbiBzZXRcbiAgICAgIHMubGF5b3V0LmVtaXQoJ2xheW91dHJlYWR5Jyk7XG4gICAgfVxuICAgIHMuZmlyc3RVcGRhdGUgPSBmYWxzZTtcbiAgfVxuXG4gIHMudGlja0luZGV4Kys7XG5cbiAgbGV0IGR1cmF0aW9uID0gRGF0ZS5ub3coKSAtIHMuc3RhcnRUaW1lO1xuXG4gIHJldHVybiAhcy5pbmZpbml0ZSAmJiAoIHRpY2tJbmRpY2F0ZXNEb25lIHx8IHMudGlja0luZGV4ID49IHMubWF4SXRlcmF0aW9ucyB8fCBkdXJhdGlvbiA+PSBzLm1heFNpbXVsYXRpb25UaW1lICk7XG59O1xuXG5sZXQgbXVsdGl0aWNrID0gZnVuY3Rpb24oIHN0YXRlLCBvbk5vdERvbmUgPSBub3AsIG9uRG9uZSA9IG5vcCApe1xuICBsZXQgZG9uZSA9IGZhbHNlO1xuICBsZXQgcyA9IHN0YXRlO1xuXG4gIGZvciggbGV0IGkgPSAwOyBpIDwgcy5yZWZyZXNoOyBpKysgKXtcbiAgICBkb25lID0gIXMucnVubmluZyB8fCB0aWNrKCBzICk7XG5cbiAgICBpZiggZG9uZSApeyBicmVhazsgfVxuICB9XG5cbiAgaWYoICFkb25lICl7XG4gICAgb25Ob3REb25lKCk7XG4gIH0gZWxzZSB7XG4gICAgb25Eb25lKCk7XG4gIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0geyB0aWNrLCBtdWx0aXRpY2sgfTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9sYXlvdXQvdGljay5qcyJdLCJzb3VyY2VSb290IjoiIn0=
\ No newline at end of file
diff --git a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/cytoscape-layers.js b/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/cytoscape-layers.js
deleted file mode 100644
index 81ab8f2..0000000
--- a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/cytoscape-layers.js
+++ /dev/null
@@ -1,2 +0,0 @@
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).CytoscapeLayers={})}(this,(function(e){"use strict";const t={position:"absolute",left:"0",top:"0",userSelect:"none",outlineStyle:"none",width:"100%",height:"100%"};function s(e){e.stopPropagation()}function n(e){e.addEventListener("click",s),e.addEventListener("mousedown",s),e.addEventListener("mouseup",s),e.addEventListener("mousemove",s)}class i{constructor(e){this.adapter=e,this.updateOnRenderEnabled=!1,this.updateOnRenderOnceEnabled=!1,this.updateOnRenderOnce=()=>{this.updateOnRenderOnceEnabled||(this.updateOnRenderOnceEnabled=!0,this.cy.one("render",(()=>{this.updateOnRenderOnceEnabled=!1,this.update()})))}}inVisibleBounds(e){return this.adapter.inVisibleBounds(e)}supportsRender(){return!1}renderInto(e,t){}get updateOnRender(){return this.updateOnRenderEnabled}set updateOnRender(e){this.updateOnRenderEnabled!==e&&(this.updateOnRenderEnabled=e,e?this.cy.on("render",this.update):this.cy.off("render",this.update))}get cy(){return this.adapter.cy}moveUp(){this.adapter.move(this,-1)}moveDown(){this.adapter.move(this,1)}moveBack(){this.adapter.move(this,Number.NEGATIVE_INFINITY)}moveFront(){this.adapter.move(this,Number.POSITIVE_INFINITY)}insertBefore(e,t){return this.adapter.insert("before",this,e,t)}insertAfter(e,t){return this.adapter.insert("after",this,e,t)}}class r extends i{constructor(e,s){super(e),this.callbacks=[],this.update=()=>{for(const e of this.callbacks)e(this.node)},this.root=s,Object.assign(this.root.style,t)}get visible(){return"none"!==this.root.style.display}set visible(e){this.visible!==e&&(this.root.style.display=e?"":"none")}show(){this.visible=!0}hide(){this.visible=!1}callback(e){return this.callbacks.push(e),this.update(),this}resize(){}remove(){this.root.remove()}}const o="http://www.w3.org/2000/svg";class a extends r{constructor(e,t,s={}){super(e,t.createElementNS(o,"svg")),this.type="svg",this.updateOnTransform=!1,this.root.__cy_layer=this,this.node=t.createElementNS(o,"g"),this.node.__cy_layer=this,this.root.appendChild(this.node),s.stopClicks&&n(this.node)}setViewport(e,t,s){this.node.setAttribute("transform",`translate(${e},${t})scale(${s})`),this.updateOnTransform&&this.update()}supportsRender(){return 0===this.node.childElementCount}}class c extends r{constructor(e,t,s={}){super(e,t.createElementNS(o,"svg")),this.type="svg-static",this.root.__cy_layer=this,this.node=t.createElementNS(o,"g"),this.node.__cy_layer=this,this.root.appendChild(this.node),s.stopClicks&&n(this.node)}setViewport(){}}class d extends i{constructor(e,s,i={}){var r,o;super(e),this.callbacks=[],this.transform={tx:0,ty:0,zoom:1},this.update=()=>this.draw(),this.node=s.createElement("canvas"),Object.assign(this.node.style,t),i.stopClicks&&n(this.node),this.pixelRatio=null!==(o=null!==(r=i.pixelRatio)&&void 0!==r?r:(null!==window&&void 0!==window?window:{}).devicePixelRatio)&&void 0!==o?o:1,this.ctx=this.node.getContext("2d",i),this.ctx.resetTransform()}get visible(){return"none"!==this.node.style.display}set visible(e){this.node.style.display=e?"":"none"}show(){this.visible=!0}hide(){this.visible=!1}get root(){return this.node}callback(e){return this.callbacks.push(e),this.update(),this}clear(){const e=this.ctx,t=e.getTransform();e.resetTransform(),e.clearRect(0,0,e.canvas.width,e.canvas.height),e.setTransform(t)}draw(){this.clear(),this.drawImpl(this.ctx)}drawImpl(e,t=1){e.save(),e.resetTransform(),e.scale(this.pixelRatio,this.pixelRatio),e.translate(this.transform.tx*t,this.transform.ty*t),e.scale(this.transform.zoom*t,this.transform.zoom*t);for(const t of this.callbacks)t(e);e.restore()}supportsRender(){return!0}renderInto(e,t){this.drawImpl(e,t.scale)}resize(e,t){this.node.width=e*this.pixelRatio,this.node.height=t*this.pixelRatio,this.update()}setViewport(e,t,s){}remove(){this.node.remove()}}class h extends d{constructor(e,t,s={}){super(e,t,s),this.type="canvas",this.node.__cy_layer=this}setViewport(e,t,s){this.transform.tx=e,this.transform.ty=t,this.transform.zoom=s,this.update()}}class l extends d{constructor(e,t,s={}){super(e,t,s),this.type="canvas-static",this.node.__cy_layer=this}}class u extends r{constructor(e,t,s={}){super(e,t.createElement("div")),this.type="html",this.updateOnTransform=!1,this.root.__cy_layer=this,this.node=t.createElement("div"),this.node.__cy_layer=this,this.node.style.position="absolute",this.node.style.left="0px",this.node.style.top="0px",this.root.appendChild(this.node),s.stopClicks&&n(this.node)}setViewport(e,t,s){this.node.style.transform=`translate(${e}px,${t}px)scale(${s})`,this.updateOnTransform&&this.update()}supportsRender(){return 0===this.node.childElementCount}}class p extends r{constructor(e,t,s={}){super(e,t.createElement("div")),this.type="html-static",this.node.__cy_layer=this,s.stopClicks&&n(this.node)}get node(){return this.root}setViewport(){}}class y extends i{constructor(e,t){super(e),this.update=()=>{},this.node=t}get root(){return this.node}resize(){}setViewport(){}remove(){}supportsRender(){return!0}}class f extends y{constructor(e,t){super(e,t),this.type="node",this.node.__cy_layer=this}}class m extends y{constructor(e,t){super(e,t),this.type="drag",this.node.__cy_layer=this}}class g extends y{constructor(e,t){super(e,t),this.type="select-box",this.node.__cy_layer=this}}function v(e,t,s){const n=Array.from(e.children);if(!s.uniqueElements){t.forEach((t=>{const i=s.bb(t);if(s.isVisible(i))if(n.length>0)s.update(n.shift(),t,i);else{const n=s.enter(t,i);e.appendChild(n),s.update(n,t,i)}}));for(const e of n)e.remove();return}const i=new Map(n.map((e=>[e.dataset.id,e])));let r=-1;t.forEach((t=>{const o=s.bb(t);if(!s.isVisible(o))return;r++;const a=t.id(),c=n[r],d=i.get(a);let h;if(d){if(s.update(d,t,o),i.delete(a),c===d)return;h=d}else h=s.enter(t,o),h.dataset.id=a,s.update(h,t,o);0===r?e.insertAdjacentElement("afterbegin",h):n[r-1].insertAdjacentElement("afterend",h),n.splice(r,0,h)})),i.forEach((e=>e.remove()))}function b(e,t){return e.callback(t),{remove:()=>{e.callbacks.splice(e.callbacks.indexOf(t),1)}}}function x(e){return{selector:":visible",updateOn:null!=e&&e.queryEachTime?"render":"position",queryEachTime:!1,checkBounds:!0}}function w(e,t,s){const n=Object.assign({checkBoundsPointCount:5,initCollection:()=>{}},x(s),s),i=n.queryEachTime?e.cy.collection():e.cy.edges(n.selector);n.queryEachTime||n.initCollection(i),"render"===n.updateOn?e.updateOnRender=!0:"position"===n.updateOn?(i.on("position add remove",e.updateOnRenderOnce),i.sources().on("position",e.updateOnRenderOnce),i.targets().on("position",e.updateOnRenderOnce)):i.on("add remove",e.updateOnRenderOnce);const r=b(e,(s=>{const r=n.queryEachTime?e.cy.edges(n.selector):i;n.queryEachTime&&n.initCollection(r),r.forEach((i=>{const r=i._private.rscratch,o=r&&null!=r.startX&&null!=r.startY?{x:r.startX,y:r.startY}:i.sourceEndpoint(),a=r&&null!=r.endX&&null!=r.endY?{x:r.endX,y:r.endY}:i.targetEndpoint();if(n.checkBounds&&n.checkBoundsPointCount>0&&!function(e,t,s,n){const i=e=>({x:t.x*e+s.x*(1-e),y:t.y*e+s.y*(1-e)});if(1===n)return e.inVisibleBounds(i(.5));const r=1/n;for(let t=0;t<=n;t++)if(e.inVisibleBounds(i(t*r)))return!0;return!1}(e,o,a,n.checkBoundsPointCount))return;if(r&&r.pathCache)return void t(s,i,r.pathCache,o,a);const c=new Path2D;c.moveTo(o.x,o.y),c.lineTo(a.x,a.y),t(s,i,c,o,a)}))}));return{layer:e,edges:i,remove:()=>{i.off("position add remove",void 0,e.updateOnRenderOnce),i.sources().off("position",void 0,e.updateOnRenderOnce),i.targets().off("position",void 0,e.updateOnRenderOnce),r.remove()}}}function O(e,t,s={}){const n=Object.assign({transform:"",position:"top-left",boundingBox:{includeLabels:!1,includeOverlays:!1},uniqueElements:!1,initCollection:()=>{}},x(s),s),i=n.queryEachTime?e.cy.collection():e.cy.nodes(n.selector);n.queryEachTime||n.initCollection(i),"render"===n.updateOn?e.updateOnRender=!0:"position"===n.updateOn?i.on("position add remove",e.updateOnRenderOnce):i.on("add remove",e.updateOnRenderOnce);const r=t=>({layer:e,nodes:i,remove:()=>{i.off("position add remove",void 0,e.updateOnRenderOnce),t.remove()}});if("canvas"===e.type){const s=n,o=r=>{const o=r.getTransform(),a=s.queryEachTime?e.cy.nodes(s.selector):i;n.queryEachTime&&n.initCollection(a),a.forEach((i=>{const a=i.boundingBox(n.boundingBox);if(!s.checkBounds||e.inVisibleBounds(a)){if("top-left"===s.position)r.translate(a.x1,a.y1);else if("center"===s.position){const e=i.position();r.translate(e.x,e.y)}t(r,i,a),"none"!==s.position&&r.setTransform(o)}}))};return r(b(e,o))}const a=n,c={bb:e=>e.boundingBox(a.boundingBox),isVisible:a.checkBounds?t=>e.inVisibleBounds(t):()=>!0,uniqueElements:!0===a.uniqueElements};if(a.checkBounds&&(e.updateOnTransform=!0),"html"===e.type){const s={...c,enter:(t,s)=>{const n=e.node.ownerDocument.createElement("div");return n.style.position="absolute",a.init&&a.init(n,t,s),n},update:(e,s,n)=>{if("top-left"===a.position)e.style.transform=`${a.transform}translate3d(${n.x1}px,${n.y1}px,0)`;else if("center"===a.position){const t=s.position();e.style.transform=`${a.transform}translate3d(${t.x}px,${t.y}px,0)`}t(e,s,n)}},o=t=>{const r=a.queryEachTime?e.cy.nodes(a.selector):i;n.queryEachTime&&n.initCollection(r),v(t,r,s)};return r(b(e,o))}const d={...c,enter:(t,s)=>{const n=e.node.ownerDocument.createElementNS(o,"g");return a.init&&a.init(n,t,s),n},update:(e,s,n)=>{if("top-left"===a.position)e.setAttribute("transform",`${a.transform}translate3d(${n.x1},${n.y1},0)`);else if("center"===a.position){const t=s.position();e.setAttribute("transform",`${a.transform}translate3d(${t.x},${t.y},0)`)}t(e,s,n)}};return r(b(e,(t=>{const s=a.queryEachTime?e.cy.nodes(a.selector):i;n.queryEachTime&&n.initCollection(s),v(t,s,d)})))}function E(e){const t=e.indexOf(",");return e.substring(t+1)}function _(e,t,s){const n=function(){return t.toDataURL(s,e.quality)};switch(e.output){case"blob-promise":return new Promise(((n,i)=>{try{t.toBlob((function(e){null!=e?n(e):i(new Error("`canvas.toBlob()` sent a null value in its callback"))}),s,e.quality)}catch(e){i(e)}}));case"blob":return function(e,t){const s=atob(e),n=new ArrayBuffer(s.length),i=new Uint8Array(n);for(let e=0;e{const e=this.cy.width(),t=this.cy.height();this.viewport.width=e,this.viewport.height=t;for(const s of this.layers)s.resize(e,t)},this.destroy=()=>{for(const e of this.layers)e.remove();this.cy.off("destroy",this.destroy),this.cy.off("viewport",this.zoomed),this.cy.off("resize",this.resize),this.cy.scratch("_layers",void 0),this.cy.png=this.bak.png,this.cy.jpg=this.bak.jpg,this.cy.jpeg=this.bak.jpeg,this.bak={}},this.zoomed=()=>{const e=this.cy.pan(),t=this.cy.zoom();this.viewport.tx=e.x,this.viewport.ty=e.y,this.viewport.zoom=t;for(const s of this.layers)s.setViewport(e.x,e.y,t)},this.renderPerEdge=w,this.renderPerNode=O,this.cy=e,this.adapter={cy:this.cy,insert:(e,t,s)=>this.insert(e,t,s),move:(e,t)=>this.move(e,t),inVisibleBounds:e=>{const t=this.viewport,s=e=>{const s=e*t.zoom+t.tx;return s>=0&&s<=t.width},n=e=>{const s=e*t.zoom+t.ty;return s>=0&&s<=t.height};return function(e){return null!=e.x}(e)?s(e.x)&&n(e.y):s(e.x1)&&n(e.y1)||s(e.x2)&&n(e.y1)||s(e.x2)&&n(e.y2)||s(e.x1)&&n(e.y2)||s((e.x1+e.x2)/2)&&n((e.y1+e.y2)/2)}};const t=e.container(),s=new f(this.adapter,t.querySelector('[data-id="layer2-node"]'));this.nodeLayer=s;const n=new m(this.adapter,t.querySelector('[data-id="layer1-drag"]'));this.dragLayer=n;const i=new g(this.adapter,t.querySelector('[data-id="layer0-selectbox"]'));this.selectBoxLayer=i,s.root.style.zIndex="",n.root.style.zIndex="",i.root.style.zIndex="",s.root.insertAdjacentElement("afterend",n.root),n.root.insertAdjacentElement("afterend",i.root),e.on("viewport",this.zoomed),e.on("resize",this.resize),e.on("destroy",this.destroy),this.bak={png:e.png,jpg:e.jpg,jpeg:e.jpeg},e.png=this.png.bind(this),e.jpg=this.jpg.bind(this),e.jpeg=this.jpeg.bind(this),this.viewport={width:this.cy.width(),height:this.cy.height(),tx:this.cy.pan().x,ty:this.cy.pan().y,zoom:this.cy.zoom()}}move(e,t){const s=this.layers,n=s.indexOf(e),i=Math.max(Math.min(n+t,s.length,0));i!==n&&(n>=s.length-1?this.root.appendChild(e.root):this.root.insertBefore(e.root,s[i].root))}get document(){return this.cy.container().ownerDocument}get root(){return this.nodeLayer.node.parentElement}get layers(){return Array.from(this.root.children).map((e=>e.__cy_layer)).filter((e=>null!=e))}getLayers(){return this.layers}init(e){return e.resize(this.viewport.width,this.viewport.height),e.setViewport(this.viewport.tx,this.viewport.ty,this.viewport.zoom),e}update(){this.zoomed();for(const e of this.layers)e instanceof h&&e.draw()}createLayer(e,t){switch(e){case"svg":return this.init(new a(this.adapter,this.document,t));case"html":return this.init(new u(this.adapter,this.document,t));case"canvas":return this.init(new h(this.adapter,this.document,t));case"html-static":return this.init(new p(this.adapter,this.document,t));case"svg-static":return this.init(new c(this.adapter,this.document,t));case"canvas-static":return this.init(new l(this.adapter,this.document,t))}}append(e,t){const s=this.createLayer(e,t);return this.root.appendChild(s.root),s}insert(e,t,s,n){const i=this.createLayer(s,n);return t.root.insertAdjacentElement("before"===e?"beforebegin":"afterend",i.root),i}getLast(){var e;const t=this.layers;return null!==(e=t[t.length-1])&&void 0!==e?e:null}getFirst(){var e;return null!==(e=this.layers[0])&&void 0!==e?e:null}hasCustomLayer(){return this.layers.some((e=>!(e instanceof y)))}toCanvas(e){var t,s;const n=this.layers;if(n.some((e=>!e.supportsRender))&&!e.ignoreUnsupportedLayers)throw new C("some layer doesn't support exporting, use {ignoreUnsupportedLayers: true} option to ignore");const i=n.indexOf(this.nodeLayer),r=n.indexOf(this.dragLayer),o=n.indexOf(this.selectBoxLayer);if((i!==r-1||r!==o-1)&&!e.ignoreUnsupportedLayerOrder)throw new C("cytoscape layers are not in order, use {ignoreUnsupportedLayerOrder: true} option to ignore");const a=this.cy.renderer(),c=e.bg,d=a.bufferCanvasImage({...e,bg:void 0}),h=d.width,l=d.height,u=d.getContext("2d"),p=n.slice(0,i).reverse().filter((e=>e.supportsRender()&&e!==this.dragLayer&&e!==this.selectBoxLayer)),y=n.slice(i+1).filter((e=>e.supportsRender()&&e!==this.dragLayer&&e!==this.selectBoxLayer)),f={scale:null!==(t=e.scale)&&void 0!==t?t:1,width:h,height:l,full:null!==(s=e.full)&&void 0!==s&&s};u.globalCompositeOperation="destination-over";for(const e of p)e.renderInto(u,f);u.globalCompositeOperation="source-over";for(const e of y)e.renderInto(u,f);return c&&(u.globalCompositeOperation="destination-over",u.fillStyle=c,u.rect(0,0,h,l),u.fill()),d}png(e){return this.hasCustomLayer()?_(null!=e?e:{},this.toCanvas(null!=e?e:{}),"image/png"):this.bak.png.call(this.cy,e)}jpg(e){if(!this.hasCustomLayer())return this.bak.jpg.call(this.cy,e);const t={bg:"#fff",...null!=e?e:{}};return _(t,this.toCanvas(t),"image/png")}jpeg(e){return this.hasCustomLayer()?this.jpg(e):this.bak.jpeg.call(this.cy,e)}}function k(e=this){if(!e.container())throw new Error("layers plugin does not work in headless environments");const t=e.scratch("_layers");if(t)return t;const s=new R(e);return e.scratch("_layers",s),s}function T(e){e("core","layers",k)}void 0!==window.cytoscape&&T(window.cytoscape),e.LayerExportException=C,e.LayersPlugin=R,e.default=T,e.layers=k,e.renderPerEdge=w,e.renderPerNode=O,Object.defineProperty(e,"__esModule",{value:!0})}));
-//# sourceMappingURL=index.umd.min.js.map
diff --git a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/cytoscape-ngraph.forcelayout.js b/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/cytoscape-ngraph.forcelayout.js
deleted file mode 100644
index a839457..0000000
--- a/tests/unimog_tests/test_cases/git_issues/containment_1/truth/align/containment/containment_communities/visualisations/communities/libs/cytoscape-ngraph.forcelayout.js
+++ /dev/null
@@ -1,7569 +0,0 @@
-(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.cytoscapeNgraph || (g.cytoscapeNgraph = {})).forcelayout = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o tag, or a module
- // using CommonJS and NodeJS or RequireJS module formats. In
- // Common/Node/RequireJS, the module exports the Q API and when
- // executed as a simple
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Legend
-
Node colours:
-
Each different colour represents a different plasmid community.
-
Due to the lack of enough colours, different plasmid communities will sometimes have same colours.
-
But hopefully they won't be connected, so we can infer they are still different communities.
-
Node shapes:
-
● Normal plasmids
-
★ Hub plasmids
-
-
-
- Filters:
-
-
-
-
-
-
-
-
-
-
-