diff --git a/.dockerignore b/.dockerignore
deleted file mode 100644
index ac2f951b..00000000
--- a/.dockerignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!releases/phpmetrics.phar
diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644
index b26a9a99..00000000
--- a/.editorconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-; This file is for unifying the coding style for different editors and IDEs.
-; More information at https://editorconfig.org
-
-root = true
-
-[*]
-charset = utf-8
-indent_size = 4
-indent_style = space
-end_of_line = lf
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*.md]
-trim_trailing_whitespace = false
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index 3318e8e6..00000000
--- a/.gitattributes
+++ /dev/null
@@ -1,16 +0,0 @@
-.git/               export-ignore
-releases/           export-ignore
-tests/              export-ignore
-artifacts/          export-ignore
-build/              export-ignore
-doc/                export-ignore
-
-.editorconfig       export-ignore
-.gitattributes      export-ignore
-.github/            export-ignore
-.gitignore          export-ignore
-.travis.yml         export-ignore
-Makefile            export-ignore
-phpcs.xml.dist      export-ignore
-phpunit.xml.dist    export-ignore
-
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index 821bcea0..00000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-# These are supported funding model platforms
-
-github: [Halleck45]
diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md
deleted file mode 100644
index da5eb2c2..00000000
--- a/.github/ISSUE_TEMPLATE/Bug_report.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-name: Bug report
-about: Inform us about a bug in PhpMetrics.
----
-
-# Bug report
-
-<!-- 
-    Write the PhpMetrics version used. 
-    Before submitting a bug, please ensure you are using the latest version.
-    Run `phpmetrics --version` to display your current version of PhpMetrics.
---> 
-<!-- Please describe your problem here. -->
diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md
deleted file mode 100644
index 70bb8c4f..00000000
--- a/.github/ISSUE_TEMPLATE/Feature_request.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: Feature request
-about: Ideas you have (maybe with a PR)!
----
-
-# Feature request
-
-<!-- Please provide a clear description of your feature request. -->
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index 68f6edee..00000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,72 +0,0 @@
-name: CI
-
-on:
-    push:
-        branches: [ master, main ]
-    pull_request:
-        branches: [ master, main ]
-    release:
-        types: [created]
-
-jobs:
-    test:
-        runs-on: ubuntu-latest
-        strategy:
-            matrix:
-                php-version: [5.6, 7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4]
-                include:
-                    - php-version: nightly
-            fail-fast: false
-
-        services:
-            docker:
-                image: docker:20.10.16
-                options: --privileged
-
-        steps:
-            - uses: actions/checkout@v4
-
-            - name: Set up PHP ${{ matrix.php-version }}
-              uses: shivammathur/setup-php@v2
-              with:
-                  php-version: ${{ matrix.php-version }}
-
-            - name: "Remove ': void' return type hint for older PHP versions"
-              run: |
-                # if php version < 7.1, remove ': void' return type hint
-                if [[ "${{ matrix.php-version }}" < "7.1" ]]; then
-                    echo "Removing ': void' return type hint for PHP version ${{ matrix.php-version }}"
-                    # Find and replace ': void' in all PHP files
-                    find . -type f -name "*.php" -exec sed -i 's/: void//g' {} +
-                fi
-
-            - name: Install Composer dependencies (${{ matrix.php-version }})
-              run: composer install --no-interaction --prefer-dist --no-progress
-
-            - name: Run tests (${{ matrix.php-version }})
-              run: make test
-
-    build:
-        if: github.event_name == 'release' && startsWith(github.ref, 'refs/tags/')
-        needs: test
-        runs-on: ubuntu-latest
-        steps:
-            -   uses: actions/checkout@v4
-
-            -   name: Set up PHP
-                uses: shivammathur/setup-php@v2
-                with:
-                    php-version: 7.0
-
-            -   name: Build project
-                run: make build
-
-            -   name: Add build artifact
-                run: git add -f build/phpmetrics.phar
-
-            -   name: Upload release asset
-                uses: softprops/action-gh-release@v2
-                with:
-                    files: build/phpmetrics.phar
-                env:
-                    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index fb488c20..d495af2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,20 +1,8 @@
 composer.lock
-vendor
-tooling/vendor
 .idea
-md5sums
-control
-files
-build/phpmetrics.dsc
-build/phpmetrics.deb
-build/phpmetrics.tar.gz
-build/phpmetrics.changes
-.php-cs-fixer.cache
-.phpunit.result.cache
-
-# build
-buildroot/
-downloads/
-pkgroot/
-source/
-spc
+/vendor/
+.vagrant
+provision.sh
+Vagrantfile
+node_modules
+build
diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php
deleted file mode 100644
index 779c7070..00000000
--- a/.php-cs-fixer.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-
-$finder = (new PhpCsFixer\Finder())
-    ->in(__DIR__ . '/src')
-;
-
-return (new PhpCsFixer\Config())
-    ->setRules([
-        '@PER-CS' => true,
-        '@PHP82Migration' => true,
-    ])
-    ->setFinder($finder)
-    ->setUnsupportedPhpVersionAllowed(true)
-    ;
diff --git a/.semver b/.semver
deleted file mode 100644
index beb37e20..00000000
--- a/.semver
+++ /dev/null
@@ -1,5 +0,0 @@
----
-:major: 2
-:minor: 8
-:patch: 2
-:special: ''
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 46f15efe..00000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,130 +0,0 @@
-# Changelog
-All notable changes to this project will be documented in this file.
-
-The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
-and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
-
-## [2.8.2] - 2023-02-??
-
-### Fixed
-- Fixed errors in HTML template. (thanks @Hikingyo and @gemal)
-- Improved README.md contents. (thanks @kudashevs)
-- Fixed junit parameter in JSON configuration file
-- Minor removals of unnecessary source code
-- Remove wrong artefacts causing download issues
-- Add favicon to HTML rendered pages (thanks @gemal)
-- Add version to CSS and script to counter cache (thanks @gemal)
-
-## [2.8.1] - 2022-03-24
-
-### Fixed
-- Fixed issue with relative pat when using YAML configuration.
-
-## [2.8.0] - 2022-03-23
-
-### New features
-- Allow to search for patterns of code.
-- Possibility to add custom violation rules via configuration.
-- Allow to use YAML for configuration
-- Add `--metrics` option to display documentation about some metrics calculated and used by PhpMetrics.
-- Exclude getters and setters from the CCN (cyclomatic complexity number) and LCoM (lack in cohesion of method) calculations
-- Add `composer` option to enable or disable the composer packages analysis
-- Add `--report-summary-json` option to report a summarized information from the calculated metrics.
-
-### Fixed
-- Fixed issue with some columns in HTML reports
-
-## [2.7.4] - 2020-06-30
-
-### Fixed
-- Fixed compatibility issue where PHP 5 was no longer available on Debian systems  (#434)
-- Fixed issue with display of charts in groups (#429, #433)
-
-## [2.7.3] - 2020-06-27
-
-### Fixed
-- Fixed missing `composer.json` files when located in the root directory.
-
-## [2.7.2] - 2020-06-27
-
-### Fixed
-- Fixed path of violations HTML templates.
-
-## [2.7.1] - 2020-06-27
-
-### Fixed
-- Fixed error due to permission on generation of HTML report (#429)
-- Fixed analysis on composer packages wrongly reported outdated when latest version is used. (#431)
-
-## [2.7.0] - 2020-06-26
-
-### New features
-- Way to group analysis by layer
-
-### Fixed
-- Improved UI
-
-## [2.6.2] - 2020-04-02
-
-### Fixed
-- Improved UI
-
-## [2.6.1] - 2020-04-02
-
-### Fixed
-- Fixed undefined constant PROJECT_DIR (#426)
-
-## [2.6.0] - 2020-03-28
-
-### New features
-- Way to download report
-- Way to download chart
-- Resolve PHP7 getters / setters (#405)
-- Add metrics description file
-- Add a carousel in the main HTML report page to display both graph at the same time
-
-### Fixed
-- Explicitly define the class \Hal\Component\Ast\NodeTraverser to make PhpMetrics work using composer --classmap-authoritative. (#402)
-- Ensure the packagist license is an array, so they can be displayed. (#404)
-- Fix warning "Division by zero" when no package is defined. (#401)
-
-### Misc
-- Move templates out of src
-- Remove folders from phpcs
-
-## [2.5.0] - 2019-12-11
-
-### Changed
-- Test the codebase against PHP 7.3 and 7.4
-
-### Fixed
-- Skip `self` and `parent` from external dependencies of dependency graph (#370) thanks to (@lencse)
-- Don't leave notice when array is small in percentile function of loc report (#372) thanks to (@lencse)
-
-## [2.4.1] - 2017-07-10
-
-### Fixed
- - Fix parsing errors with PHP < 7 (#360, #361)
- - Remain CCN for backward compatibility (#359, #362)
- 
-### Deprecated
- - CCN by classes is deprecated and will be removed in the next major release (#359, #362)
-
-## [2.4.0] - 2017-07-09
-
-### Added
- - Added package metrics (#283)
-
-### Changed
- - Enhanced composer package comparison (#337, #342, thanks @juliendufresne)
- - Better PHP 7 support (#335, #334, #336 thanks @carusogabriel)
- - Support nikic/php-parser:^4 (#345, #347)
-
-### Fixed
- - Refine Cyclomatic Complexity Metric (#343, #344, #353, #357, #358, thanks @fabianbadoi)
- - Improved composer package version comparison (#337, thanks @juliendufresne)
- - Resolved root path exclusion conflict (#355, thanks @fabianbadoi)
- - Fixed getter and setter detection with types (#335, #336, thanks @jakagacic)
- - Fixed documentation URL (#321, thanks @ottaviano)
- - Fix non unique block ids in HTML output (#356, thanks @dumith-erange)
- - Fix rounding of metrics (#339, thanks @ssfinney)
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index adce5fbc..00000000
--- a/Dockerfile
+++ /dev/null
@@ -1,16 +0,0 @@
-FROM php:8.4
-
-MAINTAINER "niconoe-" <nicolas.giraud.dev@gmail.com>
-
-COPY releases/phpmetrics.phar /usr/local/bin/phpmetrics
-
-RUN chmod +x /usr/local/bin/phpmetrics \
-    # Install git to be able to use option "--git".
-    && apt-get update && apt-get install -y git \
-    && rm -rf /var/cache/apk/* /var/tmp/* /tmp/*
-
-VOLUME ["/app"]
-WORKDIR /app
-
-ENTRYPOINT ["phpmetrics"]
-CMD ["--version"]
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 00000000..e44e449c
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,2 @@
+source 'https://rubygems.org'
+gem "github-pages", group: :jekyll_plugins
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 00000000..1a70da44
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,244 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    activesupport (6.0.3.2)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      i18n (>= 0.7, < 2)
+      minitest (~> 5.1)
+      tzinfo (~> 1.1)
+      zeitwerk (~> 2.2, >= 2.2.2)
+    addressable (2.7.0)
+      public_suffix (>= 2.0.2, < 5.0)
+    coffee-script (2.4.1)
+      coffee-script-source
+      execjs
+    coffee-script-source (1.11.1)
+    colorator (1.1.0)
+    commonmarker (0.17.13)
+      ruby-enum (~> 0.5)
+    concurrent-ruby (1.1.6)
+    dnsruby (1.61.3)
+      addressable (~> 2.5)
+    em-websocket (0.5.1)
+      eventmachine (>= 0.12.9)
+      http_parser.rb (~> 0.6.0)
+    ethon (0.12.0)
+      ffi (>= 1.3.0)
+    eventmachine (1.2.7)
+    execjs (2.7.0)
+    faraday (1.0.1)
+      multipart-post (>= 1.2, < 3)
+    ffi (1.13.1)
+    forwardable-extended (2.6.0)
+    gemoji (3.0.1)
+    github-pages (206)
+      github-pages-health-check (= 1.16.1)
+      jekyll (= 3.8.7)
+      jekyll-avatar (= 0.7.0)
+      jekyll-coffeescript (= 1.1.1)
+      jekyll-commonmark-ghpages (= 0.1.6)
+      jekyll-default-layout (= 0.1.4)
+      jekyll-feed (= 0.13.0)
+      jekyll-gist (= 1.5.0)
+      jekyll-github-metadata (= 2.13.0)
+      jekyll-mentions (= 1.5.1)
+      jekyll-optional-front-matter (= 0.3.2)
+      jekyll-paginate (= 1.1.0)
+      jekyll-readme-index (= 0.3.0)
+      jekyll-redirect-from (= 0.15.0)
+      jekyll-relative-links (= 0.6.1)
+      jekyll-remote-theme (= 0.4.1)
+      jekyll-sass-converter (= 1.5.2)
+      jekyll-seo-tag (= 2.6.1)
+      jekyll-sitemap (= 1.4.0)
+      jekyll-swiss (= 1.0.0)
+      jekyll-theme-architect (= 0.1.1)
+      jekyll-theme-cayman (= 0.1.1)
+      jekyll-theme-dinky (= 0.1.1)
+      jekyll-theme-hacker (= 0.1.1)
+      jekyll-theme-leap-day (= 0.1.1)
+      jekyll-theme-merlot (= 0.1.1)
+      jekyll-theme-midnight (= 0.1.1)
+      jekyll-theme-minimal (= 0.1.1)
+      jekyll-theme-modernist (= 0.1.1)
+      jekyll-theme-primer (= 0.5.4)
+      jekyll-theme-slate (= 0.1.1)
+      jekyll-theme-tactile (= 0.1.1)
+      jekyll-theme-time-machine (= 0.1.1)
+      jekyll-titles-from-headings (= 0.5.3)
+      jemoji (= 0.11.1)
+      kramdown (= 1.17.0)
+      liquid (= 4.0.3)
+      mercenary (~> 0.3)
+      minima (= 2.5.1)
+      nokogiri (>= 1.10.4, < 2.0)
+      rouge (= 3.19.0)
+      terminal-table (~> 1.4)
+    github-pages-health-check (1.16.1)
+      addressable (~> 2.3)
+      dnsruby (~> 1.60)
+      octokit (~> 4.0)
+      public_suffix (~> 3.0)
+      typhoeus (~> 1.3)
+    html-pipeline (2.13.0)
+      activesupport (>= 2)
+      nokogiri (>= 1.4)
+    http_parser.rb (0.6.0)
+    i18n (0.9.5)
+      concurrent-ruby (~> 1.0)
+    jekyll (3.8.7)
+      addressable (~> 2.4)
+      colorator (~> 1.0)
+      em-websocket (~> 0.5)
+      i18n (~> 0.7)
+      jekyll-sass-converter (~> 1.0)
+      jekyll-watch (~> 2.0)
+      kramdown (~> 1.14)
+      liquid (~> 4.0)
+      mercenary (~> 0.3.3)
+      pathutil (~> 0.9)
+      rouge (>= 1.7, < 4)
+      safe_yaml (~> 1.0)
+    jekyll-avatar (0.7.0)
+      jekyll (>= 3.0, < 5.0)
+    jekyll-coffeescript (1.1.1)
+      coffee-script (~> 2.2)
+      coffee-script-source (~> 1.11.1)
+    jekyll-commonmark (1.3.1)
+      commonmarker (~> 0.14)
+      jekyll (>= 3.7, < 5.0)
+    jekyll-commonmark-ghpages (0.1.6)
+      commonmarker (~> 0.17.6)
+      jekyll-commonmark (~> 1.2)
+      rouge (>= 2.0, < 4.0)
+    jekyll-default-layout (0.1.4)
+      jekyll (~> 3.0)
+    jekyll-feed (0.13.0)
+      jekyll (>= 3.7, < 5.0)
+    jekyll-gist (1.5.0)
+      octokit (~> 4.2)
+    jekyll-github-metadata (2.13.0)
+      jekyll (>= 3.4, < 5.0)
+      octokit (~> 4.0, != 4.4.0)
+    jekyll-mentions (1.5.1)
+      html-pipeline (~> 2.3)
+      jekyll (>= 3.7, < 5.0)
+    jekyll-optional-front-matter (0.3.2)
+      jekyll (>= 3.0, < 5.0)
+    jekyll-paginate (1.1.0)
+    jekyll-readme-index (0.3.0)
+      jekyll (>= 3.0, < 5.0)
+    jekyll-redirect-from (0.15.0)
+      jekyll (>= 3.3, < 5.0)
+    jekyll-relative-links (0.6.1)
+      jekyll (>= 3.3, < 5.0)
+    jekyll-remote-theme (0.4.1)
+      addressable (~> 2.0)
+      jekyll (>= 3.5, < 5.0)
+      rubyzip (>= 1.3.0)
+    jekyll-sass-converter (1.5.2)
+      sass (~> 3.4)
+    jekyll-seo-tag (2.6.1)
+      jekyll (>= 3.3, < 5.0)
+    jekyll-sitemap (1.4.0)
+      jekyll (>= 3.7, < 5.0)
+    jekyll-swiss (1.0.0)
+    jekyll-theme-architect (0.1.1)
+      jekyll (~> 3.5)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-cayman (0.1.1)
+      jekyll (~> 3.5)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-dinky (0.1.1)
+      jekyll (~> 3.5)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-hacker (0.1.1)
+      jekyll (~> 3.5)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-leap-day (0.1.1)
+      jekyll (~> 3.5)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-merlot (0.1.1)
+      jekyll (~> 3.5)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-midnight (0.1.1)
+      jekyll (~> 3.5)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-minimal (0.1.1)
+      jekyll (~> 3.5)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-modernist (0.1.1)
+      jekyll (~> 3.5)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-primer (0.5.4)
+      jekyll (> 3.5, < 5.0)
+      jekyll-github-metadata (~> 2.9)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-slate (0.1.1)
+      jekyll (~> 3.5)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-tactile (0.1.1)
+      jekyll (~> 3.5)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-time-machine (0.1.1)
+      jekyll (~> 3.5)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-titles-from-headings (0.5.3)
+      jekyll (>= 3.3, < 5.0)
+    jekyll-watch (2.2.1)
+      listen (~> 3.0)
+    jemoji (0.11.1)
+      gemoji (~> 3.0)
+      html-pipeline (~> 2.2)
+      jekyll (>= 3.0, < 5.0)
+    kramdown (1.17.0)
+    liquid (4.0.3)
+    listen (3.2.1)
+      rb-fsevent (~> 0.10, >= 0.10.3)
+      rb-inotify (~> 0.9, >= 0.9.10)
+    mercenary (0.3.6)
+    mini_portile2 (2.4.0)
+    minima (2.5.1)
+      jekyll (>= 3.5, < 5.0)
+      jekyll-feed (~> 0.9)
+      jekyll-seo-tag (~> 2.1)
+    minitest (5.14.1)
+    multipart-post (2.1.1)
+    nokogiri (1.10.9)
+      mini_portile2 (~> 2.4.0)
+    octokit (4.18.0)
+      faraday (>= 0.9)
+      sawyer (~> 0.8.0, >= 0.5.3)
+    pathutil (0.16.2)
+      forwardable-extended (~> 2.6)
+    public_suffix (3.1.1)
+    rb-fsevent (0.10.4)
+    rb-inotify (0.10.1)
+      ffi (~> 1.0)
+    rouge (3.19.0)
+    ruby-enum (0.8.0)
+      i18n
+    rubyzip (2.3.0)
+    safe_yaml (1.0.5)
+    sass (3.7.4)
+    sawyer (0.8.2)
+      addressable (>= 2.3.5)
+      faraday (> 0.8, < 2.0)
+    terminal-table (1.8.0)
+      unicode-display_width (~> 1.1, >= 1.1.1)
+    thread_safe (0.3.6)
+    typhoeus (1.4.0)
+      ethon (>= 0.9.0)
+    tzinfo (1.2.7)
+      thread_safe (~> 0.1)
+    unicode-display_width (1.7.0)
+    zeitwerk (2.3.0)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  github-pages
+
+BUNDLED WITH
+   1.17.3
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index ef6843dd..00000000
--- a/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 Jean-François Lépine <http://blog.lepine.pro>
-
-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.
\ No newline at end of file
diff --git a/Makefile b/Makefile
deleted file mode 100644
index d28f0f1d..00000000
--- a/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-.PHONY: docker build
-
-include artifacts/Makefile
-
-# Run unit tests
-test:
-	./vendor/bin/phpunit -c phpunit.xml.dist --exclude-group binary
-
-# Compatibility check
-compatibility:
-	(docker run --rm -v `pwd`:/www --workdir=/www  php:5.6-cli find src -iname "*.php" -exec php -l {} \; |grep -v "Php7NodeTraverser.php" | grep -v "No syntax errors detected") && echo OK
-
-# Used for tag releasing
-# Don't use directly, use `make release` instead
-tag:
-	echo "New release: $(TAG)"
-	echo Releasing sources
-	sed -i -r "s/(v[0-9]+\.[0-9]+\.[0-9]+)/$(TAG)/g" \
-		.github/ISSUE_TEMPLATE/Bug_report.md \
-		.github/ISSUE_TEMPLATE/Feature_request.md \
-		src/functions.php \
-		artifacts/debian/control \
-		artifacts/bintray.json \
-		doc/installation.md
-	sed -i -r "s/([0-9]{4}\-[0-9]{2}\-[0-9]{2})/`date +%Y-%m-%d`/g" artifacts/bintray.json
-	make changelog-deb
-
-
-# Tag git with last release
-new_git_version: build tag
-	git add .github/ISSUE_TEMPLATE/Bug_report.md .github/ISSUE_TEMPLATE/Feature_request.md src/functions.php doc/installation.md artifacts/* releases/*
-	git commit -m "releasing `semver tag`"
-	git tag $(TAG) -m "releasing $(TAG)"
-	git push -u origin master
-	git push origin $(TAG)
-
-docker:
-	docker build -t phpmetrics/releasing ./artifacts/releasing
-
-# Publish new release. Usage:
-#   make tag TAG=x.y.z
-release: docker
-	docker run -it --rm --mount type=bind,source=$$SSH_AUTH_SOCK,target=/ssh-agent --env SSH_AUTH_SOCK=/ssh-agent -v ~/.gitconfig:/etc/gitconfig -v $(PWD):/app -w /app phpmetrics/releasing make new_git_version TAG=$(TAG)
diff --git a/README.md b/README.md
index 3a2b2a0e..527114d6 100644
--- a/README.md
+++ b/README.md
@@ -1,53 +1,12 @@
-# PhpMetrics
+Installation
+-----
 
-
-[![License](https://poser.pugx.org/phpmetrics/phpmetrics/license.svg)](https://packagist.org/packages/phpmetrics/phpmetrics)
-[![Latest Stable Version](https://poser.pugx.org/phpmetrics/phpmetrics/v/stable.svg)](https://packagist.org/packages/phpmetrics/phpmetrics)
-[![Slack](https://img.shields.io/badge/slack/phpmetrics-yellow.svg?logo=slack)](https://join.slack.com/t/phpmetrics/shared_invite/enQtODU3MjQ4ODAxOTM5LWRhOGFhODMxN2JmMDRmOGVjNGQ0ZjNjNzVlNDIwNzQ2MWQ2YzgxYmRlNmM5NzIzZjlhYTFjZjZhYzAyMjM0YmE)
-
-
-
-![Standard report](https://phpmetrics.github.io/website/assets/preview.png)
-
-
-<img src="https://phpmetrics.org/imagesmetrics-maintenability.png" height="80px" alt="PhpMetrics" align="left" style="margin-right:20px"/>
-
-PhpMetrics provides metrics about PHP project and classes, with beautiful and readable HTML report. 
-
-[Documentation](https://phpmetrics.github.io/website/) | [Twitter](https://twitter.com/Halleck45) | [Contributing](https://github.com/phpmetrics/PhpMetrics/blob/master/doc/contributing.md)
-
-<br/><br/>
-
-
-## Quick start
-
-Follow the [quick start guide](https://phpmetrics.github.io/website/getting-started/) to get started.
 ```bash
-# install the package as a dev dependency
-composer require phpmetrics/phpmetrics --dev
-
-# run PHPMetrics to analyze a folder and generate a report
-php ./vendor/bin/phpmetrics --report-html=myreport <folder-to-analyze>
+bundle install
 ```
 
-Then open the generated `./myreport/index.html` file in your browser. 
-
-> You can use a [configuration file](https://phpmetrics.github.io/website/configuration/) to customize 
-> the report, add options, configure rules for Continuous Integration, etc.
-
-## Metrics
-
-You'll find detailed list of metrics in [documentation](https://phpmetrics.github.io/website/metrics/), or 
-running `php ./vendor/bin/phpmetrics --metrics`
-
-## Author
+Then
 
-+ Jean-François Lépine <[@Halleck45](https://twitter.com/Halleck45)>
-
-## License
-
-See the [LICENSE](LICENSE) file.
-
-## Contributing
-
-See the [CONTRIBUTING](doc/contributing.md) file.
+```bash
+bundle exec jekyll serve
+```
\ No newline at end of file
diff --git a/SECURITY.md b/SECURITY.md
deleted file mode 100644
index cbb5456d..00000000
--- a/SECURITY.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Security Policy
-
-## Supported Versions
-
-
-
-| Version | Supported          |
-| ------- | ------------------ |
-| v2.<latest>   | :white_check_mark:                |
-| v1.x   | :x: |
-
-
-## Reporting a Vulnerability
-
-Please [open an issue](https://github.com/phpmetrics/PhpMetrics/issues) with the details to reproduce the exploit.
-
-Thanks for your help !
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 00000000..260fa707
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1,3 @@
+theme: jekyll-theme-cayman
+title: PhpMetrics, static analyzer for PHP
+description: Beautiful and readable informations about your PHP code
\ No newline at end of file
diff --git a/_site/README.md b/_site/README.md
new file mode 100644
index 00000000..527114d6
--- /dev/null
+++ b/_site/README.md
@@ -0,0 +1,12 @@
+Installation
+-----
+
+```bash
+bundle install
+```
+
+Then
+
+```bash
+bundle exec jekyll serve
+```
\ No newline at end of file
diff --git a/_site/assets/css/style.css b/_site/assets/css/style.css
new file mode 100644
index 00000000..15f265e0
--- /dev/null
+++ b/_site/assets/css/style.css
@@ -0,0 +1,319 @@
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+/** 1. Set default font family to sans-serif. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */
+@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,700");
+html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ }
+
+/** Remove default margin. */
+body { margin: 0; }
+
+/* HTML5 display definitions ========================================================================== */
+/** Correct `block` display not defined for any HTML5 element in IE 8/9. Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox. Correct `block` display not defined for `main` in IE 11. */
+article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary { display: block; }
+
+/** 1. Correct `inline-block` display not defined in IE 8/9. 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. */
+audio, canvas, progress, video { display: inline-block; /* 1 */ vertical-align: baseline; /* 2 */ }
+
+/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */
+audio:not([controls]) { display: none; height: 0; }
+
+/** Address `[hidden]` styling not present in IE 8/9/10. Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. */
+[hidden], template { display: none; }
+
+/* Links ========================================================================== */
+/** Remove the gray background color from active links in IE 10. */
+a { background-color: transparent; }
+
+/** Improve readability when focused and also mouse hovered in all browsers. */
+a:active, a:hover { outline: 0; }
+
+/* Text-level semantics ========================================================================== */
+/** Address styling not present in IE 8/9/10/11, Safari, and Chrome. */
+abbr[title] { border-bottom: 1px dotted; }
+
+/** Address style set to `bolder` in Firefox 4+, Safari, and Chrome. */
+b, strong { font-weight: bold; }
+
+/** Address styling not present in Safari and Chrome. */
+dfn { font-style: italic; }
+
+/** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari, and Chrome. */
+h1 { font-size: 2em; margin: 0.67em 0; }
+
+/** Address styling not present in IE 8/9. */
+mark { background: #ff0; color: #000; }
+
+/** Address inconsistent and variable font size in all browsers. */
+small { font-size: 80%; }
+
+/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */
+sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+
+sup { top: -0.5em; }
+
+sub { bottom: -0.25em; }
+
+/* Embedded content ========================================================================== */
+/** Remove border when inside `a` element in IE 8/9/10. */
+img { border: 0; }
+
+/** Correct overflow not hidden in IE 9/10/11. */
+svg:not(:root) { overflow: hidden; }
+
+/* Grouping content ========================================================================== */
+/** Address margin not present in IE 8/9 and Safari. */
+figure { margin: 1em 40px; }
+
+/** Address differences between Firefox and other browsers. */
+hr { box-sizing: content-box; height: 0; }
+
+/** Contain overflow in all browsers. */
+pre { overflow: auto; }
+
+/** Address odd `em`-unit font size rendering in all browsers. */
+code, kbd, pre, samp { font-family: monospace, monospace; font-size: 1em; }
+
+/* Forms ========================================================================== */
+/** Known limitation: by default, Chrome and Safari on OS X allow very limited styling of `select`, unless a `border` property is set. */
+/** 1. Correct color not being inherited. Known issue: affects color of disabled elements. 2. Correct font properties not being inherited. 3. Address margins set differently in Firefox 4+, Safari, and Chrome. */
+button, input, optgroup, select, textarea { color: inherit; /* 1 */ font: inherit; /* 2 */ margin: 0; /* 3 */ }
+
+/** Address `overflow` set to `hidden` in IE 8/9/10/11. */
+button { overflow: visible; }
+
+/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. Correct `select` style inheritance in Firefox. */
+button, select { text-transform: none; }
+
+/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */
+button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ }
+
+/** Re-set default cursor for disabled elements. */
+button[disabled], html input[disabled] { cursor: default; }
+
+/** Remove inner padding and border in Firefox 4+. */
+button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
+
+/** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */
+input { line-height: normal; }
+
+/** It's recommended that you don't attempt to style these elements. Firefox's implementation doesn't respect box-sizing, padding, or width.  1. Address box sizing set to `content-box` in IE 8/9/10. 2. Remove excess padding in IE 8/9/10. */
+input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ }
+
+/** Fix the cursor style for Chrome's increment/decrement buttons. For certain `font-size` values of the `input`, it causes the cursor style of the decrement button to change from `default` to `text`. */
+input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { height: auto; }
+
+/** 1. Address `appearance` set to `searchfield` in Safari and Chrome. 2. Address `box-sizing` set to `border-box` in Safari and Chrome (include `-moz` to future-proof). */
+input[type="search"] { -webkit-appearance: textfield; /* 1 */ /* 2 */ box-sizing: content-box; }
+
+/** Remove inner padding and search cancel button in Safari and Chrome on OS X. Safari (but not Chrome) clips the cancel button when the search input has padding (and `textfield` appearance). */
+input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
+
+/** Define consistent border, margin, and padding. */
+fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
+
+/** 1. Correct `color` not being inherited in IE 8/9/10/11. 2. Remove padding so people aren't caught out if they zero out fieldsets. */
+legend { border: 0; /* 1 */ padding: 0; /* 2 */ }
+
+/** Remove default vertical scrollbar in IE 8/9/10/11. */
+textarea { overflow: auto; }
+
+/** Don't inherit the `font-weight` (applied by a rule above). NOTE: the default cannot safely be changed in Chrome and Safari on OS X. */
+optgroup { font-weight: bold; }
+
+/* Tables ========================================================================== */
+/** Remove most spacing between table cells. */
+table { border-collapse: collapse; border-spacing: 0; }
+
+td, th { padding: 0; }
+
+.highlight table td { padding: 5px; }
+
+.highlight table pre { margin: 0; }
+
+.highlight .cm { color: #999988; font-style: italic; }
+
+.highlight .cp { color: #999999; font-weight: bold; }
+
+.highlight .c1 { color: #999988; font-style: italic; }
+
+.highlight .cs { color: #999999; font-weight: bold; font-style: italic; }
+
+.highlight .c, .highlight .cd { color: #999988; font-style: italic; }
+
+.highlight .err { color: #a61717; background-color: #e3d2d2; }
+
+.highlight .gd { color: #000000; background-color: #ffdddd; }
+
+.highlight .ge { color: #000000; font-style: italic; }
+
+.highlight .gr { color: #aa0000; }
+
+.highlight .gh { color: #999999; }
+
+.highlight .gi { color: #000000; background-color: #ddffdd; }
+
+.highlight .go { color: #888888; }
+
+.highlight .gp { color: #555555; }
+
+.highlight .gs { font-weight: bold; }
+
+.highlight .gu { color: #aaaaaa; }
+
+.highlight .gt { color: #aa0000; }
+
+.highlight .kc { color: #000000; font-weight: bold; }
+
+.highlight .kd { color: #000000; font-weight: bold; }
+
+.highlight .kn { color: #000000; font-weight: bold; }
+
+.highlight .kp { color: #000000; font-weight: bold; }
+
+.highlight .kr { color: #000000; font-weight: bold; }
+
+.highlight .kt { color: #445588; font-weight: bold; }
+
+.highlight .k, .highlight .kv { color: #000000; font-weight: bold; }
+
+.highlight .mf { color: #009999; }
+
+.highlight .mh { color: #009999; }
+
+.highlight .il { color: #009999; }
+
+.highlight .mi { color: #009999; }
+
+.highlight .mo { color: #009999; }
+
+.highlight .m, .highlight .mb, .highlight .mx { color: #009999; }
+
+.highlight .sb { color: #d14; }
+
+.highlight .sc { color: #d14; }
+
+.highlight .sd { color: #d14; }
+
+.highlight .s2 { color: #d14; }
+
+.highlight .se { color: #d14; }
+
+.highlight .sh { color: #d14; }
+
+.highlight .si { color: #d14; }
+
+.highlight .sx { color: #d14; }
+
+.highlight .sr { color: #009926; }
+
+.highlight .s1 { color: #d14; }
+
+.highlight .ss { color: #990073; }
+
+.highlight .s { color: #d14; }
+
+.highlight .na { color: #008080; }
+
+.highlight .bp { color: #999999; }
+
+.highlight .nb { color: #0086B3; }
+
+.highlight .nc { color: #445588; font-weight: bold; }
+
+.highlight .no { color: #008080; }
+
+.highlight .nd { color: #3c5d5d; font-weight: bold; }
+
+.highlight .ni { color: #800080; }
+
+.highlight .ne { color: #990000; font-weight: bold; }
+
+.highlight .nf { color: #990000; font-weight: bold; }
+
+.highlight .nl { color: #990000; font-weight: bold; }
+
+.highlight .nn { color: #555555; }
+
+.highlight .nt { color: #000080; }
+
+.highlight .vc { color: #008080; }
+
+.highlight .vg { color: #008080; }
+
+.highlight .vi { color: #008080; }
+
+.highlight .nv { color: #008080; }
+
+.highlight .ow { color: #000000; font-weight: bold; }
+
+.highlight .o { color: #000000; font-weight: bold; }
+
+.highlight .w { color: #bbbbbb; }
+
+.highlight { background-color: #f8f8f8; }
+
+* { box-sizing: border-box; }
+
+body { padding: 0; margin: 0; font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.5; color: #606c71; }
+
+a { color: #1e6bb8; text-decoration: none; }
+a:hover { text-decoration: underline; }
+
+.btn { display: inline-block; margin-bottom: 1rem; color: rgba(255, 255, 255, 0.7); background-color: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.2); border-style: solid; border-width: 1px; border-radius: 0.3rem; transition: color 0.2s, background-color 0.2s, border-color 0.2s; }
+.btn:hover { color: rgba(255, 255, 255, 0.8); text-decoration: none; background-color: rgba(255, 255, 255, 0.2); border-color: rgba(255, 255, 255, 0.3); }
+.btn + .btn { margin-left: 1rem; }
+@media screen and (min-width: 64em) { .btn { padding: 0.75rem 1rem; } }
+@media screen and (min-width: 42em) and (max-width: 64em) { .btn { padding: 0.6rem 0.9rem; font-size: 0.9rem; } }
+@media screen and (max-width: 42em) { .btn { display: block; width: 100%; padding: 0.75rem; font-size: 0.9rem; }
+  .btn + .btn { margin-top: 1rem; margin-left: 0; } }
+
+.page-header { color: #fff; text-align: center; background-color: #159957; background-image: linear-gradient(120deg, #155799, #159957); }
+@media screen and (min-width: 64em) { .page-header { padding: 5rem 6rem; } }
+@media screen and (min-width: 42em) and (max-width: 64em) { .page-header { padding: 3rem 4rem; } }
+@media screen and (max-width: 42em) { .page-header { padding: 2rem 1rem; } }
+
+.project-name { margin-top: 0; margin-bottom: 0.1rem; }
+@media screen and (min-width: 64em) { .project-name { font-size: 3.25rem; } }
+@media screen and (min-width: 42em) and (max-width: 64em) { .project-name { font-size: 2.25rem; } }
+@media screen and (max-width: 42em) { .project-name { font-size: 1.75rem; } }
+
+.project-tagline { margin-bottom: 2rem; font-weight: normal; opacity: 0.7; }
+@media screen and (min-width: 64em) { .project-tagline { font-size: 1.25rem; } }
+@media screen and (min-width: 42em) and (max-width: 64em) { .project-tagline { font-size: 1.15rem; } }
+@media screen and (max-width: 42em) { .project-tagline { font-size: 1rem; } }
+
+.main-content { word-wrap: break-word; }
+.main-content :first-child { margin-top: 0; }
+@media screen and (min-width: 64em) { .main-content { max-width: 64rem; padding: 2rem 6rem; margin: 0 auto; font-size: 1.1rem; } }
+@media screen and (min-width: 42em) and (max-width: 64em) { .main-content { padding: 2rem 4rem; font-size: 1.1rem; } }
+@media screen and (max-width: 42em) { .main-content { padding: 2rem 1rem; font-size: 1rem; } }
+.main-content img { max-width: 100%; }
+.main-content h1, .main-content h2, .main-content h3, .main-content h4, .main-content h5, .main-content h6 { margin-top: 2rem; margin-bottom: 1rem; font-weight: normal; color: #159957; }
+.main-content p { margin-bottom: 1em; }
+.main-content code { padding: 2px 4px; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 0.9rem; color: #567482; background-color: #f3f6fa; border-radius: 0.3rem; }
+.main-content pre { padding: 0.8rem; margin-top: 0; margin-bottom: 1rem; font: 1rem Consolas, "Liberation Mono", Menlo, Courier, monospace; color: #567482; word-wrap: normal; background-color: #f3f6fa; border: solid 1px #dce6f0; border-radius: 0.3rem; }
+.main-content pre > code { padding: 0; margin: 0; font-size: 0.9rem; color: #567482; word-break: normal; white-space: pre; background: transparent; border: 0; }
+.main-content .highlight { margin-bottom: 1rem; }
+.main-content .highlight pre { margin-bottom: 0; word-break: normal; }
+.main-content .highlight pre, .main-content pre { padding: 0.8rem; overflow: auto; font-size: 0.9rem; line-height: 1.45; border-radius: 0.3rem; -webkit-overflow-scrolling: touch; }
+.main-content pre code, .main-content pre tt { display: inline; max-width: initial; padding: 0; margin: 0; overflow: initial; line-height: inherit; word-wrap: normal; background-color: transparent; border: 0; }
+.main-content pre code:before, .main-content pre code:after, .main-content pre tt:before, .main-content pre tt:after { content: normal; }
+.main-content ul, .main-content ol { margin-top: 0; }
+.main-content blockquote { padding: 0 1rem; margin-left: 0; color: #819198; border-left: 0.3rem solid #dce6f0; }
+.main-content blockquote > :first-child { margin-top: 0; }
+.main-content blockquote > :last-child { margin-bottom: 0; }
+.main-content table { display: block; width: 100%; overflow: auto; word-break: normal; word-break: keep-all; -webkit-overflow-scrolling: touch; }
+.main-content table th { font-weight: bold; }
+.main-content table th, .main-content table td { padding: 0.5rem 1rem; border: 1px solid #e9ebec; }
+.main-content dl { padding: 0; }
+.main-content dl dt { padding: 0; margin-top: 1rem; font-size: 1rem; font-weight: bold; }
+.main-content dl dd { padding: 0; margin-bottom: 1rem; }
+.main-content hr { height: 2px; padding: 0; margin: 1rem 0; background-color: #eff0f1; border: 0; }
+
+.site-footer { padding-top: 2rem; margin-top: 2rem; border-top: solid 1px #eff0f1; }
+@media screen and (min-width: 64em) { .site-footer { font-size: 1rem; } }
+@media screen and (min-width: 42em) and (max-width: 64em) { .site-footer { font-size: 1rem; } }
+@media screen and (max-width: 42em) { .site-footer { font-size: 0.9rem; } }
+
+.site-footer-owner { display: block; font-weight: bold; }
+
+.site-footer-credits { color: #819198; }
diff --git a/_site/assets/img/phpmetrics-overview.png b/_site/assets/img/phpmetrics-overview.png
new file mode 100644
index 00000000..f9b2e25c
Binary files /dev/null and b/_site/assets/img/phpmetrics-overview.png differ
diff --git a/_site/assets/img/phpmetrics-symfony.png b/_site/assets/img/phpmetrics-symfony.png
new file mode 100644
index 00000000..c223b333
Binary files /dev/null and b/_site/assets/img/phpmetrics-symfony.png differ
diff --git a/_site/index.html b/_site/index.html
new file mode 100644
index 00000000..9679184d
--- /dev/null
+++ b/_site/index.html
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<html lang="en-US">
+  <head>
+    <meta charset="UTF-8">
+
+<!-- Begin Jekyll SEO tag v2.6.1 -->
+<title>Static analysis must be understandable | PhpMetrics, static analyzer for PHP</title>
+<meta name="generator" content="Jekyll v3.8.7" />
+<meta property="og:title" content="Static analysis must be understandable" />
+<meta property="og:locale" content="en_US" />
+<meta name="description" content="Beautiful and readable informations about your PHP code" />
+<meta property="og:description" content="Beautiful and readable informations about your PHP code" />
+<link rel="canonical" href="http://localhost:4000/" />
+<meta property="og:url" content="http://localhost:4000/" />
+<meta property="og:site_name" content="PhpMetrics, static analyzer for PHP" />
+<script type="application/ld+json">
+{"@type":"WebSite","headline":"Static analysis must be understandable","url":"http://localhost:4000/","name":"PhpMetrics, static analyzer for PHP","description":"Beautiful and readable informations about your PHP code","@context":"https://schema.org"}</script>
+<!-- End Jekyll SEO tag -->
+
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="theme-color" content="#157878">
+    <link rel="stylesheet" href="/assets/css/style.css?v=8d3e43e04cb784f223c862472e4ab4b3f71856e7">
+  </head>
+  <body>
+    <section class="page-header">
+      <h1 class="project-name">PhpMetrics, static analyzer for PHP</h1>
+      <h2 class="project-tagline">Beautiful and readable informations about your PHP code</h2>
+      
+        <a href="https://github.com/Halleck45/tmp-website" class="btn">View on GitHub</a>
+      
+      
+    </section>
+
+    <section class="main-content">
+      <h2 id="static-analysis-must-be-understandable">Static analysis must be understandable</h2>
+
+<p>PhpMetrics analyze your PHP code and provides HTML, JSON, CSV… reports about complexity, dependencies, coupling, violations, and more !</p>
+
+<p><img src="/assets/img/phpmetrics-overview.png" alt="PhpMetrics HTML report" /></p>
+
+<h2 id="quick-start">Quick start</h2>
+
+<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>composer require phpmetrics/phpmetrics --dev
+php ./vendor/bin/phpmetrics --report-html=myreport &lt;folder-to-analyze&gt;
+</code></pre></div></div>
+
+<p>Then open the generated <code class="language-plaintext highlighter-rouge">./myreport/index.html</code> file in your browser.</p>
+
+<h2 id="configure">Configure</h2>
+
+<p>Use the <code class="language-plaintext highlighter-rouge">--config=&lt;file&gt;.json</code> option. For example:</p>
+
+<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
+    <span class="dl">"</span><span class="s2">includes</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span>   <span class="c1">// directory and files to analyze, relative to config file directory </span>
+        <span class="dl">"</span><span class="s2">src</span><span class="dl">"</span>
+    <span class="p">],</span>
+    <span class="dl">"</span><span class="s2">exclude</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span>    <span class="c1">// regex of files (or directory) to exclude from analyze</span>
+      <span class="dl">"</span><span class="s2">tests</span><span class="dl">"</span>
+    <span class="p">],</span>
+    <span class="dl">"</span><span class="s2">report</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>     <span class="c1">// list of reports to generate (html, json, csv or violation)</span>
+        <span class="dl">"</span><span class="s2">html</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">/tmp/report/</span><span class="dl">"</span><span class="p">,</span>             <span class="c1">// destination directory of HTML report </span>
+        <span class="dl">"</span><span class="s2">csv</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">/tmp/report.csv</span><span class="dl">"</span><span class="p">,</span>           <span class="c1">// destination file for CSV report</span>
+        <span class="dl">"</span><span class="s2">json</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">/tmp/report.json</span><span class="dl">"</span><span class="p">,</span>         <span class="c1">// destination file for JSON report</span>
+        <span class="dl">"</span><span class="s2">violations</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">/tmp/violations.xml</span><span class="dl">"</span> <span class="c1">// destination file for XML violations report</span>
+    <span class="p">},</span>
+    <span class="dl">"</span><span class="s2">groups</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span>     <span class="c1">// "layers" of code. You can group your classes and packages by regex, </span>
+                    <span class="c1">// to visualise specific HTML report for each of them</span>
+        <span class="p">{</span>
+            <span class="dl">"</span><span class="s2">name</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Component</span><span class="dl">"</span><span class="p">,</span>      <span class="c1">// name of the layer</span>
+            <span class="dl">"</span><span class="s2">match</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">!component!i</span><span class="dl">"</span>   <span class="c1">// regular expression used to match the group (based on </span>
+                                      <span class="c1">// the name of the fully qualified class name)</span>
+                                      <span class="c1">// remember to double escape (for json, then for regex): </span>
+                                      <span class="c1">// set "!\\\\MyPackage\\\\!" if you want to capture  </span>
+                                      <span class="c1">// expression "\MyPackage\"</span>
+        <span class="p">},</span>
+        <span class="p">{</span>
+            <span class="dl">"</span><span class="s2">name</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Example</span><span class="dl">"</span><span class="p">,</span>
+            <span class="dl">"</span><span class="s2">match</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">!example!</span><span class="dl">"</span>
+        <span class="p">}</span>
+    <span class="p">],</span>
+    <span class="dl">"</span><span class="s2">plugins</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
+        <span class="dl">"</span><span class="s2">git</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
+            <span class="dl">"</span><span class="s2">binary</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">git</span><span class="dl">"</span>           <span class="c1">// if defined, runs git analyze</span>
+        <span class="p">},</span>
+        <span class="dl">"</span><span class="s2">junit</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
+            <span class="dl">"</span><span class="s2">file</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">/tmp/junit.xml</span><span class="dl">"</span>  <span class="c1">// if defined, JUnit report file will be analyzed            </span>
+        <span class="p">}</span>
+    <span class="p">}</span>
+    <span class="dl">"</span><span class="s2">extensions</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span> <span class="dl">"</span><span class="s2">php</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">php8</span><span class="dl">"</span> <span class="p">],</span>        <span class="c1">// default: ["php", "inc"]</span>
+<span class="p">}</span>
+</code></pre></div></div>
+
+<h2 id="more">More</h2>
+
+<p>If want, you can <a href="https://github.com/phpmetrics/PhpMetrics/blob/master/doc/installation.md">install</a> PhpMetrics globally with your favorite package manager (APT, Brew…). You can also visit our <a href="http://www.phpmetrics.org/documentation/index.html">documentation</a>.</p>
+
+<p>You can integrate PhpMetrics directly <a href="https://github.com/phpmetrics/PhpMetricsCollectorBundle">in the debug bar of your Symgony project</a>, 
+or <a href="https://github.com/phpmetrics/PhpMetrics-jetbrains">in PhpStorm</a>.</p>
+
+<p><img src="/assets/img/phpmetrics-symfony.png" alt="PhpMetrics Symfony" /></p>
+
+<h2 id="metrics-list">Metrics list</h2>
+
+<p>See the <a href="https://github.com/phpmetrics/PhpMetrics/blob/master/doc/metrics.md">metrics</a> file.</p>
+
+<h2 id="author">Author</h2>
+
+<p>PhpMetrics is developed by Jean-François Lépine &lt;<a href="https://twitter.com/Halleck45">@Halleck45</a>&gt;, with the help of 
+<a href="https://github.com/phpmetrics/PhpMetrics/graphs/contributors">dozens of awesome contributors</a></p>
+
+<h2 id="license">License</h2>
+
+<p>PhpMetrics is free and Open Source under the <a href="https://github.com/phpmetrics/PhpMetrics/LICENSE">MIT LICENSE</a>.</p>
+
+
+      <footer class="site-footer">
+        
+          <span class="site-footer-owner"><a href="https://github.com/Halleck45/tmp-website">tmp-website</a> is maintained by <a href="https://github.com/Halleck45">Halleck45</a>.</span>
+        
+        <span class="site-footer-credits">This page was generated by <a href="https://pages.github.com">GitHub Pages</a>.</span>
+      </footer>
+    </section>
+
+    
+  </body>
+</html>
diff --git a/_site/index.md b/_site/index.md
new file mode 100644
index 00000000..36f374d8
--- /dev/null
+++ b/_site/index.md
@@ -0,0 +1,81 @@
+## Static analysis must be understandable
+
+PhpMetrics analyze your PHP code and provides HTML, JSON, CSV... reports about complexity, dependencies, coupling, violations, and more !
+
+![PhpMetrics HTML report](assets/img/phpmetrics-overview.png)
+
+
+## Quick start
+
+    composer require phpmetrics/phpmetrics --dev
+    php ./vendor/bin/phpmetrics --report-html=myreport <folder-to-analyze>
+    
+Then open the generated `./myreport/index.html` file in your browser. 
+
+## Configure
+
+Use the `--config=<file>.json` option. For example:
+
+```js
+{
+    "includes": [   // directory and files to analyze, relative to config file directory 
+        "src"
+    ],
+    "exclude": [    // regex of files (or directory) to exclude from analyze
+      "tests"
+    ],
+    "report": {     // list of reports to generate (html, json, csv or violation)
+        "html": "/tmp/report/",             // destination directory of HTML report 
+        "csv": "/tmp/report.csv",           // destination file for CSV report
+        "json": "/tmp/report.json",         // destination file for JSON report
+        "violations": "/tmp/violations.xml" // destination file for XML violations report
+    },
+    "groups": [     // "layers" of code. You can group your classes and packages by regex, 
+                    // to visualise specific HTML report for each of them
+        {
+            "name": "Component",      // name of the layer
+            "match": "!component!i"   // regular expression used to match the group (based on 
+                                      // the name of the fully qualified class name)
+                                      // remember to double escape (for json, then for regex): 
+                                      // set "!\\\\MyPackage\\\\!" if you want to capture  
+                                      // expression "\MyPackage\"
+        },
+        {
+            "name": "Example",
+            "match": "!example!"
+        }
+    ],
+    "plugins": {
+        "git": {
+            "binary": "git"           // if defined, runs git analyze
+        },
+        "junit": {
+            "file": "/tmp/junit.xml"  // if defined, JUnit report file will be analyzed            
+        }
+    }
+    "extensions": [ "php", "php8" ],        // default: ["php", "inc"]
+}
+```
+
+## More
+
+If want, you can [install](https://github.com/phpmetrics/PhpMetrics/blob/master/doc/installation.md) PhpMetrics globally with your favorite package manager (APT, Brew...). You can also visit our [documentation](http://www.phpmetrics.org/documentation/index.html).
+
+You can integrate PhpMetrics directly [in the debug bar of your Symgony project](https://github.com/phpmetrics/PhpMetricsCollectorBundle), 
+or [in PhpStorm](https://github.com/phpmetrics/PhpMetrics-jetbrains).
+
+![PhpMetrics Symfony](assets/img/phpmetrics-symfony.png)
+
+
+## Metrics list
+
+See the [metrics](https://github.com/phpmetrics/PhpMetrics/blob/master/doc/metrics.md) file.
+
+## Author
+
+PhpMetrics is developed by Jean-François Lépine <[@Halleck45](https://twitter.com/Halleck45)>, with the help of 
+[dozens of awesome contributors](https://github.com/phpmetrics/PhpMetrics/graphs/contributors)
+
+## License
+
+PhpMetrics is free and Open Source under the [MIT LICENSE](https://github.com/phpmetrics/PhpMetrics/LICENSE).
\ No newline at end of file
diff --git a/artifacts/Makefile b/artifacts/Makefile
deleted file mode 100644
index c7b6f873..00000000
--- a/artifacts/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-CURRENT_TAG=$(shell git tag |tail -n 2 |head -n 1)
-PREVIOUS_TAG=$(shell git tag |tail -n 1)
-BUILD_DIR=releases
-
-include artifacts/phar/Makefile
-include artifacts/debian/Makefile
-include artifacts/standalone/Makefile
-
-prepare-build:
-	@# Disable the deletion of all releases packages as task build-debian is disabled.
-	@#rm -Rf ${BUILD_DIR}
-	@#mkdir ${BUILD_DIR}
-	@# Only remove the phar that must be replaced by the new release.
-	@rm -f ${BUILD_DIR}/phpmetrics.phar
-
-build: prepare-build build-phar build-deb build-standalone
-	./vendor/bin/phpunit -c phpunit.xml.dist --group=binary &&	echo "Done"
-
diff --git a/artifacts/README.md b/artifacts/README.md
deleted file mode 100644
index 5d513d56..00000000
--- a/artifacts/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Artifacts
-
-This folder contains tools for generating and publishing artifacts (.phar, .deb...)
-
-Artifacts are stored at Bintray
-
-## Contributing
-
-Each type of artifact MUST be in a specific folder. For example, phar artifact goes in `./phar` folder.
-
-Each folder MUST have a Makefile. This Makefile should be included in `artifacts/Makefile`.
-
-All artifacts MUST be published to Bintray with the travis-ci build. Please check the `./artifacts/bintray.json` file.
diff --git a/artifacts/bintray.json b/artifacts/bintray.json
deleted file mode 100644
index b12cda5d..00000000
--- a/artifacts/bintray.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-  "package": {
-    "name": "phpmetrics",
-    "repo": "phpmetrics",
-    "subject": "phpmetrics",
-    "desc": "Static analyzer for PHP",
-    "website_url": "http://www.phpmetrics.org",
-    "issue_tracker_url": "https://github.com/phpmetrics/phpmetrics/issues",
-    "vcs_url": "https://github.com/phpmetrics/phpmetrics.git",
-    "licenses": ["MIT"]
-  },
-  "version": {
-    "name": "v2.9.0",
-    "desc": "Latest version of PhpMetrics",
-    "released": "2025-07-07",
-    "vcs_tag": "v2.9.0",
-    "attributes": [],
-    "gpgSign": false
-  },
-  "files":
-  [
-    {"includePattern": "build/(phpmetrics.*)", "uploadPattern": "/$1" }
-  ],
-  "publish": true
-}
\ No newline at end of file
diff --git a/artifacts/debian/.debhelper/generated/phpmetrics/dh_installchangelogs.dch.trimmed b/artifacts/debian/.debhelper/generated/phpmetrics/dh_installchangelogs.dch.trimmed
deleted file mode 100644
index e0f366a4..00000000
--- a/artifacts/debian/.debhelper/generated/phpmetrics/dh_installchangelogs.dch.trimmed
+++ /dev/null
@@ -1,579 +0,0 @@
-phpmetrics (3.0.0rc7) unstable; urgency=low
-   * Prepare v3. WIP. 
-   * Rebase on master (current 2.8.1) with adaptation for 3.x. Coverage got down. WIP. 
-   * Add some missing unit test. Coverage is still not back to previous state. WIP. 
-   * Continue to add up some coverage. WIP. 
-   * Set the coverage back to previous state. WIP: work on uncovered files. 
-   * Remove Git related metrics. 
-   * Remove PHPUnit metrics checks. Start but stop reviewing Html Reporter (too complex). File functions.php removed. 
-   * Fix some PHPStan issues. WIP. 
-   * Apply HTML error fixes from #477. 
-   * Update dependencies and fix unit tests. 
-   * Update QA and dev-dependencies. 
-   * Disable PHP Infection as some mutants are breaking analyse. 
-   * Add multiple locations for composer-autoloading. 
-   * Do not oblige usage of YAML extention as configuration can be set in another way. 
-   * Fix HTML rednering. 
-   * Fix HTML rednering. 
-   * Ignore PHP Attributes in detecting getter/setters. 
-   * Keep only composer installation to simplify tool usage. 
-   * Remove PageRank metric. 
-   * Get rid of more than 150 PHPStan errors. 
-   * Add cache and baselines on qa tools. 
-   * Dynamically manage version number via .semver file. Also minor fixes. 
-   * Rebase on master + update dependencies + improve QA. PHPUnit 10 is now used. 
-   * Use env variable to share volume to mount with DockerInDocker. 
-   * Adapt the releasing process with the current v3 + minor fixes. 
-   * Decouple file system operations to split responsibilities. 
-   * Complete the unit tests related to file system. 
-   * Kill some mutants. 
-   * Add a copy function to manage the copy of single files. 
-   * Fix tag management on release + recursive copy for HTML rendering. 
-   * Remove Clusterize as only used for removed Class Rank and remove useless logos. 
-   * Fix SVG icons on sidebar. 
-   * Fix resolving of FQCN when inferring externals. 
-   * Fix parsing issue on LComVisitor when code to parse contains variable property fetch. 
-   * Fix error when HTML report is not requested. 
-   * Add missing favicon + add report date in title. 
-   * Improve CSS + button to download the bubble graph. 
-   * Update minimum versions of dependencies for composer.json. 
-   * Fix unit tests for ExternalVisitor. 
-   * Remove example and management of plugins (JUnit). 
-   * Remove useless metric nbGetters/nbSetters. 
-   * Prepare changelog fro release 3.0.0-rc1. 
-   * releasing v3.0.0rc1 
-   * Fix #491: add shell command in case PHP command does not work for some OS in documenation. 
-   * Fix Fatal error when analyzing snippets like `$a->$b()` or `$c()`. 
-   * Prepare release 3.0.0-rc2. 
-   * releasing v3.0.0rc2 
-   * Fix special version label that were not taken into account on bintray. 
-   * releasing v3.0.0rc2 
-   * Fix possible parsing error + upgrade to PHPUnit 10.1. 
-   * Fix violations reporter which was trying to rely on Violations directly, rather than ViolationsHandler 
-   * Merge pull request #495 from Tithugues/fix/report-violations 
-   * SystemComplexityVisitor fix for calling methods with the same name on different objects 
-   * releasing v3.0.0rc3 
-   * Upgrade deps + add ccn value by method. Need to fnd how to display it on HTML reports now. 
-   * Merge pull request #497 from andrii-pukhalevych/patch1 
-   * Add elegant way to display CCN values for methods. 
-   * QA review: fix PHPStan/Psalm/PHPUnit/Qodana errors. 
-   * Merge pull request #498 from phpmetrics/add-ccn-value-to-every-class-method 
-   * releasing v3.0.0rc4 
-   * Fix URLs and search configuration usage. 
-   * Manage better description inference for stable dependencies principle. 
-   * Merge pull request #502 from phpmetrics/fix/501 
-   * Fix some unit tests + releasing process. 
-   * releasing v3.0.0rc5 
-   * Upgrade to PhpParser v5 + adapt code. Remove Qodana. Upgrade to PHPUnit 10.5 
-   * Merge pull request #504 from phpmetrics/fix/php-parser-v5 
-   * releasing v3.0.0rc6 
-   * Fix numeric version array key in Composer\Packagist.php - if there is an integer string set as a key of associative array, it will automatically be converted to integer, which causes the call of `ltrim` to fail, because of `declare(strict_types=1)` configuration 
-   * Merge pull request #509 from Klemo1997/fix/packagist-array-key-type-error 
-   * fix typo 
-   * Merge pull request #513 from YAhiru/fix-typo 
-   * feat: add OpenMetrics report 
-   * Merge pull request #512 from alanpoulain/feat-openmetrics 
-   * test: add OpenMetrics SummaryWriter test 
-   * Merge pull request #514 from alanpoulain/test-openmetrics-summary-writer 
-   * Make sure OpenMetrics format is available and upgrade QA. 
-   * Merge pull request #515 from phpmetrics/update/3.x-qa 
-   * releasing v3.0.0rc7 
-   * Updated tests in order to be executed in PHP 8.4, and supports Php 8.4 
-   * fixed issue introduced by phpcs, and removed phpcs 
-   * added build script for standalone build 
-   * fixed CI 
-   * Merge pull request #524 from phpmetrics/php84-standalone 
-   * #518 test about deferencing new without parenthesis in PHP 8.4 
-   * updated build 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Mon, 07 Jul 2025 13:56:00 +0200
-
-phpmetrics (3.0.0rc7) unstable; urgency=low
-   * Prepare v3. WIP. 
-   * Rebase on master (current 2.8.1) with adaptation for 3.x. Coverage got down. WIP. 
-   * Add some missing unit test. Coverage is still not back to previous state. WIP. 
-   * Continue to add up some coverage. WIP. 
-   * Set the coverage back to previous state. WIP: work on uncovered files. 
-   * Remove Git related metrics. 
-   * Remove PHPUnit metrics checks. Start but stop reviewing Html Reporter (too complex). File functions.php removed. 
-   * Fix some PHPStan issues. WIP. 
-   * Apply HTML error fixes from #477. 
-   * Update dependencies and fix unit tests. 
-   * Update QA and dev-dependencies. 
-   * Disable PHP Infection as some mutants are breaking analyse. 
-   * Add multiple locations for composer-autoloading. 
-   * Do not oblige usage of YAML extention as configuration can be set in another way. 
-   * Fix HTML rednering. 
-   * Fix HTML rednering. 
-   * Ignore PHP Attributes in detecting getter/setters. 
-   * Keep only composer installation to simplify tool usage. 
-   * Remove PageRank metric. 
-   * Get rid of more than 150 PHPStan errors. 
-   * Add cache and baselines on qa tools. 
-   * Dynamically manage version number via .semver file. Also minor fixes. 
-   * Rebase on master + update dependencies + improve QA. PHPUnit 10 is now used. 
-   * Use env variable to share volume to mount with DockerInDocker. 
-   * Adapt the releasing process with the current v3 + minor fixes. 
-   * Decouple file system operations to split responsibilities. 
-   * Complete the unit tests related to file system. 
-   * Kill some mutants. 
-   * Add a copy function to manage the copy of single files. 
-   * Fix tag management on release + recursive copy for HTML rendering. 
-   * Remove Clusterize as only used for removed Class Rank and remove useless logos. 
-   * Fix SVG icons on sidebar. 
-   * Fix resolving of FQCN when inferring externals. 
-   * Fix parsing issue on LComVisitor when code to parse contains variable property fetch. 
-   * Fix error when HTML report is not requested. 
-   * Add missing favicon + add report date in title. 
-   * Improve CSS + button to download the bubble graph. 
-   * Update minimum versions of dependencies for composer.json. 
-   * Fix unit tests for ExternalVisitor. 
-   * Remove example and management of plugins (JUnit). 
-   * Remove useless metric nbGetters/nbSetters. 
-   * Prepare changelog fro release 3.0.0-rc1. 
-   * releasing v3.0.0rc1 
-   * Fix #491: add shell command in case PHP command does not work for some OS in documenation. 
-   * Fix Fatal error when analyzing snippets like `$a->$b()` or `$c()`. 
-   * Prepare release 3.0.0-rc2. 
-   * releasing v3.0.0rc2 
-   * Fix special version label that were not taken into account on bintray. 
-   * releasing v3.0.0rc2 
-   * Fix possible parsing error + upgrade to PHPUnit 10.1. 
-   * Fix violations reporter which was trying to rely on Violations directly, rather than ViolationsHandler 
-   * Merge pull request #495 from Tithugues/fix/report-violations 
-   * SystemComplexityVisitor fix for calling methods with the same name on different objects 
-   * releasing v3.0.0rc3 
-   * Upgrade deps + add ccn value by method. Need to fnd how to display it on HTML reports now. 
-   * Merge pull request #497 from andrii-pukhalevych/patch1 
-   * Add elegant way to display CCN values for methods. 
-   * QA review: fix PHPStan/Psalm/PHPUnit/Qodana errors. 
-   * Merge pull request #498 from phpmetrics/add-ccn-value-to-every-class-method 
-   * releasing v3.0.0rc4 
-   * Fix URLs and search configuration usage. 
-   * Manage better description inference for stable dependencies principle. 
-   * Merge pull request #502 from phpmetrics/fix/501 
-   * Fix some unit tests + releasing process. 
-   * releasing v3.0.0rc5 
-   * Upgrade to PhpParser v5 + adapt code. Remove Qodana. Upgrade to PHPUnit 10.5 
-   * Merge pull request #504 from phpmetrics/fix/php-parser-v5 
-   * releasing v3.0.0rc6 
-   * Fix numeric version array key in Composer\Packagist.php - if there is an integer string set as a key of associative array, it will automatically be converted to integer, which causes the call of `ltrim` to fail, because of `declare(strict_types=1)` configuration 
-   * Merge pull request #509 from Klemo1997/fix/packagist-array-key-type-error 
-   * fix typo 
-   * Merge pull request #513 from YAhiru/fix-typo 
-   * feat: add OpenMetrics report 
-   * Merge pull request #512 from alanpoulain/feat-openmetrics 
-   * test: add OpenMetrics SummaryWriter test 
-   * Merge pull request #514 from alanpoulain/test-openmetrics-summary-writer 
-   * Make sure OpenMetrics format is available and upgrade QA. 
-   * Merge pull request #515 from phpmetrics/update/3.x-qa 
-   * releasing v3.0.0rc7 
-   * Updated tests in order to be executed in PHP 8.4, and supports Php 8.4 
-   * fixed issue introduced by phpcs, and removed phpcs 
-   * added build script for standalone build 
-   * fixed CI 
-   * Merge pull request #524 from phpmetrics/php84-standalone 
-   * #518 test about deferencing new without parenthesis in PHP 8.4 
-   * updated build 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Mon, 07 Jul 2025 13:48:16 +0200
-
-phpmetrics (3.0.0rc7) unstable; urgency=low
-   * Prepare v3. WIP. 
-   * Rebase on master (current 2.8.1) with adaptation for 3.x. Coverage got down. WIP. 
-   * Add some missing unit test. Coverage is still not back to previous state. WIP. 
-   * Continue to add up some coverage. WIP. 
-   * Set the coverage back to previous state. WIP: work on uncovered files. 
-   * Remove Git related metrics. 
-   * Remove PHPUnit metrics checks. Start but stop reviewing Html Reporter (too complex). File functions.php removed. 
-   * Fix some PHPStan issues. WIP. 
-   * Apply HTML error fixes from #477. 
-   * Update dependencies and fix unit tests. 
-   * Update QA and dev-dependencies. 
-   * Disable PHP Infection as some mutants are breaking analyse. 
-   * Add multiple locations for composer-autoloading. 
-   * Do not oblige usage of YAML extention as configuration can be set in another way. 
-   * Fix HTML rednering. 
-   * Fix HTML rednering. 
-   * Ignore PHP Attributes in detecting getter/setters. 
-   * Keep only composer installation to simplify tool usage. 
-   * Remove PageRank metric. 
-   * Get rid of more than 150 PHPStan errors. 
-   * Add cache and baselines on qa tools. 
-   * Dynamically manage version number via .semver file. Also minor fixes. 
-   * Rebase on master + update dependencies + improve QA. PHPUnit 10 is now used. 
-   * Use env variable to share volume to mount with DockerInDocker. 
-   * Adapt the releasing process with the current v3 + minor fixes. 
-   * Decouple file system operations to split responsibilities. 
-   * Complete the unit tests related to file system. 
-   * Kill some mutants. 
-   * Add a copy function to manage the copy of single files. 
-   * Fix tag management on release + recursive copy for HTML rendering. 
-   * Remove Clusterize as only used for removed Class Rank and remove useless logos. 
-   * Fix SVG icons on sidebar. 
-   * Fix resolving of FQCN when inferring externals. 
-   * Fix parsing issue on LComVisitor when code to parse contains variable property fetch. 
-   * Fix error when HTML report is not requested. 
-   * Add missing favicon + add report date in title. 
-   * Improve CSS + button to download the bubble graph. 
-   * Update minimum versions of dependencies for composer.json. 
-   * Fix unit tests for ExternalVisitor. 
-   * Remove example and management of plugins (JUnit). 
-   * Remove useless metric nbGetters/nbSetters. 
-   * Prepare changelog fro release 3.0.0-rc1. 
-   * releasing v3.0.0rc1 
-   * Fix #491: add shell command in case PHP command does not work for some OS in documenation. 
-   * Fix Fatal error when analyzing snippets like `$a->$b()` or `$c()`. 
-   * Prepare release 3.0.0-rc2. 
-   * releasing v3.0.0rc2 
-   * Fix special version label that were not taken into account on bintray. 
-   * releasing v3.0.0rc2 
-   * Fix possible parsing error + upgrade to PHPUnit 10.1. 
-   * Fix violations reporter which was trying to rely on Violations directly, rather than ViolationsHandler 
-   * Merge pull request #495 from Tithugues/fix/report-violations 
-   * SystemComplexityVisitor fix for calling methods with the same name on different objects 
-   * releasing v3.0.0rc3 
-   * Upgrade deps + add ccn value by method. Need to fnd how to display it on HTML reports now. 
-   * Merge pull request #497 from andrii-pukhalevych/patch1 
-   * Add elegant way to display CCN values for methods. 
-   * QA review: fix PHPStan/Psalm/PHPUnit/Qodana errors. 
-   * Merge pull request #498 from phpmetrics/add-ccn-value-to-every-class-method 
-   * releasing v3.0.0rc4 
-   * Fix URLs and search configuration usage. 
-   * Manage better description inference for stable dependencies principle. 
-   * Merge pull request #502 from phpmetrics/fix/501 
-   * Fix some unit tests + releasing process. 
-   * releasing v3.0.0rc5 
-   * Upgrade to PhpParser v5 + adapt code. Remove Qodana. Upgrade to PHPUnit 10.5 
-   * Merge pull request #504 from phpmetrics/fix/php-parser-v5 
-   * releasing v3.0.0rc6 
-   * Fix numeric version array key in Composer\Packagist.php - if there is an integer string set as a key of associative array, it will automatically be converted to integer, which causes the call of `ltrim` to fail, because of `declare(strict_types=1)` configuration 
-   * Merge pull request #509 from Klemo1997/fix/packagist-array-key-type-error 
-   * fix typo 
-   * Merge pull request #513 from YAhiru/fix-typo 
-   * feat: add OpenMetrics report 
-   * Merge pull request #512 from alanpoulain/feat-openmetrics 
-   * test: add OpenMetrics SummaryWriter test 
-   * Merge pull request #514 from alanpoulain/test-openmetrics-summary-writer 
-   * Make sure OpenMetrics format is available and upgrade QA. 
-   * Merge pull request #515 from phpmetrics/update/3.x-qa 
-   * releasing v3.0.0rc7 
-   * Updated tests in order to be executed in PHP 8.4, and supports Php 8.4 
-   * fixed issue introduced by phpcs, and removed phpcs 
-   * added build script for standalone build 
-   * fixed CI 
-   * Merge pull request #524 from phpmetrics/php84-standalone 
-   * #518 test about deferencing new without parenthesis in PHP 8.4 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Mon, 07 Jul 2025 09:50:33 +0200
-
-phpmetrics (2.8.1) unstable; urgency=low
-   * Fix error in html template 
-   * Merge pull request #477 from Hikingyo/fix-html-template 
-   * Update README.md fix the code block with quick start example. 
-   * Merge pull request #480 from kudashevs/feature/readme-fix 
-   * [ISSUE-441] Fix junit parameter in json config file 
-   * Remove useless checks in "isset" and replace double quotes by single quotes usages. 
-   * Remove unused method. 
-   * Fix #482: Remove useless artefacts. 
-   * add favicon 
-   * Merge pull request #486 from gemal/favicon 
-   * simplify html 
-   * Update _footer.php 
-   * Merge pull request #487 from gemal/html 
-   * add version to css and script to counter cache 
-   * Merge pull request #488 from gemal/versions 
-   * Merge pull request #457 from phpmetrics/ISSUE-441 
-   * Add missing changelogs from 2.5.0 to 2.8.1. 
-   * Add changelog for incoming version 2.8.2. 
-   * Way to release via docker 
-   * Merge pull request #489 from phpmetrics/way_to_release_with_docker 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Wed, 08 Mar 2023 15:03:36 +0000
-
-phpmetrics (2.7.4) unstable; urgency=low
-   * Fix readme file (#438) 
-   * include by default the composer.lock localized at the root dir 
-   * Allow usage behind proxy 
-   * PR review changes 
-   * Refactor  following PR comments 
-   * PR review applied changes 
-   * Add php8 in travis  ci 
-   * Merge pull request #1 from phpmetrics/master 
-   * Fix typo 
-   * Removing PHP 7+ return value typehint 
-   * Merge pull request #454 from crimsonkissaki/crimsonkissaki-patch-1 
-   * Merge pull request #449 from ssfinney/master 
-   * Merge pull request #446 from alediator/proxy_env_use 
-   * Merge pull request #442 from AlexHowansky/master 
-   * [ISSUE-445] Fix warning with test on ansi 
-   * Merge pull request #456 from phpmetrics/ISSUE-445 
-   * [ISSUE-451] remove auto scrolling of charts 
-   * Merge pull request #447 from Big-Shark/patch-2 
-   * [ISSUE-436] Restore deb compilation 
-   * Fixed issue with incorrect table header on the complexity report page 
-   * Removed extraneous and invalid HTML syntax 
-   * Merge pull request #455 from phpmetrics/ISSUE-451 
-   * Solve passing null instead of int by removing the flag on the Finder, that is unused by the code. 
-   * Add PHP Attribute "ReturnTypeWillChange" on internal overload definitions as return type is missing. 
-   * Add "unknown" status for private packages to avoid deprecated error in version_compare usage. 
-   * Merge pull request #458 from phpmetrics/ISSUE-436 
-   * Add command to get summary as Json 
-   * Merge pull request #466 from phpmetrics/remove-php8.1-deprecations 
-   * Way to search patterns of code 
-   * Merge pull request #472 from phpmetrics/searches 
-   * Merge pull request #467 from roelbaka/addJsonSummary 
-   * Merge pull request #464 from denniscoorn-paqt/fix/complexity-table-columns 
-   * releasing v2.8.0 
-   * Fixes issues with paths 
-   * Merge pull request #474 from phpmetrics/fixes_permissions_path 
-   * Updates test for phpunit compatibility 
-   * Merge pull request #475 from phpmetrics/phpunit-compatibility 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Thu, 24 Mar 2022 11:19:14 +0100
-
-phpmetrics (2.7.4) unstable; urgency=low
-   * Fix readme file (#438) 
-   * include by default the composer.lock localized at the root dir 
-   * Allow usage behind proxy 
-   * PR review changes 
-   * Refactor  following PR comments 
-   * PR review applied changes 
-   * Add php8 in travis  ci 
-   * Merge pull request #1 from phpmetrics/master 
-   * Fix typo 
-   * Removing PHP 7+ return value typehint 
-   * Merge pull request #454 from crimsonkissaki/crimsonkissaki-patch-1 
-   * Merge pull request #449 from ssfinney/master 
-   * Merge pull request #446 from alediator/proxy_env_use 
-   * Merge pull request #442 from AlexHowansky/master 
-   * [ISSUE-445] Fix warning with test on ansi 
-   * Merge pull request #456 from phpmetrics/ISSUE-445 
-   * [ISSUE-451] remove auto scrolling of charts 
-   * Merge pull request #447 from Big-Shark/patch-2 
-   * [ISSUE-436] Restore deb compilation 
-   * Fixed issue with incorrect table header on the complexity report page 
-   * Removed extraneous and invalid HTML syntax 
-   * Merge pull request #455 from phpmetrics/ISSUE-451 
-   * Solve passing null instead of int by removing the flag on the Finder, that is unused by the code. 
-   * Add PHP Attribute "ReturnTypeWillChange" on internal overload definitions as return type is missing. 
-   * Add "unknown" status for private packages to avoid deprecated error in version_compare usage. 
-   * Merge pull request #458 from phpmetrics/ISSUE-436 
-   * Add command to get summary as Json 
-   * Merge pull request #466 from phpmetrics/remove-php8.1-deprecations 
-   * Way to search patterns of code 
-   * Merge pull request #472 from phpmetrics/searches 
-   * Merge pull request #467 from roelbaka/addJsonSummary 
-   * Merge pull request #464 from denniscoorn-paqt/fix/complexity-table-columns 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Wed, 23 Mar 2022 22:00:37 +0100
-
-phpmetrics (2.7.2) unstable; urgency=low
-   * include by default the composer.json localized at the root dir 
-   * releasing v2.7.3 
-   * Create security.yml file 
-   * Bump php package required 
-   * Merge pull request #434 from Mte90/patch-1 
-   * Fix issue with charts in groups - Closes #429, Closes #433 
-   * Merge pull request #437 from phpmetrics/fix_issue_js 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Tue, 30 Jun 2020 22:31:52 +0200
-
-phpmetrics (2.7.1) unstable; urgency=low
-   * Fix path of reporter 
-   * releasing v2.7.2 
-   * include by default the composer.json localized at the root dir 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Sat, 27 Jun 2020 15:20:54 +0200
-
-phpmetrics (2.7.0) unstable; urgency=low
-   * Fixed colors of JSON file in markdown 
-   * Fixed markdown and hidden char 
-   * Fix #429, bug when generating html report. 
-   * Fix #431, only outdated packages will be reported 
-   * Merge pull request #430 from pts-contrib/bug-429 
-   * Merge pull request #432 from pts-contrib/bug-431 
-   * fix contribution typo 
-   * releasing v2.7.1 
-   * Fix path of reporter 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Sat, 27 Jun 2020 15:06:49 +0200
-
-phpmetrics (2.6.2) unstable; urgency=low
-   * New composer report and improved UI 
-   * Merge pull request #424 from phpmetrics/ui_composer 
-   * Group analyzed components by layer 
-   * Merge pull request #428 from phpmetrics/config_group 
-   * releasing v2.7.0 
-   * Fixed colors of JSON file in markdown 
-   * Fixed markdown and hidden char 
-   * Fix #429, bug when generating html report. 
-   * Fix #431, only outdated packages will be reported 
-   * Merge pull request #430 from pts-contrib/bug-429 
-   * Merge pull request #432 from pts-contrib/bug-431 
-   * fix contribution typo 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Sat, 27 Jun 2020 14:56:42 +0200
-
-phpmetrics (2.6.1) unstable; urgency=low
-   * Improved UI with help and gradients 
-   * Merge pull request #421 from phpmetrics/improved_ui 
-   * releasing v2.6.2 
-   * New composer report and improved UI 
-   * Merge pull request #424 from phpmetrics/ui_composer 
-   * Group analyzed components by layer 
-   * Merge pull request #428 from phpmetrics/config_group 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Fri, 26 Jun 2020 22:22:02 +0200
-
-phpmetrics (2.6.0) unstable; urgency=low
-   * Force GPG key for relasing 
-   * Improved page rank report, and UI #416 
-   * Merge pull request #420 from phpmetrics/416_improved_pagerank 
-   * Improved UI with help and gradients 
-   * hot fixing phar 
-   * Merge pull request #422 from phpmetrics/hf_phar 
-   * Remove not useful constant 
-   * Merge pull request #423 from phpmetrics/improved_code 
-   * releasing v2.6.1 
-   * Merge pull request #421 from phpmetrics/improved_ui 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Thu, 02 Apr 2020 22:21:45 +0200
-
-phpmetrics (2.5.0) unstable; urgency=low
-   * Documented how to release (#392) 
-   * Added editor config file (#393) 
-   * Updated changelog (#394) 
-   * improve docblocks 
-   * Added more codesniffer rules 
-   * Merge pull request #396 from phpmetrics/add-more-phpcs-rules 
-   * Merge pull request #395 from phpmetrics/docblock-improvements 
-   * Way to download report 
-   * Merge pull request #399 from phpmetrics/download_chart 
-   * Exclude doc and artifacts from phar 
-   * Explicitly define the class \Hal\Component\Ast\NodeTraverser to make PhpMetrics work using composer --classmap-authoritative. (#402) 
-   * Merge pull request #400 from phpmetrics/exclude-phar-files 
-   * Resolve PHP7 getters / setters (#405) 
-   * Ensure the packagist license is an array so they can be displayed. (#404) 
-   * Fix warning "Division by zero" when no package is defined. (#401) 
-   * move templates out of src 
-   * Remove folders from phpcs 
-   * Merge pull request #406 from phpmetrics/move-templates-out 
-   * Provide new issue template format. 
-   * Added Slack link (#411) 
-   * Provide configuration option "--maintainability-index-without-comments". 
-   * Remove command line and always provide metrics MI without comments additionnaly from MI. Add a carousel in the main HTML report page to display both graph at the same time. 
-   * Move new files for carousel inside new template folder after rebasing from master. 
-   * Fix bug with dots in the carousel + add titles on dots for accessibility. 
-   * add metrics description file 
-   * Merge pull request #408 from phpmetrics/new-issue-tpl 
-   * Merge pull request #412 from repzy/metrics-file 
-   * Merge pull request #407 from phpmetrics/issue-325-provide-miwoc 
-   * fix releasing script 
-   * releasing v2.6.0 
-   * Force GPG key for relasing 
-   * Improved page rank report, and UI #416 
-   * Merge pull request #420 from phpmetrics/416_improved_pagerank 
-   * hot fixing phar 
-   * Merge pull request #422 from phpmetrics/hf_phar 
-   * Remove not useful constant 
-   * Merge pull request #423 from phpmetrics/improved_code 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Thu, 02 Apr 2020 21:54:40 +0200
-
-phpmetrics (2.4.1) unstable; urgency=low
-   * Test on PHP 7.3 
-   * Don't leave notice when array is small 
-   * Add final to class metric 
-   * Update ClassEnumVisitor.php 
-   * Merge pull request #371 from lencse/php73 
-   * Fix issue#380. Typo in Blob report 
-   * Merge pull request #385 from phpmetrics/issue#380 
-   * Added sort package config to composer 
-   * Merge pull request #388 from phpmetrics/sort-packages 
-   * Include codesniffer. Remove alias function and short array syntax (#387) 
-   * Remove superfluous docblocks that are adding no value (#390) 
-   * Skip `self` and `parent` from external dependencies (#1) (#370) 
-   * Trying to fix deprecation of PSR-0 (issue#382) (#384) 
-   * file_exists > is_file (#366) 
-   * Apply PSR-2 codestyle (#389) 
-   * Update phpunit to use highest version possible (#391) 
-   * Merge pull request #375 from gmponos/patch-1 
-   * Merge pull request #372 from lencse/loc-report 
-   * Test against PHP 7.4 (#383) 
-   * releasing 
-   * releasing v2.4.1 
-   * Update contributing.md 
-   * update readme file 
-   * Merge branch 'master' of github.com:phpmetrics/PhpMetrics 
-   * Fixed binary tests 
-   * releasing v2.5.0 
-   * Documented how to release (#392) 
-   * Added editor config file (#393) 
-   * Updated changelog (#394) 
-   * improve docblocks 
-   * Added more codesniffer rules 
-   * Merge pull request #396 from phpmetrics/add-more-phpcs-rules 
-   * Merge pull request #395 from phpmetrics/docblock-improvements 
-   * Way to download report 
-   * Merge pull request #399 from phpmetrics/download_chart 
-   * Exclude doc and artifacts from phar 
-   * Explicitly define the class \Hal\Component\Ast\NodeTraverser to make PhpMetrics work using composer --classmap-authoritative. (#402) 
-   * Merge pull request #400 from phpmetrics/exclude-phar-files 
-   * Resolve PHP7 getters / setters (#405) 
-   * Ensure the packagist license is an array so they can be displayed. (#404) 
-   * Fix warning "Division by zero" when no package is defined. (#401) 
-   * move templates out of src 
-   * Remove folders from phpcs 
-   * Merge pull request #406 from phpmetrics/move-templates-out 
-   * Provide new issue template format. 
-   * Added Slack link (#411) 
-   * Provide configuration option "--maintainability-index-without-comments". 
-   * Remove command line and always provide metrics MI without comments additionnaly from MI. Add a carousel in the main HTML report page to display both graph at the same time. 
-   * Move new files for carousel inside new template folder after rebasing from master. 
-   * Fix bug with dots in the carousel + add titles on dots for accessibility. 
-   * add metrics description file 
-   * Merge pull request #408 from phpmetrics/new-issue-tpl 
-   * Merge pull request #412 from repzy/metrics-file 
-   * Merge pull request #407 from phpmetrics/issue-325-provide-miwoc 
-   * fix releasing script 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Sat, 28 Mar 2020 14:29:40 +0100
-
-phpmetrics (2.4.0) unstable; urgency=low
-   * Fix template type 
-   * Verify errors in php<7 
-   * Use class_alias to load php5 or php7 code 
-   * Merge pull request #361 from UFOMelkor/hotfix/360-php56 
-   * Retain the old ccn and add wmc as new metric 
-   * Merge pull request #362 from UFOMelkor/hotfix/remain-ccn 
-   * releasing v2.4.1 
-   * Test on PHP 7.3 
-   * Don't leave notice when array is small 
-   * Add final to class metric 
-   * Update ClassEnumVisitor.php 
-   * Merge pull request #371 from lencse/php73 
-   * Fix issue#380. Typo in Blob report 
-   * Merge pull request #385 from phpmetrics/issue#380 
-   * Added sort package config to composer 
-   * Merge pull request #388 from phpmetrics/sort-packages 
-   * Include codesniffer. Remove alias function and short array syntax (#387) 
-   * Remove superfluous docblocks that are adding no value (#390) 
-   * Skip `self` and `parent` from external dependencies (#1) (#370) 
-   * Trying to fix deprecation of PSR-0 (issue#382) (#384) 
-   * file_exists > is_file (#366) 
-   * Apply PSR-2 codestyle (#389) 
-   * Update phpunit to use highest version possible (#391) 
-   * Merge pull request #375 from gmponos/patch-1 
-   * Merge pull request #372 from lencse/loc-report 
-   * Test against PHP 7.4 (#383) 
-   * releasing 
-   * releasing v2.4.1 
-   * Update contributing.md 
-   * update readme file 
-   * Merge branch 'master' of github.com:phpmetrics/PhpMetrics 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Thu, 12 Dec 2019 09:01:35 +0100
-
-# Older entries have been removed from this changelog.
-# To read the complete changelog use `apt changelog phpmetrics`.
diff --git a/artifacts/debian/.debhelper/generated/phpmetrics/installed-by-dh_install b/artifacts/debian/.debhelper/generated/phpmetrics/installed-by-dh_install
deleted file mode 100644
index 869c9b67..00000000
--- a/artifacts/debian/.debhelper/generated/phpmetrics/installed-by-dh_install
+++ /dev/null
@@ -1 +0,0 @@
-debian/tmp/phpmetrics
diff --git a/artifacts/debian/.debhelper/generated/phpmetrics/installed-by-dh_installdocs b/artifacts/debian/.debhelper/generated/phpmetrics/installed-by-dh_installdocs
deleted file mode 100644
index e69de29b..00000000
diff --git a/artifacts/debian/Makefile b/artifacts/debian/Makefile
deleted file mode 100644
index 6d31211b..00000000
--- a/artifacts/debian/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-RELEASE_VERSION=$(shell echo ${CURRENT_TAG}|sed -r s/v//)
-
-# Build deb
-#build-deb: build-phar
-build-deb:
-	@echo Copying phar
-	@mkdir -p artifacts/debian/bin
-	@cp ${BUILD_DIR}/phpmetrics.phar artifacts/debian/bin/phpmetrics
-
-	@echo "Building .deb (${RELEASE_VERSION})"
-	cd artifacts && dpkg-buildpackage -us -uc
-	@echo moving deb
-	mv phpmetrics*.deb ${BUILD_DIR}/phpmetrics.deb
-	mv phpmetrics*.dsc ${BUILD_DIR}/phpmetrics.dsc
-	mv phpmetrics*.tar.gz ${BUILD_DIR}/phpmetrics.tar.gz
-	mv phpmetrics*.changes ${BUILD_DIR}/phpmetrics.changes
-	rm -Rf artifacts/debian/phpmetrics artifacts/debian/tmp artifacts/debian/bin artifacts/debian/*.log
-
-changelog-deb:
-	@echo "phpmetrics ($(RELEASE_VERSION)) unstable; urgency=low" >/tmp/changelog
-	@echo >> artifacts/debian/changelog
-	@git log $(CURRENT_TAG)...HEAD --pretty=format:'   * %s ' --reverse >> /tmp/changelog
-	@echo >> /tmp/changelog
-	@echo >> /tmp/changelog
-	@echo  "  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  $(shell date --rfc-2822)" >> /tmp/changelog
-	@echo >> /tmp/changelog
-	@# prepend to changelog
-	@cat /tmp/changelog|cat - artifacts/debian/changelog > /tmp/out && mv /tmp/out artifacts/debian/changelog
-	@echo >> artifacts/debian/changelog
\ No newline at end of file
diff --git a/artifacts/debian/changelog b/artifacts/debian/changelog
deleted file mode 100644
index 6971fef6..00000000
--- a/artifacts/debian/changelog
+++ /dev/null
@@ -1,1341 +0,0 @@
-phpmetrics (3.0.0rc7) unstable; urgency=low
-   * Prepare v3. WIP. 
-   * Rebase on master (current 2.8.1) with adaptation for 3.x. Coverage got down. WIP. 
-   * Add some missing unit test. Coverage is still not back to previous state. WIP. 
-   * Continue to add up some coverage. WIP. 
-   * Set the coverage back to previous state. WIP: work on uncovered files. 
-   * Remove Git related metrics. 
-   * Remove PHPUnit metrics checks. Start but stop reviewing Html Reporter (too complex). File functions.php removed. 
-   * Fix some PHPStan issues. WIP. 
-   * Apply HTML error fixes from #477. 
-   * Update dependencies and fix unit tests. 
-   * Update QA and dev-dependencies. 
-   * Disable PHP Infection as some mutants are breaking analyse. 
-   * Add multiple locations for composer-autoloading. 
-   * Do not oblige usage of YAML extention as configuration can be set in another way. 
-   * Fix HTML rednering. 
-   * Fix HTML rednering. 
-   * Ignore PHP Attributes in detecting getter/setters. 
-   * Keep only composer installation to simplify tool usage. 
-   * Remove PageRank metric. 
-   * Get rid of more than 150 PHPStan errors. 
-   * Add cache and baselines on qa tools. 
-   * Dynamically manage version number via .semver file. Also minor fixes. 
-   * Rebase on master + update dependencies + improve QA. PHPUnit 10 is now used. 
-   * Use env variable to share volume to mount with DockerInDocker. 
-   * Adapt the releasing process with the current v3 + minor fixes. 
-   * Decouple file system operations to split responsibilities. 
-   * Complete the unit tests related to file system. 
-   * Kill some mutants. 
-   * Add a copy function to manage the copy of single files. 
-   * Fix tag management on release + recursive copy for HTML rendering. 
-   * Remove Clusterize as only used for removed Class Rank and remove useless logos. 
-   * Fix SVG icons on sidebar. 
-   * Fix resolving of FQCN when inferring externals. 
-   * Fix parsing issue on LComVisitor when code to parse contains variable property fetch. 
-   * Fix error when HTML report is not requested. 
-   * Add missing favicon + add report date in title. 
-   * Improve CSS + button to download the bubble graph. 
-   * Update minimum versions of dependencies for composer.json. 
-   * Fix unit tests for ExternalVisitor. 
-   * Remove example and management of plugins (JUnit). 
-   * Remove useless metric nbGetters/nbSetters. 
-   * Prepare changelog fro release 3.0.0-rc1. 
-   * releasing v3.0.0rc1 
-   * Fix #491: add shell command in case PHP command does not work for some OS in documenation. 
-   * Fix Fatal error when analyzing snippets like `$a->$b()` or `$c()`. 
-   * Prepare release 3.0.0-rc2. 
-   * releasing v3.0.0rc2 
-   * Fix special version label that were not taken into account on bintray. 
-   * releasing v3.0.0rc2 
-   * Fix possible parsing error + upgrade to PHPUnit 10.1. 
-   * Fix violations reporter which was trying to rely on Violations directly, rather than ViolationsHandler 
-   * Merge pull request #495 from Tithugues/fix/report-violations 
-   * SystemComplexityVisitor fix for calling methods with the same name on different objects 
-   * releasing v3.0.0rc3 
-   * Upgrade deps + add ccn value by method. Need to fnd how to display it on HTML reports now. 
-   * Merge pull request #497 from andrii-pukhalevych/patch1 
-   * Add elegant way to display CCN values for methods. 
-   * QA review: fix PHPStan/Psalm/PHPUnit/Qodana errors. 
-   * Merge pull request #498 from phpmetrics/add-ccn-value-to-every-class-method 
-   * releasing v3.0.0rc4 
-   * Fix URLs and search configuration usage. 
-   * Manage better description inference for stable dependencies principle. 
-   * Merge pull request #502 from phpmetrics/fix/501 
-   * Fix some unit tests + releasing process. 
-   * releasing v3.0.0rc5 
-   * Upgrade to PhpParser v5 + adapt code. Remove Qodana. Upgrade to PHPUnit 10.5 
-   * Merge pull request #504 from phpmetrics/fix/php-parser-v5 
-   * releasing v3.0.0rc6 
-   * Fix numeric version array key in Composer\Packagist.php - if there is an integer string set as a key of associative array, it will automatically be converted to integer, which causes the call of `ltrim` to fail, because of `declare(strict_types=1)` configuration 
-   * Merge pull request #509 from Klemo1997/fix/packagist-array-key-type-error 
-   * fix typo 
-   * Merge pull request #513 from YAhiru/fix-typo 
-   * feat: add OpenMetrics report 
-   * Merge pull request #512 from alanpoulain/feat-openmetrics 
-   * test: add OpenMetrics SummaryWriter test 
-   * Merge pull request #514 from alanpoulain/test-openmetrics-summary-writer 
-   * Make sure OpenMetrics format is available and upgrade QA. 
-   * Merge pull request #515 from phpmetrics/update/3.x-qa 
-   * releasing v3.0.0rc7 
-   * Updated tests in order to be executed in PHP 8.4, and supports Php 8.4 
-   * fixed issue introduced by phpcs, and removed phpcs 
-   * added build script for standalone build 
-   * fixed CI 
-   * Merge pull request #524 from phpmetrics/php84-standalone 
-   * #518 test about deferencing new without parenthesis in PHP 8.4 
-   * Merge pull request #525 from phpmetrics/php84-standalone 
-   * updated build 
-   * releasing 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Mon, 07 Jul 2025 14:08:33 +0200
-
-phpmetrics (3.0.0rc7) unstable; urgency=low
-   * Prepare v3. WIP. 
-   * Rebase on master (current 2.8.1) with adaptation for 3.x. Coverage got down. WIP. 
-   * Add some missing unit test. Coverage is still not back to previous state. WIP. 
-   * Continue to add up some coverage. WIP. 
-   * Set the coverage back to previous state. WIP: work on uncovered files. 
-   * Remove Git related metrics. 
-   * Remove PHPUnit metrics checks. Start but stop reviewing Html Reporter (too complex). File functions.php removed. 
-   * Fix some PHPStan issues. WIP. 
-   * Apply HTML error fixes from #477. 
-   * Update dependencies and fix unit tests. 
-   * Update QA and dev-dependencies. 
-   * Disable PHP Infection as some mutants are breaking analyse. 
-   * Add multiple locations for composer-autoloading. 
-   * Do not oblige usage of YAML extention as configuration can be set in another way. 
-   * Fix HTML rednering. 
-   * Fix HTML rednering. 
-   * Ignore PHP Attributes in detecting getter/setters. 
-   * Keep only composer installation to simplify tool usage. 
-   * Remove PageRank metric. 
-   * Get rid of more than 150 PHPStan errors. 
-   * Add cache and baselines on qa tools. 
-   * Dynamically manage version number via .semver file. Also minor fixes. 
-   * Rebase on master + update dependencies + improve QA. PHPUnit 10 is now used. 
-   * Use env variable to share volume to mount with DockerInDocker. 
-   * Adapt the releasing process with the current v3 + minor fixes. 
-   * Decouple file system operations to split responsibilities. 
-   * Complete the unit tests related to file system. 
-   * Kill some mutants. 
-   * Add a copy function to manage the copy of single files. 
-   * Fix tag management on release + recursive copy for HTML rendering. 
-   * Remove Clusterize as only used for removed Class Rank and remove useless logos. 
-   * Fix SVG icons on sidebar. 
-   * Fix resolving of FQCN when inferring externals. 
-   * Fix parsing issue on LComVisitor when code to parse contains variable property fetch. 
-   * Fix error when HTML report is not requested. 
-   * Add missing favicon + add report date in title. 
-   * Improve CSS + button to download the bubble graph. 
-   * Update minimum versions of dependencies for composer.json. 
-   * Fix unit tests for ExternalVisitor. 
-   * Remove example and management of plugins (JUnit). 
-   * Remove useless metric nbGetters/nbSetters. 
-   * Prepare changelog fro release 3.0.0-rc1. 
-   * releasing v3.0.0rc1 
-   * Fix #491: add shell command in case PHP command does not work for some OS in documenation. 
-   * Fix Fatal error when analyzing snippets like `$a->$b()` or `$c()`. 
-   * Prepare release 3.0.0-rc2. 
-   * releasing v3.0.0rc2 
-   * Fix special version label that were not taken into account on bintray. 
-   * releasing v3.0.0rc2 
-   * Fix possible parsing error + upgrade to PHPUnit 10.1. 
-   * Fix violations reporter which was trying to rely on Violations directly, rather than ViolationsHandler 
-   * Merge pull request #495 from Tithugues/fix/report-violations 
-   * SystemComplexityVisitor fix for calling methods with the same name on different objects 
-   * releasing v3.0.0rc3 
-   * Upgrade deps + add ccn value by method. Need to fnd how to display it on HTML reports now. 
-   * Merge pull request #497 from andrii-pukhalevych/patch1 
-   * Add elegant way to display CCN values for methods. 
-   * QA review: fix PHPStan/Psalm/PHPUnit/Qodana errors. 
-   * Merge pull request #498 from phpmetrics/add-ccn-value-to-every-class-method 
-   * releasing v3.0.0rc4 
-   * Fix URLs and search configuration usage. 
-   * Manage better description inference for stable dependencies principle. 
-   * Merge pull request #502 from phpmetrics/fix/501 
-   * Fix some unit tests + releasing process. 
-   * releasing v3.0.0rc5 
-   * Upgrade to PhpParser v5 + adapt code. Remove Qodana. Upgrade to PHPUnit 10.5 
-   * Merge pull request #504 from phpmetrics/fix/php-parser-v5 
-   * releasing v3.0.0rc6 
-   * Fix numeric version array key in Composer\Packagist.php - if there is an integer string set as a key of associative array, it will automatically be converted to integer, which causes the call of `ltrim` to fail, because of `declare(strict_types=1)` configuration 
-   * Merge pull request #509 from Klemo1997/fix/packagist-array-key-type-error 
-   * fix typo 
-   * Merge pull request #513 from YAhiru/fix-typo 
-   * feat: add OpenMetrics report 
-   * Merge pull request #512 from alanpoulain/feat-openmetrics 
-   * test: add OpenMetrics SummaryWriter test 
-   * Merge pull request #514 from alanpoulain/test-openmetrics-summary-writer 
-   * Make sure OpenMetrics format is available and upgrade QA. 
-   * Merge pull request #515 from phpmetrics/update/3.x-qa 
-   * releasing v3.0.0rc7 
-   * Updated tests in order to be executed in PHP 8.4, and supports Php 8.4 
-   * fixed issue introduced by phpcs, and removed phpcs 
-   * added build script for standalone build 
-   * fixed CI 
-   * Merge pull request #524 from phpmetrics/php84-standalone 
-   * #518 test about deferencing new without parenthesis in PHP 8.4 
-   * updated build 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Mon, 07 Jul 2025 13:56:00 +0200
-
-phpmetrics (3.0.0rc7) unstable; urgency=low
-   * Prepare v3. WIP. 
-   * Rebase on master (current 2.8.1) with adaptation for 3.x. Coverage got down. WIP. 
-   * Add some missing unit test. Coverage is still not back to previous state. WIP. 
-   * Continue to add up some coverage. WIP. 
-   * Set the coverage back to previous state. WIP: work on uncovered files. 
-   * Remove Git related metrics. 
-   * Remove PHPUnit metrics checks. Start but stop reviewing Html Reporter (too complex). File functions.php removed. 
-   * Fix some PHPStan issues. WIP. 
-   * Apply HTML error fixes from #477. 
-   * Update dependencies and fix unit tests. 
-   * Update QA and dev-dependencies. 
-   * Disable PHP Infection as some mutants are breaking analyse. 
-   * Add multiple locations for composer-autoloading. 
-   * Do not oblige usage of YAML extention as configuration can be set in another way. 
-   * Fix HTML rednering. 
-   * Fix HTML rednering. 
-   * Ignore PHP Attributes in detecting getter/setters. 
-   * Keep only composer installation to simplify tool usage. 
-   * Remove PageRank metric. 
-   * Get rid of more than 150 PHPStan errors. 
-   * Add cache and baselines on qa tools. 
-   * Dynamically manage version number via .semver file. Also minor fixes. 
-   * Rebase on master + update dependencies + improve QA. PHPUnit 10 is now used. 
-   * Use env variable to share volume to mount with DockerInDocker. 
-   * Adapt the releasing process with the current v3 + minor fixes. 
-   * Decouple file system operations to split responsibilities. 
-   * Complete the unit tests related to file system. 
-   * Kill some mutants. 
-   * Add a copy function to manage the copy of single files. 
-   * Fix tag management on release + recursive copy for HTML rendering. 
-   * Remove Clusterize as only used for removed Class Rank and remove useless logos. 
-   * Fix SVG icons on sidebar. 
-   * Fix resolving of FQCN when inferring externals. 
-   * Fix parsing issue on LComVisitor when code to parse contains variable property fetch. 
-   * Fix error when HTML report is not requested. 
-   * Add missing favicon + add report date in title. 
-   * Improve CSS + button to download the bubble graph. 
-   * Update minimum versions of dependencies for composer.json. 
-   * Fix unit tests for ExternalVisitor. 
-   * Remove example and management of plugins (JUnit). 
-   * Remove useless metric nbGetters/nbSetters. 
-   * Prepare changelog fro release 3.0.0-rc1. 
-   * releasing v3.0.0rc1 
-   * Fix #491: add shell command in case PHP command does not work for some OS in documenation. 
-   * Fix Fatal error when analyzing snippets like `$a->$b()` or `$c()`. 
-   * Prepare release 3.0.0-rc2. 
-   * releasing v3.0.0rc2 
-   * Fix special version label that were not taken into account on bintray. 
-   * releasing v3.0.0rc2 
-   * Fix possible parsing error + upgrade to PHPUnit 10.1. 
-   * Fix violations reporter which was trying to rely on Violations directly, rather than ViolationsHandler 
-   * Merge pull request #495 from Tithugues/fix/report-violations 
-   * SystemComplexityVisitor fix for calling methods with the same name on different objects 
-   * releasing v3.0.0rc3 
-   * Upgrade deps + add ccn value by method. Need to fnd how to display it on HTML reports now. 
-   * Merge pull request #497 from andrii-pukhalevych/patch1 
-   * Add elegant way to display CCN values for methods. 
-   * QA review: fix PHPStan/Psalm/PHPUnit/Qodana errors. 
-   * Merge pull request #498 from phpmetrics/add-ccn-value-to-every-class-method 
-   * releasing v3.0.0rc4 
-   * Fix URLs and search configuration usage. 
-   * Manage better description inference for stable dependencies principle. 
-   * Merge pull request #502 from phpmetrics/fix/501 
-   * Fix some unit tests + releasing process. 
-   * releasing v3.0.0rc5 
-   * Upgrade to PhpParser v5 + adapt code. Remove Qodana. Upgrade to PHPUnit 10.5 
-   * Merge pull request #504 from phpmetrics/fix/php-parser-v5 
-   * releasing v3.0.0rc6 
-   * Fix numeric version array key in Composer\Packagist.php - if there is an integer string set as a key of associative array, it will automatically be converted to integer, which causes the call of `ltrim` to fail, because of `declare(strict_types=1)` configuration 
-   * Merge pull request #509 from Klemo1997/fix/packagist-array-key-type-error 
-   * fix typo 
-   * Merge pull request #513 from YAhiru/fix-typo 
-   * feat: add OpenMetrics report 
-   * Merge pull request #512 from alanpoulain/feat-openmetrics 
-   * test: add OpenMetrics SummaryWriter test 
-   * Merge pull request #514 from alanpoulain/test-openmetrics-summary-writer 
-   * Make sure OpenMetrics format is available and upgrade QA. 
-   * Merge pull request #515 from phpmetrics/update/3.x-qa 
-   * releasing v3.0.0rc7 
-   * Updated tests in order to be executed in PHP 8.4, and supports Php 8.4 
-   * fixed issue introduced by phpcs, and removed phpcs 
-   * added build script for standalone build 
-   * fixed CI 
-   * Merge pull request #524 from phpmetrics/php84-standalone 
-   * #518 test about deferencing new without parenthesis in PHP 8.4 
-   * updated build 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Mon, 07 Jul 2025 13:48:16 +0200
-
-phpmetrics (3.0.0rc7) unstable; urgency=low
-   * Prepare v3. WIP. 
-   * Rebase on master (current 2.8.1) with adaptation for 3.x. Coverage got down. WIP. 
-   * Add some missing unit test. Coverage is still not back to previous state. WIP. 
-   * Continue to add up some coverage. WIP. 
-   * Set the coverage back to previous state. WIP: work on uncovered files. 
-   * Remove Git related metrics. 
-   * Remove PHPUnit metrics checks. Start but stop reviewing Html Reporter (too complex). File functions.php removed. 
-   * Fix some PHPStan issues. WIP. 
-   * Apply HTML error fixes from #477. 
-   * Update dependencies and fix unit tests. 
-   * Update QA and dev-dependencies. 
-   * Disable PHP Infection as some mutants are breaking analyse. 
-   * Add multiple locations for composer-autoloading. 
-   * Do not oblige usage of YAML extention as configuration can be set in another way. 
-   * Fix HTML rednering. 
-   * Fix HTML rednering. 
-   * Ignore PHP Attributes in detecting getter/setters. 
-   * Keep only composer installation to simplify tool usage. 
-   * Remove PageRank metric. 
-   * Get rid of more than 150 PHPStan errors. 
-   * Add cache and baselines on qa tools. 
-   * Dynamically manage version number via .semver file. Also minor fixes. 
-   * Rebase on master + update dependencies + improve QA. PHPUnit 10 is now used. 
-   * Use env variable to share volume to mount with DockerInDocker. 
-   * Adapt the releasing process with the current v3 + minor fixes. 
-   * Decouple file system operations to split responsibilities. 
-   * Complete the unit tests related to file system. 
-   * Kill some mutants. 
-   * Add a copy function to manage the copy of single files. 
-   * Fix tag management on release + recursive copy for HTML rendering. 
-   * Remove Clusterize as only used for removed Class Rank and remove useless logos. 
-   * Fix SVG icons on sidebar. 
-   * Fix resolving of FQCN when inferring externals. 
-   * Fix parsing issue on LComVisitor when code to parse contains variable property fetch. 
-   * Fix error when HTML report is not requested. 
-   * Add missing favicon + add report date in title. 
-   * Improve CSS + button to download the bubble graph. 
-   * Update minimum versions of dependencies for composer.json. 
-   * Fix unit tests for ExternalVisitor. 
-   * Remove example and management of plugins (JUnit). 
-   * Remove useless metric nbGetters/nbSetters. 
-   * Prepare changelog fro release 3.0.0-rc1. 
-   * releasing v3.0.0rc1 
-   * Fix #491: add shell command in case PHP command does not work for some OS in documenation. 
-   * Fix Fatal error when analyzing snippets like `$a->$b()` or `$c()`. 
-   * Prepare release 3.0.0-rc2. 
-   * releasing v3.0.0rc2 
-   * Fix special version label that were not taken into account on bintray. 
-   * releasing v3.0.0rc2 
-   * Fix possible parsing error + upgrade to PHPUnit 10.1. 
-   * Fix violations reporter which was trying to rely on Violations directly, rather than ViolationsHandler 
-   * Merge pull request #495 from Tithugues/fix/report-violations 
-   * SystemComplexityVisitor fix for calling methods with the same name on different objects 
-   * releasing v3.0.0rc3 
-   * Upgrade deps + add ccn value by method. Need to fnd how to display it on HTML reports now. 
-   * Merge pull request #497 from andrii-pukhalevych/patch1 
-   * Add elegant way to display CCN values for methods. 
-   * QA review: fix PHPStan/Psalm/PHPUnit/Qodana errors. 
-   * Merge pull request #498 from phpmetrics/add-ccn-value-to-every-class-method 
-   * releasing v3.0.0rc4 
-   * Fix URLs and search configuration usage. 
-   * Manage better description inference for stable dependencies principle. 
-   * Merge pull request #502 from phpmetrics/fix/501 
-   * Fix some unit tests + releasing process. 
-   * releasing v3.0.0rc5 
-   * Upgrade to PhpParser v5 + adapt code. Remove Qodana. Upgrade to PHPUnit 10.5 
-   * Merge pull request #504 from phpmetrics/fix/php-parser-v5 
-   * releasing v3.0.0rc6 
-   * Fix numeric version array key in Composer\Packagist.php - if there is an integer string set as a key of associative array, it will automatically be converted to integer, which causes the call of `ltrim` to fail, because of `declare(strict_types=1)` configuration 
-   * Merge pull request #509 from Klemo1997/fix/packagist-array-key-type-error 
-   * fix typo 
-   * Merge pull request #513 from YAhiru/fix-typo 
-   * feat: add OpenMetrics report 
-   * Merge pull request #512 from alanpoulain/feat-openmetrics 
-   * test: add OpenMetrics SummaryWriter test 
-   * Merge pull request #514 from alanpoulain/test-openmetrics-summary-writer 
-   * Make sure OpenMetrics format is available and upgrade QA. 
-   * Merge pull request #515 from phpmetrics/update/3.x-qa 
-   * releasing v3.0.0rc7 
-   * Updated tests in order to be executed in PHP 8.4, and supports Php 8.4 
-   * fixed issue introduced by phpcs, and removed phpcs 
-   * added build script for standalone build 
-   * fixed CI 
-   * Merge pull request #524 from phpmetrics/php84-standalone 
-   * #518 test about deferencing new without parenthesis in PHP 8.4 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Mon, 07 Jul 2025 09:50:33 +0200
-
-phpmetrics (2.8.1) unstable; urgency=low
-   * Fix error in html template 
-   * Merge pull request #477 from Hikingyo/fix-html-template 
-   * Update README.md fix the code block with quick start example. 
-   * Merge pull request #480 from kudashevs/feature/readme-fix 
-   * [ISSUE-441] Fix junit parameter in json config file 
-   * Remove useless checks in "isset" and replace double quotes by single quotes usages. 
-   * Remove unused method. 
-   * Fix #482: Remove useless artefacts. 
-   * add favicon 
-   * Merge pull request #486 from gemal/favicon 
-   * simplify html 
-   * Update _footer.php 
-   * Merge pull request #487 from gemal/html 
-   * add version to css and script to counter cache 
-   * Merge pull request #488 from gemal/versions 
-   * Merge pull request #457 from phpmetrics/ISSUE-441 
-   * Add missing changelogs from 2.5.0 to 2.8.1. 
-   * Add changelog for incoming version 2.8.2. 
-   * Way to release via docker 
-   * Merge pull request #489 from phpmetrics/way_to_release_with_docker 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Wed, 08 Mar 2023 15:03:36 +0000
-
-phpmetrics (2.7.4) unstable; urgency=low
-   * Fix readme file (#438) 
-   * include by default the composer.lock localized at the root dir 
-   * Allow usage behind proxy 
-   * PR review changes 
-   * Refactor  following PR comments 
-   * PR review applied changes 
-   * Add php8 in travis  ci 
-   * Merge pull request #1 from phpmetrics/master 
-   * Fix typo 
-   * Removing PHP 7+ return value typehint 
-   * Merge pull request #454 from crimsonkissaki/crimsonkissaki-patch-1 
-   * Merge pull request #449 from ssfinney/master 
-   * Merge pull request #446 from alediator/proxy_env_use 
-   * Merge pull request #442 from AlexHowansky/master 
-   * [ISSUE-445] Fix warning with test on ansi 
-   * Merge pull request #456 from phpmetrics/ISSUE-445 
-   * [ISSUE-451] remove auto scrolling of charts 
-   * Merge pull request #447 from Big-Shark/patch-2 
-   * [ISSUE-436] Restore deb compilation 
-   * Fixed issue with incorrect table header on the complexity report page 
-   * Removed extraneous and invalid HTML syntax 
-   * Merge pull request #455 from phpmetrics/ISSUE-451 
-   * Solve passing null instead of int by removing the flag on the Finder, that is unused by the code. 
-   * Add PHP Attribute "ReturnTypeWillChange" on internal overload definitions as return type is missing. 
-   * Add "unknown" status for private packages to avoid deprecated error in version_compare usage. 
-   * Merge pull request #458 from phpmetrics/ISSUE-436 
-   * Add command to get summary as Json 
-   * Merge pull request #466 from phpmetrics/remove-php8.1-deprecations 
-   * Way to search patterns of code 
-   * Merge pull request #472 from phpmetrics/searches 
-   * Merge pull request #467 from roelbaka/addJsonSummary 
-   * Merge pull request #464 from denniscoorn-paqt/fix/complexity-table-columns 
-   * releasing v2.8.0 
-   * Fixes issues with paths 
-   * Merge pull request #474 from phpmetrics/fixes_permissions_path 
-   * Updates test for phpunit compatibility 
-   * Merge pull request #475 from phpmetrics/phpunit-compatibility 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Thu, 24 Mar 2022 11:19:14 +0100
-
-phpmetrics (2.7.4) unstable; urgency=low
-   * Fix readme file (#438) 
-   * include by default the composer.lock localized at the root dir 
-   * Allow usage behind proxy 
-   * PR review changes 
-   * Refactor  following PR comments 
-   * PR review applied changes 
-   * Add php8 in travis  ci 
-   * Merge pull request #1 from phpmetrics/master 
-   * Fix typo 
-   * Removing PHP 7+ return value typehint 
-   * Merge pull request #454 from crimsonkissaki/crimsonkissaki-patch-1 
-   * Merge pull request #449 from ssfinney/master 
-   * Merge pull request #446 from alediator/proxy_env_use 
-   * Merge pull request #442 from AlexHowansky/master 
-   * [ISSUE-445] Fix warning with test on ansi 
-   * Merge pull request #456 from phpmetrics/ISSUE-445 
-   * [ISSUE-451] remove auto scrolling of charts 
-   * Merge pull request #447 from Big-Shark/patch-2 
-   * [ISSUE-436] Restore deb compilation 
-   * Fixed issue with incorrect table header on the complexity report page 
-   * Removed extraneous and invalid HTML syntax 
-   * Merge pull request #455 from phpmetrics/ISSUE-451 
-   * Solve passing null instead of int by removing the flag on the Finder, that is unused by the code. 
-   * Add PHP Attribute "ReturnTypeWillChange" on internal overload definitions as return type is missing. 
-   * Add "unknown" status for private packages to avoid deprecated error in version_compare usage. 
-   * Merge pull request #458 from phpmetrics/ISSUE-436 
-   * Add command to get summary as Json 
-   * Merge pull request #466 from phpmetrics/remove-php8.1-deprecations 
-   * Way to search patterns of code 
-   * Merge pull request #472 from phpmetrics/searches 
-   * Merge pull request #467 from roelbaka/addJsonSummary 
-   * Merge pull request #464 from denniscoorn-paqt/fix/complexity-table-columns 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Wed, 23 Mar 2022 22:00:37 +0100
-
-phpmetrics (2.7.2) unstable; urgency=low
-   * include by default the composer.json localized at the root dir 
-   * releasing v2.7.3 
-   * Create security.yml file 
-   * Bump php package required 
-   * Merge pull request #434 from Mte90/patch-1 
-   * Fix issue with charts in groups - Closes #429, Closes #433 
-   * Merge pull request #437 from phpmetrics/fix_issue_js 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Tue, 30 Jun 2020 22:31:52 +0200
-
-phpmetrics (2.7.1) unstable; urgency=low
-   * Fix path of reporter 
-   * releasing v2.7.2 
-   * include by default the composer.json localized at the root dir 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Sat, 27 Jun 2020 15:20:54 +0200
-
-phpmetrics (2.7.0) unstable; urgency=low
-   * Fixed colors of JSON file in markdown 
-   * Fixed markdown and hidden char 
-   * Fix #429, bug when generating html report. 
-   * Fix #431, only outdated packages will be reported 
-   * Merge pull request #430 from pts-contrib/bug-429 
-   * Merge pull request #432 from pts-contrib/bug-431 
-   * fix contribution typo 
-   * releasing v2.7.1 
-   * Fix path of reporter 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Sat, 27 Jun 2020 15:06:49 +0200
-
-phpmetrics (2.6.2) unstable; urgency=low
-   * New composer report and improved UI 
-   * Merge pull request #424 from phpmetrics/ui_composer 
-   * Group analyzed components by layer 
-   * Merge pull request #428 from phpmetrics/config_group 
-   * releasing v2.7.0 
-   * Fixed colors of JSON file in markdown 
-   * Fixed markdown and hidden char 
-   * Fix #429, bug when generating html report. 
-   * Fix #431, only outdated packages will be reported 
-   * Merge pull request #430 from pts-contrib/bug-429 
-   * Merge pull request #432 from pts-contrib/bug-431 
-   * fix contribution typo 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Sat, 27 Jun 2020 14:56:42 +0200
-
-phpmetrics (2.6.1) unstable; urgency=low
-   * Improved UI with help and gradients 
-   * Merge pull request #421 from phpmetrics/improved_ui 
-   * releasing v2.6.2 
-   * New composer report and improved UI 
-   * Merge pull request #424 from phpmetrics/ui_composer 
-   * Group analyzed components by layer 
-   * Merge pull request #428 from phpmetrics/config_group 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Fri, 26 Jun 2020 22:22:02 +0200
-
-phpmetrics (2.6.0) unstable; urgency=low
-   * Force GPG key for relasing 
-   * Improved page rank report, and UI #416 
-   * Merge pull request #420 from phpmetrics/416_improved_pagerank 
-   * Improved UI with help and gradients 
-   * hot fixing phar 
-   * Merge pull request #422 from phpmetrics/hf_phar 
-   * Remove not useful constant 
-   * Merge pull request #423 from phpmetrics/improved_code 
-   * releasing v2.6.1 
-   * Merge pull request #421 from phpmetrics/improved_ui 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Thu, 02 Apr 2020 22:21:45 +0200
-
-phpmetrics (2.5.0) unstable; urgency=low
-   * Documented how to release (#392) 
-   * Added editor config file (#393) 
-   * Updated changelog (#394) 
-   * improve docblocks 
-   * Added more codesniffer rules 
-   * Merge pull request #396 from phpmetrics/add-more-phpcs-rules 
-   * Merge pull request #395 from phpmetrics/docblock-improvements 
-   * Way to download report 
-   * Merge pull request #399 from phpmetrics/download_chart 
-   * Exclude doc and artifacts from phar 
-   * Explicitly define the class \Hal\Component\Ast\NodeTraverser to make PhpMetrics work using composer --classmap-authoritative. (#402) 
-   * Merge pull request #400 from phpmetrics/exclude-phar-files 
-   * Resolve PHP7 getters / setters (#405) 
-   * Ensure the packagist license is an array so they can be displayed. (#404) 
-   * Fix warning "Division by zero" when no package is defined. (#401) 
-   * move templates out of src 
-   * Remove folders from phpcs 
-   * Merge pull request #406 from phpmetrics/move-templates-out 
-   * Provide new issue template format. 
-   * Added Slack link (#411) 
-   * Provide configuration option "--maintainability-index-without-comments". 
-   * Remove command line and always provide metrics MI without comments additionnaly from MI. Add a carousel in the main HTML report page to display both graph at the same time. 
-   * Move new files for carousel inside new template folder after rebasing from master. 
-   * Fix bug with dots in the carousel + add titles on dots for accessibility. 
-   * add metrics description file 
-   * Merge pull request #408 from phpmetrics/new-issue-tpl 
-   * Merge pull request #412 from repzy/metrics-file 
-   * Merge pull request #407 from phpmetrics/issue-325-provide-miwoc 
-   * fix releasing script 
-   * releasing v2.6.0 
-   * Force GPG key for relasing 
-   * Improved page rank report, and UI #416 
-   * Merge pull request #420 from phpmetrics/416_improved_pagerank 
-   * hot fixing phar 
-   * Merge pull request #422 from phpmetrics/hf_phar 
-   * Remove not useful constant 
-   * Merge pull request #423 from phpmetrics/improved_code 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Thu, 02 Apr 2020 21:54:40 +0200
-
-phpmetrics (2.4.1) unstable; urgency=low
-   * Test on PHP 7.3 
-   * Don't leave notice when array is small 
-   * Add final to class metric 
-   * Update ClassEnumVisitor.php 
-   * Merge pull request #371 from lencse/php73 
-   * Fix issue#380. Typo in Blob report 
-   * Merge pull request #385 from phpmetrics/issue#380 
-   * Added sort package config to composer 
-   * Merge pull request #388 from phpmetrics/sort-packages 
-   * Include codesniffer. Remove alias function and short array syntax (#387) 
-   * Remove superfluous docblocks that are adding no value (#390) 
-   * Skip `self` and `parent` from external dependencies (#1) (#370) 
-   * Trying to fix deprecation of PSR-0 (issue#382) (#384) 
-   * file_exists > is_file (#366) 
-   * Apply PSR-2 codestyle (#389) 
-   * Update phpunit to use highest version possible (#391) 
-   * Merge pull request #375 from gmponos/patch-1 
-   * Merge pull request #372 from lencse/loc-report 
-   * Test against PHP 7.4 (#383) 
-   * releasing 
-   * releasing v2.4.1 
-   * Update contributing.md 
-   * update readme file 
-   * Merge branch 'master' of github.com:phpmetrics/PhpMetrics 
-   * Fixed binary tests 
-   * releasing v2.5.0 
-   * Documented how to release (#392) 
-   * Added editor config file (#393) 
-   * Updated changelog (#394) 
-   * improve docblocks 
-   * Added more codesniffer rules 
-   * Merge pull request #396 from phpmetrics/add-more-phpcs-rules 
-   * Merge pull request #395 from phpmetrics/docblock-improvements 
-   * Way to download report 
-   * Merge pull request #399 from phpmetrics/download_chart 
-   * Exclude doc and artifacts from phar 
-   * Explicitly define the class \Hal\Component\Ast\NodeTraverser to make PhpMetrics work using composer --classmap-authoritative. (#402) 
-   * Merge pull request #400 from phpmetrics/exclude-phar-files 
-   * Resolve PHP7 getters / setters (#405) 
-   * Ensure the packagist license is an array so they can be displayed. (#404) 
-   * Fix warning "Division by zero" when no package is defined. (#401) 
-   * move templates out of src 
-   * Remove folders from phpcs 
-   * Merge pull request #406 from phpmetrics/move-templates-out 
-   * Provide new issue template format. 
-   * Added Slack link (#411) 
-   * Provide configuration option "--maintainability-index-without-comments". 
-   * Remove command line and always provide metrics MI without comments additionnaly from MI. Add a carousel in the main HTML report page to display both graph at the same time. 
-   * Move new files for carousel inside new template folder after rebasing from master. 
-   * Fix bug with dots in the carousel + add titles on dots for accessibility. 
-   * add metrics description file 
-   * Merge pull request #408 from phpmetrics/new-issue-tpl 
-   * Merge pull request #412 from repzy/metrics-file 
-   * Merge pull request #407 from phpmetrics/issue-325-provide-miwoc 
-   * fix releasing script 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Sat, 28 Mar 2020 14:29:40 +0100
-
-phpmetrics (2.4.0) unstable; urgency=low
-   * Fix template type 
-   * Verify errors in php<7 
-   * Use class_alias to load php5 or php7 code 
-   * Merge pull request #361 from UFOMelkor/hotfix/360-php56 
-   * Retain the old ccn and add wmc as new metric 
-   * Merge pull request #362 from UFOMelkor/hotfix/remain-ccn 
-   * releasing v2.4.1 
-   * Test on PHP 7.3 
-   * Don't leave notice when array is small 
-   * Add final to class metric 
-   * Update ClassEnumVisitor.php 
-   * Merge pull request #371 from lencse/php73 
-   * Fix issue#380. Typo in Blob report 
-   * Merge pull request #385 from phpmetrics/issue#380 
-   * Added sort package config to composer 
-   * Merge pull request #388 from phpmetrics/sort-packages 
-   * Include codesniffer. Remove alias function and short array syntax (#387) 
-   * Remove superfluous docblocks that are adding no value (#390) 
-   * Skip `self` and `parent` from external dependencies (#1) (#370) 
-   * Trying to fix deprecation of PSR-0 (issue#382) (#384) 
-   * file_exists > is_file (#366) 
-   * Apply PSR-2 codestyle (#389) 
-   * Update phpunit to use highest version possible (#391) 
-   * Merge pull request #375 from gmponos/patch-1 
-   * Merge pull request #372 from lencse/loc-report 
-   * Test against PHP 7.4 (#383) 
-   * releasing 
-   * releasing v2.4.1 
-   * Update contributing.md 
-   * update readme file 
-   * Merge branch 'master' of github.com:phpmetrics/PhpMetrics 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Thu, 12 Dec 2019 09:01:35 +0100
-
-phpmetrics (2.0.0-rc) unstable; urgency=low
-   * way to get infos about unexpected bugs 
-   * Don't trigger the issuer on suppressed errors 
-   * Merge pull request #246 from UFOMelkor/hotfix/240 
-   * issuer logs are stored in file instead of stdout 
-   * analyze does not break in case of error 
-   * added tests about namespace resolution in externals 
-   * major issue with traverser 
-   * Way to get metric about Unit tests of project 
-   * added JUnit HTML report file 
-   * added icon for junit report 
-   * changed status code for --help and --version option 
-   * added a way to get latest results directly in json 
-   * released new phar 
-   * moved directory of releases in order to prevserve v1 compatibility 
-   * forced version of phar 
-   * preparing v2 
-   * php7 is now the main version for building artifacts 
-   * updated ci 
-   * releasing v2.0.0 
-   * Fix undefined MaintainabilityIndex on interfaces. 
-   * Run on Trusty Beta Container 
-   * Disable JIT compilation in hhvm, as the JIT is useless for short live scripts like tests. 
-   * Fixed typo 
-   * improved unit testing report 
-   * removed symfony/console component 
-   * force phpunit version to <v6.0 
-   * expose ClassEnumVisitor failure with anonymous class 
-   * now junit parser uses DomDocument. Fixed codeception junit files parsing 
-   * dropped support of PHP 5.4 
-   * improved UI 
-   * fixed link of html report page 
-   * changed colors of Junit report graph 
-   * dropped support of hhvm-nighly 
-   * lot of minors changes in UI 
-   * Merge branch 'master' of https://github.com/marcosh/PhpMetrics into marcosh-master 
-   * way to disable issuer 
-   * fixes #266 - notice while parsing of anonymous classes 
-   * Merge branch 'marcosh-master' 
-   * Merge pull request #265 from Vincentv92/master 
-   * Spelling fixes and removing some extra whitespace 
-   * Merge branch 'fix-undefined-mi-on-interfaces' of https://github.com/niconoe-/PhpMetrics into niconoe--fix-undefined-mi-on-interfaces 
-   * Merge branch 'niconoe--fix-undefined-mi-on-interfaces' 
-   * added calculation for max cyclomatic complexity for method in class 
-   * added tests for #238 
-   * resolving conflict 
-   * Merge branch 'improve-travis-ci' 
-   * updated documentation about PATH envvar and composer gloab require 
-   * fixed typos (whitespaces) in readme 
-   * released v2.1.0 
-   * Merge pull request #272 from kazimierasbutkus/master 
-   * Fix version number. 
-   * Merge pull request #275 from mageekguy/patch-1 
-   * fixes #276 issue whith OutputInterface 
-   * added Composer analysis 
-   * fixed warning with undeclared variable 
-   * minimal support of mobile in HTML report 
-   * fixed issue with composer report : only one composer.json was considered 
-   * simplified and splitted documentation 
-   * fixed typos in README with blank spaces 
-   * fixed link of image in documentation 
-   * added link to spdx license in composer report 
-   * fixed responsive typos 
-   * documentation about releasing 
-   * releasing v2.2.0 
-   * Fix twitter link 
-   * Adjust PHPDoc types 
-   * Fix name resolving of anonymous classes 
-   * Allow // in text without counting it as comment 
-   * Fixed typo in description 
-   * Update style.css 
-   * updated pmd priority levels 
-   * Added changelog 
-   * typo fix 
-   * added links to changelog 
-   * changed markdown to match keep-a-changelog 
-   * added links to footer 
-   * Change heading for LOC graph. 
-   * add preg_quote around dir 
-   * Merge pull request #278 from UFOMelkor/typo/twitter-link 
-   * Merge pull request #281 from UFOMelkor/hotfix/280 
-   * Merge pull request #282 from UFOMelkor/hotfix/273 
-   * Merge pull request #285 from j92/fix_typo 
-   * Merge pull request #287 from rafaelign/master 
-   * Merge pull request #290 from bangpound/patch-1 
-   * Merge pull request #293 from paolomainardi/feature/fix-preg-quoting 
-   * Fix for #280 (anonymous classes support for PHP 7.1) 
-   * Added a newline to the end of a test file 
-   * Merge pull request #299 from FractalizeR-Forks/fix-anonymous-classes-in-php-7.1 
-   * fix: disabled deb artifact 
-   * fix: disabled deb artifact in travis 
-   * way to know parents 
-   * way to get information about depth and childs of node in a tree 
-   * way to get average height of branches in graph 
-   * way to know the Depth of inheritance tree 
-   * way to get the list of metrics 
-   * added CSV report 
-   * added json report 
-   * fixed style 
-   * added the key --report-json to validator 
-   * Merge pull request #301 from phpmetrics/feature/reports 
-   * Adding support for configuration files to read settings from 
-   * Add installed package column when composer.lock file is found. 
-   * Preventing duplicate edges from appearing in a graph using Deduplicated graph class. Fixes #291. 
-   * Add export-ignore option to reduce the archive size of composer downloading. 
-   * Add dockerfile in project to use the latest phar. 
-   * Merge pull request #303 from FractalizeR-Forks/configuration-file-support 
-   * Merge pull request #305 from phpmetrics/fix-284 
-   * Merge pull request #306 from phpmetrics/ignore-export-composer-installation 
-   * Merge pull request #304 from FractalizeR-Forks/avoid_duplicate_edges_in_graph 
-   * Add Traits in parsing through all visitors. 
-   * Fix #286: Missing files in the phar build due to bad regexp filter. 
-   * Fix bad preg_quote usage that fails the regexp and so, fails the Finder. 
-   * Merge pull request #310 from phpmetrics/fix-286 
-   * Add unit tests to check the bugfix about finder. 
-   * Merge pull request #311 from phpmetrics/fix-bad-regexp-finder 
-   * Merge pull request #307 from phpmetrics/fix-244 
-   * Merge pull request #279 from UFOMelkor/docs/phpdoc 
-   * Embed dependent files so generated reports can be used offline 
-   * Fix bad output in the junit report. 
-   * Dropped the changelog 
-   * Merge pull request #312 from phpmetrics/fix-263 
-   * Merge pull request #309 from phpmetrics/fix-308 
-   * Merge pull request #302 from dennisdegreef/localFilesOnly 
-   * Merge pull request #288 from krukru/pmd-priority-rewrite 
-   * Fix makefiles about releasing a new version. 
-   * Fix bad carridge return when displaying the version. 
-   * Merge pull request #313 from phpmetrics/fix-release 
-   * releasing v2.3.0 
-   * Fix missing escapeshellarg on git command arguments to avoid security and access troubles. 
-   * Fix #317: Only consolidate class metrics that groups Classes and Traits to calculate sums and averages. 
-   * Merge pull request #316 from phpmetrics/fix-315 
-   * Merge pull request #318 from phpmetrics/fix-317 
-   * releasing v2.3.1 
-   * HotFix #317: Bad assignement on item classmetrics. 
-   * Merge pull request #319 from phpmetrics/hotfix-classmetric 
-   * releasing v2.3.2 
-   * Adds www. in URLs phpmetrics.org 
-   * Add package metrics 
-   * Add package violation and some charts 
-   * Ignore traits for now 
-   * Test package metrics 
-   * Add cli output 
-   * Use assertCount 
-   * Test against PHP 7.2 
-   * Merge pull request #333 from carusogabriel/assert-count 
-   * Merge pull request #334 from carusogabriel/patch-1 
-   * Handle traits like classes 
-   * Add Stable Abstractions Principle 
-   * Detect getters and setters with types 
-   * Improve composer package version comparison 
-   * Rename method - typo 
-   * Round percentiles on X-axis to prevent roundoff error 
-   * Add else and elseif statements to the cyclomatic complexity test 
-   * Fix bug that caused cyclomatic complexity to be underreported 
-   * Merge pull request #336 from UFOMelkor/hotfix/335-role-detection-with-php7 
-   * Support nikic/php-parser:^4 
-   * Switch node traverser depending on php version 
-   * Merge pull request #337 from juliendufresne/master 
-   * Merge pull request #283 from UFOMelkor/feature/package-metrics 
-   * Add changelog 
-   * Filter identifiers to simplify php-parser:^4 compatibility 
-   * Do not crash using php-parser:^4 
-   * Add Support for Stmt\Expression 
-   * Merge pull request #339 from ssfinney/fixRoundingOnLocReport 
-   * Merge pull request #344 from fabianbadoi/fix-343 
-   * Remove php 7 code 
-   * Change the calculation of cyclomatic complexity 
-   * Verify that traits are abstract 
-   * Force traits to be abstract 
-   * Merge pull request #354 from UFOMelkor/hotfix/351 
-   * fix for repeating bloc-ids 
-   * Finalize cyclomatic complexity changes 
-   * Test against lowest and highest dependencies 
-   * Raise version of sebastian/comparator to at least 1.2.3 
-   * Merge pull request #356 from dumith-eranga/fix/report-html-violation-bloc-toggle 
-   * Fix phpdoc argument types not matching actual types 
-   * Fix issue where phpmetrics would not find any files 
-   * Add test for current path exclusion 
-   * Merge pull request #321 from ottaviano/fix-url-phpmetrics.org 
-   * Merge pull request #353 from UFOMelkor/metric/ccn 
-   * Merge pull request #347 from UFOMelkor/feature/345-php-parser-4 
-   * Do not iterate over ->expr twice 
-   * Merge pull request #357 from UFOMelkor/hotfix/ccn 
-   * Adjust cc violation limits 
-   * Merge pull request #358 from UFOMelkor/feature/cc-violation-adjustments 
-   * releasing 2.4.0 
-   * Fix template type 
-   * Verify errors in php<7 
-   * Use class_alias to load php5 or php7 code 
-   * Merge pull request #361 from UFOMelkor/hotfix/360-php56 
-   * Retain the old ccn and add wmc as new metric 
-   * Merge pull request #362 from UFOMelkor/hotfix/remain-ccn 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Tue, 10 Jul 2018 19:17:23 +0200
-
-phpmetrics (2.4.0) unstable; urgency=low
-   * HotFix #317: Bad assignement on item classmetrics.
-   * Merge pull request #319 from phpmetrics/hotfix-classmetric
-   * releasing v2.3.2
-   * Adds www. in URLs phpmetrics.org
-   * Add package metrics
-   * Add package violation and some charts
-   * Ignore traits for now
-   * Test package metrics
-   * Add cli output
-   * Use assertCount
-   * Test against PHP 7.2
-   * Merge pull request #333 from carusogabriel/assert-count
-   * Merge pull request #334 from carusogabriel/patch-1
-   * Handle traits like classes
-   * Add Stable Abstractions Principle
-   * Detect getters and setters with types
-   * Improve composer package version comparison
-   * Rename method - typo
-   * Round percentiles on X-axis to prevent roundoff error
-   * Add else and elseif statements to the cyclomatic complexity test
-   * Fix bug that caused cyclomatic complexity to be underreported
-   * Merge pull request #336 from UFOMelkor/hotfix/335-role-detection-with-php7
-   * Support nikic/php-parser:^4
-   * Switch node traverser depending on php version
-   * Merge pull request #337 from juliendufresne/master
-   * Merge pull request #283 from UFOMelkor/feature/package-metrics
-   * Add changelog
-   * Filter identifiers to simplify php-parser:^4 compatibility
-   * Do not crash using php-parser:^4
-   * Add Support for Stmt\Expression
-   * Merge pull request #339 from ssfinney/fixRoundingOnLocReport
-   * Merge pull request #344 from fabianbadoi/fix-343
-   * Remove php 7 code
-   * Change the calculation of cyclomatic complexity
-   * Verify that traits are abstract
-   * Force traits to be abstract
-   * Merge pull request #354 from UFOMelkor/hotfix/351
-   * fix for repeating bloc-ids
-   * Finalize cyclomatic complexity changes
-   * Test against lowest and highest dependencies
-   * Raise version of sebastian/comparator to at least 1.2.3
-   * Merge pull request #356 from dumith-eranga/fix/report-html-violation-bloc-toggle
-   * Fix phpdoc argument types not matching actual types
-   * Fix issue where phpmetrics would not find any files
-   * Add test for current path exclusion
-   * Merge pull request #321 from ottaviano/fix-url-phpmetrics.org
-   * Merge pull request #353 from UFOMelkor/metric/ccn
-   * Merge pull request #347 from UFOMelkor/feature/345-php-parser-4
-   * Do not iterate over ->expr twice
-   * Merge pull request #357 from UFOMelkor/hotfix/ccn
-   * Adjust cc violation limits
-   * Merge pull request #358 from UFOMelkor/feature/cc-violation-adjustments
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Mon, 09 Jul 2018 14:22:08 +0200
-
-phpmetrics (2.3.0) unstable; urgency=low
-   * Fix missing escapeshellarg on git command arguments to avoid security and access troubles. 
-   * Fix #317: Only consolidate class metrics that groups Classes and Traits to calculate sums and averages. 
-   * Merge pull request #316 from phpmetrics/fix-315 
-   * Merge pull request #318 from phpmetrics/fix-317 
-   * releasing v2.3.1 
-   * HotFix #317: Bad assignement on item classmetrics. 
-   * Merge pull request #319 from phpmetrics/hotfix-classmetric 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Fri, 13 Oct 2017 18:11:18 +0200
-
-phpmetrics (2.2.0) unstable; urgency=low
-   * fix: disabled deb artifact 
-   * fix: disabled deb artifact in travis 
-   * Fix twitter link 
-   * Adjust PHPDoc types 
-   * Fix name resolving of anonymous classes 
-   * Allow // in text without counting it as comment 
-   * Fixed typo in description 
-   * Update style.css 
-   * updated pmd priority levels 
-   * Added changelog 
-   * typo fix 
-   * added links to changelog 
-   * changed markdown to match keep-a-changelog 
-   * added links to footer 
-   * Change heading for LOC graph. 
-   * add preg_quote around dir 
-   * Merge pull request #278 from UFOMelkor/typo/twitter-link 
-   * Merge pull request #281 from UFOMelkor/hotfix/280 
-   * Merge pull request #282 from UFOMelkor/hotfix/273 
-   * Merge pull request #285 from j92/fix_typo 
-   * Merge pull request #287 from rafaelign/master 
-   * Merge pull request #290 from bangpound/patch-1 
-   * Merge pull request #293 from paolomainardi/feature/fix-preg-quoting 
-   * Fix for #280 (anonymous classes support for PHP 7.1) 
-   * Added a newline to the end of a test file 
-   * Merge pull request #299 from FractalizeR-Forks/fix-anonymous-classes-in-php-7.1 
-   * fix: disabled deb artifact 
-   * fix: disabled deb artifact in travis 
-   * way to know parents 
-   * way to get information about depth and childs of node in a tree 
-   * way to get average height of branches in graph 
-   * way to know the Depth of inheritance tree 
-   * way to get the list of metrics 
-   * added CSV report 
-   * added json report 
-   * fixed style 
-   * added the key --report-json to validator 
-   * Merge pull request #301 from phpmetrics/feature/reports 
-   * Adding support for configuration files to read settings from 
-   * Add installed package column when composer.lock file is found. 
-   * Preventing duplicate edges from appearing in a graph using Deduplicated graph class. Fixes #291. 
-   * Add export-ignore option to reduce the archive size of composer downloading. 
-   * Add dockerfile in project to use the latest phar. 
-   * Merge pull request #303 from FractalizeR-Forks/configuration-file-support 
-   * Merge pull request #305 from phpmetrics/fix-284 
-   * Merge pull request #306 from phpmetrics/ignore-export-composer-installation 
-   * Merge pull request #304 from FractalizeR-Forks/avoid_duplicate_edges_in_graph 
-   * Add Traits in parsing through all visitors. 
-   * Fix #286: Missing files in the phar build due to bad regexp filter. 
-   * Fix bad preg_quote usage that fails the regexp and so, fails the Finder. 
-   * Merge pull request #310 from phpmetrics/fix-286 
-   * Add unit tests to check the bugfix about finder. 
-   * Merge pull request #311 from phpmetrics/fix-bad-regexp-finder 
-   * Merge pull request #307 from phpmetrics/fix-244 
-   * Merge pull request #279 from UFOMelkor/docs/phpdoc 
-   * Embed dependent files so generated reports can be used offline 
-   * Fix bad output in the junit report. 
-   * Dropped the changelog 
-   * Merge pull request #312 from phpmetrics/fix-263 
-   * Merge pull request #309 from phpmetrics/fix-308 
-   * Merge pull request #302 from dennisdegreef/localFilesOnly 
-   * Merge pull request #288 from krukru/pmd-priority-rewrite 
-   * Fix makefiles about releasing a new version. 
-   * Fix bad carridge return when displaying the version. 
-   * Merge pull request #313 from phpmetrics/fix-release 
-   * releasing v2.3.0 
-   * Fix missing escapeshellarg on git command arguments to avoid security and access troubles. 
-   * Fix #317: Only consolidate class metrics that groups Classes and Traits to calculate sums and averages. 
-   * Merge pull request #316 from phpmetrics/fix-315 
-   * Merge pull request #318 from phpmetrics/fix-317 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Fri, 13 Oct 2017 18:01:53 +0200
-
-phpmetrics (2.1.0) unstable; urgency=low
-   * added calculation for max cyclomatic complexity for method in class 
-   * fixed typos (whitespaces) in readme 
-   * released v2.1.0 
-   * Merge pull request #272 from kazimierasbutkus/master 
-   * Fix version number. 
-   * Merge pull request #275 from mageekguy/patch-1 
-   * fixes #276 issue whith OutputInterface 
-   * added Composer analysis 
-   * fixed warning with undeclared variable 
-   * minimal support of mobile in HTML report 
-   * fixed issue with composer report : only one composer.json was considered 
-   * simplified and splitted documentation 
-   * fixed typos in README with blank spaces 
-   * fixed link of image in documentation 
-   * added link to spdx license in composer report 
-   * fixed responsive typos 
-   * documentation about releasing 
-   * releasing v2.2.0 
-   * Fix twitter link 
-   * Adjust PHPDoc types 
-   * Fix name resolving of anonymous classes 
-   * Allow // in text without counting it as comment 
-   * Fixed typo in description 
-   * Update style.css 
-   * updated pmd priority levels 
-   * Added changelog 
-   * typo fix 
-   * added links to changelog 
-   * changed markdown to match keep-a-changelog 
-   * added links to footer 
-   * Change heading for LOC graph. 
-   * add preg_quote around dir 
-   * Merge pull request #278 from UFOMelkor/typo/twitter-link 
-   * Merge pull request #281 from UFOMelkor/hotfix/280 
-   * Merge pull request #282 from UFOMelkor/hotfix/273 
-   * Merge pull request #285 from j92/fix_typo 
-   * Merge pull request #287 from rafaelign/master 
-   * Merge pull request #290 from bangpound/patch-1 
-   * Merge pull request #293 from paolomainardi/feature/fix-preg-quoting 
-   * Fix for #280 (anonymous classes support for PHP 7.1) 
-   * Added a newline to the end of a test file 
-   * Merge pull request #299 from FractalizeR-Forks/fix-anonymous-classes-in-php-7.1 
-   * fix: disabled deb artifact 
-   * fix: disabled deb artifact in travis 
-   * way to know parents 
-   * way to get information about depth and childs of node in a tree 
-   * way to get average height of branches in graph 
-   * way to know the Depth of inheritance tree 
-   * way to get the list of metrics 
-   * added CSV report 
-   * added json report 
-   * fixed style 
-   * added the key --report-json to validator 
-   * Merge pull request #301 from phpmetrics/feature/reports 
-   * Adding support for configuration files to read settings from 
-   * Add installed package column when composer.lock file is found. 
-   * Preventing duplicate edges from appearing in a graph using Deduplicated graph class. Fixes #291. 
-   * Add export-ignore option to reduce the archive size of composer downloading. 
-   * Add dockerfile in project to use the latest phar. 
-   * Merge pull request #303 from FractalizeR-Forks/configuration-file-support 
-   * Merge pull request #305 from phpmetrics/fix-284 
-   * Merge pull request #306 from phpmetrics/ignore-export-composer-installation 
-   * Merge pull request #304 from FractalizeR-Forks/avoid_duplicate_edges_in_graph 
-   * Add Traits in parsing through all visitors. 
-   * Fix #286: Missing files in the phar build due to bad regexp filter. 
-   * Fix bad preg_quote usage that fails the regexp and so, fails the Finder. 
-   * Merge pull request #310 from phpmetrics/fix-286 
-   * Add unit tests to check the bugfix about finder. 
-   * Merge pull request #311 from phpmetrics/fix-bad-regexp-finder 
-   * Merge pull request #307 from phpmetrics/fix-244 
-   * Merge pull request #279 from UFOMelkor/docs/phpdoc 
-   * Embed dependent files so generated reports can be used offline 
-   * Fix bad output in the junit report. 
-   * Dropped the changelog 
-   * Merge pull request #312 from phpmetrics/fix-263 
-   * Merge pull request #309 from phpmetrics/fix-308 
-   * Merge pull request #302 from dennisdegreef/localFilesOnly 
-   * Merge pull request #288 from krukru/pmd-priority-rewrite 
-   * Fix makefiles about releasing a new version. 
-   * Fix bad carridge return when displaying the version. 
-   * Merge pull request #313 from phpmetrics/fix-release 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Fri, 22 Sep 2017 11:32:45 +0200
-
-phpmetrics (1.9.2) unstable; urgency=low
-   * Removed unneeded code 
-   * Removed unneeded code 
-   * plugin engine: added a way to executing analayzes from plugin and to customize reports 
-   * updated tests of formaters in order to take care of extensions service 
-   * updated documentation about plugins 
-   * Merge pull request #166 from fonsecas72/fix_unused_params 
-   * releasing v1.9.2 
-   * added bintray.json in process of releasing 
-   * minor change in HTML report: footer is fixed 
-   * fixed an error in travis with bintray deploy 
-   * releasing v1.9.2 
-   * added bintray.json in process of releasing 
-   * minor change in HTML report: footer is fixed 
-   * added new default ruleset object 
-   * new command: way to generate default config file 
-   * added tests for InitConfigCommand 
-   * added template for new issues on github 
-   * pass TokenCollection instead of Tokenizer to Metrics 
-   * added compatibility with Symfony3 
-   * installation of graphviz is checked before running analyze 
-   * Merge pull request #211 from phpmetrics/features/210-check-for-graphviz-when-bubbles-chart-is-generated 
-   * restored Cache classes (ref #208) 
-   * Typo 
-   * fixed typos with new plugin feature 
-   * Merge pull request #208 from pavarnos/master 
-   * Merge pull request #207 from phpmetrics/features/default-ruleset 
-   * Merge pull request #202 from phpmetrics/plugins 
-   * Merge pull request #197 from phpmetrics/features/192-compatibility-with-sf3 
-   * resolving conflicts 
-   * Merge branch 'patch-1' of https://github.com/theofidry/PhpMetrics into theofidry-patch-1 
-   * Merge branch 'theofidry-patch-1' 
-   * releasing v1.10.0 
-   * added information about composer plugin in README 
-   * imported new v2 stack, with nikic parser 
-   * updated CI 
-   * cleaned documentation 
-   * added CLI report 
-   * added screenshot 
-   * moved screenshot 
-   * removed unused files 
-   * downgraded PHPUnit version 
-   * way to have Debian package 
-   * Artifacts are pushed to bintray 
-   * way yo have trends of build 
-   * trend for ccn 
-   * fixed bad require 
-   * way to have Git statistics 
-   * added infos about git in CLI report 
-   * added some functional tests for Phar artifact 
-   * added a TV panel 
-   * fixed warnings when log directory already exists 
-   * tool to detect role of method (getter, setter) 
-   * added Metric interface 
-   * way to detect role of method 
-   * new violation engine and report 
-   * fixed issue when parameter contains double quotes 
-   * fixed error in test of phar 
-   * fixed tests on PHP <5.6 
-   * annotations are listed in externals 
-   * Violations in CLI report 
-   * added 'cache' in the default exclusion list 
-   * new XML violations report 
-   * releases are also stored in Github 
-   * fixes #236 : incorrect parsing of options with values 
-   * fixes #237 - warning in consolidation under php7 
-   * updated autoload 
-   * updated deb genetation 
-   * externals resources are loaded HTTPS 
-   * fixed warning with PHP 5.4 
-   * git add use --force to add .deb to release 
-   * way to get infos about unexpected bugs 
-   * Don't trigger the issuer on suppressed errors 
-   * Merge pull request #246 from UFOMelkor/hotfix/240 
-   * issuer logs are stored in file instead of stdout 
-   * analyze does not break in case of error 
-   * added tests about namespace resolution in externals 
-   * major issue with traverser 
-   * Way to get metric about Unit tests of project 
-   * added JUnit HTML report file 
-   * added icon for junit report 
-   * changed status code for --help and --version option 
-   * added a way to get latest results directly in json 
-   * released new phar 
-   * moved directory of releases in order to prevserve v1 compatibility 
-   * forced version of phar 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Mon, 30 Jan 2017 06:17:27 +0100
-
-phpmetrics (1.9.2) unstable; urgency=low
-   * Removed unneeded code 
-   * Removed unneeded code 
-   * plugin engine: added a way to executing analayzes from plugin and to customize reports 
-   * updated tests of formaters in order to take care of extensions service 
-   * updated documentation about plugins 
-   * Merge pull request #166 from fonsecas72/fix_unused_params 
-   * releasing v1.9.2 
-   * added bintray.json in process of releasing 
-   * minor change in HTML report: footer is fixed 
-   * fixed an error in travis with bintray deploy 
-   * releasing v1.9.2 
-   * added bintray.json in process of releasing 
-   * minor change in HTML report: footer is fixed 
-   * added new default ruleset object 
-   * new command: way to generate default config file 
-   * added tests for InitConfigCommand 
-   * added template for new issues on github 
-   * pass TokenCollection instead of Tokenizer to Metrics 
-   * added compatibility with Symfony3 
-   * installation of graphviz is checked before running analyze 
-   * Merge pull request #211 from phpmetrics/features/210-check-for-graphviz-when-bubbles-chart-is-generated 
-   * restored Cache classes (ref #208) 
-   * Typo 
-   * fixed typos with new plugin feature 
-   * Merge pull request #208 from pavarnos/master 
-   * Merge pull request #207 from phpmetrics/features/default-ruleset 
-   * Merge pull request #202 from phpmetrics/plugins 
-   * Merge pull request #197 from phpmetrics/features/192-compatibility-with-sf3 
-   * resolving conflicts 
-   * Merge branch 'patch-1' of https://github.com/theofidry/PhpMetrics into theofidry-patch-1 
-   * Merge branch 'theofidry-patch-1' 
-   * releasing v1.10.0 
-   * added information about composer plugin in README 
-   * imported new v2 stack, with nikic parser 
-   * updated CI 
-   * cleaned documentation 
-   * added CLI report 
-   * added screenshot 
-   * moved screenshot 
-   * removed unused files 
-   * downgraded PHPUnit version 
-   * way to have Debian package 
-   * Artifacts are pushed to bintray 
-   * way yo have trends of build 
-   * trend for ccn 
-   * fixed bad require 
-   * way to have Git statistics 
-   * added infos about git in CLI report 
-   * added some functional tests for Phar artifact 
-   * added a TV panel 
-   * fixed warnings when log directory already exists 
-   * tool to detect role of method (getter, setter) 
-   * added Metric interface 
-   * way to detect role of method 
-   * new violation engine and report 
-   * fixed issue when parameter contains double quotes 
-   * fixed error in test of phar 
-   * fixed tests on PHP <5.6 
-   * annotations are listed in externals 
-   * Violations in CLI report 
-   * added 'cache' in the default exclusion list 
-   * new XML violations report 
-   * releases are also stored in Github 
-   * fixes #236 : incorrect parsing of options with values 
-   * fixes #237 - warning in consolidation under php7 
-   * updated autoload 
-   * updated deb genetation 
-   * externals resources are loaded HTTPS 
-   * fixed warning with PHP 5.4 
-   * git add use --force to add .deb to release 
-   * way to get infos about unexpected bugs 
-   * Don't trigger the issuer on suppressed errors 
-   * Merge pull request #246 from UFOMelkor/hotfix/240 
-   * issuer logs are stored in file instead of stdout 
-   * analyze does not break in case of error 
-   * added tests about namespace resolution in externals 
-   * major issue with traverser 
-   * Way to get metric about Unit tests of project 
-   * added JUnit HTML report file 
-   * added icon for junit report 
-   * changed status code for --help and --version option 
-   * added a way to get latest results directly in json 
-   * released new phar 
-   * moved directory of releases in order to prevserve v1 compatibility 
-   * forced version of phar 
-
-  -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Mon, 30 Jan 2017 06:17:05 +0100
-
-phpmetrics (1.8.2) unstable; urgency=low
-
-   * resolves problems with output during unit tests
-   * releasing v1.8.3
-   * fix calculation of duration
-   * rename variable
-   * force $duration to postive integer
-   * add test with data provider to check for correct calculated duration on CLI detail output
-   * travis and packagist migrated to new organization
-   * Merge pull request #182 from Halleck45/master
-   * better explanation
-   * way to have correct version in bin/phpmetrics. Fixes #177
-   * typo in 'latest stable version' badge
-   * Merge pull request #183 from Halleck45/master
-   * Merge pull request #180 from skors/patch-1
-   * provide current version of PhpMetrics in HTML report. Fixes #161
-   * fixed typos with version
-   * Merge pull request #184 from Halleck45/master
-   * phar is now pushed to bintray
-   * configured travis (local)
-   * phar is pushed to bintray when build is on master
-   * [bintray] minor improvements
-   * Ruby is installed by build only when deployment is required
-   * wip debian
-
- -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Wed, 24 Feb 2016 17:44:56 +0100
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/artifacts/debian/compat b/artifacts/debian/compat
deleted file mode 100644
index c7930257..00000000
--- a/artifacts/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-7
\ No newline at end of file
diff --git a/artifacts/debian/control b/artifacts/debian/control
deleted file mode 100644
index bea0068b..00000000
--- a/artifacts/debian/control
+++ /dev/null
@@ -1,16 +0,0 @@
-Source: phpmetrics
-Section: base
-Priority: optional
-Maintainer: Jean-François Lépine <lepinejeanfrancois@yahoo.fr>
-Build-Depends: make
-Standards-Version: 0.0.0
-Vcs-Git: https://github.com/phpmetrics/PhpMetrics.git
-Vcs-Browser: https://github.com/phpmetrics/PhpMetrics
-Homepage: http://www.phpmetrics.org
-
-Package: phpmetrics
-Architecture: all
-Depends: php-cli (>= 7.0.0+)
-Description: Static analyzer for PHP
-  PhpMetrics provides informations and charts about quality, complexity, maintainability... of your
-  PHP code. Its supports any PHP code from PHP 5.3 to PHP 7
diff --git a/artifacts/debian/copyright b/artifacts/debian/copyright
deleted file mode 100644
index 79be43ec..00000000
--- a/artifacts/debian/copyright
+++ /dev/null
@@ -1,30 +0,0 @@
-Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=135
-name: phpmetrics
-Maintainer: Jean-François Lépine <lepinejeanfrancois@yahoo.fr>
-Source: https://github.com/phpmetrics/PhpMetrics
-
-Copyright: 2016 Jean-François Lépine <lepinejeanfrancois@yahoo.fr>
-License: MIT
-
-License: MIT
-  The MIT License (MIT)
-
-  Copyright (c) 2013 Jean-François Lépine <http://blog.lepine.pro>
-
-  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.
\ No newline at end of file
diff --git a/artifacts/debian/files b/artifacts/debian/files
deleted file mode 100644
index 4dbe1fbe..00000000
--- a/artifacts/debian/files
+++ /dev/null
@@ -1,2 +0,0 @@
-phpmetrics_3.0.0rc7_all.deb base optional
-phpmetrics_3.0.0rc7_amd64.buildinfo base optional
diff --git a/artifacts/debian/install b/artifacts/debian/install
deleted file mode 100644
index bfed0d71..00000000
--- a/artifacts/debian/install
+++ /dev/null
@@ -1 +0,0 @@
-phpmetrics /usr/bin
\ No newline at end of file
diff --git a/artifacts/debian/phpmetrics.1 b/artifacts/debian/phpmetrics.1
deleted file mode 100644
index 46cb7427..00000000
--- a/artifacts/debian/phpmetrics.1
+++ /dev/null
@@ -1,35 +0,0 @@
-.TH PHPMETRICS 1
-.SH NAME
-phpmetrics \- static analysis for PHP
-.SH SYNOPSIS
-.B phpmetrics
-[\fB\-\-report\-html=\fR\fIPATH\fR]
-.IR file_or_directory ...
-.SH DESCRIPTION
-.B phpmetrics
-executes a static analysis on PHP (PHP 5 to PHP 7 included) code and provides various reports (HTML, XML, JSON...).
-.SH OPTIONS
-.TP
-.BR \-h ", " \-\-help\fI
-Display help.
-.TP
-.BR \-\-report-html =\fIdirectory
-Path to save report in HTML format. Example: /tmp/my-directory
-.TP
-.BR \-\-report-violations =\fIfilename
-Path to save violations in XML format. Example: /tmp/report.xml
-.TP
-.BR \-\-extensions =\fIextension1,extension2
-Extensions to include, separated by comma (,)
-.TP
-.BR \-\-exclude =\fIdirectory1,directory2
-Subdirectories to exclude
-.TP
-.BR \-\-symlinks
-Enable following symlinks
-.TP
-.BR \-q ", " \-\-quiet\fI
-Do not output any message.
-.TP
-.BR \-V ", " \-\-version\fI
-Display version of PhpMetrics
diff --git a/artifacts/debian/phpmetrics.substvars b/artifacts/debian/phpmetrics.substvars
deleted file mode 100644
index 978fc8b5..00000000
--- a/artifacts/debian/phpmetrics.substvars
+++ /dev/null
@@ -1,2 +0,0 @@
-misc:Depends=
-misc:Pre-Depends=
diff --git a/artifacts/debian/rules b/artifacts/debian/rules
deleted file mode 100755
index 63c09fd6..00000000
--- a/artifacts/debian/rules
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/make -f
-#DH_VERBOSE = 1
-DPKG_EXPORT_BUILDFLAGS = 1
-include /usr/share/dpkg/default.mk
-
-%:
-	dh $@
-
-override_dh_auto_test:
-ifeq (,$(findstring nocheck, $(DEB_BUILD_OPTIONS)))
-	bash debian/testing/binaryTest.sh
-else
-	@echo "** tests disabled"
-endif
-
-
-
-override_dh_auto_clean:
-	@echo "** no need to clean"
-override_dh_auto_build:
-	@echo "** no need to build"
-override_dh_auto_install:
-	@echo "** no need to install"
-	mkdir -p debian/tmp && cp debian/bin/phpmetrics debian/tmp/phpmetrics
-override_dh_usrlocal:
\ No newline at end of file
diff --git a/artifacts/debian/testing/binaryTest.sh b/artifacts/debian/testing/binaryTest.sh
deleted file mode 100755
index 1682a934..00000000
--- a/artifacts/debian/testing/binaryTest.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env bash
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-echo $DIR
-function testPharIsNotCorrupted {
-     ${DIR}/../bin/phpmetrics --version|grep "PhpMetrics"
-}
-
-testPharIsNotCorrupted > /dev/null && echo "." ||exit 1
\ No newline at end of file
diff --git a/artifacts/phar/Makefile b/artifacts/phar/Makefile
deleted file mode 100644
index fb7adeab..00000000
--- a/artifacts/phar/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# Build phar
-build-phar: test
-	@mkdir -p ${BUILD_DIR}
-	@echo Copying sources
-	@mkdir -p /tmp/phpmetrics-build
-	@cp * -R /tmp/phpmetrics-build
-	@rm -Rf /tmp/phpmetrics-build/vendor /tmp/phpmetrics-build/composer.lock
-
-	@echo Releasing phar
-	@sed -i "s/<VERSION>/$CURRENT_TAG/g" /tmp/phpmetrics-build/artifacts/phar/build.php
-
-	@echo Installing dependencies
-	@cd /tmp/phpmetrics-build && composer install --no-dev --optimize-autoloader --prefer-dist
-
-	@echo Building phar
-	@cd /tmp/phpmetrics-build && php artifacts/phar/build.php
-	@cp /tmp/phpmetrics-build/build/phpmetrics.phar ${BUILD_DIR}/phpmetrics.phar
-	@rm -Rf /tmp/phpmetrics-build
-
diff --git a/artifacts/phar/build.php b/artifacts/phar/build.php
deleted file mode 100644
index 8ab7d1ad..00000000
--- a/artifacts/phar/build.php
+++ /dev/null
@@ -1,67 +0,0 @@
-<?php
-chdir(__DIR__ . '/../../');
-
-if (!file_exists('vendor/autoload.php')) {
-    echo '[ERROR] It\'s required to run "composer install" before building PhpMetrics!' . PHP_EOL;
-    exit(1);
-}
-
-$filename = 'build/phpmetrics.phar';
-if (file_exists($filename)) {
-    unlink($filename);
-}
-
-$phar = new \Phar($filename, 0, 'phpmetrics.phar');
-$phar->setSignatureAlgorithm(\Phar::SHA1);
-$phar->startBuffering();
-
-$files = array_merge(rglob('*.php'), rglob('*.js'), rglob('*.html'), rglob('*.css'), rglob('*.png'), rglob('*.ttf'));
-$exclude = '!^(\.git)|(\.svn)|(bin)|([tT]ests)|(doc)|(artifacts)!';
-foreach ($files as $file) {
-    if (preg_match($exclude, $file)) {
-        continue;
-    }
-    $path = str_replace(__DIR__ . '/', '', $file);
-    $phar->addFromString($path, file_get_contents($file));
-}
-
-$phar->setStub(<<<STUB
-#!/usr/bin/env php
-<?php
-
-/*
-* This file is part of the PhpMetrics
-*
-* (c) Jean-François Lépine
-*
-* This source file is subject to the MIT license that is bundled
-* with this source code in the file LICENSE.
-*/
-
-Phar::mapPhar('phpmetrics.phar');
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-// PLEASE do not edit this file without editing bin/phpmetrics
-// PLEASE do not edit this file without editing bin/phpmetrics
-// PLEASE do not edit this file without editing bin/phpmetrics
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-require_once 'phar://phpmetrics.phar/vendor/autoload.php';
-(new \Hal\Application\Application())->run(\$argv);
-
-__HALT_COMPILER();
-STUB
-);
-$phar->stopBuffering();
-
-chmod($filename, 0755);
-
-function rglob($pattern = '*', $flags = 0, $path = '')
-{
-    $paths = glob($path . '*', GLOB_MARK | GLOB_ONLYDIR | GLOB_NOSORT);
-    $files = glob($path . $pattern, $flags);
-    foreach ($paths as $path) {
-        $files = array_merge($files, rglob($pattern, $flags, $path));
-    }
-    return $files;
-}
diff --git a/artifacts/phar/phpmetrics.deb b/artifacts/phar/phpmetrics.deb
deleted file mode 100644
index bc63aec9..00000000
Binary files a/artifacts/phar/phpmetrics.deb and /dev/null differ
diff --git a/artifacts/releasing/Dockerfile b/artifacts/releasing/Dockerfile
deleted file mode 100644
index 1525f60b..00000000
--- a/artifacts/releasing/Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-FROM composer/composer:2-bin AS composer
-
-# please do not use alpine here: We need a debian based image for .deb distribution
-FROM php:8.4-cli-bullseye
-
-# Installing ruby, semver and required dependencies
-RUN apt update \
-    && apt install -y ruby ruby-dev make build-essential git gnupg2 debhelper \
-    && gem install semver \
-    && echo "phar.readonly=0" > /usr/local/etc/php/conf.d/phar.ini
-
-RUN git config --global --add safe.directory /app
-
-# Installing musl-wrapper
-RUN apt install -y musl-dev musl-tools \
-    && ln -s /usr/bin/musl-gcc /usr/local/bin/musl-gcc \
-    && ln -s /usr/bin/musl-g++ /usr/local/bin/musl-g++
-
-# Installing composer
-ENV COMPOSER_ALLOW_SUPERUSER=1
-ENV PATH="${PATH}:/root/.composer/vendor/bin"
-COPY --from=composer /composer /usr/bin/composer
diff --git a/artifacts/standalone/Makefile b/artifacts/standalone/Makefile
deleted file mode 100644
index 4723dff2..00000000
--- a/artifacts/standalone/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-build-standalone: build-standalone-linux
-
-build-standalone-linux:
-	mkdir -p ${BUILD_DIR}
-	curl -fsSL -o spc.tgz https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64.tar.gz && tar -zxvf spc.tgz && rm spc.tgz
-	./spc doctor --auto-fix
-	./spc download --with-php=8.4 --for-extensions "apcu,phar,curl,dom,fileinfo,filter,intl,mbstring,mysqlnd,openssl,tokenizer,zlib" --prefer-pre-built
-	./spc install-pkg upx
-	./spc build --build-micro "apcu,phar,curl,dom,fileinfo,filter,intl,mbstring,mysqlnd,openssl,tokenizer,zlib" --with-upx-pack
-	./spc micro:combine ${BUILD_DIR}/phpmetrics.phar --output=${BUILD_DIR}/phpmetrics-linux-x86_64
-
diff --git a/assets/img/phpmetrics-overview.png b/assets/img/phpmetrics-overview.png
new file mode 100644
index 00000000..f9b2e25c
Binary files /dev/null and b/assets/img/phpmetrics-overview.png differ
diff --git a/assets/img/phpmetrics-symfony.png b/assets/img/phpmetrics-symfony.png
new file mode 100644
index 00000000..c223b333
Binary files /dev/null and b/assets/img/phpmetrics-symfony.png differ
diff --git a/bin/phpmetrics b/bin/phpmetrics
deleted file mode 100755
index 66551234..00000000
--- a/bin/phpmetrics
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env php
-<?php
-function includeIfExists($file)
-{
-    if (is_file($file)) {
-        return include $file;
-    }
-}
-if (
-    (!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php'))
-    && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))
-) {
-    die(
-        'You must set up the project dependencies, run the following commands:'.PHP_EOL.
-        'curl -s http://getcomposer.org/installer | php'.PHP_EOL.
-        'php composer.phar install'.PHP_EOL
-    );
-};
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-// PLEASE do not edit this file without editing artifacts/phar/build.php
-// PLEASE do not edit this file without editing artifacts/phar/build.php
-// PLEASE do not edit this file without editing artifacts/phar/build.php
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-
-(new \Hal\Application\Application())->run($argv);
diff --git a/build/README.md b/build/README.md
deleted file mode 100644
index f8af0b29..00000000
--- a/build/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Be careful
-
-This `phar` archive is **NOT** the latest version of PhpMetrics.
-
-This file is here in order to preserve compatibility with old v1.* builds.
-
-Please follow [this link]() to download the latest version.
\ No newline at end of file
diff --git a/build/phpmetrics.phar b/build/phpmetrics.phar
deleted file mode 100755
index 0ced4297..00000000
Binary files a/build/phpmetrics.phar and /dev/null differ
diff --git a/composer.json b/composer.json
deleted file mode 100644
index edfdaebe..00000000
--- a/composer.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
-    "name": "phpmetrics/phpmetrics",
-    "replace": {
-        "halleck45/phpmetrics": "*",
-        "halleck45/php-metrics": "*"
-    },
-    "description": "Static analyzer tool for PHP : Coupling, Cyclomatic complexity, Maintainability Index, Halstead's metrics... and more !",
-    "license": "MIT",
-    "keywords": [
-        "quality",
-        "analysis",
-        "testing",
-        "qa"
-    ],
-    "authors": [
-        {
-            "name": "Jean-François Lépine",
-            "email": "lepinejeanfrancois@yahoo.fr",
-            "homepage": "http://www.lepine.pro",
-            "role": "Copyright Holder"
-        }
-    ],
-    "homepage": "http://www.phpmetrics.org",
-    "support": {
-        "issues": "https://github.com/PhpMetrics/PhpMetrics/issues"
-    },
-    "autoload": {
-        "psr-0": {
-            "Hal\\": "./src/"
-        },
-        "files": ["./src/functions.php"]
-    },
-    "autoload-dev": {
-        "psr-4": {
-            "Test\\Hal\\": "tests/"
-        }
-    },
-    "require": {
-        "ext-dom": "*",
-        "ext-tokenizer": "*",
-        "nikic/php-parser": "^3|^4|^5"
-    },
-    "bin": [
-        "bin/phpmetrics"
-    ],
-    "config": {
-        "sort-packages": true
-    },
-    "require-dev": {
-        "phpunit/phpunit": "*"
-    }
-}
diff --git a/config-example.json b/config-example.json
deleted file mode 100644
index 18ceeaa9..00000000
--- a/config-example.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
-    "includes": [
-        "Controller"
-    ],
-    "excludes": [
-        "tests"
-    ],
-    "report": {
-        "html": "/tmp/report/",
-        "csv": "/tmp/report.csv",
-        "json": "/tmp/report.json",
-        "violations": "/tmp/violations.xml"
-    },
-    "groups": [
-        {
-            "name": "Component",
-            "match": "!component!i"
-        },
-        {
-            "name": "Reporters",
-            "match": "!Report!"
-        }
-    ],
-    "searches": {
-        "Repository which uses Service": {
-            "type": "class",
-            "instanceOf": [
-                "App\\MyRepository"
-            ],
-            "nameMatches": ".*Repository.*",
-            "usesClasses": [
-                ".*Service"
-            ],
-            "failIfFound": true
-        },
-        "Class with too complex code": {
-            "type": "class",
-            "ccn": ">=3",
-            "failIfFound": true
-        }
-    }
-}
diff --git a/config.yml b/config.yml
deleted file mode 100644
index bc6dd405..00000000
--- a/config.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-composer: false
-includes:
-    - "src"
-excludes:
-extensions:
-    - php
-    - php8
-report:
-    html: "/tmp/report/"
-    csv: "/tmp/report.csv"
-    json: "/tmp/report.json"
-    violations: "/tmp/violations.xml"
-groups:
-    - name: Component
-      match: "!component!i"
-    - name: Metric
-      match: "!metric!i"
-plugins:
-    git:
-        binary: git
-    junit:
-        file: "/tmp/junit.xml"
diff --git a/craft.yml b/craft.yml
deleted file mode 100644
index 8f3ca668..00000000
--- a/craft.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-php-version: 8.4
-extensions: "apcu,phar,curl,dom,fileinfo,filter,intl,mbstring,mysqlnd,openssl,tokenizer,zlib"
-sapi: micro
-build-options:
-    with-upx-pack: true
-    prefer-pre-built: true
diff --git a/doc/contributing.md b/doc/contributing.md
deleted file mode 100644
index d5a7c08b..00000000
--- a/doc/contributing.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# Contribute
-
-In order to run unit tests, please install the dev dependencies:
-
-    curl -sS https://getcomposer.org/installer | php
-    php composer.phar install
-
-Then, in order to run the test suite:
-
-    ./vendor/bin/phpunit
-
-Thanks for your help.
-
-## Why the code is so old?
-
-### Philosophy
-
-PhpMetrics has several goals:
-+ be stable
-+ be performant
-+ run on the **maximum of PHP versions** (PHP 5.3 to PHP 8.4)
-+ be installable everywhere, **without dependency conflicts**
-
-For these reasons, the code of PhpMetrics is intentionally written in "legacy" PHP.
-
-### Dependencies
-
-Not all projects are on the latest version of PHP, Symfony, or Laravel. Yes, there are projects that use Symfony 2. And these projects may also need metrics and quality.
-
-For these reasons, PhpMetrics comes with the minimum of dependencies. Only the dependency on `nikic/php-parser` is accepted.
-
-No Pull Request that modifies the `require` block will be accepted.
-
-
-## Releasing
-
-Please NEVER tag manually.
-
-### Requirements
-
-You will need to install :
-
-+ [`docker`](https://www.docker.com/)
-+ [make](https://www.gnu.org/software/make/)
-
-### Usage
-
-These commands will create `phar`, `debian` and `binary` release, 
-then run all tests and push new release to Github:
-
-```bash
-make release TAG=<vx.y.z>
-# where x is the major version, y is the minor version and z is the patch version
-```
diff --git a/doc/installation.md b/doc/installation.md
deleted file mode 100644
index c9e71ab3..00000000
--- a/doc/installation.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# Installation
-
-
-## Composer
-
-```bash
-composer global require 'phpmetrics/phpmetrics'
-```
-    
-Please note that the `~/.composer/vendor/bin` directory must be in your `$PATH`. For example in your `~/.bash_profile` (or `~/.bashrc`), add :
-
-```bash
-export PATH=~/.composer/vendor/bin:$PATH
-```
-    
-## Phar
-
-```bash
-curl https://github.com/phpmetrics/PhpMetrics/releases/download/v2.9.0/phpmetrics.phar
-chmod +x phpmetrics.phar && mv phpmetrics.phar /usr/local/bin/phpmetrics
-```
-
-## Apt (Debian, Ubuntu...)
-
-```bash
-curl https://github.com/phpmetrics/PhpMetrics/releases/download/v2.9.0/phpmetrics.deb
-dpkg -i phpmetrics.deb
-``` 
-
-## Brew (OSX)
-
-
-```bash
-brew install phpmetrics
-```
-
-## PhpArch
-
-```bash
-yaourt install phpmetrics
-```
-
-## Docker
-
-```bash
-docker run --rm \
-    --user $(id -u):$(id -g) \
-    --volume /local/path:/project \
-    herloct/phpmetrics [<options>]
-```
-
diff --git a/doc/metrics.md b/doc/metrics.md
deleted file mode 100644
index b452967e..00000000
--- a/doc/metrics.md
+++ /dev/null
@@ -1,168 +0,0 @@
-# List of available metrics
-
-## Halstead complexity measures 
-### Metrics: 
-length, vocabulary, volume, difficulty, effort, level, bugs, time, intelligentContent, number_operators, number_operands, number_operators_unique, number_operands_unique    
-
-### Description
-
-**n1** = the number of distinct operators      
-**n2** = the number of distinct operands      
-**N1** = the total number of operators      
-**N2** = the total number of operands      
-    
-From these numbers, eight measures can be calculated:      
-    
-**Program vocabulary:** n = n1 + n2      
-**Program length:** N = N1 + N2      
-**Calculated program length:** N' = n1 * log2(n1) + n2 * log2(n2)      
-**Volume:** V = N * log2(n)        
-**Difficulty:** D = (n1/2) * (N2/n2)        
-**Effort:** E = D * V      
-**Time required to program:** T = E / 18 seconds      
-**Number of delivered bugs:** B = V / 3000
-
-### Links     
-[https://en.wikipedia.org/wiki/Halstead_complexity_measures](https://en.wikipedia.org/wiki/Halstead_complexity_measures)
-[https://www.verifysoft.com/en_halstead_metrics.html](https://www.verifysoft.com/en_halstead_metrics.html)
-    
-## Cyclomatic complexity number and weighted method count 
-### Metrics: 
-wmc, ccn, ccnMethodMax
-    
-### Description
-The cyclomatic complexity (CCN) is a measure of control structure complexity of a function or procedure.    
-We can calculate ccn in two ways (we choose the second):    
-    
-1. Cyclomatic complexity (CCN) = E - N + 2P    
-  Where:    
-  P = number of disconnected parts of the flow graph (e.g. a calling program and a subroutine)    
-  E = number of edges (transfers of control)    
-  N = number of nodes (sequential group of statements containing only one transfer of control)    
-    
-2. CCN = Number of each decision point    
-    
-The weighted method count (WMC) is count of methods parameterized by a algorithm to compute the weight of a method.    
-Given a weight metric w and methods m it can be computed as    
-    
-sum m(w') over (w' in w)    
-    
-Possible algorithms are:    
-    
-- Cyclomatic Complexity    
-- Lines of Code    
-- 1 (unweighted WMC)    
-    
-This visitor provides two metrics, the maximal CCN of all methods from one class (currently stored as ccnMethodMax)    
-and the WMC using the CCN as weight metric (currently stored as ccn).    
-
-### Links
-[https://en.wikipedia.org/wiki/Cyclomatic_complexity](https://en.wikipedia.org/wiki/Cyclomatic_complexity)    
-[http://www.literateprogramming.com/mccabe.pdf](http://www.literateprogramming.com/mccabe.pdf)    
-[https://www.pitt.edu/~ckemerer/CK%20research%20papers/MetricForOOD_ChidamberKemerer94.pdf](https://www.pitt.edu/~ckemerer/CK%20research%20papers/MetricForOOD_ChidamberKemerer94.pdf)    
-     
-## Kan's defects 
-### Metrics: 
-kanDefect    
-
-### Description
-**kanDefect** = 0.15 + 0.23 *  number of do…while() + 0.22 *  number of switch() + 0.07 * number of if()    
-
-### Links
-    
-## Maintainability Index 
-### Metrics: 
-mi, mIwoC, commentWeight    
-
-### Description
-    
-According to Wikipedia, "Maintainability Index is a software metric which measures how maintainable (easy to support and change) the source code is. The maintainability index is calculated as a factored formula consisting  of Lines Of Code, Cyclomatic Complexity and Halstead volume."    
-    
-mIwoC: Maintainability Index without comments    
-MIcw: Maintainability Index comment weight    
-mi: Maintainability Index = MIwoc + MIcw    
-    
-**MIwoc** = 171 - 5.2 * ln(aveV) -0.23 * aveG -16.2 * ln(aveLOC)    
-**MIcw** = 50 * sin(sqrt(2.4 * perCM))    
-**mi** = MIwoc + MIcw    
-
-### Links
-
-[https://www.verifysoft.com/en_maintainability.html](https://www.verifysoft.com/en_maintainability.html)
- 
-    
-## Lack of cohesion of methods 
-### Metrics: 
-lcom    
- 
-### Description   
-
-Cohesion metrics measure how well the methods of a class are related to each other. A cohesive class performs one function while a non-cohesive class performs two or more unrelated functions. A non-cohesive class may need to be restructured into two or more smaller classes.    
-High cohesion is desirable since it promotes encapsulation. As a drawback, a highly cohesive class has high coupling between the methods of the class, which in turn indicates high testing effort for that class.    
-Low cohesion indicates inappropriate design and high complexity. It has also been found to indicate a high likelihood of errors. The class should probably be split into two or more smaller classes.    
-
-### Links
-[https://blog.ndepend.com/lack-of-cohesion-methods/](https://blog.ndepend.com/lack-of-cohesion-methods/)
-[http://www.arisa.se/compendium/node116.html](http://www.arisa.se/compendium/node116.html)
-    
-## Card and Agresti metric 
-### Metrics 
-relativeStructuralComplexity, relativeDataComplexity, relativeSystemComplexity, totalStructuralComplexity, totalDataComplexity, totalSystemComplexity    
-  
-### Description 
-Fan-out = Structural fan-out = Number of other procedures this procedure calls    
-    
-v = number of input/output variables for a procedure    
-    
-(SC) Structural complexity = fan-out^2    
-(DC) Data complexity = v / (fan-out + 1)  
-  
-### Links  
-[https://www.witpress.com/Secure/elibrary/papers/SQM94/SQM94024FU.pdf](https://www.witpress.com/Secure/elibrary/papers/SQM94/SQM94024FU.pdf)
-
-## Length 
-### Metrics: 
-cloc, loc, lloc    
-
-### Description
-
-**loc:** lines count      
-**cloc:** lines count without multiline comments    
-**lloc:** lines count without empty lines    
-
-### Links
-    
-## Methods 
-### Metrics: 
-nbMethodsIncludingGettersSetters, nbMethods, nbMethodsPrivate, nbMethodsPublic, nbMethodsGetter, nbMethodsSetters    
-    
-## Coupling 
-### Metrics: 
-afferentCoupling, efferentCoupling, instability    
-
-### Description
-    
-**Afferent couplings (Ca):** The number of classes in other packages that depend upon classes within the package is an indicator of the package's responsibility.    
-**Efferent couplings (Ce):** The number of classes in other packages that the classes in a package depend upon is an indicator of the package's dependence on externalities.    
-**Instability (I):** The ratio of efferent coupling (Ce) to total coupling (Ce + Ca) such that I = Ce / (Ce + Ca).    
-
-### Links
-[https://www.future-processing.pl/blog/object-oriented-metrics-by-robert-martin/](https://www.future-processing.pl/blog/object-oriented-metrics-by-robert-martin/)
-[https://en.wikipedia.org/wiki/Software_package_metrics](https://en.wikipedia.org/wiki/Software_package_metrics)
-    
-## Depth of inheritance tree 
-### Metrics: 
-depthOfInheritanceTree    
-
-### Description
-Measures the length of inheritance from a class up to the root class.
-
-### Links    
-    
-## Page rank 
-### Metrics: 
-pageRank
-
-### Description
-
-### Links
diff --git a/doc/overview.png b/doc/overview.png
deleted file mode 100644
index 3761e07b..00000000
Binary files a/doc/overview.png and /dev/null differ
diff --git a/index.md b/index.md
new file mode 100644
index 00000000..cae9360e
--- /dev/null
+++ b/index.md
@@ -0,0 +1,81 @@
+## Static analysis must be understandable
+
+PhpMetrics analyze your PHP code and provides HTML, JSON, CSV... reports about complexity, dependencies, coupling, violations, and more !
+
+![PhpMetrics HTML report](assets/img/phpmetrics-overview.png)
+
+
+## Quick start
+
+    composer require phpmetrics/phpmetrics --dev
+    php ./vendor/bin/phpmetrics --report-html=myreport <folder-to-analyze>
+    
+Then open the generated `./myreport/index.html` file in your browser. 
+
+## Configure
+
+Use the `--config=<file>.json` option. For example:
+
+```js
+{
+    "includes": [   // directory and files to analyze, relative to config file directory 
+        "src"
+    ],
+    "exclude": [    // regex of files (or directory) to exclude from analyze
+      "tests"
+    ],
+    "report": {     // list of reports to generate (html, json, csv or violation)
+        "html": "/tmp/report/",             // destination directory of HTML report 
+        "csv": "/tmp/report.csv",           // destination file for CSV report
+        "json": "/tmp/report.json",         // destination file for JSON report
+        "violations": "/tmp/violations.xml" // destination file for XML violations report
+    },
+    "groups": [     // "layers" of code. You can group your classes and packages by regex, 
+                    // to visualise specific HTML report for each of them
+        {
+            "name": "Component",      // name of the layer
+            "match": "!component!i"   // regular expression used to match the group (based on 
+                                      // the name of the fully qualified class name)
+                                      // remember to double escape (for json, then for regex): 
+                                      // set "!\\\\MyPackage\\\\!" if you want to capture  
+                                      // expression "\MyPackage\"
+        },
+        {
+            "name": "Example",
+            "match": "!example!"
+        }
+    ],
+    "plugins": {
+        "git": {
+            "binary": "git"           // if defined, runs git analyze
+        },
+        "junit": {
+            "file": "/tmp/junit.xml"  // if defined, JUnit report file will be analyzed            
+        }
+    }
+    "extensions": [ "php", "php8" ],        // default: ["php", "inc"]
+}
+```
+
+## More
+
+If want, you can [install](https://github.com/phpmetrics/PhpMetrics/blob/master/doc/installation.md) PhpMetrics globally with your favorite package manager (APT, Brew...). You can also visit our [documentation](http://www.phpmetrics.org/documentation/index.html).
+
+You can integrate PhpMetrics directly [in the debug bar of your Symfony project](https://github.com/phpmetrics/PhpMetricsCollectorBundle), 
+or [in PhpStorm](https://github.com/phpmetrics/PhpMetrics-jetbrains).
+
+![PhpMetrics Symfony](assets/img/phpmetrics-symfony.png)
+
+
+## Metrics list
+
+See the [metrics](https://github.com/phpmetrics/PhpMetrics/blob/master/doc/metrics.md) file.
+
+## Author
+
+PhpMetrics is developed by Jean-François Lépine <[@Halleck45](https://twitter.com/Halleck45)>, with the help of 
+[dozens of awesome contributors](https://github.com/phpmetrics/PhpMetrics/graphs/contributors)
+
+## License
+
+PhpMetrics is free and Open Source under the [MIT LICENSE](https://github.com/phpmetrics/PhpMetrics/LICENSE).
\ No newline at end of file
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
deleted file mode 100644
index ec987918..00000000
--- a/phpunit.xml.dist
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<phpunit
-         backupGlobals="false"
-         colors="true"
-         processIsolation="false"
-         stopOnFailure="false"
-         bootstrap="./tests/bootstrap.php"
-        >
-
-    <testsuites>
-        <testsuite name="PhpMetrics Suite">
-            <directory>./tests/</directory>
-        </testsuite>
-    </testsuites>
-
-    <groups>
-        <exclude>
-            <group>binary</group>
-        </exclude>
-    </groups>
-</phpunit>
diff --git a/rector.php b/rector.php
deleted file mode 100644
index c9a4ae89..00000000
--- a/rector.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-use Rector\Config\RectorConfig;
-
-return RectorConfig::configure()
-    ->withPaths([
-        __DIR__ . '/src',
-        __DIR__ . '/tests',
-    ])
-    ->withSets([
-        \Rector\PHPUnit\Set\PHPUnitSetList::PHPUNIT_110,
-    ])
-    ->withRules([
-        \Rector\TypeDeclaration\Rector\Class_\AddTestsVoidReturnTypeWhereNoReturnRector::class,
-        \Rector\PHPUnit\CodeQuality\Rector\Class_\AddParentSetupCallOnSetupRector::class,
-        \Rector\PHPUnit\PHPUnit60\Rector\ClassMethod\ExceptionAnnotationRector::class,
-        \Rector\PHPUnit\PHPUnit100\Rector\StmtsAwareInterface\WithConsecutiveRector::class,
-        \Rector\PHPUnit\PHPUnit100\Rector\Class_\StaticDataProviderClassMethodRector::class,
-    ]);
diff --git a/releases/phpmetrics-linux-x86_64 b/releases/phpmetrics-linux-x86_64
deleted file mode 100755
index 1f3c2457..00000000
Binary files a/releases/phpmetrics-linux-x86_64 and /dev/null differ
diff --git a/releases/phpmetrics.changes b/releases/phpmetrics.changes
deleted file mode 100644
index a93c4e92..00000000
--- a/releases/phpmetrics.changes
+++ /dev/null
@@ -1,118 +0,0 @@
-Format: 1.8
-Date: Mon, 07 Jul 2025 14:03:08 +0200
-Source: phpmetrics
-Binary: phpmetrics
-Built-For-Profiles: noudeb
-Architecture: source all
-Version: 3.0.0rc7
-Distribution: unstable
-Urgency: low
-Maintainer: Jean-François Lépine <lepinejeanfrancois@yahoo.fr>
-Description:
- phpmetrics - Static analyzer for PHP
-Changes:
- phpmetrics (3.0.0rc7) unstable; urgency=low
- .
-    * Prepare v3. WIP.
-    * Rebase on master (current 2.8.1) with adaptation for 3.x. Coverage got down. WIP.
-    * Add some missing unit test. Coverage is still not back to previous state. WIP.
-    * Continue to add up some coverage. WIP.
-    * Set the coverage back to previous state. WIP: work on uncovered files.
-    * Remove Git related metrics.
-    * Remove PHPUnit metrics checks. Start but stop reviewing Html Reporter (too complex). File functions.php removed.
-    * Fix some PHPStan issues. WIP.
-    * Apply HTML error fixes from #477.
-    * Update dependencies and fix unit tests.
-    * Update QA and dev-dependencies.
-    * Disable PHP Infection as some mutants are breaking analyse.
-    * Add multiple locations for composer-autoloading.
-    * Do not oblige usage of YAML extention as configuration can be set in another way.
-    * Fix HTML rednering.
-    * Fix HTML rednering.
-    * Ignore PHP Attributes in detecting getter/setters.
-    * Keep only composer installation to simplify tool usage.
-    * Remove PageRank metric.
-    * Get rid of more than 150 PHPStan errors.
-    * Add cache and baselines on qa tools.
-    * Dynamically manage version number via .semver file. Also minor fixes.
-    * Rebase on master + update dependencies + improve QA. PHPUnit 10 is now used.
-    * Use env variable to share volume to mount with DockerInDocker.
-    * Adapt the releasing process with the current v3 + minor fixes.
-    * Decouple file system operations to split responsibilities.
-    * Complete the unit tests related to file system.
-    * Kill some mutants.
-    * Add a copy function to manage the copy of single files.
-    * Fix tag management on release + recursive copy for HTML rendering.
-    * Remove Clusterize as only used for removed Class Rank and remove useless logos.
-    * Fix SVG icons on sidebar.
-    * Fix resolving of FQCN when inferring externals.
-    * Fix parsing issue on LComVisitor when code to parse contains variable property fetch.
-    * Fix error when HTML report is not requested.
-    * Add missing favicon + add report date in title.
-    * Improve CSS + button to download the bubble graph.
-    * Update minimum versions of dependencies for composer.json.
-    * Fix unit tests for ExternalVisitor.
-    * Remove example and management of plugins (JUnit).
-    * Remove useless metric nbGetters/nbSetters.
-    * Prepare changelog fro release 3.0.0-rc1.
-    * releasing v3.0.0rc1
-    * Fix #491: add shell command in case PHP command does not work for some OS in documenation.
-    * Fix Fatal error when analyzing snippets like `$a->$b()` or `$c()`.
-    * Prepare release 3.0.0-rc2.
-    * releasing v3.0.0rc2
-    * Fix special version label that were not taken into account on bintray.
-    * releasing v3.0.0rc2
-    * Fix possible parsing error + upgrade to PHPUnit 10.1.
-    * Fix violations reporter which was trying to rely on Violations directly, rather than ViolationsHandler
-    * Merge pull request #495 from Tithugues/fix/report-violations
-    * SystemComplexityVisitor fix for calling methods with the same name on different objects
-    * releasing v3.0.0rc3
-    * Upgrade deps + add ccn value by method. Need to fnd how to display it on HTML reports now.
-    * Merge pull request #497 from andrii-pukhalevych/patch1
-    * Add elegant way to display CCN values for methods.
-    * QA review: fix PHPStan/Psalm/PHPUnit/Qodana errors.
-    * Merge pull request #498 from phpmetrics/add-ccn-value-to-every-class-method
-    * releasing v3.0.0rc4
-    * Fix URLs and search configuration usage.
-    * Manage better description inference for stable dependencies principle.
-    * Merge pull request #502 from phpmetrics/fix/501
-    * Fix some unit tests + releasing process.
-    * releasing v3.0.0rc5
-    * Upgrade to PhpParser v5 + adapt code. Remove Qodana. Upgrade to PHPUnit 10.5
-    * Merge pull request #504 from phpmetrics/fix/php-parser-v5
-    * releasing v3.0.0rc6
-    * Fix numeric version array key in Composer\Packagist.php - if there is an integer string set as a key of associative array, it will automatically be converted to integer, which causes the call of `ltrim` to fail, because of `declare(strict_types=1)` configuration
-    * Merge pull request #509 from Klemo1997/fix/packagist-array-key-type-error
-    * fix typo
-    * Merge pull request #513 from YAhiru/fix-typo
-    * feat: add OpenMetrics report
-    * Merge pull request #512 from alanpoulain/feat-openmetrics
-    * test: add OpenMetrics SummaryWriter test
-    * Merge pull request #514 from alanpoulain/test-openmetrics-summary-writer
-    * Make sure OpenMetrics format is available and upgrade QA.
-    * Merge pull request #515 from phpmetrics/update/3.x-qa
-    * releasing v3.0.0rc7
-    * Updated tests in order to be executed in PHP 8.4, and supports Php 8.4
-    * fixed issue introduced by phpcs, and removed phpcs
-    * added build script for standalone build
-    * fixed CI
-    * Merge pull request #524 from phpmetrics/php84-standalone
-    * #518 test about deferencing new without parenthesis in PHP 8.4
-    * updated build
- .
-   -- Jean-François Lépine <lepinejeanfrancois@yahoo.fr>  Mon, 07 Jul 2025 13:56:00 +0200
-Checksums-Sha1:
- eabc66661a9a736c2fdc07e3dc233c0518868180 681 phpmetrics_3.0.0rc7.dsc
- db3393d0e0b82660b0762bc76e15fa3b8daa63ac 2721095 phpmetrics_3.0.0rc7.tar.gz
- 267cfde8587bb6d6b3237c583fb643f689f6e8bb 1601434 phpmetrics_3.0.0rc7_all.deb
- 8a75159726cd1e6936ed84c8a2a5e4a3f469c4be 5219 phpmetrics_3.0.0rc7_amd64.buildinfo
-Checksums-Sha256:
- 8218f1e4f84e3e1e1552d797917c2107c77281d6190ddd64f23296e3ddddee32 681 phpmetrics_3.0.0rc7.dsc
- 96ff540790a625bbcb7364c3d8cf867869eeba12c78a3db5ef98045aca5e5ecc 2721095 phpmetrics_3.0.0rc7.tar.gz
- 6511d51c6b5c74773c10d26c9a877dc578e88d344597a2038bcea5ebae16b57c 1601434 phpmetrics_3.0.0rc7_all.deb
- 373d8a80415eb18eaea0b2df1f81bfac31a4f4f87e2fdb214dccb8d0271668f5 5219 phpmetrics_3.0.0rc7_amd64.buildinfo
-Files:
- b507938ad8493602ca53ae0ad2194837 681 base optional phpmetrics_3.0.0rc7.dsc
- b8f33f1a399884b586fc4cf01b4a2a20 2721095 base optional phpmetrics_3.0.0rc7.tar.gz
- 5cd1169a0a80cb8e859d01ff6b8d4693 1601434 base optional phpmetrics_3.0.0rc7_all.deb
- 2ff7e2a230a9acde5a13f786b64891f2 5219 base optional phpmetrics_3.0.0rc7_amd64.buildinfo
diff --git a/releases/phpmetrics.deb b/releases/phpmetrics.deb
deleted file mode 100644
index b5ba5870..00000000
Binary files a/releases/phpmetrics.deb and /dev/null differ
diff --git a/releases/phpmetrics.dsc b/releases/phpmetrics.dsc
deleted file mode 100644
index 34724136..00000000
--- a/releases/phpmetrics.dsc
+++ /dev/null
@@ -1,19 +0,0 @@
-Format: 1.0
-Source: phpmetrics
-Binary: phpmetrics
-Architecture: all
-Version: 3.0.0rc7
-Maintainer: Jean-François Lépine <lepinejeanfrancois@yahoo.fr>
-Homepage: http://www.phpmetrics.org
-Standards-Version: 0.0.0
-Vcs-Browser: https://github.com/phpmetrics/PhpMetrics
-Vcs-Git: https://github.com/phpmetrics/PhpMetrics.git
-Build-Depends: make
-Package-List:
- phpmetrics deb base optional arch=all
-Checksums-Sha1:
- db3393d0e0b82660b0762bc76e15fa3b8daa63ac 2721095 phpmetrics_3.0.0rc7.tar.gz
-Checksums-Sha256:
- 96ff540790a625bbcb7364c3d8cf867869eeba12c78a3db5ef98045aca5e5ecc 2721095 phpmetrics_3.0.0rc7.tar.gz
-Files:
- b8f33f1a399884b586fc4cf01b4a2a20 2721095 phpmetrics_3.0.0rc7.tar.gz
diff --git a/releases/phpmetrics.phar b/releases/phpmetrics.phar
deleted file mode 100755
index 4373f72e..00000000
Binary files a/releases/phpmetrics.phar and /dev/null differ
diff --git a/releases/phpmetrics.tar.gz b/releases/phpmetrics.tar.gz
deleted file mode 100644
index 31ebe306..00000000
Binary files a/releases/phpmetrics.tar.gz and /dev/null differ
diff --git a/src/Hal/Application/Analyze.php b/src/Hal/Application/Analyze.php
deleted file mode 100644
index 8fa01219..00000000
--- a/src/Hal/Application/Analyze.php
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-
-namespace Hal\Application;
-
-use Hal\Application\Config\Config;
-use Hal\Component\Ast\NodeTraverser;
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Component\Ast\ParserTraverserVisitorsAssigner;
-use Hal\Component\Issue\Issuer;
-use Hal\Component\Output\Output;
-use Hal\Component\Output\ProgressBar;
-use Hal\Metric\Class_\ClassEnumVisitor;
-use Hal\Metric\Class_\Complexity\CyclomaticComplexityVisitor;
-use Hal\Metric\Class_\Complexity\KanDefectVisitor;
-use Hal\Metric\Class_\Component\MaintainabilityIndexVisitor;
-use Hal\Metric\Class_\Coupling\ExternalsVisitor;
-use Hal\Metric\Class_\Structural\LcomVisitor;
-use Hal\Metric\Class_\Structural\SystemComplexityVisitor;
-use Hal\Metric\Class_\Text\HalsteadVisitor;
-use Hal\Metric\Class_\Text\LengthVisitor;
-use Hal\Metric\Metrics;
-use Hal\Metric\Package\PackageAbstraction;
-use Hal\Metric\Package\PackageCollectingVisitor;
-use Hal\Metric\Package\PackageDependencies;
-use Hal\Metric\Package\PackageDistance;
-use Hal\Metric\Package\PackageInstability;
-use Hal\Metric\System\Changes\GitChanges;
-use Hal\Metric\System\Coupling\Coupling;
-use Hal\Metric\System\Coupling\DepthOfInheritanceTree;
-use Hal\Metric\System\Coupling\PageRank;
-use Hal\Metric\System\Packages\Composer\Composer;
-use Hal\Metric\System\UnitTesting\UnitTesting;
-use PhpParser\Error;
-use PhpParser\NodeVisitor\NameResolver;
-use PhpParser\ParserFactory;
-
-/**
- * @package Hal\Application
- */
-class Analyze
-{
-    /**
-     * @var Output
-     */
-    private $output;
-
-    /**
-     * @var Config
-     */
-    private $config;
-
-    /**
-     * @var Issuer
-     */
-    private $issuer;
-
-    /**
-     * @param Output $output
-     */
-    public function __construct(Config $config, Output $output, Issuer $issuer)
-    {
-        $this->output = $output;
-        $this->config = $config;
-        $this->issuer = $issuer;
-    }
-
-    /**
-     * Runs analyze
-     */
-    public function run($files)
-    {
-        // config
-        ini_set('xdebug.max_nesting_level', 3000);
-
-        $metrics = new Metrics();
-
-        // traverse all
-        $whenToStop = function () {
-            return true;
-        };
-
-        // prepare parser
-        $parser = (new ParserFactoryBridge())->create();
-        $traverser = new NodeTraverser();
-
-        (new ParserTraverserVisitorsAssigner())->assign(
-            $traverser,
-            [
-                new NameResolver(),
-                new ClassEnumVisitor($metrics),
-                new CyclomaticComplexityVisitor($metrics),
-                new ExternalsVisitor($metrics),
-                new LcomVisitor($metrics),
-                new HalsteadVisitor($metrics),
-                new LengthVisitor($metrics),
-                new CyclomaticComplexityVisitor($metrics),
-                new MaintainabilityIndexVisitor($metrics),
-                new KanDefectVisitor($metrics),
-                new SystemComplexityVisitor($metrics),
-                new PackageCollectingVisitor($metrics)
-            ]
-        );
-
-        // create a new progress bar (50 units)
-        $progress = new ProgressBar($this->output, count($files));
-        $progress->start();
-
-        foreach ($files as $file) {
-            $progress->advance();
-            $code = file_get_contents($file);
-            $this->issuer->set('filename', $file);
-            try {
-                $stmts = $parser->parse($code);
-                $this->issuer->set('statements', $stmts);
-                $traverser->traverse($stmts);
-            } catch (Error $e) {
-                $this->output->writeln(sprintf('<error>Cannot parse %s</error>', $file));
-            }
-            $this->issuer->clear('filename');
-            $this->issuer->clear('statements');
-        }
-
-        $progress->clear();
-
-        $this->output->write('Executing system analyzes...');
-
-        //
-        // System analyses
-        (new PageRank())->calculate($metrics);
-        (new Coupling())->calculate($metrics);
-        (new DepthOfInheritanceTree())->calculate($metrics);
-
-        //
-        // Package analyses
-        (new PackageDependencies())->calculate($metrics);
-        (new PackageAbstraction())->calculate($metrics);
-        (new PackageInstability())->calculate($metrics);
-        (new PackageDistance())->calculate($metrics);
-
-        //
-        // File analyses
-        (new GitChanges($this->config, $files))->calculate($metrics);
-
-        //
-        // Unit test
-        (new UnitTesting($this->config, $files))->calculate($metrics);
-
-        $this->output->clearln();
-
-        //
-        // Composer
-        $this->output->write('Executing composer analyzes, requesting https://packagist.org...');
-        (new Composer($this->config, $files))->calculate($metrics);
-
-        $this->output->clearln();
-
-        return $metrics;
-    }
-}
diff --git a/src/Hal/Application/Application.php b/src/Hal/Application/Application.php
deleted file mode 100644
index 5b755fe7..00000000
--- a/src/Hal/Application/Application.php
+++ /dev/null
@@ -1,130 +0,0 @@
-<?php
-
-namespace Hal\Application;
-
-use Exception;
-use Hal\Application\Config\ConfigException;
-use Hal\Application\Config\Parser;
-use Hal\Application\Config\Validator;
-use Hal\Component\File\Finder;
-use Hal\Component\Issue\Issuer;
-use Hal\Component\Output\CliOutput;
-use Hal\Metric\SearchMetric;
-use Hal\Report;
-use Hal\Search\PatternSearcher;
-use Hal\Violation\Violation;
-use Hal\Violation\ViolationParser;
-
-class Application
-{
-    /**
-     * @param array $argv
-     */
-    public function run(array $argv)
-    {
-        // formatter
-        $output = new CliOutput();
-
-        // issues and debug
-        $issuer = (new Issuer($output));//->enable();
-
-        // config
-        $config = (new Parser())->parse($argv);
-
-        // Help
-        if ($config->has('help')) {
-            $output->writeln((new Validator())->help());
-            exit(0);
-        }
-
-        // Metrics list
-        if ($config->has('metrics')) {
-            $output->writeln((new Validator())->metrics());
-            exit(0);
-        }
-
-        // Version
-        if ($config->has('version')) {
-            $output->writeln(sprintf(
-                "PhpMetrics %s <http://www.phpmetrics.org>\nby Jean-François Lépine <https://twitter.com/Halleck45>\n",
-                getVersion()
-            ));
-            exit(0);
-        }
-
-        try {
-            (new Validator())->validate($config);
-        } catch (ConfigException $e) {
-            $output->writeln(sprintf("\n<error>%s</error>\n", $e->getMessage()));
-            $output->writeln((new Validator())->help());
-            exit(1);
-        }
-
-        if ($config->has('quiet')) {
-            $output->setQuietMode(true);
-        }
-
-        // find files
-        $finder = new Finder($config->get('extensions'), $config->get('exclude'));
-        $files = $finder->fetch($config->get('files'));
-
-        // analyze
-        try {
-            $metrics = (new Analyze($config, $output, $issuer))->run($files);
-        } catch (ConfigException $e) {
-            $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
-            exit(1);
-        }
-
-        // search
-        $searches = $config->get('searches');
-        $searcher = new PatternSearcher();
-        $foundSearch = new SearchMetric('searches');
-        foreach ($searches->all() as $search) {
-            $foundSearch->set($search->getName(), $searcher->executes($search, $metrics));
-        }
-        $metrics->attach($foundSearch);
-
-        // violations
-        (new ViolationParser($config, $output))->apply($metrics);
-
-        // report
-        try {
-            (new Report\Cli\Reporter($config, $output))->generate($metrics);
-            (new Report\Cli\SearchReporter($config, $output))->generate($metrics);
-            (new Report\Html\Reporter($config, $output))->generate($metrics);
-            (new Report\Csv\Reporter($config, $output))->generate($metrics);
-            (new Report\Json\Reporter($config, $output))->generate($metrics);
-            (new Report\Json\SummaryReporter($config, $output))->generate($metrics);
-            (new Report\Violations\Xml\Reporter($config, $output))->generate($metrics);
-        } catch (Exception $e) {
-            $output->writeln(sprintf('<error>Cannot generate report: %s</error>', $e->getMessage()));
-            $output->writeln('');
-            exit(1);
-        }
-
-        // exit status
-        $shouldExitDueToCriticalViolationsCount = 0;
-        foreach ($metrics->all() as $metric) {
-            foreach ($metric->get('violations') as $violation) {
-                if (Violation::CRITICAL === $violation->getLevel()) {
-                    $shouldExitDueToCriticalViolationsCount++;
-                }
-            }
-        }
-        if (!empty($shouldExitDueToCriticalViolationsCount)) {
-            $output->writeln('');
-            $output->writeln(sprintf(
-                '<error>[ERR] Failed du to %d critical violations</error>',
-                $shouldExitDueToCriticalViolationsCount
-            ));
-            $output->writeln('');
-            exit(1);
-        }
-
-        // end
-        $output->writeln('');
-        $output->writeln('<success>Done</success>');
-        $output->writeln('');
-    }
-}
diff --git a/src/Hal/Application/Config/Config.php b/src/Hal/Application/Config/Config.php
deleted file mode 100644
index ab4d991d..00000000
--- a/src/Hal/Application/Config/Config.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-
-namespace Hal\Application\Config;
-
-class Config
-{
-    /**
-     * @var array
-     */
-    private $bag = [];
-
-    /**
-     * @param $key
-     * @param $value
-     * @return $this
-     */
-    public function set($key, $value)
-    {
-        $this->bag[$key] = $value;
-        return $this;
-    }
-
-    /**
-     * @param $key
-     * @return bool
-     */
-    public function has($key)
-    {
-        return isset($this->bag[$key]);
-    }
-
-    /**
-     * @param $key
-     * @return null
-     */
-    public function get($key)
-    {
-        return $this->has($key) ? $this->bag[$key] : null;
-    }
-
-    /**
-     * @return array
-     */
-    public function all()
-    {
-        return $this->bag;
-    }
-
-    /**
-     * @param array $array
-     * @return $this
-     */
-    public function fromArray(array $array)
-    {
-        foreach ($array as $key => $value) {
-            $this->set($key, $value);
-        }
-        return $this;
-    }
-}
diff --git a/src/Hal/Application/Config/ConfigException.php b/src/Hal/Application/Config/ConfigException.php
deleted file mode 100644
index 7063df2c..00000000
--- a/src/Hal/Application/Config/ConfigException.php
+++ /dev/null
@@ -1,5 +0,0 @@
-<?php
-
-namespace Hal\Application\Config;
-
-class ConfigException extends \Exception {}
diff --git a/src/Hal/Application/Config/File/ConfigFileReaderFactory.php b/src/Hal/Application/Config/File/ConfigFileReaderFactory.php
deleted file mode 100644
index 694dfc18..00000000
--- a/src/Hal/Application/Config/File/ConfigFileReaderFactory.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-
-namespace Hal\Application\Config\File;
-
-class ConfigFileReaderFactory
-{
-    /**
-     * @param string $filename
-     *
-     * @return ConfigFileReaderInterface
-     */
-    public static function createFromFileName($filename)
-    {
-        if (!is_file($filename) || !is_readable($filename)) {
-            throw new \InvalidArgumentException("Cannot read configuration file '{$filename}'");
-        }
-
-        switch (pathinfo($filename, PATHINFO_EXTENSION)) {
-            case 'json':
-                return new ConfigFileReaderJson($filename);
-            case 'yaml':
-            case 'yml':
-                return new ConfigFileReaderYaml($filename);
-            case 'ini':
-                return new ConfigFileReaderIni($filename);
-                break;
-            default:
-                throw new \InvalidArgumentException("Unsupported config file format: '$filename'");
-        }
-    }
-}
diff --git a/src/Hal/Application/Config/File/ConfigFileReaderIni.php b/src/Hal/Application/Config/File/ConfigFileReaderIni.php
deleted file mode 100644
index cacdd85b..00000000
--- a/src/Hal/Application/Config/File/ConfigFileReaderIni.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-namespace Hal\Application\Config\File;
-
-use Hal\Application\Config\Config;
-
-class ConfigFileReaderIni implements ConfigFileReaderInterface
-{
-    /**
-     * @var string
-     */
-    private $filename;
-
-    /**
-     * @param string $filename
-     */
-    public function __construct($filename)
-    {
-        $this->filename = $filename;
-    }
-
-    /**
-     * @param Config $config
-     *
-     * @return void
-     */
-    public function read(Config $config)
-    {
-        $options = parse_ini_file($this->filename);
-
-        if (false === $options) {
-            throw new \InvalidArgumentException("Cannot parse configuration file '{$this->filename}'");
-        }
-
-        foreach ($options as $name => $value) {
-            $config->set($name, $value);
-        }
-    }
-}
diff --git a/src/Hal/Application/Config/File/ConfigFileReaderInterface.php b/src/Hal/Application/Config/File/ConfigFileReaderInterface.php
deleted file mode 100644
index af410aa3..00000000
--- a/src/Hal/Application/Config/File/ConfigFileReaderInterface.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-
-namespace Hal\Application\Config\File;
-
-use Hal\Application\Config\Config;
-
-interface ConfigFileReaderInterface
-{
-    /**
-     * @param Config $config
-     *
-     * @return void
-     */
-    public function read(Config $config);
-}
diff --git a/src/Hal/Application/Config/File/ConfigFileReaderJson.php b/src/Hal/Application/Config/File/ConfigFileReaderJson.php
deleted file mode 100644
index ce0164e4..00000000
--- a/src/Hal/Application/Config/File/ConfigFileReaderJson.php
+++ /dev/null
@@ -1,125 +0,0 @@
-<?php
-
-namespace Hal\Application\Config\File;
-
-use Hal\Application\Config\Config;
-use Hal\Search\SearchesFactory;
-use InvalidArgumentException;
-
-class ConfigFileReaderJson implements ConfigFileReaderInterface
-{
-    /**
-     * @var string
-     */
-    protected $filename;
-
-    /**
-     * @param string $filename
-     */
-    public function __construct($filename)
-    {
-        $this->filename = $filename;
-    }
-
-    /**
-     * @param Config $config
-     *
-     * @return void
-     */
-    public function read(Config $config)
-    {
-        $jsonText = file_get_contents($this->filename);
-
-        if (false === $jsonText) {
-            throw new InvalidArgumentException("Cannot read configuration file '{$this->filename}'");
-        }
-
-        $jsonData = json_decode($jsonText, true);
-
-        $this->parseJson($jsonData, $config);
-    }
-
-    /**
-     * @return string
-     */
-    private function resolvePath($path)
-    {
-        if (DIRECTORY_SEPARATOR !== $path[0]) {
-            $path = dirname($this->filename) . DIRECTORY_SEPARATOR . $path;
-        }
-
-        return $path;
-    }
-
-    protected function parseJson($jsonData, Config $config)
-    {
-        if (false === $jsonData || null === $jsonData) {
-            throw new InvalidArgumentException("Bad config file '{$this->filename}'");
-        }
-
-        if (isset($jsonData['includes'])) {
-            $includes = $jsonData['includes'];
-            $files = [];
-            // with config file, includes are relative to config file
-            foreach ($includes as $include) {
-                $include = $this->resolvePath($include);
-                $files[] = $include;
-            }
-            $config->set('files', $files);
-        }
-
-        if (isset($jsonData['groups'])) {
-            $config->set('groups', $jsonData['groups']);
-        }
-
-        if (isset($jsonData['extensions'])) {
-            $config->set('extensions', implode(',', $jsonData['extensions']));
-        }
-
-        // Composer
-        if (array_key_exists('composer', $jsonData)) {
-            $config->set('composer', (bool) $jsonData['composer']);
-        }
-
-        // Search
-        if (!isset($jsonData['searches'])) {
-            $jsonData['searches'] = [];
-        }
-        $factory = new SearchesFactory();
-        $config->set('searches', $factory->factory($jsonData['searches']));
-
-        if (isset($jsonData['excludes'])) {
-            // retro-compatibility
-            // "exclude" is a string
-            // excludes is an array
-            $config->set('exclude', implode(',', $jsonData['excludes']));
-        } else {
-            if (isset($jsonData['exclude'])) {
-                $config->set('exclude', $jsonData['exclude']);
-            }
-        }
-
-        if (isset($jsonData['plugins']['git']['binary'])) {
-            $config->set('git', $jsonData['plugins']['git']['binary']);
-        }
-
-        // backward compatibility with typo in documentation
-        // see https://github.com/phpmetrics/PhpMetrics/issues/441
-        // file -> report
-        if (isset($jsonData['plugins']['junit']['file'])) {
-            $jsonData['plugins']['junit']['report'] = $jsonData['plugins']['junit']['file'];
-        }
-
-        if (isset($jsonData['plugins']['junit']['report'])) {
-            $config->set('junit', $jsonData['plugins']['junit']['report']);
-        }
-
-        // reports
-        if (isset($jsonData['report']) && is_array($jsonData['report'])) {
-            foreach ($jsonData['report'] as $reportType => $path) {
-                $path = $this->resolvePath($path);
-                $config->set('report-' . $reportType, $path);
-            }
-        }
-    }
-}
diff --git a/src/Hal/Application/Config/File/ConfigFileReaderYaml.php b/src/Hal/Application/Config/File/ConfigFileReaderYaml.php
deleted file mode 100644
index 7afb6923..00000000
--- a/src/Hal/Application/Config/File/ConfigFileReaderYaml.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-namespace Hal\Application\Config\File;
-
-use Hal\Application\Config\Config;
-
-class ConfigFileReaderYaml extends ConfigFileReaderJson implements ConfigFileReaderInterface
-{
-    /**
-     * @param Config $config
-     */
-    public function read(Config $config)
-    {
-        if (!function_exists('yaml_parse')) {
-            throw new \RuntimeException('YAML parser not found. Please install the PECL extension "yaml".');
-        }
-
-        $json = yaml_parse_file($this->filename);
-
-        $this->parseJson($json, $config);
-    }
-}
diff --git a/src/Hal/Application/Config/Parser.php b/src/Hal/Application/Config/Parser.php
deleted file mode 100644
index 7cec93d2..00000000
--- a/src/Hal/Application/Config/Parser.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
-namespace Hal\Application\Config;
-
-use Hal\Application\Config\File\ConfigFileReaderFactory;
-
-class Parser
-{
-    public function parse(array $argv)
-    {
-        $config = new Config();
-
-        if (count($argv) === 0) {
-            return $config;
-        }
-
-        if (preg_match('!\.php$!', $argv[0]) || preg_match('!phpmetrics$!', $argv[0]) || preg_match('!phpmetrics.phar$!', $argv[0])) {
-            array_shift($argv);
-        }
-
-        // Checking for a configuration file option key and importing options
-        foreach ($argv as $k => $arg) {
-            if (preg_match('!\-\-config=(.*)!', $arg, $matches)) {
-                $fileReader = ConfigFileReaderFactory::createFromFileName($matches[1]);
-                $fileReader->read($config);
-                unset($argv[$k]);
-            }
-        }
-
-        // arguments with options
-        foreach ($argv as $k => $arg) {
-            if (preg_match('!\-\-([\w\-]+)=(.*)!', $arg, $matches)) {
-                list(, $parameter, $value) = $matches;
-                $config->set($parameter, trim($value, ' "\''));
-                unset($argv[$k]);
-            }
-        }
-
-        // arguments without options
-        foreach ($argv as $k => $arg) {
-            if (preg_match('!\-\-([\w\-]+)$!', $arg, $matches)) {
-                list(, $parameter) = $matches;
-                $config->set($parameter, true);
-                unset($argv[$k]);
-            }
-        }
-
-        // last argument
-        $files = array_pop($argv);
-        if ($files && !preg_match('!^\-\-!', $files)) {
-            $config->set('files', explode(',', $files));
-        }
-
-        return $config;
-    }
-}
diff --git a/src/Hal/Application/Config/Validator.php b/src/Hal/Application/Config/Validator.php
deleted file mode 100644
index 1e96187c..00000000
--- a/src/Hal/Application/Config/Validator.php
+++ /dev/null
@@ -1,155 +0,0 @@
-<?php
-
-namespace Hal\Application\Config;
-
-use Hal\Metric\Definitions;
-use Hal\Metric\Group\Group;
-use Hal\Metric\Registry;
-use Hal\Search\Searches;
-use Hal\Search\SearchesValidator;
-
-/**
- * @package Hal\Application\Config
- */
-class Validator
-{
-    /**
-     * @param Config $config
-     * @throws ConfigException
-     */
-    public function validate(Config $config)
-    {
-        // required
-        if (!$config->has('files')) {
-            throw new ConfigException('Directory to parse is missing or incorrect');
-        }
-        foreach ($config->get('files') as $dir) {
-            if (!file_exists($dir)) {
-                throw new ConfigException(sprintf('Directory %s does not exist', $dir));
-            }
-        }
-
-        // extensions
-        if (!$config->has('extensions')) {
-            $config->set('extensions', 'php,inc');
-        }
-        $config->set('extensions', explode(',', $config->get('extensions')));
-
-        // excluded directories
-        if (!$config->has('exclude')) {
-            $config->set(
-                'exclude',
-                'vendor,test,Test,tests,Tests,testing,Testing,bower_components,node_modules,cache,spec'
-            );
-        }
-
-        // retro-compatibility with excludes as string in config files
-        if (is_array($config->get('exclude'))) {
-            $config->set('exclude', implode(',', $config->get('exclude')));
-        }
-        $config->set('exclude', array_filter(explode(',', $config->get('exclude'))));
-
-        // groups by regex
-        if (!$config->has('groups')) {
-            $config->set('groups', []);
-        }
-        $groupsRaw = $config->get('groups');
-
-        $groups = array_map(static function (array $groupRaw) {
-            return new Group($groupRaw['name'], $groupRaw['match']);
-        }, $groupsRaw);
-        $config->set('groups', $groups);
-
-        if (!$config->has('composer')) {
-            $config->set('composer', true);
-        }
-
-        if (function_exists('filter_var')) {
-            $config->set('composer', filter_var($config->get('composer'), FILTER_VALIDATE_BOOLEAN));
-        } else {
-            // When PHP is not compiled with the filter extension, we need to do it manually
-            $bool = $config->get('composer');
-            if( is_string($bool) ) {
-                $bool = strtolower($bool);
-                $bool = in_array($bool, ['true', '1', 'yes', 'on'], true);
-            }
-            $config->set('composer', (bool) $bool);
-        }
-
-        // Search
-        $validator = new SearchesValidator();
-        if (null === $config->get('searches')) {
-            $config->set('searches', new Searches());
-        }
-        $validator->validates($config->get('searches'));
-
-        // parameters with values
-        $keys = ['report-html', 'report-csv', 'report-violation', 'report-json', 'report-summary-json', 'extensions', 'config'];
-        foreach ($keys as $key) {
-            $value = $config->get($key);
-            if ($config->has($key) && empty($value) || true === $value) {
-                throw new ConfigException(sprintf('%s option requires a value', $key));
-            }
-        }
-    }
-
-    /**
-     * @return string
-     */
-    public function help()
-    {
-        return <<<EOT
-Usage:
-
-    phpmetrics [...options...] <directories>
-
-Required:
-
-    <directories>                     List of directories to parse, separated by a comma (,)
-
-Optional:
-
-    --config=<file>                   Use a file for configuration. File can be a JSON, YAML or INI file.
-    --exclude=<directory>             List of directories to exclude, separated by a comma (,)
-    --extensions=<php,inc>            List of extensions to parse, separated by a comma (,)
-    --metrics                         Display list of available metrics
-    --report-html=<directory>         Folder where report HTML will be generated
-    --report-csv=<file>               File where report CSV will be generated
-    --report-json=<file>              File where report Json will be generated
-    --report-summary-json=<file>      File where the summary report Json will be generated
-    --report-violations=<file>        File where XML violations report will be generated
-    --git[=</path/to/git_binary>]     Perform analyses based on Git History (default binary path: "git")
-    --junit[=</path/to/junit.xml>]    Evaluates metrics according to JUnit logs
-    --quiet                           Quiet mode
-    --version                         Display current version
-
-Examples:
-
-    phpmetrics --report-html="./report" ./src
-
-        Analyze the "./src" directory and generate a HTML report on the "./report" folder
-
-
-    phpmetrics --report-violations="./build/violations.xml" ./src,./lib
-
-        Analyze the "./src" and "./lib" directories, and generate the "./build/violations.xml" file. This file could
-        be read by any Continuous Integration Platform, and follows the "PMD Violation" standards.
-EOT;
-    }
-
-    public function metrics()
-    {
-        $help = <<<EOT
-Main metrics are:
-EOT;
-
-        $registry = new Registry();
-        $definitions = $registry->getDefinitions();
-        foreach ($definitions as $key => $description) {
-            $help .= sprintf("\n    %s%s", str_pad($key, 40, ' ', STR_PAD_RIGHT), $description);
-        }
-
-        $help .= PHP_EOL;
-        return $help;
-    }
-}
diff --git a/src/Hal/Component/Ast/NodeTraverser.php b/src/Hal/Component/Ast/NodeTraverser.php
deleted file mode 100644
index e5ece784..00000000
--- a/src/Hal/Component/Ast/NodeTraverser.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Ast;
-
-if (PHP_VERSION_ID >= 80000) {
-    class_alias(Php8NodeTraverser::class, __NAMESPACE__ . '\\ActualNodeTraverser');
-}elseif (PHP_VERSION_ID >= 70000) {
-    class_alias(Php7NodeTraverser::class, __NAMESPACE__ . '\\ActualNodeTraverser');
-} else {
-    class_alias(Php5NodeTraverser::class, __NAMESPACE__ . '\\ActualNodeTraverser');
-}
-
-/**
- * Empty class to refer the good ActualNodeTraverser depending on the PHP version.
- * This class must be hard-coded and not directly used as an alias because composer can not handle class-aliases when
- * flag --classmap-authoritative is set.
- * @see https://github.com/phpmetrics/PhpMetrics/issues/373
- */
-/** @noinspection PhpUndefinedClassInspection */
-class NodeTraverser extends ActualNodeTraverser {}
diff --git a/src/Hal/Component/Ast/NodeTyper.php b/src/Hal/Component/Ast/NodeTyper.php
deleted file mode 100644
index 5a046eae..00000000
--- a/src/Hal/Component/Ast/NodeTyper.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-
-namespace Hal\Component\Ast;
-
-use PhpParser\Node;
-use PhpParser\Node\Stmt;
-
-class NodeTyper {
-    public static function isOrganizedStructure($node)
-    {
-        if ($node instanceof Stmt\Class_
-            || $node instanceof Stmt\Interface_
-            || $node instanceof Stmt\Trait_
-            // || $node instanceof Node\Identifier // non namespaced name
-        ) {
-            return true;
-        }
-
-        return false;
-    }
-
-    public static function isOrganizedLogicalClassStructure($node)
-    {
-        if ($node instanceof Stmt\Class_
-            || $node instanceof Stmt\Trait_
-          //  || $node instanceof Node\Identifier // non namespaced name
-        ) {
-            return true;
-        }
-
-        return false;
-    }
-
-}
diff --git a/src/Hal/Component/Ast/ParserFactoryBridge.php b/src/Hal/Component/Ast/ParserFactoryBridge.php
deleted file mode 100644
index dffe5f7e..00000000
--- a/src/Hal/Component/Ast/ParserFactoryBridge.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-namespace Hal\Component\Ast;
-
-/**
- * This class exists for retro compatibility between nikic/php-parser v3, v4 et v5
- */
-class ParserFactoryBridge
-{
-    public function create($kind = null)
-    {
-        if (!method_exists('PhpParser\ParserFactory', 'createForNewestSupportedVersion')) {
-            if(null === $kind) {
-                $kind = \PhpParser\ParserFactory::PREFER_PHP7;
-            }
-            return (new \PhpParser\ParserFactory())->create($kind);
-        }
-
-        if ($kind !== null) {
-            return (new \PhpParser\ParserFactory())->createForVersion($kind);
-        }
-
-        return (new \PhpParser\ParserFactory())->createForNewestSupportedVersion();
-    }
-}
diff --git a/src/Hal/Component/Ast/ParserTraverserVisitorsAssigner.php b/src/Hal/Component/Ast/ParserTraverserVisitorsAssigner.php
deleted file mode 100644
index 61811e10..00000000
--- a/src/Hal/Component/Ast/ParserTraverserVisitorsAssigner.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-namespace Hal\Component\Ast;
-
-use Hal\Metric\Class_\Text\NameVisitor;
-
-/**
- * This class exists for retro compatibility between nikic/php-parser v3, v4 et v5
- */
-class ParserTraverserVisitorsAssigner
-{
-    public function assign(\PhpParser\NodeTraverser $traverser, array $visitors)
-    {
-        // With nikic/php-parser >= v5, visitors are traversed in LIFO order.
-        // With nikic/php-parser < v5, visitors are traversed in FIFO order.
-
-        if (! method_exists('PhpParser\ParserFactory', 'create')) {
-            $visitors = array_reverse($visitors);
-        }
-
-        foreach ($visitors as $visitor) {
-            $traverser->addVisitor($visitor);
-        }
-    }
-}
diff --git a/src/Hal/Component/Ast/Php5NodeTraverser.php b/src/Hal/Component/Ast/Php5NodeTraverser.php
deleted file mode 100644
index 29e9df60..00000000
--- a/src/Hal/Component/Ast/Php5NodeTraverser.php
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-
-namespace Hal\Component\Ast;
-
-use PhpParser\Node;
-use PhpParser\NodeTraverser as Mother;
-
-class Php5NodeTraverser extends Mother
-{
-    /** @var Traverser */
-    private $traverser;
-
-    /**
-     * @param bool $cloneNodes
-     * @param callable|null $stopCondition
-     */
-    public function __construct($cloneNodes = false, $stopCondition = null)
-    {
-        parent::__construct();
-        $this->traverser = new Traverser($this, $stopCondition);
-    }
-
-    public function traverseNode(Node $node)
-    {
-        return parent::traverseNode($node);
-    }
-
-    protected function traverseArray(array $nodes)
-    {
-        return $this->traverser->traverseArray($nodes, $this->visitors);
-    }
-}
diff --git a/src/Hal/Component/Ast/Php7NodeTraverser.php b/src/Hal/Component/Ast/Php7NodeTraverser.php
deleted file mode 100644
index 72b4ee62..00000000
--- a/src/Hal/Component/Ast/Php7NodeTraverser.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-
-namespace Hal\Component\Ast;
-
-use PhpParser\NodeTraverser as Mother;
-
-class Php7NodeTraverser extends Mother
-{
-
-}
diff --git a/src/Hal/Component/Ast/Php8NodeTraverser.php b/src/Hal/Component/Ast/Php8NodeTraverser.php
deleted file mode 100644
index bb8753f7..00000000
--- a/src/Hal/Component/Ast/Php8NodeTraverser.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-
-namespace Hal\Component\Ast;
-
-use PhpParser\NodeTraverser as Mother;
-
-class Php8NodeTraverser extends Mother
-{
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-}
diff --git a/src/Hal/Component/Ast/Traverser.php b/src/Hal/Component/Ast/Traverser.php
deleted file mode 100644
index 39299c54..00000000
--- a/src/Hal/Component/Ast/Traverser.php
+++ /dev/null
@@ -1,102 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Ast;
-
-use PhpParser\Node;
-use PhpParser\NodeTraverser as Mother;
-use PhpParser\NodeVisitor;
-
-/**
- * @author Jean-François Lépine <https://twitter.com/Halleck45>
- * @internal
- */
-class Traverser
-{
-    /**
-     * @var callable
-     */
-    protected $stopCondition;
-
-    /** @var Mother */
-    private $traverser;
-
-    /**
-     * @param Mother $traverser
-     * @param callable|null $stopCondition
-     */
-    public function __construct(Mother $traverser, $stopCondition = null)
-    {
-        if (null === $stopCondition) {
-            $stopCondition = function ($node) {
-                if ($node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\Interface_) {
-                    return false;
-                }
-
-                return true;
-            };
-        }
-
-        $this->stopCondition = $stopCondition;
-        $this->traverser = $traverser;
-    }
-
-    /**
-     * @param array $nodes
-     * @param NodeVisitor[] $visitors
-     * @return array
-     */
-    public function traverseArray(array $nodes, array $visitors)
-    {
-        $doNodes = [];
-
-        foreach ($nodes as $i => &$node) {
-            if (is_array($node)) {
-                $node = $this->traverseArray($node, $visitors);
-            } elseif ($node instanceof Node) {
-                $traverseChildren = call_user_func($this->stopCondition, $node);
-
-                foreach ($visitors as $visitor) {
-                    $return = $visitor->enterNode($node);
-                    if (Mother::DONT_TRAVERSE_CHILDREN === $return) {
-                        $traverseChildren = false;
-                    } elseif (null !== $return) {
-                        $node = $return;
-                    }
-                }
-
-                if ($traverseChildren) {
-                    $node = $this->traverser->traverseNode($node);
-                }
-
-                foreach ($visitors as $visitor) {
-                    $return = $visitor->leaveNode($node);
-
-                    if (Mother::REMOVE_NODE === $return) {
-                        $doNodes[] = [$i, []];
-                        break;
-                    } elseif (is_array($return)) {
-                        $doNodes[] = [$i, $return];
-                        break;
-                    } elseif (null !== $return) {
-                        $node = $return;
-                    }
-                }
-            }
-        }
-
-        if (!empty($doNodes)) {
-            while (list($i, $replace) = array_pop($doNodes)) {
-                array_splice($nodes, $i, 1, $replace);
-            }
-        }
-
-        return $nodes;
-    }
-}
diff --git a/src/Hal/Component/File/Finder.php b/src/Hal/Component/File/Finder.php
deleted file mode 100644
index 6269b6ae..00000000
--- a/src/Hal/Component/File/Finder.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\File;
-
-use RecursiveDirectoryIterator;
-use RecursiveIteratorIterator;
-use RegexIterator;
-
-/**
- * @author Jean-François Lépine <https://twitter.com/Halleck45>
- */
-class Finder
-{
-    /**
-     * Follow symlinks
-     */
-    const FOLLOW_SYMLINKS = RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
-
-    /**
-     * Extensions to match
-     *
-     * @var array
-     */
-    private $extensions = [];
-
-    /**
-     * Subdirectories to exclude
-     *
-     * @var array
-     */
-    private $excludedDirs = [];
-
-    /**
-     * @param string[] $extensions   regex of file extensions to include
-     * @param string[] $excludedDirs regex of directories to exclude
-     */
-    public function __construct(array $extensions = ['php'], array $excludedDirs = [])
-    {
-        $this->extensions = $extensions;
-        $this->excludedDirs = $excludedDirs;
-    }
-
-    /**
-     * Find files in path
-     *
-     * @param string[] $paths
-     * @return array
-     */
-    public function fetch(array $paths)
-    {
-        $files = [];
-        foreach ($paths as $path) {
-            if (is_dir($path)) {
-                $path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
-                $directory = new RecursiveDirectoryIterator($path);
-                $iterator = new RecursiveIteratorIterator($directory);
-
-                $filterRegex = sprintf(
-                    '`^%s%s%s$`',
-                    preg_quote($path, '`'),
-                    !empty($this->excludedDirs) ? '((?!' . implode('|', array_map('preg_quote', $this->excludedDirs)) . ').)+' : '.+',
-                    '\.(' . implode('|', $this->extensions) . ')'
-                );
-
-                $filteredIterator = new RegexIterator(
-                    $iterator,
-                    $filterRegex,
-                    \RecursiveRegexIterator::GET_MATCH
-                );
-
-                foreach ($filteredIterator as $file) {
-                    $files[] = $file[0];
-                }
-            } elseif (is_file($path)) {
-                $files[] = $path;
-            }
-        }
-        return $files;
-    }
-}
diff --git a/src/Hal/Component/Issue/Issuer.php b/src/Hal/Component/Issue/Issuer.php
deleted file mode 100644
index bd1a7225..00000000
--- a/src/Hal/Component/Issue/Issuer.php
+++ /dev/null
@@ -1,178 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Issue;
-
-use Hal\Component\Output\Output;
-use PhpParser\Node;
-use PhpParser\PrettyPrinter\Standard;
-
-/**
- * @package Hal\Component\Issue
- */
-class Issuer
-{
-    /**
-     * @var array
-     */
-    private $debug = [];
-
-    /**
-     * @var Output
-     */
-    private $output;
-
-    /**
-     * @param Output $output
-     */
-    public function __construct(Output $output)
-    {
-        $this->output = $output;
-    }
-
-    /**
-     * @param $errno
-     * @param $errstr
-     * @param $errfile
-     * @param $errline
-     * @throws \ErrorException
-     */
-    public function onError($errno, $errstr, $errfile, $errline)
-    {
-        if (error_reporting() == 0) {
-            return;
-        }
-        $php = PHP_VERSION;
-        $os = php_uname();
-        $phpmetrics = getVersion();
-        $traces = debug_backtrace(0, 10);
-        $trace = '';
-        foreach ($traces as $c) {
-            if (isset($c['file'])) {
-                $trace .= sprintf("+ %s (line %d)\n", $c['file'], $c['line']);
-            }
-        }
-
-        $debug = '';
-        foreach ($this->debug as $key => $value) {
-            if ($value instanceof Node || is_array($value)) {
-                $value = (new Standard())->prettyPrint($value);
-            }
-
-            $debug .= sprintf("%s: %s\n", $key, $value);
-        }
-
-        $logfile = './phpmetrics-error.log';
-
-        $message = <<<EOT
-
-<error>We're sorry : an unexpected error occured.</error>
-
-<question>Can you help us ?</question> Please open a new issue at https://github.com/phpmetrics/PhpMetrics/issues/new, and copy-paste the content
-of this file: $logfile ?
-
-Thanks for your help :)
-EOT;
-
-$log = <<<EOT
-## Title: $errstr
-
-## Message:
-
-Hi,
-
-This issue occured:
-
-$errstr
-
-**Environment**
-
-+ PHP: $php
-+ PhpMetrics: $phpmetrics
-+ Operating System: $os
-+ File: $errfile (line $errline)
-
-<details>
-  <summary>Details</summary>
-  ```
-$trace
-
-
-$debug
-```
-</details>
-EOT;
-
-        $this->output->write($message);
-
-        $this->log($logfile, $log);
-        $this->terminate(1);
-    }
-
-    /**
-     * @return $this
-     */
-    public function enable()
-    {
-        set_error_handler([$this, 'onError']);
-        return $this;
-    }
-
-    /**
-     * @return $this
-     */
-    public function disable()
-    {
-        restore_error_handler();
-        return $this;
-    }
-
-    /**
-     * @param $status
-     */
-    protected function terminate($status)
-    {
-        exit($status);
-    }
-
-    /**
-     * @param $log
-     * @return $this
-     */
-    protected function log($logfile, $log)
-    {
-        if (is_writable(getcwd())) {
-            file_put_contents($logfile, $log);
-        } else {
-            $this->output->write($log);
-        }
-        return $this;
-    }
-
-    /**
-     * @param $debugKey
-     * @param $value
-     * @return $this
-     */
-    public function set($debugKey, $value)
-    {
-        $this->debug[$debugKey] = $value;
-        return $this;
-    }
-
-    /**
-     * @param $debugKey
-     * @return $this
-     */
-    public function clear($debugKey)
-    {
-        unset($this->debug[$debugKey]);
-        return $this;
-    }
-}
diff --git a/src/Hal/Component/Output/CliOutput.php b/src/Hal/Component/Output/CliOutput.php
deleted file mode 100644
index d2f28f25..00000000
--- a/src/Hal/Component/Output/CliOutput.php
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Output;
-
-/**
- * @package Hal\Component\Issue
- */
-class CliOutput implements Output
-{
-    /**
-     * @var bool
-     */
-    private $quietMode = false;
-
-    /**
-     * @param string $message
-     * @return $this
-     */
-    public function writeln($message)
-    {
-        $this->write(PHP_EOL . $message);
-        return $this;
-    }
-
-    /**
-     * @param string $message
-     * @return $this
-     */
-    public function write($message)
-    {
-        if (preg_match_all('!<([a-z]+)(?:=[^}]+)?>(.*?)</\\1>!', $message, $matches, PREG_SET_ORDER)) {
-            list(, $type, $message) = $matches[0];
-            $color = '';
-            switch ($type) {
-                case 'error':
-                    $color = "\033[31m";
-                    break;
-                case 'warning':
-                    $color = "\033[33m";
-                    break;
-                case 'success':
-                    $color = "\033[32m";
-                    break;
-                case 'info':
-                    $color = "\033[34m";
-                    break;
-            }
-
-            $message = $color . $message . "\033[0m";
-        }
-
-        $this->quietMode || file_put_contents('php://stdout', $message);
-        return $this;
-    }
-
-    /**
-     * @param string $message
-     * @return $this
-     */
-    public function err($message)
-    {
-        file_put_contents('php://stderr', $message);
-        return $this;
-    }
-
-    public function clearln()
-    {
-        $this->writeln("\x0D");
-        $this->writeln("\x1B[2K");
-        return $this;
-    }
-
-    /**
-     * @param bool $quietMode
-     * @return $this
-     */
-    public function setQuietMode($quietMode)
-    {
-        $this->quietMode = $quietMode;
-        return $this;
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public function hasAnsi()
-    {
-        if (DIRECTORY_SEPARATOR === '\\') {
-            return
-                0 >= version_compare(
-                    '10.0.10586',
-                    PHP_WINDOWS_VERSION_MAJOR . '.' . PHP_WINDOWS_VERSION_MINOR . '.' . PHP_WINDOWS_VERSION_BUILD
-                )
-                || false !== getenv('ANSICON')
-                || 'ON' === getenv('ConEmuANSI')
-                || 'xterm' === getenv('TERM');
-        }
-
-        return function_exists('posix_isatty') && @posix_isatty(STDOUT);
-    }
-}
diff --git a/src/Hal/Component/Output/Output.php b/src/Hal/Component/Output/Output.php
deleted file mode 100644
index 698bebcf..00000000
--- a/src/Hal/Component/Output/Output.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Output;
-
-/**
- * @package Hal\Component\Output
- */
-interface Output
-{
-    /**
-     * @param string $message
-     * @return $this
-     */
-    public function writeln($message);
-
-    /**
-     * @param string $message
-     * @return $this
-     */
-    public function write($message);
-
-    /**
-     * @param string $message
-     * @return $this
-     */
-    public function err($message);
-
-    /**
-     * @return $this
-     */
-    public function clearln();
-
-    /**
-     * Detects ANSI support
-     *
-     * @return bool
-     */
-    public function hasAnsi();
-}
diff --git a/src/Hal/Component/Output/ProgressBar.php b/src/Hal/Component/Output/ProgressBar.php
deleted file mode 100644
index 8ffeb510..00000000
--- a/src/Hal/Component/Output/ProgressBar.php
+++ /dev/null
@@ -1,78 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Output;
-
-/**
- * @package Hal\Component\Output
- */
-class ProgressBar
-{
-    /**
-     * @var Output
-     */
-    private $output;
-
-    /**
-     * @var int
-     */
-    private $max;
-
-    /**
-     * @var int
-     */
-    private $current = 0;
-
-    /**
-     * @param Output $output
-     * @param int $max
-     */
-    public function __construct(Output $output, $max)
-    {
-        $this->output = $output;
-        $this->max = $max;
-    }
-
-    /**
-     * Start progress bar
-     */
-    public function start()
-    {
-        $this->current = 0;
-    }
-
-    /**
-     * Advance progress bar
-     */
-    public function advance()
-    {
-        $this->current++;
-
-        if ($this->output->hasAnsi()) {
-            $percent = round($this->current / $this->max * 100);
-            $this->output->write("\x0D");
-            $this->output->write("\x1B[2K");
-            $this->output->write(sprintf('... %s%% ...', $percent));
-        } else {
-            $this->output->write('.');
-        }
-    }
-
-    /**
-     * Clear console
-     */
-    public function clear()
-    {
-        if ($this->output->hasAnsi()) {
-            $this->output->write("\x0D");
-            $this->output->write("\x1B[2K");
-            $this->output->clearln();
-        }
-    }
-}
diff --git a/src/Hal/Component/Output/TestOutput.php b/src/Hal/Component/Output/TestOutput.php
deleted file mode 100644
index f5b70ab2..00000000
--- a/src/Hal/Component/Output/TestOutput.php
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Output;
-
-/**
- * @package Hal\Component\Issue
- */
-class TestOutput implements Output
-{
-    public $output;
-    public $err;
-
-    /**
-     * @inheritdoc
-     */
-    public function writeln($message)
-    {
-        $this->write(PHP_EOL . $message);
-        return $this;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function write($message)
-    {
-        $this->output .= $message;
-        return $this;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function err($message)
-    {
-        $this->err .= $message;
-        return $this;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function clearln() {}
-
-    /**
-     * @inheritdoc
-     */
-    public function hasAnsi()
-    {
-        return false;
-    }
-}
diff --git a/src/Hal/Component/Tree/Edge.php b/src/Hal/Component/Tree/Edge.php
deleted file mode 100644
index f679ee21..00000000
--- a/src/Hal/Component/Tree/Edge.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Tree;
-
-class Edge
-{
-    /**
-     * @var Node
-     */
-    private $from;
-
-    /**
-     * @var Node
-     */
-    private $to;
-
-    /**
-     * @var boolean
-     */
-    public $cyclic = false;
-
-    /**
-     * @param Node $from
-     * @param Node $to
-     */
-    public function __construct(Node $from, Node $to)
-    {
-        $this->from = $from;
-        $this->to = $to;
-    }
-
-    /**
-     * @return Node
-     */
-    public function getFrom()
-    {
-        return $this->from;
-    }
-
-    /**
-     * @return Node
-     */
-    public function getTo()
-    {
-        return $this->to;
-    }
-
-    /**
-     * @return string
-     */
-    public function asString()
-    {
-        return sprintf('%s -> %s', $this->from->getKey(), $this->to->getKey());
-    }
-}
diff --git a/src/Hal/Component/Tree/Graph.php b/src/Hal/Component/Tree/Graph.php
deleted file mode 100644
index fd724a2c..00000000
--- a/src/Hal/Component/Tree/Graph.php
+++ /dev/null
@@ -1,154 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Tree;
-
-class Graph implements \Countable
-{
-    /**
-     * @var Node[]
-     */
-    private $data = [];
-
-    /**
-     * @var Edge[]
-     */
-    private $edges = [];
-
-    /**
-     * @param Node $node
-     * @return $this
-     */
-    public function insert(Node $node)
-    {
-        if ($this->has($node->getKey())) {
-            throw new GraphException(sprintf('node %s is already present', $node->getKey()));
-        }
-        $this->data[$node->getKey()] = $node;
-        return $this;
-    }
-
-    /**
-     * @param Node $from
-     * @param Node $to
-     * @return $this
-     */
-    public function addEdge(Node $from, Node $to)
-    {
-        if (!$this->has($from->getKey())) {
-            throw new GraphException('from is not is in the graph');
-        }
-        if (!$this->has($to->getKey())) {
-            throw new GraphException('to is not is in the graph');
-        }
-
-        $edge = new Edge($from, $to);
-        $from->addEdge($edge);
-        $to->addEdge($edge);
-        array_push($this->edges, $edge);
-
-        return $this;
-    }
-
-    /**
-     * @return string
-     */
-    public function asString()
-    {
-        $string = '';
-        foreach ($this->all() as $node) {
-            $string .= sprintf("%s;\n", $node->getKey());
-        }
-        foreach ($this->getEdges() as $edge) {
-            $string .= sprintf("%s;\n", $edge->asString());
-        }
-        return $string;
-    }
-
-    /**
-     * @return Edge[]
-     */
-    public function getEdges()
-    {
-        return $this->edges;
-    }
-
-    /**
-     * @param $key
-     * @return Node|null
-     */
-    public function get($key)
-    {
-        return $this->has($key) ? $this->data[$key] : null;
-    }
-
-    /**
-     * @param $key
-     * @return bool
-     */
-    public function has($key)
-    {
-        return isset($this->data[$key]);
-    }
-
-    /**
-     * @return int
-     */
-    #[\ReturnTypeWillChange]
-    public function count()
-    {
-        return count($this->data);
-    }
-
-    /**
-     * @return Node[]
-     */
-    public function all()
-    {
-        return $this->data;
-    }
-
-    /**
-     * @return $this
-     */
-    public function resetVisits()
-    {
-        foreach ($this->all() as $node) {
-            $node->visited = false;
-        }
-        return $this;
-    }
-
-    /**
-     * Get the list of all root nodes
-     *
-     *      we can have array of roots : graph can be a "forest"
-     *
-     * @return array
-     */
-    public function getRootNodes()
-    {
-        $roots = [];
-        foreach ($this->all() as $node) {
-            $isRoot = true;
-
-            foreach ($node->getEdges() as $edge) {
-                if ($edge->getTo() == $node) {
-                    $isRoot = false;
-                }
-            }
-
-            if ($isRoot) {
-                array_push($roots, $node);
-            }
-        }
-
-        return $roots;
-    }
-}
diff --git a/src/Hal/Component/Tree/GraphDeduplicated.php b/src/Hal/Component/Tree/GraphDeduplicated.php
deleted file mode 100644
index 093a82c8..00000000
--- a/src/Hal/Component/Tree/GraphDeduplicated.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-namespace Hal\Component\Tree;
-
-class GraphDeduplicated extends Graph
-{
-    /**
-     * @var array list of already present edges in this graph
-     */
-    private $edgesMap = [];
-
-    /**
-     * @param Node $from
-     * @param Node $to
-     *
-     * @return $this
-     */
-    public function addEdge(Node $from, Node $to)
-    {
-        $key = $from->getUniqueId() . '->' . $to->getUniqueId();
-
-        if (isset($this->edgesMap[$key])) {
-            return $this;
-        }
-
-        $this->edgesMap[$key] = true;
-
-        return parent::addEdge($from, $to);
-    }
-}
diff --git a/src/Hal/Component/Tree/GraphException.php b/src/Hal/Component/Tree/GraphException.php
deleted file mode 100644
index 428d3202..00000000
--- a/src/Hal/Component/Tree/GraphException.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Tree;
-
-class GraphException extends \LogicException {}
diff --git a/src/Hal/Component/Tree/HashMap.php b/src/Hal/Component/Tree/HashMap.php
deleted file mode 100644
index 586cc97e..00000000
--- a/src/Hal/Component/Tree/HashMap.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Tree;
-
-class HashMap implements \Countable, \IteratorAggregate
-{
-    /**
-     * @var array
-     */
-    private $nodes = [];
-
-    /**
-     * @param Node $node
-     * @return $this
-     */
-    public function attach(Node $node)
-    {
-        $this->nodes[$node->getKey()] = $node;
-        return $this;
-    }
-
-    /**
-     * @param $key
-     * @return Node
-     */
-    public function get($key)
-    {
-        return $this->has($key) ? $this->nodes[$key] : null;
-    }
-
-    /**
-     * @param $key
-     * @return bool
-     */
-    public function has($key)
-    {
-        return isset($this->nodes[$key]);
-    }
-
-    /**
-     * @return int
-     */
-    public function count()
-    {
-        return count($this->nodes);
-    }
-
-    /**
-     * @return \ArrayIterator
-     */
-    public function getIterator()
-    {
-        return new \ArrayIterator($this->nodes);
-    }
-}
diff --git a/src/Hal/Component/Tree/Node.php b/src/Hal/Component/Tree/Node.php
deleted file mode 100644
index 48f01025..00000000
--- a/src/Hal/Component/Tree/Node.php
+++ /dev/null
@@ -1,117 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Tree;
-
-class Node
-{
-    /**
-     * @var mixed
-     */
-    private $data;
-
-    /**
-     * @var string
-     */
-    private $key;
-
-    /**
-     * @var Edge[]
-     */
-    private $edges = [];
-
-    /**
-     * @var bool
-     */
-    public $visited = false;
-
-    /**
-     * @var bool
-     */
-    public $cyclic = false;
-
-    /**
-     * @param string $key
-     * @param mixed $data
-     */
-    public function __construct($key, $data = null)
-    {
-        $this->key = $key;
-        $this->data = $data;
-    }
-
-    /**
-     * @return string
-     */
-    public function getKey()
-    {
-        return $this->key;
-    }
-
-    /**
-     * @return array
-     */
-    public function getAdjacents()
-    {
-        $adjacents = [];
-        foreach ($this->edges as $edge) {
-            if ($edge->getFrom()->getKey() != $this->getKey()) {
-                $adjacents[$edge->getFrom()->getKey()] = $edge->getFrom();
-            }
-            if ($edge->getTo()->getKey() != $this->getKey()) {
-                $adjacents[$edge->getTo()->getKey()] = $edge->getTo();
-            }
-        }
-        return $adjacents;
-    }
-
-    /**
-     * @return Edge[]
-     */
-    public function getEdges()
-    {
-        return $this->edges;
-    }
-
-    /**
-     * @param Edge $edge
-     * @return $this
-     */
-    public function addEdge(Edge $edge)
-    {
-        array_push($this->edges, $edge);
-        return $this;
-    }
-
-    /**
-     * @return mixed
-     */
-    public function getData()
-    {
-        return $this->data;
-    }
-
-    /**
-     * @param mixed $data
-     * @return Node
-     */
-    public function setData($data)
-    {
-        $this->data = $data;
-        return $this;
-    }
-
-    /**
-     * @return string Unique id for this node independent of class name or node type
-     */
-    public function getUniqueId()
-    {
-        return spl_object_hash($this);
-    }
-}
diff --git a/src/Hal/Component/Tree/Operator/CycleDetector.php b/src/Hal/Component/Tree/Operator/CycleDetector.php
deleted file mode 100644
index 3aa10f53..00000000
--- a/src/Hal/Component/Tree/Operator/CycleDetector.php
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Tree\Operator;
-
-use Hal\Component\Tree\Graph;
-use Hal\Component\Tree\Node;
-
-/**
- * @package Hal\Component\Tree\Util
- * @see http://www.geeksforgeeks.org/detect-cycle-in-a-graph/
- */
-class CycleDetector
-{
-    /**
-     * Check if graph contains cycle
-     *
-     * Each node in cycle is flagged with the "cyclic" attribute
-     *
-     * @param Graph $graph
-     * @return bool
-     */
-    public function isCyclic(Graph $graph)
-    {
-        // prepare stack
-        $recursionStack = [];
-        foreach ($graph->all() as $node) {
-            $recursionStack[$node->getKey()] = false;
-        }
-
-        // start analysis
-        $isCyclic = false;
-        foreach ($graph->getEdges() as $edge) {
-            if ($r = $this->detectCycle($edge->getFrom(), $recursionStack)) {
-                $edge->cyclic = true;
-                $isCyclic = true;
-            }
-
-            $recursionStack[$node->getKey()] = false;
-        }
-
-        $graph->resetVisits();
-
-        return $isCyclic;
-    }
-
-    /**
-     * @param Node $node
-     * @param $recursionStack
-     * @return bool
-     */
-    private function detectCycle(Node $node, &$recursionStack)
-    {
-        if (!$node->visited) {
-            // mark the current node as visited and part of recursion stack
-            $recursionStack[$node->getKey()] = true;
-            $node->visited = true;
-
-            // recur for all the vertices adjacent to this vertex
-            foreach ($node->getEdges() as $edge) {
-                if ($edge->getTo() === $node) {
-                    continue;
-                }
-
-                if (!$edge->getTo()->visited && $this->detectCycle($edge->getTo(), $recursionStack)) {
-                    $edge->cyclic = $edge->getTo()->cyclic = true;
-                    return true;
-                } elseif ($recursionStack[$edge->getTo()->getKey()]) {
-                    $edge->cyclic = $edge->getTo()->cyclic = true;
-                    return true;
-                }
-            }
-        }
-        // remove the vertex from recursion stack
-        $recursionStack[$node->getKey()] = false;
-        return false;
-    }
-}
diff --git a/src/Hal/Component/Tree/Operator/SizeOfTree.php b/src/Hal/Component/Tree/Operator/SizeOfTree.php
deleted file mode 100644
index fc3593da..00000000
--- a/src/Hal/Component/Tree/Operator/SizeOfTree.php
+++ /dev/null
@@ -1,140 +0,0 @@
-<?php
-
-/*
- * (c) Jean-François Lépine <https://twitter.com/Halleck45>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Hal\Component\Tree\Operator;
-
-use Hal\Component\Tree\Graph;
-use Hal\Component\Tree\Node;
-
-class SizeOfTree
-{
-    /**
-     * @var Graph
-     */
-    private $graph;
-
-    /**
-     * @param Graph $graph
-     */
-    public function __construct(Graph $graph)
-    {
-        if ((new CycleDetector())->isCyclic($graph)) {
-            throw new \LogicException('Cannot get size informations of cyclic graph');
-        }
-
-        $this->graph = $graph;
-    }
-
-    /**
-     * Get depth of node
-     *
-     * @param Node $node
-     * @return int
-     */
-    public function getDepthOfNode(Node $node)
-    {
-        $edges = $node->getEdges();
-
-        if (0 === count($edges)) {
-            return 0;
-        }
-
-        // our tree is not binary : interface can have more than one parent
-        $max = 0;
-        foreach ($edges as $edge) {
-            if ($edge->getFrom() == $node) {
-                continue;
-            }
-
-            $n = 1 + $this->getDepthOfNode($edge->getFrom());
-            if ($n > $max) {
-                $max = $n;
-            }
-        }
-
-        return $max;
-    }
-
-    /**
-     * Get depth of node
-     *
-     * @param Node $node
-     * @return int
-     */
-    public function getNumberOfChilds(Node $node, $uniqs = false)
-    {
-        $edges = $node->getEdges();
-
-        if (0 === count($edges)) {
-            return 0;
-        }
-
-        // our tree is not binary : interface can have more than one parent
-        $max = 0;
-        $n = 0;
-
-        foreach ($edges as $edge) {
-            if ($edge->getTo() == $node) {
-                continue;
-            }
-
-            if (true == $uniqs && $edge->getTo()->visited) {
-                continue;
-            }
-            $edge->getTo()->visited = true;
-
-            $n += 1 + $this->getNumberOfChilds($edge->getTo(), $uniqs);
-
-            $edge->getTo()->visited = false;
-
-            if ($n > $max) {
-                $max = $n;
-            }
-        }
-
-        return $max;
-    }
-
-    /**
-     * Get average height of graph
-     *
-     * @return float
-     */
-    public function getAverageHeightOfGraph()
-    {
-        $ns = [];
-        foreach ($this->graph->getRootNodes() as $node) {
-            array_push($ns, $this->getLongestBranch($node));
-        }
-        return round(array_sum($ns) / max(1, count($ns)), 2);
-    }
-
-    /**
-     * @param Node $node
-     * @return int
-     */
-    public function getLongestBranch(Node $node)
-    {
-        $max = 1;
-        foreach ($node->getEdges() as $edge) {
-            if ($node == $edge->getTo()) {
-                // only descendants
-                continue;
-            }
-
-            $n = 1 + $this->getLongestBranch($edge->getTo());
-
-            if ($n > $max) {
-                $max = $n;
-            }
-        }
-
-        return $max;
-    }
-}
diff --git a/src/Hal/Metric/BagTrait.php b/src/Hal/Metric/BagTrait.php
deleted file mode 100644
index 0a2d792f..00000000
--- a/src/Hal/Metric/BagTrait.php
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php
-
-namespace Hal\Metric;
-
-trait BagTrait
-{
-    private $name;
-
-    /**
-     * @var array
-     */
-    private $bag = [];
-
-    /**
-     * @param string $name
-     */
-    public function __construct($name)
-    {
-        $this->name = $name;
-        $this->set('name', $name);
-    }
-
-    /**
-     * @return string
-     */
-    public function getName()
-    {
-        return $this->name;
-    }
-
-    /**
-     * @param $key
-     * @param $value
-     * @return $this
-     */
-    public function set($key, $value)
-    {
-        $this->bag[$key] = $value;
-        return $this;
-    }
-
-    /**
-     * @param $key
-     * @return bool
-     */
-    public function has($key)
-    {
-        return isset($this->bag[$key]);
-    }
-
-    /**
-     * @param $key
-     * @return null
-     */
-    public function get($key)
-    {
-        return $this->has($key) ? $this->bag[$key] : null;
-    }
-
-    /**
-     * @return array
-     */
-    public function all()
-    {
-        return $this->bag;
-    }
-
-    /**
-     * @param array $array
-     * @return $this
-     */
-    public function fromArray(array $array)
-    {
-        foreach ($array as $key => $value) {
-            $this->set($key, $value);
-        }
-        return $this;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    #[\ReturnTypeWillChange]
-    public function jsonSerialize()
-    {
-        return array_merge($this->all(), ['_type' => get_class($this)]);
-    }
-}
diff --git a/src/Hal/Metric/ClassMetric.php b/src/Hal/Metric/ClassMetric.php
deleted file mode 100644
index a3e1f87f..00000000
--- a/src/Hal/Metric/ClassMetric.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-namespace Hal\Metric;
-
-class ClassMetric implements Metric, \JsonSerializable
-{
-    use BagTrait;
-}
diff --git a/src/Hal/Metric/Class_/ClassEnumVisitor.php b/src/Hal/Metric/Class_/ClassEnumVisitor.php
deleted file mode 100644
index 8193e675..00000000
--- a/src/Hal/Metric/Class_/ClassEnumVisitor.php
+++ /dev/null
@@ -1,111 +0,0 @@
-<?php
-
-namespace Hal\Metric\Class_;
-
-use Hal\Component\Ast\NodeTyper;
-use Hal\Metric\ClassMetric;
-use Hal\Metric\FunctionMetric;
-use Hal\Metric\Helper\RoleOfMethodDetector;
-use Hal\Metric\InterfaceMetric;
-use Hal\Metric\Metrics;
-use PhpParser\Node;
-use PhpParser\Node\Stmt;
-use PhpParser\NodeVisitorAbstract;
-
-class ClassEnumVisitor extends NodeVisitorAbstract
-{
-    /**
-     * @var Metrics
-     */
-    private $metrics;
-
-    /**
-     * @param Metrics $metrics
-     */
-    public function __construct(Metrics $metrics)
-    {
-        $this->metrics = $metrics;
-    }
-
-
-    public function leaveNode(Node $node)
-    {
-        if (
-            NodeTyper::isOrganizedStructure($node)
-        ) {
-            if ($node instanceof Stmt\Interface_) {
-                $class = new InterfaceMetric($node->namespacedName->toString());
-                $class->set('interface', true);
-                $class->set('abstract', true);
-            } else {
-                $name = getNameOfNode($node);
-                $class = new ClassMetric($name);
-                $class->set('interface', false);
-
-                $isAbstract = false;
-                if ($node instanceof Stmt\Class_) {
-                    $isAbstract = $node->isAbstract();
-                } elseif ($node instanceof Stmt\Trait_) {
-                    $isAbstract = true; // Traits are always abstract
-                }
-
-                $isFinal = false;
-                if ($node instanceof Stmt\Class_) {
-                    $isFinal = $node->isFinal();
-                } elseif ($node instanceof Stmt\Trait_) {
-                    $isFinal = false; // Traits cannot be final
-                }
-
-                $class->set('abstract', $isAbstract);
-                $class->set('final', $isFinal);
-            }
-
-            $methods = [];
-
-            $methodsPublic = $methodsPrivate = $nbGetters = $nbSetters = 0;
-            $roleDetector = new RoleOfMethodDetector();
-            foreach ($node->stmts as $stmt) {
-                if ($stmt instanceof Stmt\ClassMethod) {
-                    $function = new FunctionMetric((string)$stmt->name);
-
-                    $role = $roleDetector->detects($stmt);
-                    $function->set('role', $role);
-                    switch ($role) {
-                        case 'getter':
-                            $nbGetters++;
-                            break;
-                        case 'setter':
-                            $nbSetters++;
-                            break;
-                    }
-
-                    if (null === $role) {
-                        if ($stmt->isPublic()) {
-                            $methodsPublic++;
-                            $function->set('public', true);
-                            $function->set('private', false);
-                        }
-
-                        if ($stmt->isPrivate() || $stmt->isProtected()) {
-                            $methodsPrivate++;
-                            $function->set('public', false);
-                            $function->set('private', true);
-                        }
-                    }
-
-                    array_push($methods, $function);
-                }
-            }
-
-            $class->set('methods', $methods);
-            $class->set('nbMethodsIncludingGettersSetters', count($methods));
-            $class->set('nbMethods', count($methods) - ($nbGetters + $nbSetters));
-            $class->set('nbMethodsPrivate', $methodsPrivate);
-            $class->set('nbMethodsPublic', $methodsPublic);
-            $class->set('nbMethodsGetter', $nbGetters);
-            $class->set('nbMethodsSetters', $nbSetters);
-
-            $this->metrics->attach($class);
-        }
-    }
-}
diff --git a/src/Hal/Metric/Class_/Complexity/CyclomaticComplexityVisitor.php b/src/Hal/Metric/Class_/Complexity/CyclomaticComplexityVisitor.php
deleted file mode 100644
index 70aafcee..00000000
--- a/src/Hal/Metric/Class_/Complexity/CyclomaticComplexityVisitor.php
+++ /dev/null
@@ -1,130 +0,0 @@
-<?php
-
-namespace Hal\Metric\Class_\Complexity;
-
-use Hal\Component\Ast\NodeTyper;
-use Hal\Metric\Helper\RoleOfMethodDetector;
-use Hal\Metric\Metrics;
-use PhpParser\Node;
-use PhpParser\Node\Stmt;
-use PhpParser\NodeVisitorAbstract;
-
-/**
- * Calculate cyclomatic complexity number and weighted method count.
- *
- * The cyclomatic complexity (CCN) is a measure of control structure complexity of a function or procedure.
- * We can calculate ccn in two ways (we choose the second):
- *
- *  1.  Cyclomatic complexity (CCN) = E - N + 2P
- *      Where:
- *      P = number of disconnected parts of the flow graph (e.g. a calling program and a subroutine)
- *      E = number of edges (transfers of control)
- *      N = number of nodes (sequential group of statements containing only one transfer of control)
- *
- *  2. CCN = Number of each decision point
- *
- * The weighted method count (WMC) is count of methods parameterized by a algorithm to compute the weight of a method.
- * Given a weight metric w and methods m it can be computed as
- *
- *  sum m(w') over (w' in w)
- *
- * Possible algorithms are:
- *
- *  - Cyclomatic Complexity
- *  - Lines of Code
- *  - 1 (unweighted WMC)
- *
- * This visitor provides two metrics, the maximal CCN of all methods from one class (currently stored as ccnMethodMax)
- * and the WMC using the CCN as weight metric (currently stored as ccn).
- *
- * @see https://en.wikipedia.org/wiki/Cyclomatic_complexity
- * @see http://www.literateprogramming.com/mccabe.pdf
- * @see https://www.pitt.edu/~ckemerer/CK%20research%20papers/MetricForOOD_ChidamberKemerer94.pdf
- */
-class CyclomaticComplexityVisitor extends NodeVisitorAbstract
-{
-    /** @var Metrics */
-    private $metrics;
-
-    public function __construct(Metrics $metrics)
-    {
-        $this->metrics = $metrics;
-    }
-
-    public function leaveNode(Node $node)
-    {
-        if (NodeTyper::isOrganizedStructure($node)) {
-            $class = $this->metrics->get(getNameOfNode($node));
-            if ($class === null) {
-                throw new \RuntimeException('Class metric not found for ' . getNameOfNode($node));
-            }
-
-            $ccn = 1;
-            $wmc = 0;
-            $ccnByMethod = [0]; // default maxMethodCcn if no methods are available
-
-            $roleDetector = new RoleOfMethodDetector();
-
-            foreach ($node->stmts as $stmt) {
-                if ($stmt instanceof Stmt\ClassMethod) {
-
-                    $role = $roleDetector->detects($stmt);
-                    if (in_array($role, ['getter', 'setter'])) {
-                        // We don't want to increase the CCN for getters and setters,
-                        continue;
-                    }
-
-                    // iterate over children, recursively
-                    $cb = function ($node) use (&$cb) {
-                        $ccn = 0;
-
-                        foreach (get_object_vars($node) as $name => $member) {
-                            foreach (is_array($member) ? $member : [$member] as $memberItem) {
-                                if ($memberItem instanceof Node) {
-                                    $ccn += $cb($memberItem);
-                                }
-                            }
-                        }
-                        switch (true) {
-                            case $node instanceof Stmt\If_:
-                            case $node instanceof Stmt\ElseIf_:
-                            case $node instanceof Stmt\For_:
-                            case $node instanceof Stmt\Foreach_:
-                            case $node instanceof Stmt\While_:
-                            case $node instanceof Stmt\Do_:
-                            case $node instanceof Node\Expr\BinaryOp\LogicalAnd:
-                            case $node instanceof Node\Expr\BinaryOp\LogicalOr:
-                            case $node instanceof Node\Expr\BinaryOp\LogicalXor:
-                            case $node instanceof Node\Expr\BinaryOp\BooleanAnd:
-                            case $node instanceof Node\Expr\BinaryOp\BooleanOr:
-                            case $node instanceof Stmt\Catch_:
-                            case $node instanceof Node\Expr\Ternary:
-                            case $node instanceof Node\Expr\BinaryOp\Coalesce:
-                                $ccn++;
-                                break;
-                            case $node instanceof Stmt\Case_: // include default
-                                if ($node->cond !== null) { // exclude default
-                                    $ccn++;
-                                }
-                                break;
-                            case $node instanceof Node\Expr\BinaryOp\Spaceship:
-                                $ccn += 2;
-                                break;
-                        }
-                        return $ccn;
-                    };
-
-                    $methodCcn = $cb($stmt) + 1; // each method by default is CCN 1 even if it's empty
-
-                    $wmc += $methodCcn;
-                    $ccn += $methodCcn - 1;
-                    $ccnByMethod[] = $methodCcn;
-                }
-            }
-
-            $class->set('wmc', $wmc);
-            $class->set('ccn', $ccn);
-            $class->set('ccnMethodMax', max($ccnByMethod));
-        }
-    }
-}
diff --git a/src/Hal/Metric/Class_/Complexity/KanDefectVisitor.php b/src/Hal/Metric/Class_/Complexity/KanDefectVisitor.php
deleted file mode 100644
index bb055e75..00000000
--- a/src/Hal/Metric/Class_/Complexity/KanDefectVisitor.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-
-namespace Hal\Metric\Class_\Complexity;
-
-use Hal\Component\Ast\NodeTyper;
-use Hal\Component\Reflected\Method;
-use Hal\Metric\Metrics;
-use PhpParser\Node;
-use PhpParser\Node\Stmt;
-use PhpParser\NodeVisitorAbstract;
-
-/**
- * Calculate Kan's defects
- *
- * defects = 0.15 + 0.23 *  number of do…while() + 0.22 *  number of select() + 0.07 * number of if()
- */
-class KanDefectVisitor extends NodeVisitorAbstract
-{
-    /**
-     * @var Metrics
-     */
-    private $metrics;
-
-    /**
-     * @param Metrics $metrics
-     */
-    public function __construct(Metrics $metrics)
-    {
-        $this->metrics = $metrics;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function leaveNode(Node $node)
-    {
-        if (NodeTyper::isOrganizedStructure($node)) {
-            $class = $this->metrics->get(getNameOfNode($node));
-
-            $select = $while = $if = 0;
-
-            iterate_over_node($node, function ($node) use (&$while, &$select, &$if) {
-                switch (true) {
-                    case $node instanceof Stmt\Do_:
-                    case $node instanceof Stmt\Foreach_:
-                    case $node instanceof Stmt\While_:
-                        $while++;
-                        break;
-                    case $node instanceof Stmt\If_:
-                        $if++;
-                        break;
-                    case $node instanceof Stmt\Switch_:
-                        $select++;
-                        break;
-                }
-            });
-
-            $defect = 0.15 + 0.23 *  $while + 0.22 *  $select + 0.07 * $if;
-            $class->set('kanDefect', round($defect, 2));
-        }
-    }
-}
diff --git a/src/Hal/Metric/Class_/Component/MaintainabilityIndexVisitor.php b/src/Hal/Metric/Class_/Component/MaintainabilityIndexVisitor.php
deleted file mode 100644
index cca79094..00000000
--- a/src/Hal/Metric/Class_/Component/MaintainabilityIndexVisitor.php
+++ /dev/null
@@ -1,105 +0,0 @@
-<?php
-
-namespace Hal\Metric\Class_\Component;
-
-use Hal\Component\Ast\NodeTyper;
-use Hal\Metric\FunctionMetric;
-use Hal\Metric\Metrics;
-use Hoa\Ruler\Model\Bag\Scalar;
-use PhpParser\Node;
-use PhpParser\Node\Stmt;
-use PhpParser\NodeVisitorAbstract;
-
-/**
- * Calculates Maintainability Index
- *
- *      According to Wikipedia, "Maintainability Index is a software metric which measures how maintainable (easy to
- *      support and change) the source code is. The maintainability index is calculated as a factored formula consisting
- *      of Lines Of Code, Cyclomatic Complexity and Halstead volume."
- *
- *      MIwoc: Maintainability Index without comments
- *      MIcw: Maintainability Index comment weight
- *      MI: Maintainability Index = MIwoc + MIcw
- *
- *      MIwoc = 171 - 5.2 * ln(aveV) -0.23 * aveG -16.2 * ln(aveLOC)
- *      MIcw = 50 * sin(sqrt(2.4 * perCM))
- *      MI = MIwoc + MIcw
- *
- * @author Jean-François Lépine <https://twitter.com/Halleck45>
- */
-class MaintainabilityIndexVisitor extends NodeVisitorAbstract
-{
-    /**
-     * @var Metrics
-     */
-    private $metrics;
-
-    /**
-     * @param Metrics $metrics
-     */
-    public function __construct(Metrics $metrics)
-    {
-        $this->metrics = $metrics;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function leaveNode(Node $node)
-    {
-        if (NodeTyper::isOrganizedLogicalClassStructure($node)) {
-            $name = getNameOfNode($node);
-            $classOrFunction = $this->metrics->get($name);
-
-            if(null === $classOrFunction) {
-                throw new \LogicException('class or function ' . $name . ' not found in metrics');
-            }
-
-            if (null === $lloc = $classOrFunction->get('lloc')) {
-                throw new \LogicException('please enable length (lloc) visitor first');
-            }
-            if (null === $cloc = $classOrFunction->get('cloc')) {
-                throw new \LogicException('please enable length (cloc) visitor first');
-            }
-            if (null === $loc = $classOrFunction->get('loc')) {
-                throw new \LogicException('please enable length (loc) visitor first');
-            }
-            if (null === $ccn = $classOrFunction->get('ccn')) {
-                throw new \LogicException('please enable McCabe visitor first');
-            }
-            if (null === $volume = $classOrFunction->get('volume')) {
-                throw new \LogicException('please enable Halstead visitor first');
-            }
-
-            // maintainability index without comment
-            $MIwoC = max(
-                (
-                    171
-                    - (5.2 * \log($volume))
-                    - (0.23 * $ccn)
-                    - (16.2 * \log($lloc))
-                ) * 100 / 171,
-                0
-            );
-            if (is_infinite($MIwoC)) {
-                $MIwoC = 171;
-            }
-
-            // comment weight
-            if ($loc > 0) {
-                $CM = $cloc / $loc;
-                $commentWeight = 50 * sin(sqrt(2.4 * $CM));
-            }
-
-            // maintainability index
-            $mi = $MIwoC + $commentWeight;
-
-            // save result
-            $classOrFunction
-                ->set('mi', round($mi, 2))
-                ->set('mIwoC', round($MIwoC, 2))
-                ->set('commentWeight', round($commentWeight, 2));
-            $this->metrics->attach($classOrFunction);
-        }
-    }
-}
diff --git a/src/Hal/Metric/Class_/Coupling/ExternalsVisitor.php b/src/Hal/Metric/Class_/Coupling/ExternalsVisitor.php
deleted file mode 100644
index be3870c4..00000000
--- a/src/Hal/Metric/Class_/Coupling/ExternalsVisitor.php
+++ /dev/null
@@ -1,148 +0,0 @@
-<?php
-
-namespace Hal\Metric\Class_\Coupling;
-
-use Hal\Component\Ast\NodeTyper;
-use Hal\Metric\Metrics;
-use PhpParser\Node;
-use PhpParser\Node\Stmt;
-use PhpParser\NodeVisitorAbstract;
-
-/**
- * List externals dependencies
- *
- * @package Hal\Metric\Class_\Coupling
- */
-class ExternalsVisitor extends NodeVisitorAbstract
-{
-    /**
-     * @var Metrics
-     */
-    private $metrics;
-
-    /**
-     * @var Stmt\UseUse[]
-     */
-    private $uses = [];
-
-    /**
-     * @param Metrics $metrics
-     */
-    public function __construct(Metrics $metrics)
-    {
-        $this->metrics = $metrics;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function leaveNode(Node $node)
-    {
-        if ($node instanceof Stmt\Namespace_) {
-            $this->uses = [];
-        }
-
-        if ($node instanceof Stmt\Use_) {
-            $this->uses = array_merge($this->uses, $node->uses);
-        }
-
-        if (NodeTyper::isOrganizedStructure($node)) {
-            $class = $this->metrics->get(getNameOfNode($node));
-
-            if(null === $class) {
-                throw new \RuntimeException('Class metric not found for ' . getNameOfNode($node));
-            }
-
-            $parents = [];
-            $interfaces = [];
-
-            $dependencies = [];
-
-            // extends
-            if (isset($node->extends)) {
-                if (is_array($node->extends)) {
-                    foreach ((array) $node->extends as $interface) {
-                        $this->pushToDependencies($dependencies, (string) $interface);
-                        array_push($parents, (string) $interface);
-                    }
-                } else {
-                    $this->pushToDependencies($dependencies, (string) $node->extends);
-                    array_push($parents, (string) $node->extends);
-                }
-            }
-
-            // implements
-            if (isset($node->implements)) {
-                foreach ($node->implements as $interface) {
-                    $this->pushToDependencies($dependencies, (string) $interface);
-                    array_push($interfaces, (string) $interface);
-                }
-            }
-
-            foreach ($node->stmts as $stmt) {
-                if ($stmt instanceof Stmt\ClassMethod) {
-                    // return
-                    if (isset($stmt->returnType)) {
-                        if ($stmt->returnType instanceof Node\Name\FullyQualified) {
-                            $this->pushToDependencies($dependencies, (string) $stmt->returnType);
-                        }
-                    }
-
-                    // Type hint of method's parameters
-                    foreach ($stmt->params as $param) {
-                        if ($param->type) {
-                            if ($param->type instanceof Node\Name\FullyQualified) {
-                                $this->pushToDependencies($dependencies, (string) $param->type);
-                            }
-                        }
-                    }
-
-                    // instantiations, static calls
-                    \iterate_over_node($stmt, function ($node) use (&$dependencies) {
-                        switch (true) {
-                            case $node instanceof Node\Expr\New_:
-                                // new MyClass
-                                $this->pushToDependencies($dependencies, getNameOfNode($node));
-                                break;
-                            case $node instanceof Node\Expr\StaticCall:
-                                // MyClass::Call
-                                $this->pushToDependencies($dependencies, getNameOfNode($node));
-                                break;
-                        }
-                    });
-
-                    // annotations
-                    $comments = $stmt->getDocComment();
-                    if ($comments && false !== preg_match_all('!\s+\*\s+@(\w+)!', $comments->getText(), $matches)) {
-                        foreach ($matches[1] as $check) {
-                            foreach ($this->uses as $use) {
-                                if (method_exists($use, 'getAlias')) {
-                                    if (((string) $use->getAlias()) === $check) {
-                                        $this->pushToDependencies($dependencies, (string) ($use->name));
-                                    }
-                                    continue;
-                                }
-                                if ($use->alias === $check) {
-                                    $this->pushToDependencies($dependencies, (string) ($use->name));
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
-            $class->set('externals', $dependencies);
-            $class->set('parents', $parents);
-            $class->set('implements', $interfaces);
-        }
-    }
-
-    private function pushToDependencies(array &$dependencies, $dependency)
-    {
-        $lowercase = strtolower($dependency);
-        if ('self' === $lowercase || 'parent' === $lowercase) {
-            return;
-        }
-        array_push($dependencies, (string) $dependency);
-    }
-}
diff --git a/src/Hal/Metric/Class_/Structural/LcomVisitor.php b/src/Hal/Metric/Class_/Structural/LcomVisitor.php
deleted file mode 100644
index 4c93565b..00000000
--- a/src/Hal/Metric/Class_/Structural/LcomVisitor.php
+++ /dev/null
@@ -1,118 +0,0 @@
-<?php
-
-namespace Hal\Metric\Class_\Structural;
-
-use Hal\Component\Ast\NodeTyper;
-use Hal\Component\Tree\GraphDeduplicated;
-use Hal\Component\Tree\Node as TreeNode;
-use Hal\Metric\Helper\RoleOfMethodDetector;
-use Hal\Metric\Metrics;
-use PhpParser\Node;
-use PhpParser\Node\Stmt;
-use PhpParser\NodeVisitorAbstract;
-
-/**
- * Lack of cohesion of methods
- *
- * @package Hal\Metric\Class_\Coupling
- */
-class LcomVisitor extends NodeVisitorAbstract
-{
-    /**
-     * @var Metrics
-     */
-    private $metrics;
-
-    /**
-     * @param Metrics $metrics
-     */
-    public function __construct(Metrics $metrics)
-    {
-        $this->metrics = $metrics;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function leaveNode(Node $node)
-    {
-        if (NodeTyper::isOrganizedLogicalClassStructure($node)) {
-            // we build a graph of internal dependencies in class
-            $graph = new GraphDeduplicated();
-            $class = $this->metrics->get(getNameOfNode($node));
-
-            $roleDetector = new RoleOfMethodDetector();
-
-            foreach ($node->stmts as $stmt) {
-                if ($stmt instanceof Stmt\ClassMethod) {
-
-                    $role = $roleDetector->detects($stmt);
-                    if (in_array($role, ['getter', 'setter'])) {
-                        // We don't want to increase the LCOM for getters and setters,
-                        continue;
-                    }
-
-                    if (!$graph->has($stmt->name . '()')) {
-                        $graph->insert(new TreeNode($stmt->name . '()'));
-                    }
-                    $from = $graph->get($stmt->name . '()');
-
-                    \iterate_over_node($stmt, function ($node) use ($from, &$graph) {
-                        if ($node instanceof Node\Expr\PropertyFetch && isset($node->var->name) && $node->var->name == 'this') {
-                            $name = getNameOfNode($node);
-                            // use of attribute $this->xxx;
-                            if (!$graph->has($name)) {
-                                $graph->insert(new TreeNode($name));
-                            }
-                            $to = $graph->get($name);
-                            $graph->addEdge($from, $to);
-                            return;
-                        }
-
-                        if ($node instanceof Node\Expr\MethodCall) {
-                            if (!$node->var instanceof Node\Expr\New_ && isset($node->var->name) && getNameOfNode($node->var) === 'this') {
-                                // use of method call $this->xxx();
-                                // use of attribute $this->xxx;
-                                $name = getNameOfNode($node->name) . '()';
-                                if (!$graph->has($name)) {
-                                    $graph->insert(new TreeNode($name));
-                                }
-                                $to = $graph->get($name);
-                                $graph->addEdge($from, $to);
-                                return;
-                            }
-                        }
-                    });
-                }
-            }
-
-            // we count paths
-            $paths = 0;
-            foreach ($graph->all() as $node) {
-                $paths += $this->traverse($node);
-            }
-
-            $class->set('lcom', $paths);
-        }
-    }
-
-    /**
-     * Traverse node, and return 1 if node has not been visited yet
-     *
-     * @param TreeNode $node
-     * @return int
-     */
-    private function traverse(TreeNode $node)
-    {
-        if ($node->visited) {
-            return 0;
-        }
-        $node->visited = true;
-
-        foreach ($node->getAdjacents() as $adjacent) {
-            $this->traverse($adjacent);
-        }
-
-        return 1;
-    }
-}
diff --git a/src/Hal/Metric/Class_/Structural/SystemComplexityVisitor.php b/src/Hal/Metric/Class_/Structural/SystemComplexityVisitor.php
deleted file mode 100644
index e4ccd95b..00000000
--- a/src/Hal/Metric/Class_/Structural/SystemComplexityVisitor.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-
-namespace Hal\Metric\Class_\Structural;
-
-use Hal\Component\Ast\NodeTyper;
-use Hal\Metric\Metrics;
-use PhpParser\Node;
-use PhpParser\Node\Stmt;
-use PhpParser\NodeVisitorAbstract;
-
-/**
- * Calculates Card And Agresti metric
- *
- *      Fan-out = Structural fan-out = Number of other procedures this procedure calls
- *      v = number of input/output variables for a procedure
- *
- *      (SC) Structural complexity = fan-out^2
- *      (DC) Data complexity = v / (fan-out + 1)
- *
- * @author Jean-François Lépine <https://twitter.com/Halleck45>
- */
-class SystemComplexityVisitor extends NodeVisitorAbstract
-{
-    /**
-     * @var Metrics
-     */
-    private $metrics;
-
-    /**
-     * @param Metrics $metrics
-     */
-    public function __construct(Metrics $metrics)
-    {
-        $this->metrics = $metrics;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function leaveNode(Node $node)
-    {
-        if (NodeTyper::isOrganizedLogicalClassStructure($node)) {
-            $class = $this->metrics->get(getNameOfNode($node));
-            if (null === $class) {
-                throw new \RuntimeException('Class metric not found for ' . getNameOfNode($node));
-            }
-
-            $sy = $dc = $sc = [];
-
-            foreach ($node->stmts as $stmt) {
-                if ($stmt instanceof Stmt\ClassMethod) {
-                    // number of returns and calls
-                    $output = 0;
-                    $fanout = [];
-
-                    $parentNode = $node;
-                    iterate_over_node($node, function ($node) use (&$output, &$fanout, $parentNode) {
-                        switch (true) {
-                            case $node instanceof Stmt\Return_:
-                                $output++;
-                                break;
-                            case $node instanceof Node\Expr\StaticCall:
-                                $class = getNameOfNode($node->class);
-                                if ('static' === $class || 'self' === $class) {
-                                    $class = getNameOfNode($parentNode);
-                                }
-                                $fanout[] = $class . '::' . getNameOfNode($node->name) . '()';
-                                break;
-                            case $node instanceof Node\Expr\MethodCall:
-                                $class = getNameOfNode($node->var);
-                                if ('this' === $class) {
-                                    $class = getNameOfNode($parentNode);
-                                }
-                                $fanout[] = $class . '->' . getNameOfNode($node->name) . '()';
-                                break;
-                        }
-                    });
-
-                    $fanout = count(array_unique($fanout));
-                    $v = count($stmt->params) + $output;
-                    $ldc = $v / ($fanout + 1);
-                    $lsc = pow($fanout, 2);
-                    $sy[] = $ldc + $lsc;
-                    $dc[] = $ldc;
-                    $sc[] = $lsc;
-                }
-            }
-
-            // average for class
-            $class
-                ->set('relativeStructuralComplexity', empty($sc) ? 0 : round(array_sum($sc) / count($sc), 2))
-                ->set('relativeDataComplexity', empty($dc) ? 0 : round(array_sum($dc) / count($dc), 2))
-                ->set('relativeSystemComplexity', empty($sy) ? 0 : round(array_sum($sy) / count($sy), 2))
-                ->set('totalStructuralComplexity', round(array_sum($sc), 2))
-                ->set('totalDataComplexity', round(array_sum($dc), 2))
-                ->set('totalSystemComplexity', round(array_sum($dc) + array_sum($sc), 2));
-        }
-    }
-}
diff --git a/src/Hal/Metric/Class_/Text/HalsteadVisitor.php b/src/Hal/Metric/Class_/Text/HalsteadVisitor.php
deleted file mode 100644
index 6e7d793b..00000000
--- a/src/Hal/Metric/Class_/Text/HalsteadVisitor.php
+++ /dev/null
@@ -1,144 +0,0 @@
-<?php
-
-namespace Hal\Metric\Class_\Text;
-
-use Hal\Component\Ast\NodeTyper;
-use Hal\Metric\FunctionMetric;
-use Hal\Metric\Metrics;
-use Hoa\Ruler\Model\Bag\Scalar;
-use PhpParser\Node;
-use PhpParser\Node\Stmt;
-use PhpParser\NodeVisitorAbstract;
-
-/**
- * Calculates Halstead complexity
- *
- *      According Wikipedia, "Halstead complexity measures are software metrics introduced by Maurice Howard Halstead in
- *      1977 as part of his treatise on establishing an empirical science of software development.
- *      Halstead makes the observation that metrics of the software should reflect the implementation or
- *      expression of algorithms in different languages, but be independent of their execution on a specific platform.
- *      These metrics are therefore computed statically from the code."
- *
- * @author Jean-François Lépine <https://twitter.com/Halleck45>
- * @package Hal\Metric\Class_\Coupling
- */
-class HalsteadVisitor extends NodeVisitorAbstract
-{
-    /**
-     * @var Metrics
-     */
-    private $metrics;
-
-    /**
-     * @param Metrics $metrics
-     */
-    public function __construct(Metrics $metrics)
-    {
-        $this->metrics = $metrics;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function leaveNode(Node $node)
-    {
-        if (
-            NodeTyper::isOrganizedLogicalClassStructure($node)
-            || $node instanceof Stmt\Function_
-        ) {
-            if (NodeTyper::isOrganizedLogicalClassStructure($node) ) {
-                $name = getNameOfNode($node);
-                $classOrFunction = $this->metrics->get($name);
-            } else {
-                $classOrFunction = new FunctionMetric((string) $node->name);
-                $this->metrics->attach($classOrFunction);
-            }
-
-            // search for operands and operators
-            $operands = [];
-            $operators = [];
-
-            iterate_over_node($node, function ($node) use (&$operators, &$operands) {
-                if ($node instanceof Node\Expr\BinaryOp
-                    || $node instanceof Node\Expr\AssignOp
-                    || $node instanceof Stmt\If_
-                    || $node instanceof Stmt\For_
-                    || $node instanceof Stmt\Switch_
-                    || $node instanceof Stmt\Catch_
-                    || $node instanceof Stmt\Return_
-                    || $node instanceof Stmt\While_
-                    || $node instanceof Node\Expr\Assign
-                ) {
-                    // operators
-                    array_push($operators, get_class($node));
-                }
-
-                // nicik/php-parser:^4
-                if ($node instanceof Node\Param
-                    && isset($node->var)
-                    && $node->var instanceof Node\Expr\Variable
-                ) {
-                    return;
-                }
-
-                if ($node instanceof Node\Expr\Cast
-                    || $node instanceof Node\Expr\Variable
-                    || $node instanceof Node\Param
-                    || $node instanceof Node\Scalar
-                ) {
-                    // operands
-                    if (isset($node->value)) {
-                        $name = $node->value;
-                    } elseif (isset($node->name)) {
-                        $name = $node->name;
-                    } else {
-                        $name = get_class($node);
-                    }
-                    array_push($operands, $name);
-                }
-            });
-
-            // calculate halstead metrics
-            $uniqueOperators = array_map('unserialize', array_unique(array_map('serialize', $operators)));
-            $uniqueOperands = array_map('unserialize', array_unique(array_map('serialize', $operands)));
-
-            $n1 = count($uniqueOperators, COUNT_NORMAL);
-            $n2 = count($uniqueOperands, COUNT_NORMAL);
-            $N1 = count($operators, COUNT_NORMAL);
-            $N2 = count($operands, COUNT_NORMAL);
-
-            if (($n2 == 0) || ($N2 == 0)) {
-                // files without operators
-                $V = $n1 = $n2 = $N1 = $N2 = $E = $D = $B = $T = $I = $L = 0;
-            } else {
-                $devAbility = 3000;
-                $N = $N1 + $N2;
-                $n = $n1 + $n2;
-                $V = $N * log($n, 2);
-                $L = (2 / max(1, $n1)) * ($n2 / $N2);
-                $D = ($n1 / 2) * ($N2 / $n2);
-                $E = $V * $D;
-                $B = $V / $devAbility;
-                $T = $E / 18;
-                $I = $L * $V;
-            }
-
-            // save result
-            $classOrFunction
-                ->set('length', $N1 + $N2)
-                ->set('vocabulary', $n1 + $n2)
-                ->set('volume', round($V, 2))
-                ->set('difficulty', round($D, 2))
-                ->set('effort', round($E, 2))
-                ->set('level', round($L, 2))
-                ->set('bugs', round($B, 2))
-                ->set('time', round($T))
-                ->set('intelligentContent', round($I, 2))
-                ->set('number_operators', $N1)
-                ->set('number_operands', $N2)
-                ->set('number_operators_unique', $n1)
-                ->set('number_operands_unique', $n2);
-            $this->metrics->attach($classOrFunction);
-        }
-    }
-}
diff --git a/src/Hal/Metric/Class_/Text/LengthVisitor.php b/src/Hal/Metric/Class_/Text/LengthVisitor.php
deleted file mode 100644
index 0fa26bf6..00000000
--- a/src/Hal/Metric/Class_/Text/LengthVisitor.php
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-
-namespace Hal\Metric\Class_\Text;
-
-use Hal\Component\Ast\NodeTyper;
-use Hal\Metric\FunctionMetric;
-use Hal\Metric\Metrics;
-use PhpParser\Node;
-use PhpParser\Node\Stmt;
-use PhpParser\NodeVisitorAbstract;
-use PhpParser\PrettyPrinter;
-
-/**
- * @package Hal\Metric\Class_\Text
- */
-class LengthVisitor extends NodeVisitorAbstract
-{
-    /**
-     * @var Metrics
-     */
-    private $metrics;
-
-    /**
-     * @param Metrics $metrics
-     */
-    public function __construct(Metrics $metrics)
-    {
-        $this->metrics = $metrics;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function leaveNode(Node $node)
-    {
-        if (
-            NodeTyper::isOrganizedLogicalClassStructure($node)
-            || $node instanceof Stmt\Function_
-        ) {
-            if (
-                NodeTyper::isOrganizedLogicalClassStructure($node)
-            ) {
-                $name = getNameOfNode($node);
-                $classOrFunction = $this->metrics->get($name);
-            } else {
-                $classOrFunction = new FunctionMetric((string) $node->name);
-                $this->metrics->attach($classOrFunction);
-            }
-
-            $prettyPrinter = new PrettyPrinter\Standard();
-            $code = $prettyPrinter->prettyPrintFile([$node]);
-
-            // count all lines
-            $loc = count(preg_split('/\r\n|\r|\n/', $code)) - 1;
-
-            // count and remove multi lines comments
-            $cloc = 0;
-            if (preg_match_all('!/\*.*?\*/!s', $code, $matches)) {
-                foreach ($matches[0] as $match) {
-                    $cloc += max(1, count(preg_split('/\r\n|\r|\n/', $match)));
-                }
-            }
-            $code = preg_replace('!/\*.*?\*/!s', '', $code);
-
-            // count and remove single line comments
-            $code = preg_replace_callback('!(\'[^\']*\'|"[^"]*")|((?:#|\/\/).*$)!m', function (array $matches) use (&$cloc) {
-                if (isset($matches[2])) {
-                    $cloc += 1;
-                }
-                return $matches[1];
-            }, $code, -1);
-
-            // count and remove empty lines
-            $code = trim(preg_replace('!(^\s*[\r\n])!sm', '', $code));
-            $lloc = count(preg_split('/\r\n|\r|\n/', $code));
-
-            // save result
-            $classOrFunction
-                ->set('cloc', $cloc)
-                ->set('loc', $loc)
-                ->set('lloc', $lloc);
-            $this->metrics->attach($classOrFunction);
-        }
-    }
-}
diff --git a/src/Hal/Metric/Consolidated.php b/src/Hal/Metric/Consolidated.php
deleted file mode 100644
index 02b92c48..00000000
--- a/src/Hal/Metric/Consolidated.php
+++ /dev/null
@@ -1,227 +0,0 @@
-<?php
-
-namespace Hal\Metric;
-
-use Hal\Violation\Violation;
-
-class Consolidated
-{
-    /**
-     * @var object
-     */
-    private $avg;
-
-    /**
-     * @var object
-     */
-    private $sum;
-
-    /**
-     * @var array
-     */
-    private $classes = [];
-
-    /**
-     * @var array
-     */
-    private $files = [];
-
-    /**
-     * @var array
-     */
-    private $project = [];
-
-    /** @var array */
-    private $packages;
-
-    /**
-     * @param Metrics $metrics
-     */
-    public function __construct(Metrics $metrics)
-    {
-        $classMetrics = [];
-
-        // grouping results
-        $classes = [];
-        $functions = [];
-        $files = [];
-        $packages = [];
-        $project = [];
-        $nbInterfaces = 0;
-        foreach ($metrics->all() as $key => $item) {
-            $classItem = get_class($item);
-            if (ClassMetric::class === $classItem) {
-                $classes[] = $item->all();
-                $classMetrics[] = $item;
-            } elseif (InterfaceMetric::class === $classItem) {
-                $nbInterfaces++;
-            } elseif (FunctionMetric::class === $classItem) {
-                $functions[$key] = $item->all();
-            } elseif (FileMetric::class === $classItem) {
-                $files[$key] = $item->all();
-            } elseif (ProjectMetric::class === $classItem) {
-                $project[$key] = $item->all();
-            } elseif (PackageMetric::class === $classItem) {
-                $packages[$key] = $item->all();
-            }
-        }
-
-        // sums
-        $sum = (object) [
-            'loc' => 0,
-            'cloc' => 0,
-            'lloc' => 0,
-            'nbMethods' => 0,
-        ];
-        $avg = (object) [
-            'wmc' => [],
-            'ccn' => [],
-            'bugs' => [],
-            'kanDefect' => [],
-            'relativeSystemComplexity' => [],
-            'relativeDataComplexity' => [],
-            'relativeStructuralComplexity' => [],
-            'volume' => [],
-            'commentWeight' => [],
-            'intelligentContent' => [],
-            'lcom' => [],
-            'instability' => [],
-            'afferentCoupling' => [],
-            'efferentCoupling' => [],
-            'difficulty' => [],
-            'mi' => [],
-        ];
-
-        foreach ($classMetrics as $key => $item) {
-            $sum->loc += $item->get('loc');
-            $sum->lloc += $item->get('lloc');
-            $sum->cloc += $item->get('cloc');
-            $sum->nbMethods += $item->get('nbMethods');
-
-            foreach ($avg as $k => $a) {
-                array_push($avg->$k, $item->get($k));
-            }
-        }
-        $sum->nbClasses = count($classes);
-        $sum->nbInterfaces = $nbInterfaces;
-        $sum->nbPackages = count($packages);
-
-        foreach ($avg as &$a) {
-            if (count($a) > 0) {
-                $a = round(array_sum((array) $a) / count($a), 2);
-            } else {
-                $a = 0;
-            }
-        }
-
-        $avg->distance = 0;
-        $avg->incomingCDep = 0;
-        $avg->incomingPDep = 0;
-        $avg->outgoingCDep = 0;
-        $avg->outgoingPDep = 0;
-        $avg->classesPerPackage = 0;
-        if (0 !== $sum->nbPackages) {
-            foreach (array_keys($packages) as $eachName) {
-                /* @var $eachPackage PackageMetric */
-                $eachPackage = $metrics->get($eachName);
-                $avg->distance += $eachPackage->getDistance();
-                $avg->incomingCDep += count($eachPackage->getIncomingClassDependencies());
-                $avg->incomingPDep += count($eachPackage->getIncomingPackageDependencies());
-                $avg->outgoingCDep += count($eachPackage->getOutgoingClassDependencies());
-                $avg->outgoingPDep += count($eachPackage->getOutgoingPackageDependencies());
-                $avg->classesPerPackage += count($eachPackage->getClasses());
-            }
-            $avg->distance = round($avg->distance / $sum->nbPackages, 2);
-            $avg->incomingCDep = round($avg->incomingCDep / $sum->nbPackages, 2);
-            $avg->incomingPDep = round($avg->incomingPDep / $sum->nbPackages, 2);
-            $avg->outgoingCDep = round($avg->outgoingCDep / $sum->nbPackages, 2);
-            $avg->outgoingPDep = round($avg->outgoingPDep / $sum->nbPackages, 2);
-            $avg->classesPerPackage = round($avg->classesPerPackage / $sum->nbPackages, 2);
-        }
-
-        // sums of violations
-        $violations = [
-            'total' => 0,
-            'information' => 0,
-            'warning' => 0,
-            'error' => 0,
-            'critical' => 0,
-        ];
-        $map = [
-            Violation::INFO => 'information',
-            Violation::WARNING => 'warning',
-            Violation::ERROR => 'error',
-            Violation::CRITICAL => 'critical',
-        ];
-        foreach ($classes as $class) {
-            foreach ($class['violations'] as $violation) {
-                $violations['total']++;
-                $name = $map[$violation->getLevel()];
-                $violations[$name]++;
-            }
-        }
-        foreach ($packages as $package) {
-            foreach ($package['violations'] as $violation) {
-                $violations['total']++;
-                $name = $map[$violation->getLevel()];
-                $violations[$name]++;
-            }
-        }
-        $sum->violations = (object) $violations;
-
-        $this->avg = $avg;
-        $this->sum = $sum;
-        $this->classes = $classes;
-        $this->files = $files;
-        $this->project = $project;
-        $this->packages = $packages;
-    }
-
-    /**
-     * @return object
-     */
-    public function getAvg()
-    {
-        return $this->avg;
-    }
-
-    /**
-     * @return object
-     */
-    public function getSum()
-    {
-        return $this->sum;
-    }
-
-    /**
-     * @return array
-     */
-    public function getClasses()
-    {
-        return $this->classes;
-    }
-
-    /**
-     * @return array
-     */
-    public function getFiles()
-    {
-        return $this->files;
-    }
-
-    /**
-     * @return array
-     */
-    public function getProject()
-    {
-        return $this->project;
-    }
-
-    /**
-     * @return array
-     */
-    public function getPackages()
-    {
-        return $this->packages;
-    }
-}
diff --git a/src/Hal/Metric/FileMetric.php b/src/Hal/Metric/FileMetric.php
deleted file mode 100644
index 67494477..00000000
--- a/src/Hal/Metric/FileMetric.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-namespace Hal\Metric;
-
-class FileMetric implements Metric, \JsonSerializable
-{
-    use BagTrait;
-}
diff --git a/src/Hal/Metric/FunctionMetric.php b/src/Hal/Metric/FunctionMetric.php
deleted file mode 100644
index ba58a3b5..00000000
--- a/src/Hal/Metric/FunctionMetric.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-namespace Hal\Metric;
-
-class FunctionMetric implements Metric, \JsonSerializable
-{
-    use BagTrait;
-}
diff --git a/src/Hal/Metric/Group/Group.php b/src/Hal/Metric/Group/Group.php
deleted file mode 100644
index 2b19e547..00000000
--- a/src/Hal/Metric/Group/Group.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-
-namespace Hal\Metric\Group;
-
-use Hal\Metric\Metrics;
-
-/**
- * Class Group
- * Allows to group metrics by regex, given them a name
- * @package Hal\Metric\Group
- */
-class Group
-{
-    /**
-     * @var string
-     */
-    private $name;
-
-    /**
-     * @var string
-     */
-    private $regex;
-
-    /**
-     * Group constructor.
-     * @param string $name
-     * @param string $regex
-     */
-    public function __construct($name, $regex)
-    {
-        $this->name = $name;
-        $this->regex = $regex;
-    }
-
-    /**
-     * @return string
-     */
-    public function getName()
-    {
-        return $this->name;
-    }
-
-    /**
-     * @return string
-     */
-    public function getRegex()
-    {
-        return $this->regex;
-    }
-
-    /**
-     * @param Metrics $metrics
-     * @return Metrics
-     */
-    public function reduceMetrics(Metrics $metrics)
-    {
-        $all = $metrics->all();
-        $matched = new Metrics();
-
-        foreach ($all as $metric) {
-            if (!preg_match($this->regex, $metric->getName())) {
-                continue;
-            }
-
-            $matched->attach($metric);
-        }
-
-        return $matched;
-    }
-}
diff --git a/src/Hal/Metric/Helper/RoleOfMethodDetector.php b/src/Hal/Metric/Helper/RoleOfMethodDetector.php
deleted file mode 100644
index 10e00949..00000000
--- a/src/Hal/Metric/Helper/RoleOfMethodDetector.php
+++ /dev/null
@@ -1,148 +0,0 @@
-<?php
-
-namespace Hal\Metric\Helper;
-
-use PhpParser\Node\Expr\Cast;
-use PhpParser\Node\Expr\Variable;
-use PhpParser\Node\Identifier;
-use PhpParser\Node\Name;
-use PhpParser\Node\NullableType;
-use PhpParser\Node\Stmt\ClassMethod;
-use PhpParser\Node\Stmt\Return_;
-
-/**
- * @package Hal\Metric\Helper
- */
-class RoleOfMethodDetector
-{
-    /**
-     * @var array
-     */
-    private $fingerprints = [
-        'getter' => [
-            [
-                'PhpParser\\Node\\Stmt\\ClassMethod',
-                'PhpParser\\Node\\Stmt\\Return_',
-                'PhpParser\\Node\\Expr\\PropertyFetch',
-                'PhpParser\\Node\\Expr\\Variable',
-            ],
-            [
-                'PhpParser\\Node\\Stmt\\ClassMethod',
-                'PhpParser\\Node\\Stmt\\Return_',
-                'PhpParser\\Node\\Expr\\PropertyFetch',
-                'PhpParser\\Node\\Expr\\Variable',
-                'PhpParser\\Node\\Name',
-            ],
-            [
-                'PhpParser\\Node\\Stmt\\ClassMethod',
-                'PhpParser\\Node\\Stmt\\Return_',
-                'PhpParser\\Node\\Expr\\PropertyFetch',
-                'PhpParser\\Node\\Expr\\Variable',
-            ],
-        ],
-        'setter' => [
-            [
-                'PhpParser\\Node\\Stmt\\ClassMethod',
-                'PhpParser\\Node\\Expr\\Assign',
-                'PhpParser\\Node\\Expr\\Variable',
-                'PhpParser\\Node\\Expr\\PropertyFetch',
-                'PhpParser\\Node\\Expr\\Variable',
-                'PhpParser\\Node\\Param',
-            ],
-            [
-                'PhpParser\\Node\\Stmt\\ClassMethod',
-                'PhpParser\\Node\\Expr\\Assign',
-                'PhpParser\\Node\\Expr\\Variable',
-                'PhpParser\\Node\\Expr\\PropertyFetch',
-                'PhpParser\\Node\\Expr\\Variable',
-                'PhpParser\\Node\\Param',
-                'PhpParser\\Node\\Name',
-            ],
-            // nicik/php-parser:^4
-            [
-                'PhpParser\\Node\\Stmt\\ClassMethod',
-                'PhpParser\\Node\\Stmt\\Expression',
-                'PhpParser\\Node\\Expr\\Assign',
-                'PhpParser\\Node\\Expr\\Variable',
-                'PhpParser\\Node\\Expr\\PropertyFetch',
-                'PhpParser\\Node\\Expr\\Variable',
-                'PhpParser\\Node\\Param',
-                'PhpParser\\Node\\Expr\\Variable',
-            ],
-            [
-                'PhpParser\\Node\\Stmt\\ClassMethod',
-                'PhpParser\\Node\\Stmt\\Expression',
-                'PhpParser\\Node\\Expr\\Assign',
-                'PhpParser\\Node\\Expr\\Variable',
-                'PhpParser\\Node\\Expr\\PropertyFetch',
-                'PhpParser\\Node\\Expr\\Variable',
-                'PhpParser\\Node\\Param',
-                'PhpParser\\Node\\Expr\\Variable',
-                'PhpParser\\Node\\Name',
-            ],[
-                // function setOk(?bool $ok): self { $this->isOk = $ok; return $this; }
-                'PhpParser\\Node\\Stmt\\ClassMethod',
-                'PhpParser\\Node\\Stmt\\Expression',
-                'PhpParser\\Node\\Expr\\Assign',
-                'PhpParser\\Node\\Expr\\Variable',
-                'PhpParser\\Node\\Expr\\PropertyFetch',
-                'PhpParser\\Node\\Expr\\Variable',
-                'PhpParser\\Node\\Param',
-                'PhpParser\\Node\\Expr\\Variable',
-            ],
-        ],
-    ];
-
-    /**
-     * @param $node
-     * @return string|null
-     */
-    public function detects($node)
-    {
-        if (! $node instanceof ClassMethod) {
-            return null;
-        }
-
-        // build a fingerprint of the given method
-        $fingerprintOfMethod = [];
-        iterate_over_node($node, function ($node) use (&$fingerprintOfMethod) {
-            // avoid identifier (php-parser:^4)
-            if ($node instanceof Identifier) {
-                return;
-            }
-
-            // avoid cast
-            if ($node instanceof Cast) {
-                return;
-            }
-
-            // avoid fluent interface
-            if ($node instanceof Return_ && $node->expr instanceof Variable && $node->expr->name === 'this') {
-                unset($fingerprintOfMethod[count($fingerprintOfMethod) - 1]);
-                return;
-            }
-
-            // avoid type hint
-            if ($node instanceof Name) {
-                return;
-            }
-
-            // avoid nullable type
-            if ($node instanceof NullableType) {
-                return;
-            }
-
-            $fingerprintOfMethod[] = get_class($node);
-        });
-        $fingerprintOfMethod = array_reverse($fingerprintOfMethod);
-
-        // compare with database of fingerprints
-        foreach ($this->fingerprints as $type => $fingerprints) {
-            if (in_array($fingerprintOfMethod, $fingerprints, true)) {
-                return $type;
-            }
-        }
-
-        return null;
-    }
-}
diff --git a/src/Hal/Metric/InterfaceMetric.php b/src/Hal/Metric/InterfaceMetric.php
deleted file mode 100644
index 425b3c48..00000000
--- a/src/Hal/Metric/InterfaceMetric.php
+++ /dev/null
@@ -1,5 +0,0 @@
-<?php
-
-namespace Hal\Metric;
-
-class InterfaceMetric extends ClassMetric {}
diff --git a/src/Hal/Metric/Metric.php b/src/Hal/Metric/Metric.php
deleted file mode 100644
index 29cbcafd..00000000
--- a/src/Hal/Metric/Metric.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-namespace Hal\Metric;
-
-/**
- * Interface Metric
- * @package Hal\Metric
- */
-interface Metric
-{
-    /**
-     * @return string
-     */
-    public function getName();
-
-    /**
-     * @param $key
-     * @return mixed
-     */
-    public function get($key);
-
-    /**
-     * @param $key
-     * @param $value
-     * @return mixed
-     */
-    public function set($key, $value);
-
-    /**
-     * @param $key
-     * @return mixed
-     */
-    public function has($key);
-
-    /**
-     * @return array
-     */
-    public function all();
-}
diff --git a/src/Hal/Metric/Metrics.php b/src/Hal/Metric/Metrics.php
deleted file mode 100644
index 9440bb18..00000000
--- a/src/Hal/Metric/Metrics.php
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-
-namespace Hal\Metric;
-
-/**
- * @package Hal\Metric
- */
-class Metrics implements \JsonSerializable
-{
-    /**
-     * @var array
-     */
-    private $data = [];
-
-    /**
-     * @param Metric $metric
-     * @return $this
-     */
-    public function attach($metric)
-    {
-        $this->data[$metric->getName()] = $metric;
-        return $this;
-    }
-
-    /**
-     * @param $key
-     * @return Metric|null
-     */
-    public function get($key)
-    {
-        return $this->has($key) ? $this->data[$key] : null;
-    }
-
-    /**
-     * @param $key
-     * @return bool
-     */
-    public function has($key)
-    {
-        return isset($this->data[$key]);
-    }
-
-    /**
-     * @return Metric[]
-     */
-    public function all()
-    {
-        return $this->data;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    #[\ReturnTypeWillChange]
-    public function jsonSerialize()
-    {
-        return $this->all();
-    }
-}
diff --git a/src/Hal/Metric/Package/PackageAbstraction.php b/src/Hal/Metric/Package/PackageAbstraction.php
deleted file mode 100644
index 90a55ff0..00000000
--- a/src/Hal/Metric/Package/PackageAbstraction.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-namespace Hal\Metric\Package;
-
-use Hal\Metric\Metrics;
-use Hal\Metric\PackageMetric;
-
-class PackageAbstraction
-{
-    public function calculate(Metrics $metrics)
-    {
-        /* @var $packages PackageMetric[] */
-        foreach ($metrics->all() as $eachPackage) {
-            if (! $eachPackage instanceof PackageMetric) {
-                continue;
-            }
-            $abstractClassCount = 0;
-            $classCount = count($eachPackage->getClasses());
-            foreach ($eachPackage->getClasses() as $eachClassName) {
-                $eachClass = $metrics->get($eachClassName);
-                $abstractClassCount += $eachClass->get('abstract');
-            }
-            $eachPackage->setAbstraction($abstractClassCount / $classCount);
-        }
-    }
-}
diff --git a/src/Hal/Metric/Package/PackageCollectingVisitor.php b/src/Hal/Metric/Package/PackageCollectingVisitor.php
deleted file mode 100644
index 87035fa5..00000000
--- a/src/Hal/Metric/Package/PackageCollectingVisitor.php
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-
-namespace Hal\Metric\Package;
-
-use Hal\Metric\Metrics;
-use Hal\Metric\PackageMetric;
-use PhpParser\Node;
-use PhpParser\Node\Stmt\Class_;
-use PhpParser\Node\Stmt\Interface_;
-use PhpParser\Node\Stmt\Namespace_;
-use PhpParser\Node\Stmt\Trait_;
-use PhpParser\NodeVisitorAbstract;
-
-class PackageCollectingVisitor extends NodeVisitorAbstract
-{
-    /** @var string */
-    private $namespace = '';
-
-    /** @var Metrics */
-    private $metrics;
-
-    public function __construct(Metrics $metrics)
-    {
-        $this->metrics = $metrics;
-    }
-
-    public function enterNode(Node $node)
-    {
-        if ($node instanceof Namespace_) {
-            $this->namespace = (string) $node->name;
-        }
-    }
-
-    public function leaveNode(Node $node)
-    {
-        if ($node instanceof Class_ || $node instanceof Interface_ || $node instanceof Trait_) {
-            $package = $this->namespace;
-
-            $docComment = $node->getDocComment();
-            $docBlockText = $docComment ? $docComment->getText() : '';
-            if (preg_match('/^\s*\* @package (.*)/m', $docBlockText, $matches)) {
-                $package = $matches[1];
-            }
-            if (preg_match('/^\s*\* @subpackage (.*)/m', $docBlockText, $matches)) {
-                $package = $package . '\\' . $matches[1];
-            }
-
-            $packageName = $package . '\\';
-            if (! $packageMetric = $this->metrics->get($packageName)) {
-                $packageMetric = new PackageMetric($packageName);
-                $this->metrics->attach($packageMetric);
-            }
-            /* @var PackageMetric $packageMetric */
-            $elementName = getNameOfNode($node);
-            $elementName = (string) $elementName;
-            $packageMetric->addClass($elementName);
-
-            $this->metrics->get($elementName)->set('package', $packageName);
-        }
-    }
-}
diff --git a/src/Hal/Metric/Package/PackageDependencies.php b/src/Hal/Metric/Package/PackageDependencies.php
deleted file mode 100644
index b7fcec49..00000000
--- a/src/Hal/Metric/Package/PackageDependencies.php
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-
-namespace Hal\Metric\Package;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\InterfaceMetric;
-use Hal\Metric\Metric;
-use Hal\Metric\Metrics;
-use Hal\Metric\PackageMetric;
-
-class PackageDependencies
-{
-    public function calculate(Metrics $metrics)
-    {
-        $classes = array_filter($metrics->all(), function (Metric $metric) {
-            return $metric instanceof ClassMetric || $metric instanceof InterfaceMetric;
-        });
-
-        foreach ($classes as $each) {
-            $this->increaseDependencies($each, $metrics);
-        }
-    }
-
-    /**
-     * @param ClassMetric|InterfaceMetric|Metric $class
-     * @param Metrics $metrics
-     */
-    private function increaseDependencies(Metric $class, Metrics $metrics)
-    {
-        if (! $class->has('package') || ! $class->has('externals')) {
-            return;
-        }
-        $incomingPackage = $metrics->get($class->get('package')); /* @var $incomingPackage PackageMetric */
-        foreach ($class->get('externals') as $outgoingClassName) {
-            // same package?
-            if (in_array($outgoingClassName, $incomingPackage->getClasses())) {
-                continue;
-            }
-            $outgoingPackageName = $this->getPackageOfClass($outgoingClassName, $metrics);
-            $incomingPackage->addOutgoingClassDependency($outgoingClassName, $outgoingPackageName);
-            $outgoingPackage = $metrics->get($outgoingPackageName);
-
-            if ($outgoingPackage instanceof PackageMetric) {
-                $outgoingPackage->addIncomingClassDependency($class->getName(), $incomingPackage->getName());
-            }
-        }
-    }
-
-    private function getPackageOfClass($className, Metrics $metrics)
-    {
-        if ($metrics->has($className) && $metrics->get($className)->has('package')) {
-            return $metrics->get($className)->get('package');
-        }
-        if (strpos($className, '\\') === false) {
-            return '\\';
-        }
-        $parts = explode('\\', $className);
-        array_pop($parts);
-        return implode('\\', $parts) . '\\';
-    }
-}
diff --git a/src/Hal/Metric/Package/PackageDistance.php b/src/Hal/Metric/Package/PackageDistance.php
deleted file mode 100644
index 54881c8b..00000000
--- a/src/Hal/Metric/Package/PackageDistance.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-namespace Hal\Metric\Package;
-
-use Hal\Metric\Metrics;
-use Hal\Metric\PackageMetric;
-
-class PackageDistance
-{
-    public function calculate(Metrics $metrics)
-    {
-        foreach ($metrics->all() as $each) {
-            if ($each instanceof PackageMetric && $each->getAbstraction() !== null && $each->getInstability() !== null) {
-                $each->setNormalizedDistance(abs($each->getAbstraction() + $each->getInstability() - 1));
-            }
-        }
-    }
-}
diff --git a/src/Hal/Metric/Package/PackageInstability.php b/src/Hal/Metric/Package/PackageInstability.php
deleted file mode 100644
index 877df344..00000000
--- a/src/Hal/Metric/Package/PackageInstability.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-
-namespace Hal\Metric\Package;
-
-use Hal\Metric\Metrics;
-use Hal\Metric\PackageMetric;
-
-class PackageInstability
-{
-    public function calculate(Metrics $metrics)
-    {
-        /* @var $packages PackageMetric[] */
-        $packages = array_filter($metrics->all(), function ($metric) {
-            return $metric instanceof PackageMetric;
-        });
-
-        // Calculate instability
-        $instabilitiesByPackage = [];
-        foreach ($packages as $eachPackage) {
-            $afferentCoupling = count($eachPackage->getIncomingClassDependencies());
-            $efferentCoupling = count($eachPackage->getOutgoingClassDependencies());
-            if ($afferentCoupling + $efferentCoupling !== 0) {
-                $eachPackage->setInstability(
-                    $efferentCoupling / ($afferentCoupling + $efferentCoupling)
-                );
-                $instabilitiesByPackage[$eachPackage->getName()] = $eachPackage->getInstability();
-            }
-        }
-        // Set depending instabilities
-        foreach ($packages as $eachPackage) {
-            $dependentInstabilities = array_map(function ($packageName) use ($instabilitiesByPackage) {
-                //return $instabilitiesByPackage[$packageName] ?? null;
-                return isset($instabilitiesByPackage[$packageName]) ? $instabilitiesByPackage[$packageName] : null;
-            }, $eachPackage->getOutgoingPackageDependencies());
-            $dependentInstabilities = array_combine(
-                $eachPackage->getOutgoingPackageDependencies(),
-                $dependentInstabilities
-            );
-            $dependentInstabilities = array_filter($dependentInstabilities, 'is_float');
-            $eachPackage->setDependentInstabilities($dependentInstabilities);
-        }
-    }
-}
diff --git a/src/Hal/Metric/PackageMetric.php b/src/Hal/Metric/PackageMetric.php
deleted file mode 100644
index 46e31b49..00000000
--- a/src/Hal/Metric/PackageMetric.php
+++ /dev/null
@@ -1,151 +0,0 @@
-<?php
-
-namespace Hal\Metric;
-
-use JsonSerializable;
-
-class PackageMetric implements Metric, JsonSerializable
-{
-    use BagTrait;
-
-    /** @return string[] */
-    public function getClasses()
-    {
-        return $this->has('classes') ? $this->get('classes') : [];
-    }
-
-    /** @param string $name */
-    public function addClass($name)
-    {
-        $elements = $this->get('classes');
-        $elements[] = (string) $name;
-        $this->set('classes', $elements);
-    }
-
-    /** @param float $abstraction */
-    public function setAbstraction($abstraction)
-    {
-        if ($abstraction !== null) {
-            $abstraction = (float) $abstraction;
-        }
-        $this->set('abstraction', $abstraction);
-    }
-
-    /** @return float|null */
-    public function getAbstraction()
-    {
-        return $this->get('abstraction');
-    }
-
-    /** @param float $instability */
-    public function setInstability($instability)
-    {
-        if ($instability !== null) {
-            $instability = (float) $instability;
-        }
-        $this->set('instability', $instability);
-    }
-
-    /** @return float|null */
-    public function getInstability()
-    {
-        return $this->get('instability');
-    }
-
-    /**
-     * @param string $className
-     * @param string $packageName
-     */
-    public function addOutgoingClassDependency($className, $packageName)
-    {
-        if ($packageName === $this->getName()) {
-            return;
-        }
-        $classDependencies = $this->getOutgoingClassDependencies();
-        $packageDependencies = $this->getOutgoingPackageDependencies();
-        if (! in_array($className, $classDependencies)) {
-            $classDependencies[] = $className;
-            $this->set('outgoing_class_dependencies', $classDependencies);
-        }
-        if (! in_array($packageName, $packageDependencies)) {
-            $packageDependencies[] = $packageName;
-            $this->set('outgoing_package_dependencies', $packageDependencies);
-        }
-    }
-
-    /** @return string[] */
-    public function getOutgoingClassDependencies()
-    {
-        return $this->has('outgoing_class_dependencies') ? $this->get('outgoing_class_dependencies') : [];
-    }
-
-    /** @return string[] */
-    public function getOutgoingPackageDependencies()
-    {
-        return $this->has('outgoing_package_dependencies') ? $this->get('outgoing_package_dependencies') : [];
-    }
-
-    /**
-     * @param string $className
-     * @param string $packageName
-     */
-    public function addIncomingClassDependency($className, $packageName)
-    {
-        if ($packageName === $this->getName()) {
-            return;
-        }
-        $classDependencies = $this->getIncomingClassDependencies();
-        $packageDependencies = $this->getIncomingPackageDependencies();
-        if (! in_array($className, $classDependencies)) {
-            $classDependencies[] = $className;
-            $this->set('incoming_class_dependencies', $classDependencies);
-        }
-        if (! in_array($packageName, $packageDependencies)) {
-            $packageDependencies[] = $packageName;
-            $this->set('incoming_package_dependencies', $packageDependencies);
-        }
-    }
-
-    /** @return string[] */
-    public function getIncomingClassDependencies()
-    {
-        return $this->has('incoming_class_dependencies') ? $this->get('incoming_class_dependencies') : [];
-    }
-
-    /** @return string[] */
-    public function getIncomingPackageDependencies()
-    {
-        return $this->has('incoming_package_dependencies') ? $this->get('incoming_package_dependencies') : [];
-    }
-
-    /** @param float $normalizedDistance */
-    public function setNormalizedDistance($normalizedDistance)
-    {
-        $this->set('distance', $normalizedDistance / sqrt(2.0));
-        $this->set('normalized_distance', $normalizedDistance);
-    }
-
-    /** @return float|null */
-    public function getDistance()
-    {
-        return $this->get('distance');
-    }
-
-    /** @return float|null */
-    public function getNormalizedDistance()
-    {
-        return $this->get('normalized_distance');
-    }
-
-    /** @param float[] $instabilities */
-    public function setDependentInstabilities(array $instabilities)
-    {
-        $this->set('dependent_instabilities', $instabilities);
-    }
-
-    /** @return float[] */
-    public function getDependentInstabilities()
-    {
-        return $this->has('dependent_instabilities') ? $this->get('dependent_instabilities') : [];
-    }
-}
diff --git a/src/Hal/Metric/ProjectMetric.php b/src/Hal/Metric/ProjectMetric.php
deleted file mode 100644
index 70cce4d3..00000000
--- a/src/Hal/Metric/ProjectMetric.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-namespace Hal\Metric;
-
-class ProjectMetric implements Metric, \JsonSerializable
-{
-    use BagTrait;
-}
diff --git a/src/Hal/Metric/Registry.php b/src/Hal/Metric/Registry.php
deleted file mode 100644
index 457add50..00000000
--- a/src/Hal/Metric/Registry.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-
-namespace Hal\Metric;
-
-class Registry
-{
-    private $definitionsForStructures = [
-        'name' => 'Name of component',
-        'length' => "Halstead'e program length",
-        'vocabulary' => "Halstead's vocabulary",
-        'volume' => "Halstead's program volume",
-        'difficulty' => "Halstead's difficulty",
-        'effort' => "Halstead's effort",
-        'level' => "Halstead's program level",
-        'bugs' => "Halstead's estimation of number of bugs",
-        'time' => "Halstead's estimated time to program",
-        'intelligentContent' => "Halstead's program level",
-        'number_operators' => 'Number of operators',
-        'number_operands' => 'Number of operands',
-        'number_operators_unique' => 'Number of unique operators',
-        'number_operands_unique' => 'Number of unique operands',
-        'ccn' => "Cyclomatic complexity",
-        'ccnMethodMax' => 'Max Cyclomatic complexity for method',
-        'kanDefect' => "Kan's defects",
-        'mi' => "Maintainability Index",
-        'mIwoC' => "Maintainability Index without comments",
-        'commentWeight' => "Weight of comments",
-        'externals' => "List of external dependencies",
-        'parents' => "List of parent classes",
-        'lcom' => "Lack of cohesion of methods",
-        'relativeStructuralComplexity' => "Relative structural complexity",
-        'relativeDataComplexity' => "Relative data complexity",
-        'relativeSystemComplexity' => "Relative system complexity",
-        'totalStructuralComplexity' => "Total structural complexity",
-        'totalDataComplexity' => "Total data complexity",
-        'totalSystemComplexity' => "Total system complexity",
-        'cloc' => "Comment Lines of Code",
-        'loc' => "Lines of Code",
-        'lloc' => "Logical Lines of Code",
-        'methods' => "List of methods",
-        'nbMethodsIncludingGettersSetters' => "Number of methods including getters and setters",
-        'nbMethods' => "Number of methods excluding getters and setters",
-        'nbMethodsPrivate' => "Number of private methods",
-        'nbMethodsPublic' => "Number of public methods",
-        'nbMethodsGetter' => "Number of getters",
-        'nbMethodsSetters' => "Number of setters",
-        'afferentCoupling' => "Afferent coupling",
-        'efferentCoupling' => "Efferent coupling",
-        'instability' => "Package Instability",
-        'depthOfInheritanceTree' => "Depth of inheritance tree",
-        'pageRank' => "PageRank for component",
-    ];
-
-    public function allForProject() {}
-
-    public function allForStructures()
-    {
-        return array_keys($this->definitionsForStructures);
-    }
-
-    public function getDefinitions()
-    {
-        return $this->definitionsForStructures;
-    }
-}
diff --git a/src/Hal/Metric/SearchMetric.php b/src/Hal/Metric/SearchMetric.php
deleted file mode 100644
index 5de228d9..00000000
--- a/src/Hal/Metric/SearchMetric.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-namespace Hal\Metric;
-
-class SearchMetric implements Metric, \JsonSerializable
-{
-    use BagTrait;
-}
diff --git a/src/Hal/Metric/System/Changes/GitChanges.php b/src/Hal/Metric/System/Changes/GitChanges.php
deleted file mode 100644
index 7aa04979..00000000
--- a/src/Hal/Metric/System/Changes/GitChanges.php
+++ /dev/null
@@ -1,181 +0,0 @@
-<?php
-
-namespace Hal\Metric\System\Changes;
-
-use Hal\Application\Config\Config;
-use Hal\Application\Config\ConfigException;
-use Hal\Metric\FileMetric;
-use Hal\Metric\Metrics;
-use Hal\Metric\ProjectMetric;
-
-class GitChanges
-{
-    /**
-     * @var array
-     */
-    private $files = [];
-
-    /**
-     * @var Config
-     */
-    private $config;
-
-    /**
-     * @param array $files
-     */
-    public function __construct(Config $config, array $files)
-    {
-        $this->files = $files;
-        $this->config = $config;
-    }
-
-    /**
-     * @param Metrics $metrics
-     * @throws ConfigException
-     */
-    public function calculate(Metrics $metrics)
-    {
-        if (!$this->config->has('git')) {
-            return;
-        }
-
-        $bin = $this->config->get('git');
-        if (is_bool($bin)) {
-            $bin = 'git';
-        }
-
-        if (count($this->files) == 0) {
-            return;
-        }
-
-        $r = shell_exec(sprintf('%s --version', $bin));
-        if (!preg_match('!git version!', $r)) {
-            throw new ConfigException(sprintf('Git binary (%s) incorrect', $bin));
-        }
-
-        // get all history (for only on directory for the moment
-        // @todo: git history for multiple repositories
-        // 500 last commits max
-        $file = current($this->files);
-        $command = sprintf(
-            "cd %s && %s log --format='* %%at\t%%cn' --numstat -n 500",
-            escapeshellarg(realpath(dirname($file))),
-            escapeshellarg($bin)
-        );
-        $r = shell_exec($command);
-        $r = array_filter(explode(PHP_EOL, $r));
-
-        // build a range of commits info, stepped by week number
-        $history = [];
-        $dateFormat = 'Y-W';
-
-        // calculate statistics
-        $firstCommitDate = null;
-        $commitsByFile = [];
-        $localFiles = [];
-        $localFiles['additions'] = 0;
-        $localFiles['removes'] = 0;
-        $localFiles['nbFiles'] = 0;
-        $authors = [];
-
-        foreach ($r as $line) {
-            if (preg_match('!^\* (\d+)\s+(.*)!', $line, $matches)) {
-                // head line
-
-                if (isset($date)) {
-                    // new head line ($author is set). Consolidate now for last commit
-                    if (!isset($history[$date])) {
-                        $history[$date] = ['nbFiles' => 0, 'additions' => 0, 'removes' => 0];
-                    }
-                    $history[$date]['nbFiles'] += $localFiles['nbFiles'];
-                    $history[$date]['additions'] += $localFiles['additions'];
-                    $history[$date]['removes'] += $localFiles['removes'];
-
-                    // reset
-                    $localFiles['additions'] = 0;
-                    $localFiles['removes'] = 0;
-                    $localFiles['nbFiles'] = 0;
-                }
-
-                // new infos
-                list(, $timestamp, $author) = $matches;
-                $date = (new \DateTime())->setTimestamp($timestamp)->format($dateFormat);
-
-                if ($firstCommitDate === null) {
-                    $firstCommitDate = $timestamp;
-                }
-
-                // author
-                if (!isset($authors[$author])) {
-                    $authors[$author] = ['nbFiles' => 0, 'commits' => 0, 'additions' => 0, 'removes' => 0];
-                }
-                $authors[$author]['commits']++;
-            } else {
-                if (preg_match('!(\d+)\s+(\d+)\s+(.*)!', $line, $matches)) {
-                    // additions and changes for each file
-                    list(, $additions, $removes, $filename) = $matches;
-
-                    if (!$this->doesThisFileShouldBeCounted($filename)) {
-                        // we don't care about all files
-                        continue;
-                    }
-
-                    // global history
-                    $localFiles['additions'] += $additions;
-                    $localFiles['removes'] += $removes;
-                    $localFiles['nbFiles']++;
-
-                    // commits by file
-                    if (!isset($commitsByFile[$filename])) {
-                        $commitsByFile[$filename] = 0;
-                    }
-                    $commitsByFile[$filename]++;
-
-                    // author
-                    if (isset($author)) {
-                        $authors[$author]['nbFiles']++;
-                        $authors[$author]['additions'] += $additions;
-                        $authors[$author]['removes'] += $removes;
-                    }
-                }
-            }
-        }
-
-        // build a range of dates since first commit
-        // (pad weeks without any commit)
-        $current = $firstCommitDate;
-        $last = time();
-        while ($current <= $last) {
-            $key = date($dateFormat, $current);
-            if (!isset($history[$key])) {
-                $history[$key] = [
-                    'nbFiles' => 0,
-                    'additions' => 0,
-                    'removes' => 0,
-                ];
-            }
-            $current = strtotime('+7 day', $current);
-        }
-
-        // store results
-        $result = new ProjectMetric('git');
-        $result->set('history', $history);
-        $result->set('authors', $authors);
-        $metrics->attach($result);
-
-        foreach ($commitsByFile as $filename => $nbCommits) {
-            $info = new FileMetric($filename);
-            $info->set('gitChanges', $nbCommits);
-            $metrics->attach($info);
-        }
-    }
-
-    /**
-     * @param $file
-     * @return int
-     */
-    private function doesThisFileShouldBeCounted($file)
-    {
-        return preg_match('!\.(php|inc)$!i', $file);
-    }
-}
diff --git a/src/Hal/Metric/System/Coupling/Coupling.php b/src/Hal/Metric/System/Coupling/Coupling.php
deleted file mode 100644
index e649fc57..00000000
--- a/src/Hal/Metric/System/Coupling/Coupling.php
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-
-namespace Hal\Metric\System\Coupling;
-
-use Hal\Component\Tree\GraphDeduplicated;
-use Hal\Component\Tree\Node;
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metrics;
-
-/**
- * Estimates coupling (based on work of Henry And Kafura)
- *
- * @author Jean-François Lépine <https://twitter.com/Halleck45>
- */
-class Coupling
-{
-    /**
-     * @param Metrics $metrics
-     */
-    public function calculate(Metrics $metrics)
-    {
-        // build a graph of relations
-        $graph = new GraphDeduplicated();
-
-        foreach ($metrics->all() as $metric) {
-            if (!$metric instanceof ClassMetric) {
-                continue;
-            }
-
-            if (!$graph->has($metric->get('name'))) {
-                $graph->insert(new Node($metric->get('name')));
-            }
-            $from = $graph->get($metric->get('name'));
-
-            foreach ($metric->get('externals') as $external) {
-                if (!$graph->has($external)) {
-                    $graph->insert(new Node($external));
-                }
-
-                $to = $graph->get($external);
-
-                $graph->addEdge($from, $to);
-            }
-        }
-
-        // analyze relations
-        foreach ($metrics->all() as $metric) {
-            if (!$metric instanceof ClassMetric) {
-                continue;
-            }
-            $efferent = $afferent = 0;
-
-            $node = $graph->get($metric->get('name'));
-            foreach ($node->getEdges() as $edge) {
-                if ($edge->getTo()->getKey() == $node->getKey()) {
-                    // affects
-                    $afferent++;
-                }
-
-                if ($edge->getFrom()->getKey() == $node->getKey()) {
-                    // receive effects
-                    $efferent++;
-                }
-            }
-
-            $instability = 0;
-            if ($efferent + $afferent > 0) {
-                $instability = $efferent / ($afferent + $efferent);
-            }
-            $metric
-                ->set('afferentCoupling', $afferent)
-                ->set('efferentCoupling', $efferent)
-                ->set('instability', round($instability, 2));
-        }
-    }
-}
diff --git a/src/Hal/Metric/System/Coupling/DepthOfInheritanceTree.php b/src/Hal/Metric/System/Coupling/DepthOfInheritanceTree.php
deleted file mode 100644
index 45914d18..00000000
--- a/src/Hal/Metric/System/Coupling/DepthOfInheritanceTree.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-namespace Hal\Metric\System\Coupling;
-
-use Hal\Component\Tree\GraphDeduplicated;
-use Hal\Component\Tree\Node;
-use Hal\Component\Tree\Operator\SizeOfTree;
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metrics;
-use Hal\Metric\ProjectMetric;
-
-/**
- * Estimates DIT
- * @see https://www.cse.iitb.ac.in/~rkj/inheritancemetrics.pdf
- *
- * @author Jean-François Lépine <https://twitter.com/Halleck45>
- */
-class DepthOfInheritanceTree
-{
-    /**
-     * @param Metrics $metrics
-     */
-    public function calculate(Metrics $metrics)
-    {
-        $projectMetric = new ProjectMetric('tree');
-
-        // building graph with parents / childs relations only
-        $graph = new GraphDeduplicated();
-
-        foreach ($metrics->all() as $metric) {
-            if (!$metric instanceof ClassMetric) {
-                continue;
-            }
-
-            if (!$graph->has($metric->get('name'))) {
-                $graph->insert(new Node($metric->get('name')));
-            }
-
-            $to = $graph->get($metric->get('name'));
-
-            foreach ($metric->get('parents') as $parent) {
-                if (!$graph->has($parent)) {
-                    $graph->insert(new Node($parent));
-                }
-
-                $from = $graph->get($parent);
-
-                $graph->addEdge($from, $to);
-            }
-        }
-
-        $size = new SizeOfTree($graph);
-        $averageHeight = $size->getAverageHeightOfGraph();
-
-        $projectMetric->set('depthOfInheritanceTree', $averageHeight);
-        $metrics->attach($projectMetric);
-    }
-}
diff --git a/src/Hal/Metric/System/Coupling/PageRank.php b/src/Hal/Metric/System/Coupling/PageRank.php
deleted file mode 100644
index 71b39971..00000000
--- a/src/Hal/Metric/System/Coupling/PageRank.php
+++ /dev/null
@@ -1,91 +0,0 @@
-<?php
-
-namespace Hal\Metric\System\Coupling;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metrics;
-
-/**
- * @package Hal\Metric\System\Coupling
- */
-class PageRank
-{
-    /**
-     * @param Metrics $metrics
-     */
-    public function calculate(Metrics $metrics)
-    {
-        // build an array of relations
-        $links = [];
-        foreach ($metrics->all() as $metric) {
-            if (!$metric instanceof ClassMetric) {
-                continue;
-            }
-
-            $links[$metric->get('name')] = $metric->get('externals');
-        }
-
-        $ranks = $this->calculatePageRank($links);
-
-        // save in the metrics object
-        foreach ($ranks as $name => $rank) {
-            $metrics->get($name)->set('pageRank', round($rank, 2));
-        }
-    }
-
-    /**
-     * @see http://phpir.com/pagerank-in-php/
-     * @param $linkGraph
-     * @param float $dampingFactor
-     * @return array
-     */
-    private function calculatePageRank($linkGraph, $dampingFactor = 0.15)
-    {
-        $pageRank = [];
-        $tempRank = [];
-        $nodeCount = count($linkGraph);
-
-        // initialise the PR as 1/n
-        foreach ($linkGraph as $node => $outbound) {
-            $pageRank[$node] = 1 / $nodeCount;
-            $tempRank[$node] = 0;
-        }
-
-        $change = 1;
-        $i = 0;
-        while ($change > 0.00005 && $i < 100) {
-            $change = 0;
-            $i++;
-
-            // distribute the PR of each page
-            foreach ($linkGraph as $node => $outbound) {
-                $outboundCount = count($outbound);
-                foreach ($outbound as $link) {
-                    // case of unversionned dependency
-                    if (!isset($tempRank[$link])) {
-                        $tempRank[$link] = 0;
-                    }
-                    $tempRank[$link] += $pageRank[$node] / $outboundCount;
-                }
-            }
-
-            $total = 0;
-            // calculate the new PR using the damping factor
-            foreach ($linkGraph as $node => $outbound) {
-                $tempRank[$node] = ($dampingFactor / $nodeCount)
-                    + (1 - $dampingFactor) * $tempRank[$node];
-                $change += abs($pageRank[$node] - $tempRank[$node]);
-                $pageRank[$node] = $tempRank[$node];
-                $tempRank[$node] = 0;
-                $total += $pageRank[$node];
-            }
-
-            // Normalise the page ranks so it's all a proportion 0-1
-            foreach ($pageRank as $node => $score) {
-                $pageRank[$node] /= $total;
-            }
-        }
-
-        return $pageRank;
-    }
-}
diff --git a/src/Hal/Metric/System/Packages/Composer/Composer.php b/src/Hal/Metric/System/Packages/Composer/Composer.php
deleted file mode 100644
index 95ffe0b7..00000000
--- a/src/Hal/Metric/System/Packages/Composer/Composer.php
+++ /dev/null
@@ -1,148 +0,0 @@
-<?php
-
-namespace Hal\Metric\System\Packages\Composer;
-
-use Hal\Application\Config\Config;
-use Hal\Application\Config\ConfigException;
-use Hal\Component\File\Finder;
-use Hal\Metric\Metrics;
-use Hal\Metric\ProjectMetric;
-
-/**
- * @package Hal\Metric\System\Packages\Composer
- */
-class Composer
-{
-    /**
-     * @var Config
-     */
-    private $config;
-
-    /**
-     * @param array $files
-     */
-    public function __construct(Config $config, array $files)
-    {
-        $this->config = $config;
-    }
-
-    /**
-     * @param Metrics $metrics
-     * @throws ConfigException
-     */
-    public function calculate(Metrics $metrics)
-    {
-        if ($this->config->has('composer') && false === $this->config->get('composer')) {
-            return;
-        }
-
-        $projectMetric = new ProjectMetric('composer');
-        $projectMetric->set('packages', []);
-        $metrics->attach($projectMetric);
-        $packages = [];
-        $rawRequirements = $this->getComposerJsonRequirements();
-        $rawInstalled = $this->getComposerLockInstalled(\array_keys($rawRequirements));
-
-        $packagist = new Packagist();
-        foreach ($rawRequirements as $requirement => $version) {
-            $installed = isset($rawInstalled[$requirement]) ? $rawInstalled[$requirement] : null;
-            $package = $packagist->get($requirement);
-
-            $package->installed = $installed;
-            $package->required = $version;
-            $package->name = $requirement;
-            // Manage case where the package is not hosted on packagist (private repository) so we can't know the status
-            if ($installed === null || $package->latest === null) {
-                $package->status = 'unknown';
-            } else {
-                $package->status = version_compare($installed, $package->latest, '<') ? 'outdated' : 'latest';
-            }
-            $packages[$requirement] = $package;
-        }
-
-        // exclude extensions
-        $packages = array_filter($packages, function ($package) {
-            return !preg_match('!(^php$|^ext\-)!', $package->name);
-        });
-
-        $projectMetric->set('packages', $packages);
-        $projectMetric->set('packages-installed', $rawInstalled);
-    }
-
-    /**
-     * Returns the requirements defined in the composer(-dist)?.json file.
-     * @return array
-     */
-    protected function getComposerJsonRequirements()
-    {
-        $rawRequirements = [[]];
-
-        // find composer.json files
-        $exclude = $this->config->has('exclude') ? $this->config->get('exclude') : [];
-        $finder = new Finder(['json'], $exclude);
-
-        // include root dir by default
-        $files = $this->config->has('files') ? $this->config->get('files') : [];
-        $files = array_merge($files, ['./']);
-        $files = $finder->fetch($files);
-
-        foreach ($files as $filename) {
-            if (!\preg_match('/composer(-dist)?\.json/', $filename)) {
-                continue;
-            }
-            $composerJson = (object) \json_decode(\file_get_contents($filename));
-
-            if (!isset($composerJson->require)) {
-                continue;
-            }
-
-            $rawRequirements[] = (array) $composerJson->require;
-        }
-
-        return \call_user_func_array('array_merge', $rawRequirements);
-    }
-
-    /**
-     * Returns the installed packages from the composer.lock file.
-     * @param array $rootPackageRequirements List of requirements to match installed packages only with requirements.
-     * @return array
-     */
-    protected function getComposerLockInstalled($rootPackageRequirements)
-    {
-        $rawInstalled = [[]];
-
-        // Find composer.lock file
-        $exclude = $this->config->has('exclude') ? $this->config->get('exclude') : [];
-        $finder = new Finder(['lock'], $exclude);
-
-        // include root dir by default
-        $files = $this->config->has('files') ? $this->config->get('files') : [];
-        $files = array_merge($files, ['./']);
-        $files = $finder->fetch($files);
-
-        // List all composer.lock found in the project.
-        foreach ($files as $filename) {
-            if (false === \strpos($filename, 'composer.lock')) {
-                continue;
-            }
-            $composerLockJson = (object) \json_decode(\file_get_contents($filename));
-
-            if (!isset($composerLockJson->packages)) {
-                continue;
-            }
-
-            $installed = [];
-            foreach ($composerLockJson->packages as $package) {
-                if (!\in_array($package->name, $rootPackageRequirements, true)) {
-                    continue;
-                }
-
-                $installed[$package->name] = \preg_replace('#[^.\d]#', '', $package->version);
-            }
-
-            $rawInstalled[] = $installed;
-        }
-
-        return \call_user_func_array('array_merge', $rawInstalled);
-    }
-}
diff --git a/src/Hal/Metric/System/Packages/Composer/Packagist.php b/src/Hal/Metric/System/Packages/Composer/Packagist.php
deleted file mode 100644
index 2880f30e..00000000
--- a/src/Hal/Metric/System/Packages/Composer/Packagist.php
+++ /dev/null
@@ -1,107 +0,0 @@
-<?php
-
-namespace Hal\Metric\System\Packages\Composer;
-
-/**
- * @package Hal\Metric\System\Packages\Composer
- */
-class Packagist
-{
-    /**
-     * @param $package
-     * @return \StdClass
-     */
-    public function get($package)
-    {
-        $response = new \StdClass();
-        $response->latest = null;
-        $response->license = [];
-        $response->homepage = null;
-        $response->description = null;
-        $response->time = null;
-        $response->zip = null;
-        $response->compare = null;
-        $response->type = 'unknown';
-        $response->github_stars = 0;
-        $response->github_watchers = 0;
-        $response->github_forks = 0;
-        $response->github_open_issues = 0;
-        $response->download_total = 0;
-        $response->download_monthly = 0;
-        $response->download_daily = 0;
-        $response->favers = 0;
-
-        if (!preg_match('/\w+\/\w+/', $package)) {
-            return $response;
-        }
-        list($user, $name) = explode('/', $package);
-        $uri = sprintf('https://packagist.org/packages/%s/%s.json', $user, $name);
-        $json = $this->getURIContentAsJson($uri);
-
-        if (!isset($json->package) || !is_object($json->package)) {
-            return $response;
-        }
-
-        $response->type = $json->package->type;
-        $response->description = $json->package->description;
-        $response->type = $json->package->type;
-        $response->github_stars = $json->package->github_stars;
-        $response->github_watchers = $json->package->github_watchers;
-        $response->github_forks = $json->package->github_forks;
-        $response->github_open_issues = $json->package->github_open_issues;
-        $response->download_total = $json->package->downloads->total;
-        $response->download_monthly = $json->package->downloads->monthly;
-        $response->download_daily = $json->package->downloads->daily;
-        $response->favers = $json->package->favers;
-
-        // get latest version
-        $latest = '0.0.0';
-        foreach ((array) $json->package->versions as $version => $datas) {
-            if ($version[0] === 'v') {
-                $version = substr($version, 1);
-            }
-            if (!preg_match('#^[\.\d]+$#', $version)) {
-                continue;
-            }
-            if ($compare = version_compare($version, $latest) == 1) {
-                $latest = $version;
-                $response->name = $package;
-                $response->latest = $version;
-                $response->license = (array) $datas->license;
-                $response->homepage = $datas->homepage;
-                $response->time = $datas->time;
-                $response->zip = $datas->dist->url;
-                $response->compare = $compare;
-            }
-        }
-
-        return $response;
-    }
-
-    /**
-     * Download the given URI and decode it as JSON.
-     *
-     * @param string $uri
-     *
-     * @return mixed
-     */
-    private function getURIContentAsJson($uri)
-    {
-        // Get the environment variable.
-        $httpsProxy = getenv('https_proxy');
-        $context = null;
-        if ('' !== $httpsProxy) {
-            // Create the context.
-            $context = stream_context_create(
-                [
-                    'http' => [
-                        'proxy' => str_replace(['http://', 'https://'], 'tcp://', $httpsProxy),
-                        'request_fulluri' => true,
-                    ],
-                ]
-            );
-        }
-
-        return json_decode(@file_get_contents($uri, false, $context));
-    }
-}
diff --git a/src/Hal/Metric/System/UnitTesting/UnitTesting.php b/src/Hal/Metric/System/UnitTesting/UnitTesting.php
deleted file mode 100644
index d8614812..00000000
--- a/src/Hal/Metric/System/UnitTesting/UnitTesting.php
+++ /dev/null
@@ -1,188 +0,0 @@
-<?php
-
-namespace Hal\Metric\System\UnitTesting;
-
-use Hal\Application\Config\Config;
-use Hal\Application\Config\ConfigException;
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Component\Ast\ParserTraverserVisitorsAssigner;
-use Hal\Metric\Class_\ClassEnumVisitor;
-use Hal\Metric\Class_\Coupling\ExternalsVisitor;
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metrics;
-use Hal\Metric\ProjectMetric;
-use PhpParser\ParserFactory;
-
-class UnitTesting
-{
-    /**
-     * @var array
-     */
-    private $files = [];
-
-    /**
-     * @var Config
-     */
-    private $config;
-
-    /**
-     * @param array $files
-     */
-    public function __construct(Config $config, array $files)
-    {
-        $this->files = $files;
-        $this->config = $config;
-    }
-
-    /**
-     * @param Metrics $metrics
-     * @throws ConfigException
-     */
-    public function calculate(Metrics $metrics)
-    {
-        if (!$this->config->has('junit')) {
-            return;
-        }
-
-        // parse junit file
-        $filename = $this->config->get('junit');
-        if (!file_exists($filename) || !is_readable($filename)) {
-            throw new ConfigException('JUnit report cannot be read');
-        }
-
-        $unitsTests = [];
-        $infoAboutTests = [];
-        $assertions = 0;
-        $projectMetric = new ProjectMetric('unitTesting');
-
-        // injects default value for each metric
-        foreach ($metrics->all() as $metric) {
-            $metric->set('numberOfUnitTests', 0);
-        }
-
-        // parsing of XML file without any dependency to DomDocument or simpleXML
-        // we want to be compatible with every platforms. Maybe (probably) that's a really stupid idea, but I want to try it :p
-        $testsuites = [];
-        $alreadyParsed = [];
-
-        $dom = new \DOMDocument('1.0', 'UTF-8');
-        $dom->load($filename);
-        $xpath = new \DOMXpath($dom);
-
-        // JUNIT format
-        foreach ($xpath->query('//testsuite[@file]') as $suite) {
-            array_push($testsuites, (object) [
-                'file' => $suite->getAttribute('file'),
-                'name' => $suite->getAttribute('name'),
-                'assertions' => $suite->getAttribute('assertions'),
-                'time' => $suite->getAttribute('time'),
-            ]);
-        }
-
-        // CODECEPTION format (file is stored in the <testcase> node
-        foreach ($xpath->query('//testcase[@file]') as $index => $case) {
-            $suite = $case->parentNode;
-
-            if ($suite->hasAttribute('file')) {
-                // avoid duplicates
-                continue;
-            }
-
-            if (isset($testsuites[$case->getAttribute('class')])) {
-                // codeception does not consider testcase like junit does
-                continue;
-            }
-
-            if ($suite->hasAttribute('assertions')) {
-                // codeception store assertions in testsuite, not in testcase
-                // (but it stores classname in the testcase node) oO
-                // so we will store "assertions" in the first testcase of the testsuite only
-                $assertions = $case === $suite->firstChild->nextSibling ? $suite->getAttribute('assertions') : 0;
-            }
-
-            $testsuites[$case->getAttribute('class')] = (object) [
-                'file' => $case->getAttribute('file'),
-                'name' => $case->getAttribute('class'),
-                'assertions' => $assertions,
-                'time' => $suite->getAttribute('time'),
-            ];
-        }
-
-        // analyze each unit test
-        // This code is slow and can be optimized
-        foreach ($testsuites as $suite) {
-            $metricsOfUnitTest = new Metrics();
-            $parser = (new ParserFactoryBridge())->create();
-            $traverser = new \PhpParser\NodeTraverser();
-            (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-                new \PhpParser\NodeVisitor\NameResolver(),
-                new ClassEnumVisitor($metricsOfUnitTest),
-                new ExternalsVisitor($metricsOfUnitTest)
-            ]);
-
-            if (!file_exists($suite->file) || !is_readable($suite->file)) {
-                throw new \LogicException('Cannot find source file referenced in testsuite: ' . $suite->file);
-            }
-
-            $code = file_get_contents($suite->file);
-            $stmts = $parser->parse($code);
-            $traverser->traverse($stmts);
-
-            if (!$metricsOfUnitTest->has($suite->name)) {
-                continue;
-            }
-
-            // list of externals sources of unit test
-            $metric = $metricsOfUnitTest->get($suite->name);
-            $externals = (array) $metric->get('externals');
-
-            // global stats for each test
-            $infoAboutTests[$suite->name] = (object) [
-                'nbExternals' => count(array_unique($externals)),
-                'externals' => array_unique($externals),
-                'filename' => $suite->file,
-                'classname' => $suite->name,
-                'assertions' => $suite->assertions,
-                'time' => $suite->time,
-            ];
-
-            $assertions += $suite->assertions;
-
-            foreach ($externals as $external) {
-                // search for this external in metrics
-                if (!$metrics->has($external)) {
-                    continue;
-                }
-
-                // SUT (tested class) has unit test
-                $numberOfUnitTest = $metrics->get($external)->get('numberOfUnitTests');
-                $numberOfUnitTest++;
-                $metrics->get($external)->set('numberOfUnitTests', $numberOfUnitTest);
-            }
-        }
-
-        // statistics
-        $sum = 0;
-        $nb = 0;
-        foreach ($metrics->all() as $metric) {
-            if (!$metric instanceof ClassMetric) {
-                continue;
-            }
-
-            $sum++;
-            if ($metric->get('numberOfUnitTests') > 0) {
-                $nb++;
-            }
-        }
-
-        $projectMetric->set('assertions', $assertions);
-        $projectMetric->set('tests', $infoAboutTests);
-        $projectMetric->set('nbSuites', count($testsuites));
-        $projectMetric->set('nbCoveredClasses', $nb);
-        $projectMetric->set('percentCoveredClasses', round($nb / max($sum, 1) * 100, 2));
-        $projectMetric->set('nbUncoveredClasses', $sum - $nb);
-        $projectMetric->set('percentUncoveredClasses', round(($sum - $nb) / max($sum, 1) * 100, 2));
-
-        $metrics->attach($projectMetric);
-    }
-}
diff --git a/src/Hal/Report/Cli/Reporter.php b/src/Hal/Report/Cli/Reporter.php
deleted file mode 100644
index d8e3f57a..00000000
--- a/src/Hal/Report/Cli/Reporter.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-
-namespace Hal\Report\Cli;
-
-use Hal\Application\Config\Config;
-use Hal\Component\Output\Output;
-use Hal\Metric\Consolidated;
-use Hal\Metric\Metrics;
-
-class Reporter
-{
-    /**
-     * @var Config
-     */
-    private $config;
-
-    /**
-     * @var Output
-     */
-    private $output;
-
-    /**
-     * @param Config $config
-     * @param Output $output
-     */
-    public function __construct(Config $config, Output $output)
-    {
-        $this->config = $config;
-        $this->output = $output;
-    }
-
-    public function generate(Metrics $metrics)
-    {
-        if ($this->config->has('quiet')) {
-            return;
-        }
-
-        $this->output->write(
-            (new SummaryWriter($metrics, new Consolidated($metrics), $this->config))->getReport()
-        );
-    }
-}
diff --git a/src/Hal/Report/Cli/SearchReporter.php b/src/Hal/Report/Cli/SearchReporter.php
deleted file mode 100644
index ceb688b7..00000000
--- a/src/Hal/Report/Cli/SearchReporter.php
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php
-
-namespace Hal\Report\Cli;
-
-use Hal\Application\Config\Config;
-use Hal\Component\Output\Output;
-use Hal\Metric\ClassMetric;
-use Hal\Metric\InterfaceMetric;
-use Hal\Metric\Metrics;
-use Hal\Metric\SearchMetric;
-use Hal\Search\PatternSearcher;
-use Hal\Search\Searches;
-
-class SearchReporter
-{
-    /**
-     * @var Config
-     */
-    private $config;
-
-    /**
-     * @var Output
-     */
-    private $output;
-
-    /**
-     * @param Config $config
-     * @param Output $output
-     */
-    public function __construct(Config $config, Output $output)
-    {
-        $this->config = $config;
-        $this->output = $output;
-    }
-
-    /**
-     * @param Metrics $metrics
-     */
-    public function generate(Metrics $metrics)
-    {
-        /** @var SearchMetric $searches */
-        $searches = $metrics->get('searches');
-        if (empty($searches)) {
-            return;
-        }
-
-        foreach ($searches->all() as $name => $search) {
-
-            if (!is_array($search)) {
-                continue;
-            }
-
-            $this->displayCliReport($name, $search);
-        }
-    }
-
-    private function displayCliReport($searchName, array $foundSearch)
-    {
-        $title = sprintf(
-            '<info>Found %d occurrences for search "%s"</info>',
-            sizeof($foundSearch),
-            $searchName
-        );
-
-        $config = $this->config->get('searches')->get($searchName)->getConfig();
-        if (!empty($foundSearch) && !empty($config->failIfFound) && true === $config->failIfFound) {
-            $title = sprintf(
-                '<error>[ERR] Found %d occurrences for search "%s"</error>',
-                sizeof($foundSearch),
-                $searchName
-            );
-        }
-
-        $sampleToDisplay = 5;
-        $this->output->writeln($title);
-
-        $parts = array_slice($foundSearch, 0, $sampleToDisplay);
-        foreach ($parts as $part) {
-            $this->output->writeln(sprintf('- %s', $part->getName()));
-        }
-
-        if (sizeof($foundSearch) > $sampleToDisplay) {
-            $this->output->writeln(sprintf('... and %d more', sizeof($foundSearch) - $sampleToDisplay));
-        }
-
-        $this->output->writeln(PHP_EOL);
-    }
-}
diff --git a/src/Hal/Report/Cli/SummaryWriter.php b/src/Hal/Report/Cli/SummaryWriter.php
deleted file mode 100644
index 4f76ccbf..00000000
--- a/src/Hal/Report/Cli/SummaryWriter.php
+++ /dev/null
@@ -1,92 +0,0 @@
-<?php
-
-namespace Hal\Report\Cli;
-
-use Hal\Report\SummaryProvider;
-
-class SummaryWriter extends SummaryProvider
-{
-    public function getReport()
-    {
-        $out = <<<EOT
-LOC
-    Lines of code                               {$this->sum->loc}
-    Logical lines of code                       {$this->sum->lloc}
-    Comment lines of code                       {$this->sum->cloc}
-    Average volume                              {$this->avg->volume}
-    Average comment weight                      {$this->avg->commentWeight}
-    Average intelligent content                 {$this->avg->commentWeight}
-    Logical lines of code by class              {$this->locByClass}
-    Logical lines of code by method             {$this->locByMethod}
-Object oriented programming
-    Classes                                     {$this->sum->nbClasses}
-    Interface                                   {$this->sum->nbInterfaces}
-    Methods                                     {$this->sum->nbMethods}
-    Methods by class                            {$this->methodsByClass}
-    Lack of cohesion of methods                 {$this->avg->lcom}
-
-Coupling
-    Average afferent coupling                   {$this->avg->afferentCoupling}
-    Average efferent coupling                   {$this->avg->efferentCoupling}
-    Average instability                         {$this->avg->instability}
-    Depth of Inheritance Tree                   {$this->treeInheritenceDepth}
-
-Package
-    Packages                                    {$this->sum->nbPackages}
-    Average classes per package                 {$this->avg->classesPerPackage}
-    Average distance                            {$this->avg->distance}
-    Average incoming class dependencies         {$this->avg->incomingCDep}
-    Average outgoing class dependencies         {$this->avg->outgoingCDep}
-    Average incoming package dependencies       {$this->avg->incomingPDep}
-    Average outgoing package dependencies       {$this->avg->outgoingPDep}
-Complexity
-    Average Cyclomatic complexity by class      {$this->avg->ccn}
-    Average Weighted method count by class      {$this->avg->wmc}
-    Average Relative system complexity          {$this->avg->relativeSystemComplexity}
-    Average Difficulty                          {$this->avg->difficulty}
-
-Bugs
-    Average bugs by class                       {$this->avg->bugs}
-    Average defects by class (Kan)              {$this->avg->kanDefect}
-Violations
-    Critical                                    {$this->sum->violations->critical}
-    Error                                       {$this->sum->violations->error}
-    Warning                                     {$this->sum->violations->warning}
-    Information                                 {$this->sum->violations->information}
-EOT;
-
-        // git
-        if ($this->config->has('git')) {
-            $commits = [];
-            foreach ($this->consolidated->getFiles() as $name => $file) {
-                $commits[$name] = $file['gitChanges'];
-            }
-            arsort($commits);
-            $commits = array_slice($commits, 0, 10);
-
-            $out .= "\nTop 10 committed files";
-            foreach ($commits as $file => $nb) {
-                $out .= sprintf("\n    %d    %s", $nb, $file);
-            }
-            if (0 === count($commits)) {
-                $out .= "\n    NA";
-            }
-            $out .= "\n";
-        }
-
-        // Junit
-        if ($this->config->has('junit')) {
-            $out .= <<<EOT
-
-Unit testing
-    Number of unit tests                        {$this->metrics->get('unitTesting')->get('nbSuites')}
-    Classes called by tests                     {$this->metrics->get('unitTesting')->get('nbCoveredClasses')}
-    Classes called by tests (percent)           {$this->metrics->get('unitTesting')->get('percentCoveredClasses')} %
-EOT;
-        }
-
-        $out .= "\n\n";
-
-        return $out;
-    }
-}
diff --git a/src/Hal/Report/Csv/Reporter.php b/src/Hal/Report/Csv/Reporter.php
deleted file mode 100644
index 2e9ba022..00000000
--- a/src/Hal/Report/Csv/Reporter.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-
-namespace Hal\Report\Csv;
-
-use Hal\Application\Config\Config;
-use Hal\Component\Output\Output;
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metrics;
-use Hal\Metric\Registry;
-
-class Reporter
-{
-    /**
-     * @var Config
-     */
-    private $config;
-
-    /**
-     * @var Output
-     */
-    private $output;
-
-    /**
-     * @param Config $config
-     * @param Output $output
-     */
-    public function __construct(Config $config, Output $output)
-    {
-        $this->config = $config;
-        $this->output = $output;
-    }
-
-
-    public function generate(Metrics $metrics)
-    {
-        if ($this->config->has('quiet')) {
-            return;
-        }
-
-        $logFile = $this->config->get('report-csv');
-        if (!$logFile) {
-            return;
-        }
-        if (!file_exists(dirname($logFile)) || !is_writable(dirname($logFile))) {
-            throw new \RuntimeException('You don\'t have permissions to write CSV report in ' . $logFile);
-        }
-
-        $availables = (new Registry())->allForStructures();
-        $hwnd = fopen($logFile, 'w');
-        fputcsv($hwnd, $availables);
-
-        foreach ($metrics->all() as $metric) {
-            if (!$metric instanceof ClassMetric) {
-                continue;
-            }
-            $row = [];
-            foreach ($availables as $key) {
-                $data = $metric->get($key);
-                if (is_array($data) || !is_scalar($data)) {
-                    $data = 'N/A';
-                }
-
-                array_push($row, $data);
-            }
-            fputcsv($hwnd, $row);
-        }
-
-        fclose($hwnd);
-    }
-}
diff --git a/src/Hal/Report/Html/Reporter.php b/src/Hal/Report/Html/Reporter.php
deleted file mode 100644
index 6304d8c2..00000000
--- a/src/Hal/Report/Html/Reporter.php
+++ /dev/null
@@ -1,306 +0,0 @@
-<?php
-
-namespace Hal\Report\Html;
-
-use Hal\Application\Config\Config;
-use Hal\Component\Output\Output;
-use Hal\Metric\Consolidated;
-use Hal\Metric\Group\Group;
-use Hal\Metric\Metrics;
-use RuntimeException as RuntimeExceptionAlias;
-
-class Reporter
-{
-    /**
-     * @var Config
-     */
-    private $config;
-
-    /**
-     * @var Output
-     */
-    private $output;
-
-    /**
-     * @var string
-     */
-    protected $templateDir;
-
-    /**
-     * @var Consolidated[]
-     */
-    private $consolidatedByGroups;
-
-    /**
-     * @var Group[]
-     */
-    private $groups = [];
-
-    /**
-     * @var string
-     */
-    private $currentGroup;
-
-    /**
-     * @var string
-     */
-    private $assetPath = '';
-
-    /**
-     * @param Config $config
-     * @param Output $output
-     */
-    public function __construct(Config $config, Output $output)
-    {
-        $this->config = $config;
-        $this->output = $output;
-        $this->templateDir = __DIR__ . '/../../../../templates';
-    }
-
-
-    public function generate(Metrics $metrics)
-    {
-        $logDir = $this->config->get('report-html');
-        if (!$logDir) {
-            return;
-        }
-
-        // consolidate
-
-        /** @var Group[] $groups */
-        $groups = $this->config->get('groups');
-        $this->groups = $groups;
-        $consolidatedGroups = [];
-        foreach ($groups as $group) {
-            $reducedMetricsByGroup = $group->reduceMetrics($metrics);
-            $consolidatedGroups[$group->getName()] = new Consolidated($reducedMetricsByGroup);
-        }
-
-        $consolidated = new Consolidated($metrics);
-
-        // history of builds
-        $today = (object) [
-            'avg' => $consolidated->getAvg(),
-            'sum' => $consolidated->getSum(),
-        ];
-        $files = glob($logDir . '/js/history-*.json');
-        $next = count($files) + 1;
-        $history = [];
-        natsort($files);
-        foreach ($files as $filename) {
-            array_push($history, json_decode(file_get_contents($filename)));
-        }
-
-        // copy sources
-        if (!file_exists($logDir . '/js')) {
-            mkdir($logDir . '/js', 0755, true);
-        }
-        if (!file_exists($logDir . '/css')) {
-            mkdir($logDir . '/css', 0755, true);
-        }
-        if (!file_exists($logDir . '/images')) {
-            mkdir($logDir . '/images', 0755, true);
-        }
-        if (!file_exists($logDir . '/fonts')) {
-            mkdir($logDir . '/fonts', 0755, true);
-        }
-
-        if (!is_writable($logDir)) {
-            throw new RuntimeExceptionAlias(sprintf('Unable to write in the directory "%s"', $logDir));
-        }
-
-        copy($this->templateDir . '/html_report/favicon.ico', $logDir . '/favicon.ico');
-
-        recurse_copy($this->templateDir . '/html_report/js', $logDir . '/js');
-        recurse_copy($this->templateDir . '/html_report/css', $logDir . '/css');
-        recurse_copy($this->templateDir . '/html_report/images', $logDir . '/images');
-        recurse_copy($this->templateDir . '/html_report/fonts', $logDir . '/fonts');
-
-        // render dynamic pages
-        $this->renderPage($this->templateDir . '/html_report/index.php', $logDir . '/index.html', $consolidated, $history);
-        $this->renderPage($this->templateDir . '/html_report/loc.php', $logDir . '/loc.html', $consolidated, $history);
-        $this->renderPage($this->templateDir . '/html_report/relations.php', $logDir . '/relations.html', $consolidated, $history);
-        $this->renderPage($this->templateDir . '/html_report/coupling.php', $logDir . '/coupling.html', $consolidated, $history);
-        $this->renderPage($this->templateDir . '/html_report/all.php', $logDir . '/all.html', $consolidated, $history);
-        $this->renderPage($this->templateDir . '/html_report/oop.php', $logDir . '/oop.html', $consolidated, $history);
-        $this->renderPage($this->templateDir . '/html_report/complexity.php', $logDir . '/complexity.html', $consolidated, $history);
-        $this->renderPage($this->templateDir . '/html_report/panel.php', $logDir . '/panel.html', $consolidated, $history);
-        $this->renderPage($this->templateDir . '/html_report/violations.php', $logDir . '/violations.html', $consolidated, $history);
-        $this->renderPage($this->templateDir . '/html_report/packages.php', $logDir . '/packages.html', $consolidated, $history);
-        $this->renderPage($this->templateDir . '/html_report/package_relations.php', $logDir . '/package_relations.html', $consolidated, $history);
-        $this->renderPage($this->templateDir . '/html_report/composer.php', $logDir . '/composer.html', $consolidated, $history);
-        if ($this->config->has('git')) {
-            $this->renderPage($this->templateDir . '/html_report/git.php', $logDir . '/git.html', $consolidated, $consolidatedGroups, $history);
-        }
-        $this->renderPage($this->templateDir . '/html_report/junit.php', $logDir . '/junit.html', $consolidated, $consolidatedGroups, $history);
-
-        // js data
-        file_put_contents(
-            sprintf('%s/js/history-%d.json', $logDir, $next),
-            json_encode($today, JSON_PRETTY_PRINT)
-        );
-        file_put_contents(
-            sprintf('%s/js/latest.json', $logDir),
-            json_encode($today, JSON_PRETTY_PRINT)
-        );
-
-        // json data
-        file_put_contents(
-            $logDir . '/classes.js',
-            'var classes = ' . json_encode($consolidated->getClasses(), JSON_PRETTY_PRINT)
-        );
-
-        // HTML files to generate
-        $filesToGenerate = [
-            'index',
-            'loc',
-            'relations',
-            'coupling',
-            'all',
-            'oop',
-            'complexity',
-            'panel',
-            'violations',
-            'packages',
-            'package_relations',
-            'composer',
-        ];
-
-        // consolidated by groups
-        foreach ($consolidatedGroups as $name => $consolidated) {
-            $outDir = $logDir . DIRECTORY_SEPARATOR . $name;
-            $this->currentGroup = $name;
-            $this->assetPath = '../';
-
-            if (!file_exists($outDir)) {
-                mkdir($outDir, 0755, true);
-            }
-
-            foreach ($filesToGenerate as $filename) {
-                $this->renderPage(
-                    sprintf('%s/html_report/%s.php', $this->templateDir, $filename),
-                    sprintf('%s/%s.html', $outDir, $filename),
-                    $consolidated,
-                    $history
-                );
-
-                file_put_contents(
-                    $outDir . '/classes.js',
-                    'var classes = ' . json_encode($consolidated->getClasses(), JSON_PRETTY_PRINT)
-                );
-            }
-        }
-
-        $this->output->writeln(sprintf('HTML report generated in "%s" directory', $logDir));
-    }
-
-    /**
-     * @param $source
-     * @param $destination
-     * @return $this
-     */
-    public function renderPage($source, $destination, Consolidated $consolidated, $history)
-    {
-        if (!is_writable(dirname($destination))) {
-            throw new RuntimeExceptionAlias(sprintf('Unable to write in the directory "%s"', dirname($destination)));
-        }
-
-        $this->sum = $sum = $consolidated->getSum();
-        $this->avg = $avg = $consolidated->getAvg();
-        $this->classes = $classes = $consolidated->getClasses();
-        $this->files = $files = $consolidated->getFiles();
-        $this->project = $project = $consolidated->getProject();
-        $this->packages = $packages = $consolidated->getPackages();
-        $config = $this->config;
-        $this->history = $history;
-
-        ob_start();
-        require $source;
-        $content = ob_get_clean();
-        file_put_contents($destination, $content);
-        return $this;
-    }
-
-    /**
-     * @param $type
-     * @param $key
-     * @return string
-     */
-    protected function getTrend($type, $key, $lowIsBetter = false, $highIsBetter = false)
-    {
-        if (!$this->isHomePage()) {
-            return '';
-        }
-
-        $svg = [];
-        $svg['gt'] = '<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
-    <path d="M16 6l2.29 2.29-4.88 4.88-4-4L2 16.59 3.41 18l6-6 4 4 6.3-6.29L22 12V6z"/>
-    <path d="M0 0h24v24H0z" fill="none"/>
-</svg>';
-        $svg['eq'] = '<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
-    <path d="M22 12l-4-4v3H3v2h15v3z"/>
-    <path d="M0 0h24v24H0z" fill="none"/>
-</svg>';
-        $svg['lt'] = '<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
-    <path d="M16 18l2.29-2.29-4.88-4.88-4 4L2 7.41 3.41 6l6 6 4-4 6.3 6.29L22 12v6z"/>
-    <path d="M0 0h24v24H0z" fill="none"/>
-</svg>';
-
-        $last = end($this->history);
-        if (!isset($last->$type->$key)) {
-            return '';
-        }
-
-        $oldValue = $last->$type->$key;
-        $newValue = isset($this->sum->$type->$key) ? $this->sum->$type->$key : 0;
-        if ($newValue > $oldValue) {
-            $r = 'gt';
-        } elseif ($newValue < $oldValue) {
-            $r = 'lt';
-        } else {
-            $r = 'eq';
-        }
-
-        $diff = $newValue - $oldValue;
-        if ($diff > 0) {
-            $diff = '+' . $diff;
-        }
-
-        $goodOrBad = 'neutral';
-        if ($lowIsBetter) {
-            if ($newValue > $oldValue) {
-                $goodOrBad = 'bad';
-            } else {
-                if ($newValue < $oldValue) {
-                    $goodOrBad = 'good';
-                }
-            }
-        }
-        if ($highIsBetter) {
-            if ($newValue > $oldValue) {
-                $goodOrBad = 'good';
-            } else {
-                if ($newValue < $oldValue) {
-                    $goodOrBad = 'bad';
-                }
-            }
-        }
-
-        return sprintf(
-            '<span title="Last value: %s" class="progress progress-%s progress-%s">%s %s</span>',
-            $oldValue,
-            $goodOrBad,
-            $r,
-            $diff,
-            $svg[$r]
-        );
-    }
-
-    /**
-     * @return bool
-     */
-    private function isHomePage()
-    {
-        return null === $this->currentGroup;
-    }
-}
diff --git a/src/Hal/Report/Json/Reporter.php b/src/Hal/Report/Json/Reporter.php
deleted file mode 100644
index 35637c4c..00000000
--- a/src/Hal/Report/Json/Reporter.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-
-namespace Hal\Report\Json;
-
-use Hal\Application\Config\Config;
-use Hal\Component\Output\Output;
-use Hal\Metric\Metrics;
-
-class Reporter
-{
-    /**
-     * @var Config
-     */
-    private $config;
-
-    /**
-     * @var Output
-     */
-    private $output;
-
-    /**
-     * @param Config $config
-     * @param Output $output
-     */
-    public function __construct(Config $config, Output $output)
-    {
-        $this->config = $config;
-        $this->output = $output;
-    }
-
-
-    public function generate(Metrics $metrics)
-    {
-        if ($this->config->has('quiet')) {
-            return;
-        }
-
-        $logFile = $this->config->get('report-json');
-        if (!$logFile) {
-            return;
-        }
-        if (!file_exists(dirname($logFile)) || !is_writable(dirname($logFile))) {
-            throw new \RuntimeException('You don\'t have permissions to write JSON report in ' . $logFile);
-        }
-
-        file_put_contents($logFile, json_encode($metrics, JSON_PRETTY_PRINT));
-    }
-}
diff --git a/src/Hal/Report/Json/SummaryReporter.php b/src/Hal/Report/Json/SummaryReporter.php
deleted file mode 100644
index e4dc7a26..00000000
--- a/src/Hal/Report/Json/SummaryReporter.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-namespace Hal\Report\Json;
-
-use Hal\Application\Config\Config;
-use Hal\Component\Output\Output;
-use Hal\Metric\Consolidated;
-use Hal\Metric\Metrics;
-use Hal\Report\SummaryProvider;
-
-class SummaryReporter
-{
-    /**
-     * @var Config
-     */
-    private $config;
-
-    /**
-     * @var Output
-     */
-    private $output;
-
-    /**
-     * @param Config $config
-     * @param Output $output
-     */
-    public function __construct(Config $config, Output $output)
-    {
-        $this->config = $config;
-        $this->output = $output;
-    }
-
-    public function generate(Metrics $metrics)
-    {
-        if ($this->config->has('quiet')) {
-            return;
-        }
-
-        $logFile = $this->config->get('report-summary-json');
-        if (!$logFile) {
-            return;
-        }
-        if (!file_exists(dirname($logFile)) || !is_writable(dirname($logFile))) {
-            throw new \RuntimeException('You don\'t have permissions to write JSON report in ' . $logFile);
-        }
-
-        $summaryWriter = new SummaryWriter($metrics, new Consolidated($metrics), $this->config);
-        file_put_contents($logFile, json_encode($summaryWriter->getReport(), JSON_PRETTY_PRINT));
-    }
-}
diff --git a/src/Hal/Report/Json/SummaryWriter.php b/src/Hal/Report/Json/SummaryWriter.php
deleted file mode 100644
index 993320c4..00000000
--- a/src/Hal/Report/Json/SummaryWriter.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-
-namespace Hal\Report\Json;
-
-use Hal\Report\SummaryProvider;
-
-class SummaryWriter extends SummaryProvider
-{
-    public function getReport()
-    {
-        return [
-            'LOC' => [
-                'linesOfCode' => $this->sum->loc,
-                'logicalLinesOfCode' => $this->sum->lloc,
-                'commentLinesOfCode' => $this->sum->cloc,
-                'avgVolume' => $this->avg->volume,
-                'avgCommentWeight' => $this->avg->commentWeight,
-                'avgIntelligentContent' => $this->avg->commentWeight,
-                'logicalLinesByClass' => $this->locByClass,
-                'logicalLinesByMethod' => $this->locByMethod,
-            ],
-            'OOP' => [
-                'classes' => $this->sum->nbClasses,
-                'interface' => $this->sum->nbInterfaces,
-                'methods' => $this->sum->nbMethods,
-                'methodsByClass' => $this->methodsByClass,
-                'lackCohesionOfMethods' => $this->avg->lcom,
-            ],
-            'Coupling' => [
-                'avgAfferentCoupling' => $this->avg->afferentCoupling,
-                'avgEfferentCoupling' => $this->avg->efferentCoupling,
-                'avgInstability' => $this->avg->instability,
-                'inheritanceTreeDepth' => $this->treeInheritenceDepth,
-            ],
-            'Package' => [
-                'packages' => $this->sum->nbPackages,
-                'acgClassesPerPackage' => $this->avg->classesPerPackage,
-                'avgDistance' => $this->avg->distance,
-                'avgIncomingClassDependencies' => $this->avg->incomingCDep,
-                'avgOutgoingClassDependencies' => $this->avg->outgoingCDep,
-                'avgIncomingPackageDependencies' => $this->avg->incomingPDep,
-                'avgOutgoingPackageDependencies' => $this->avg->outgoingPDep,
-            ],
-            'Complexity' => [
-                'avgCyclomaticComplexityByClass' => $this->avg->ccn,
-                'avgWeightedMethodCountByClass' => $this->avg->wmc,
-                'avgRelativeSystemComplexity' => $this->avg->relativeSystemComplexity,
-                'avgDifficulty' => $this->avg->difficulty,
-            ],
-            'Bugs' => [
-                'avgBugsByClass' => $this->avg->bugs,
-                'avgDefectsByClass' => $this->avg->kanDefect,
-            ],
-            'Violations' => [
-                'critical' => $this->sum->violations->critical,
-                'error' => $this->sum->violations->error,
-                'warning' => $this->sum->violations->warning,
-                'information' => $this->sum->violations->information,
-            ],
-        ];
-    }
-}
diff --git a/src/Hal/Report/SummaryProvider.php b/src/Hal/Report/SummaryProvider.php
deleted file mode 100644
index 0144adaf..00000000
--- a/src/Hal/Report/SummaryProvider.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-
-namespace Hal\Report;
-
-use Hal\Application\Config\Config;
-use Hal\Metric\Consolidated;
-use Hal\Metric\Metrics;
-
-abstract class SummaryProvider
-{
-    /**
-     * @var int
-     */
-    protected $methodsByClass = 0;
-
-    /**
-     * @var int
-     */
-    protected $locByClass = 0;
-
-    /**
-     * @var int
-     */
-    protected $locByMethod = 0;
-
-    /**
-     * @var object
-     */
-    protected $sum;
-
-    /**
-     * @var object
-     */
-    protected $avg;
-
-    /**
-     * @var mixed
-     */
-    protected $treeInheritenceDepth;
-
-    /**
-     * @var Consolidated
-     */
-    protected $consolidated;
-
-    /**
-     * @var Config
-     */
-    protected $config;
-
-    /**
-     * @var Metrics
-     */
-    protected $metrics;
-
-    public function __construct(Metrics $metrics, Consolidated $consolidated, Config $config)
-    {
-        $this->consolidated = $consolidated;
-        $this->config = $config;
-        $this->metrics = $metrics;
-        $this->sum = $consolidated->getSum();
-        $this->avg = $consolidated->getAvg();
-
-        // grouping results
-        if ($this->sum->nbClasses > 0) {
-            $this->methodsByClass = round($this->sum->nbMethods / $this->sum->nbClasses, 2);
-            $this->locByClass = round($this->sum->lloc / $this->sum->nbClasses);
-        }
-        if ($this->sum->nbMethods > 0) {
-            $this->locByMethod = round($this->sum->lloc / $this->sum->nbMethods);
-        }
-
-        $this->treeInheritenceDepth = $metrics->get('tree')->get('depthOfInheritanceTree');
-    }
-
-    abstract public function getReport();
-}
diff --git a/src/Hal/Report/Violations/Xml/Reporter.php b/src/Hal/Report/Violations/Xml/Reporter.php
deleted file mode 100644
index 11682dd4..00000000
--- a/src/Hal/Report/Violations/Xml/Reporter.php
+++ /dev/null
@@ -1,91 +0,0 @@
-<?php
-
-namespace Hal\Report\Violations\Xml;
-
-use Hal\Application\Config\Config;
-use Hal\Component\Output\Output;
-use Hal\Metric\Metrics;
-use Hal\Violation\Violation;
-
-class Reporter
-{
-    /**
-     * @var Config
-     */
-    private $config;
-
-    /**
-     * @var Output
-     */
-    private $output;
-
-    /**
-     * @param Config $config
-     * @param Output $output
-     */
-    public function __construct(Config $config, Output $output)
-    {
-        $this->config = $config;
-        $this->output = $output;
-    }
-
-
-    public function generate(Metrics $metrics)
-    {
-        if (!class_exists('\DOMDocument')) {
-            $this->output->writeln('<error>The DOM extension is not available. Please install it if you want to use the Xml Violations report.</error>');
-            return;
-        }
-
-        $logFile = $this->config->get('report-violations');
-        if (!$logFile) {
-            return;
-        }
-
-        // map of levels
-        $map = [
-            Violation::CRITICAL => 1,
-            Violation::ERROR => 2,
-            Violation::WARNING => 3,
-            Violation::INFO => 4,
-        ];
-
-        // root
-        $xml = new \DOMDocument("1.0", "UTF-8");
-        $xml->formatOutput = true;
-        $root = $xml->createElement("pmd");
-        $root->setAttribute('version', '@package_version@');
-        $root->setAttribute('timestamp', date('c'));
-
-        foreach ($metrics->all() as $metric) {
-            $violations = $metric->get('violations');
-            if (null === $violations || count($violations) == 0) {
-                continue;
-            }
-
-            $node = $xml->createElement('file');
-            $node->setAttribute('name', $metric->get('name'));
-
-            foreach ($violations as $violation) {
-                $item = $xml->createElement('violation');
-                $item->setAttribute('beginline', 1);
-                $item->setAttribute('rule', $violation->getName());
-                $item->setAttribute('ruleset', $violation->getName());
-                $item->setAttribute('externalInfoUrl', 'http://www.phpmetrics.org/documentation/index.html');
-                $item->setAttribute('priority', $map[$violation->getLevel()]);
-                $item->nodeValue = $violation->getDescription();
-                $node->appendChild($item);
-            }
-
-            $root->appendChild($node);
-        }
-
-        $xml->appendChild($root);
-
-        // save file
-        file_exists(dirname($logFile)) || mkdir(dirname($logFile), 0755, true);
-        file_put_contents($logFile, $xml->saveXML());
-
-        $this->output->writeln(sprintf('XML report generated in "%s"', $logFile));
-    }
-}
diff --git a/src/Hal/Search/PatternSearcher.php b/src/Hal/Search/PatternSearcher.php
deleted file mode 100644
index 34c311ef..00000000
--- a/src/Hal/Search/PatternSearcher.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-namespace Hal\Search;
-
-use Hal\Metric\Metrics;
-
-class PatternSearcher
-{
-    public function executes(Search $search, Metrics $metrics)
-    {
-        $found = [];
-        foreach ($metrics->all() as $metric) {
-            if (!$search->matches($metric)) {
-                continue;
-            }
-
-            $matched = [];
-            if ($metric->has('matched-searches')) {
-                $matched[] = $metric->get('matched-searches');
-            }
-            $matched[] = $search->getName();
-            $metric->set('matched-searches', $matched);
-
-
-            $found[] = $metric;
-        }
-
-        return $found;
-    }
-}
diff --git a/src/Hal/Search/Search.php b/src/Hal/Search/Search.php
deleted file mode 100644
index dec71bd7..00000000
--- a/src/Hal/Search/Search.php
+++ /dev/null
@@ -1,174 +0,0 @@
-<?php
-
-namespace Hal\Search;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\InterfaceMetric;
-use Hal\Metric\Metric;
-use Hal\Metric\Registry;
-
-class Search
-{
-    /**
-     * @var string
-     */
-    private $name;
-
-    /**
-     * @var array
-     */
-    private $config;
-
-    /**
-     * @param string $name
-     * @param array $config
-     */
-    public function __construct($name, array $config)
-    {
-        $this->name = $name;
-        $this->config = (object) $config;
-    }
-
-    /**
-     * @return string
-     */
-    public function getName()
-    {
-        return $this->name;
-    }
-
-    /**
-     * @return array
-     */
-    public function getConfig()
-    {
-        return $this->config;
-    }
-
-    public function matches(Metric $metric)
-    {
-        $configAsArray = (array) $this->config;
-
-        if (!empty($this->config->type)) {
-            // Does the search concerns type ?
-            if (!$this->matchExpectedType($metric, $this->config->type)) {
-                return false;
-            }
-        }
-
-        if (!empty($this->config->nameMatches)) {
-            // Does the search concerns name ?
-            if (!$this->matchExpectedName($metric, $this->config->nameMatches)) {
-                return false;
-            }
-        }
-
-        if (!empty($this->config->instanceOf)) {
-            // Does the search is instance of given class or interface ?
-            if (!$this->matchInstanceOf($metric, $this->config->instanceOf)) {
-                return false;
-            }
-        }
-
-
-        if (!empty($this->config->usesClasses)) {
-            // Does the search use some classes
-            if (!$this->usesClasses($metric, $this->config->usesClasses)) {
-                return false;
-            }
-        }
-
-        $registry = new Registry();
-        foreach ($registry->allForStructures() as $metricName) {
-            if (array_key_exists($metricName, $configAsArray)) {
-                // Does the search use some structures (ccn, etc. )
-                if (!$this->matchesMetric($metric, $metricName, $configAsArray[$metricName])) {
-                    return false;
-                }
-            }
-        }
-
-        // should be latest in checks
-        if (array_key_exists('failIfFound', $configAsArray)) {
-            if (true === $this->config->failIfFound) {
-                $metric->set('was-not-expected', true);
-                if (!$metric->has('was-not-expected-by')) {
-                    $metric->set('was-not-expected-by', []);
-                }
-                $bys = $metric->get('was-not-expected-by');
-                $bys[] = $this->name;
-                $metric->set('was-not-expected-by', $bys);
-            }
-        }
-
-        return true;
-    }
-
-    private function matchExpectedType(Metric $metric, $expectedType)
-    {
-        switch ($expectedType) {
-            case 'class':
-                return $metric instanceof ClassMetric && !$metric instanceof InterfaceMetric;
-            case 'interface':
-                return $metric instanceof InterfaceMetric;
-        }
-
-        return false;
-    }
-
-    private function matchExpectedName(Metric $metric, $expectedName)
-    {
-        return preg_match('@' . $expectedName . '@i', $metric->getName());
-    }
-
-    private function matchInstanceOf(Metric $metric, $instanceOf)
-    {
-        foreach ($instanceOf as $expectedInterface) {
-            $expectedInterface = ltrim($expectedInterface, '\\');
-            if (!in_array($expectedInterface, (array) $metric->get('implements'))) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    private function usesClasses(Metric $metric, $usesClasses)
-    {
-        foreach ($usesClasses as $expectedClass) {
-            foreach ((array) $metric->get('externals') as $use) {
-                if (preg_match('@' . $expectedClass . '@i', $use)) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    private function matchesMetric(Metric $metric, $metricName, $metricValue)
-    {
-        if (!preg_match_all('!^([=><]*)([\d\.]+)!', $metricValue, $matches, PREG_SET_ORDER)) {
-            throw new \LogicException('Invalid search expression for key ' . $metricValue);
-        }
-        list(, $operator, $expected) = $matches[0];
-
-        switch ($operator) {
-            case '=':
-            case '':
-                return $metric->get($metricName) == $expected; // do not use === here
-            case '>':
-                return $metric->get($metricName) > $expected;
-            case '<':
-                return $metric->get($metricName) < $expected;
-            case '>=':
-            case '=>':
-                return $metric->get($metricName) >= $expected;
-            case '<=':
-            case '=<':
-                return $metric->get($metricName) <= $expected;
-        }
-
-        return false;
-    }
-}
diff --git a/src/Hal/Search/Searches.php b/src/Hal/Search/Searches.php
deleted file mode 100644
index 817ecc9e..00000000
--- a/src/Hal/Search/Searches.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-namespace Hal\Search;
-
-class Searches
-{
-    /**
-     * @var array
-     */
-    private $searches = [];
-
-    /**
-     * @param Search $search
-     * @return $this
-     */
-    public function add(Search $search)
-    {
-        $this->searches[$search->getName()] = $search;
-        return $this;
-    }
-
-    /**
-     * @param $name
-     * @return Search|null
-     */
-    public function get($name)
-    {
-        return $this->has($name) ? $this->searches[$name] : null;
-    }
-
-    /**
-     * @param $name
-     * @return bool
-     */
-    public function has($name)
-    {
-        return isset($this->searches[$name]);
-    }
-
-    /**
-     * @return array
-     */
-    public function all()
-    {
-        return $this->searches;
-    }
-}
diff --git a/src/Hal/Search/SearchesFactory.php b/src/Hal/Search/SearchesFactory.php
deleted file mode 100644
index b3a08b6a..00000000
--- a/src/Hal/Search/SearchesFactory.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-namespace Hal\Search;
-
-class SearchesFactory
-{
-    /**
-     * @param array $data
-     * @return Searches
-     */
-    public function factory(array $data)
-    {
-        $searches = new Searches();
-
-        foreach ($data as $name => $search) {
-            $searches->add(new Search($name, $search));
-        }
-
-        return $searches;
-    }
-}
diff --git a/src/Hal/Search/SearchesValidator.php b/src/Hal/Search/SearchesValidator.php
deleted file mode 100644
index f7014623..00000000
--- a/src/Hal/Search/SearchesValidator.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-
-namespace Hal\Search;
-
-use Hal\Application\Config\ConfigException;
-use Hal\Metric\Registry;
-
-class SearchesValidator
-{
-    public function validates(Searches $searches)
-    {
-        foreach ($searches->all() as $search) {
-            $config = $search->getConfig();
-
-            $allowedKeys = [
-                'type',
-                'nameMatches',
-                'instanceOf',
-                'usesClasses',
-                'failIfFound',
-            ];
-            $registry = new Registry();
-            $allowedKeys = array_merge($allowedKeys, $registry->allForStructures());
-
-            $diff = array_diff(array_keys((array) $config), $allowedKeys);
-            if (count($diff) > 0) {
-                throw new ConfigException(
-                    sprintf(
-                        'Invalid config for search "%s". Allowed keys are {%s}',
-                        $search->getName(),
-                        implode(', ', $allowedKeys)
-                    )
-                );
-            }
-
-            if (isset($config->type) && !in_array($config->type, ['class', 'interface'])) {
-                throw new ConfigException('Invalid config for "type". Should be "class" or "interface"');
-            }
-
-            if (isset($config->nameMatches) && !is_string($config->nameMatches)) {
-                throw new ConfigException('Invalid config for "nameMatches". Should be a regex');
-            }
-
-            if (isset($config->instanceOf) && !is_array($config->instanceOf)) {
-                throw new ConfigException('Invalid config for "instanceOf". Should be an array of classnames');
-            }
-
-            // usesMatches
-            if (isset($config->usesClasses) && !is_array($config->usesClasses)) {
-                throw new ConfigException('Invalid config for "usesClasses". Should be a, array of classnames or regexes matching classnames');
-            }
-        }
-    }
-}
diff --git a/src/Hal/Violation/Class_/Blob.php b/src/Hal/Violation/Class_/Blob.php
deleted file mode 100644
index b90f0bdf..00000000
--- a/src/Hal/Violation/Class_/Blob.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-namespace Hal\Violation\Class_;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metric;
-use Hal\Violation\Violation;
-
-class Blob implements Violation
-{
-    /**
-     * @inheritdoc
-     */
-    public function getName()
-    {
-        return 'Blob / God object';
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function apply(Metric $metric)
-    {
-        if (!$metric instanceof ClassMetric) {
-            return;
-        }
-
-        $this->metric = $metric;
-
-        $suspect = 0;
-        if ($metric->get('nbMethodsPublic') >= 8) {
-            $suspect++;
-        }
-
-        if ($metric->get('lcom') >= 3) {
-            $suspect++;
-        }
-
-        if (count($metric->get('externals')) >= 8) {
-            $suspect++;
-        }
-
-        if ($suspect >= 3) {
-            $metric->get('violations')->add($this);
-        }
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function getLevel()
-    {
-        return Violation::ERROR;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function getDescription()
-    {
-        return <<<EOT
-            A blob object (or "god class") does not follow the Single responsibility principle.
-
-            * object has lot of public methods  ({$this->metric->get('nbMethodsPublic')}, excluding getters and setters)
-            * object has a high Lack of cohesion of methods (LCOM={$this->metric->get('lcom')})
-            * object knows everything (and use lot of external classes)
-
-            Maybe you should reducing the number of methods splitting this object in many sub objects.
-EOT;
-    }
-}
diff --git a/src/Hal/Violation/Class_/ProbablyBugged.php b/src/Hal/Violation/Class_/ProbablyBugged.php
deleted file mode 100644
index 1b12fa26..00000000
--- a/src/Hal/Violation/Class_/ProbablyBugged.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-
-namespace Hal\Violation\Class_;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metric;
-use Hal\Violation\Violation;
-
-class ProbablyBugged implements Violation
-{
-    /**
-     * @inheritdoc
-     */
-    public function getName()
-    {
-        return 'Probably bugged';
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function apply(Metric $metric)
-    {
-        if (!$metric instanceof ClassMetric) {
-            return;
-        }
-
-        $this->metric = $metric;
-
-        $suspect = 0;
-        if ($metric->get('bugs') >= .35) {
-            $metric->get('violations')->add($this);
-            return;
-        }
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function getLevel()
-    {
-        return Violation::WARNING;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function getDescription()
-    {
-        return <<<EOT
-            This component contains in theory {$this->metric->get('bugs')} bugs.
-
-            * Calculation is based on number of operators, operands, cyclomatic complexity
-            * See more details at https://en.wikipedia.org/wiki/Halstead_complexity_measures
-            * {$this->metric->get('numberOfUnitTests')} testsuites has dependency to this class.
-
-            Maybe you should check your unit tests for this class.
-EOT;
-    }
-}
diff --git a/src/Hal/Violation/Class_/TooComplexClassCode.php b/src/Hal/Violation/Class_/TooComplexClassCode.php
deleted file mode 100644
index d772b003..00000000
--- a/src/Hal/Violation/Class_/TooComplexClassCode.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-
-namespace Hal\Violation\Class_;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metric;
-use Hal\Violation\Violation;
-
-/**
- * 50 as a threshold seems to be widely accepted in open source metric tools.
- *
- * @see http://staff.unak.is/andy/StaticAnalysis0809/metrics/wmc.html
- * @see https://github.com/phpmd/phpmd/blob/f1c145e538d7cf8c2d1a45fd8fb723eca64005f4/src/main/resources/rulesets/codesize.xml#L390
- */
-class TooComplexClassCode implements Violation
-{
-    /** @var Metric|null */
-    private $metric;
-
-    public function getName()
-    {
-        return 'Too complex class code';
-    }
-
-    public function apply(Metric $metric)
-    {
-        if (! $metric instanceof ClassMetric) {
-            return;
-        }
-
-        $this->metric = $metric;
-
-        if ($metric->get('wmc') > 50) {
-            $metric->get('violations')->add($this);
-        }
-    }
-
-    public function getLevel()
-    {
-        return Violation::ERROR;
-    }
-
-    public function getDescription()
-    {
-        return <<<EOT
-            This class looks really complex.
-
-            * Algorithms are complex (Total cyclomatic complexity of class is {$this->metric->get('ccn')})
-            * Component uses {$this->metric->get('number_operators')} operators
-
-            Maybe you should delegate some code to other objects.
-EOT;
-    }
-}
diff --git a/src/Hal/Violation/Class_/TooComplexMethodCode.php b/src/Hal/Violation/Class_/TooComplexMethodCode.php
deleted file mode 100644
index 38e9274b..00000000
--- a/src/Hal/Violation/Class_/TooComplexMethodCode.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
-namespace Hal\Violation\Class_;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metric;
-use Hal\Violation\Violation;
-
-/**
- * According to McCabe,
- *
- *  The particular upper bound that has been used for cyclomatic complexity is 10
- *  which seems like a reasonable, but not magical, upper limit.
- *
- * @see http://www.literateprogramming.com/mccabe.pdf
- */
-class TooComplexMethodCode implements Violation
-{
-    /** @var Metric|null */
-    private $metric;
-
-    public function getName()
-    {
-        return 'Too complex method code';
-    }
-
-    public function apply(Metric $metric)
-    {
-        if (! $metric instanceof ClassMetric) {
-            return;
-        }
-
-        $this->metric = $metric;
-
-        if ($metric->get('ccnMethodMax') > 10) {
-            $metric->get('violations')->add($this);
-            return;
-        }
-    }
-
-    public function getLevel()
-    {
-        return Violation::ERROR;
-    }
-
-    public function getDescription()
-    {
-        return <<<EOT
-            This class looks really complex.
-
-            * Algorithms are complex (Max cyclomatic complexity of class methods is {$this->metric->get('ccnMethodMax')})
-
-            Maybe you should delegate some code to other objects or split complex method.
-EOT;
-    }
-}
diff --git a/src/Hal/Violation/Class_/TooDependent.php b/src/Hal/Violation/Class_/TooDependent.php
deleted file mode 100644
index 60d3fbfb..00000000
--- a/src/Hal/Violation/Class_/TooDependent.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-
-namespace Hal\Violation\Class_;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metric;
-use Hal\Violation\Violation;
-
-class TooDependent implements Violation
-{
-    /**
-     * @inheritdoc
-     */
-    public function getName()
-    {
-        return 'Too dependent';
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function apply(Metric $metric)
-    {
-        if (!$metric instanceof ClassMetric) {
-            return;
-        }
-
-        $this->metric = $metric;
-
-        if ($metric->get('efferentCoupling') >= 20) {
-            $metric->get('violations')->add($this);
-            return;
-        }
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function getLevel()
-    {
-        return Violation::INFO;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function getDescription()
-    {
-        return <<<EOT
-            This class looks use really high number of components.
-
-            * Efferent coupling is {$this->metric->get('efferentCoupling')}, so this class uses {$this->metric->get('efferentCoupling')} different external components.
-
-            Maybe you should check why this class has lot of dependencies.
-EOT;
-    }
-}
diff --git a/src/Hal/Violation/Class_/TooLong.php b/src/Hal/Violation/Class_/TooLong.php
deleted file mode 100644
index 7d3ef77a..00000000
--- a/src/Hal/Violation/Class_/TooLong.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-
-namespace Hal\Violation\Class_;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metric;
-use Hal\Violation\Violation;
-
-class TooLong implements Violation
-{
-    /**
-     * @inheritdoc
-     */
-    public function getName()
-    {
-        return 'Too long';
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function apply(Metric $metric)
-    {
-        if (!$metric instanceof ClassMetric) {
-            return;
-        }
-
-        $this->metric = $metric;
-
-        if ($metric->get('lloc') >= 200) {
-            $metric->get('violations')->add($this);
-        }
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function getLevel()
-    {
-        return Violation::INFO;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function getDescription()
-    {
-        return <<<EOT
-            This class looks really long.
-
-            * Class has {$this->metric->get('lloc')} logical lines of code
-            * Class has {$this->metric->get('loc')} lines of code
-
-            Maybe your class should not exceed 200 lines of logical code
-EOT;
-    }
-}
diff --git a/src/Hal/Violation/Package/StableAbstractionsPrinciple.php b/src/Hal/Violation/Package/StableAbstractionsPrinciple.php
deleted file mode 100644
index c5894b11..00000000
--- a/src/Hal/Violation/Package/StableAbstractionsPrinciple.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-namespace Hal\Violation\Package;
-
-use Hal\Metric\Metric;
-use Hal\Metric\PackageMetric;
-use Hal\Violation\Violation;
-
-class StableAbstractionsPrinciple implements Violation
-{
-    /** @var PackageMetric|null */
-    private $metric;
-
-    public function getName()
-    {
-        return 'Stable Abstractions Principle';
-    }
-
-    public function apply(Metric $metric)
-    {
-        if (! $metric instanceof PackageMetric) {
-            return;
-        }
-        if (abs($metric->getDistance()) > sqrt(2) / 4) {
-            $this->metric = $metric;
-            $metric->get('violations')->add($this);
-        }
-    }
-
-    public function getLevel()
-    {
-        return Violation::WARNING;
-    }
-
-    public function getDescription()
-    {
-        $violation = $this->metric->getDistance() > 0
-            ? 'instable and abstract'
-            : 'stable and concrete';
-
-        return <<<EOT
-            Packages should be either abstract and stable or concrete and instable.
-
-            This package is {$violation}.
-EOT;
-    }
-}
diff --git a/src/Hal/Violation/Package/StableDependenciesPrinciple.php b/src/Hal/Violation/Package/StableDependenciesPrinciple.php
deleted file mode 100644
index 789d5b1c..00000000
--- a/src/Hal/Violation/Package/StableDependenciesPrinciple.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-
-namespace Hal\Violation\Package;
-
-use Hal\Metric\Metric;
-use Hal\Metric\PackageMetric;
-use Hal\Violation\Violation;
-
-class StableDependenciesPrinciple implements Violation
-{
-    /** @var PackageMetric|null */
-    private $metric;
-
-    /** @var array */
-    private $violatingInstabilities = [];
-
-    public function getName()
-    {
-        return 'Stable Dependencies Principle';
-    }
-
-    public function apply(Metric $metric)
-    {
-        if (! $metric instanceof PackageMetric) {
-            return;
-        }
-        $instability = $metric->getInstability();
-        $violatingInstabilities = array_filter(
-            $metric->getDependentInstabilities(),
-            function ($otherInstability) use ($instability) {
-                return $otherInstability >= $instability;
-            }
-        );
-        if (count($violatingInstabilities) > 0) {
-            $this->violatingInstabilities = $violatingInstabilities;
-            $this->metric = $metric;
-            $metric->get('violations')->add($this);
-        }
-    }
-
-    public function getLevel()
-    {
-        return Violation::WARNING;
-    }
-
-    public function getDescription()
-    {
-        $count = count($this->violatingInstabilities);
-        $thisInstability = round($this->metric->getInstability(), 3);
-        $packages = implode("\n* ", array_map(function ($name, $instability) {
-            $name = $name === '\\' ? 'global' : substr($name, 0, -1);
-            $instability = round($instability, 3);
-            return "$name ($instability)";
-        }, array_keys($this->violatingInstabilities), $this->violatingInstabilities));
-        return <<<EOT
-            Packages should depend in the direction of stability.
-
-            This package is more stable ({$thisInstability}) than {$count} package(s) that it depends on.
-            The packages that are more stable are
-
-            * {$packages}
-EOT;
-    }
-}
diff --git a/src/Hal/Violation/Search/SearchShouldNotBeFoundPrinciple.php b/src/Hal/Violation/Search/SearchShouldNotBeFoundPrinciple.php
deleted file mode 100644
index a6a84cc5..00000000
--- a/src/Hal/Violation/Search/SearchShouldNotBeFoundPrinciple.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-namespace Hal\Violation\Search;
-
-use Hal\Metric\Metric;
-use Hal\Violation\Violation;
-
-class SearchShouldNotBeFoundPrinciple implements Violation
-{
-    private $concernedSearches = [];
-
-    public function getName()
-    {
-        return implode(', ', $this->concernedSearches);
-    }
-
-    public function apply(Metric $metric)
-    {
-        if ($metric->has('was-not-expected') && $metric->get('was-not-expected')) {
-            $this->concernedSearches = array_unique(
-                array_merge(
-                    $this->concernedSearches,
-                    $metric->get('was-not-expected-by')
-                )
-            );
-            $metric->get('violations')->add($this);
-        }
-    }
-
-    public function getLevel()
-    {
-        return Violation::CRITICAL;
-    }
-
-    public function getDescription()
-    {
-        return 'According configuration, this component is not expected to be found in the code.';
-    }
-}
diff --git a/src/Hal/Violation/Violation.php b/src/Hal/Violation/Violation.php
deleted file mode 100644
index d5935d85..00000000
--- a/src/Hal/Violation/Violation.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-namespace Hal\Violation;
-
-use Hal\Metric\Metric;
-
-interface Violation
-{
-    const INFO = 0;
-    const WARNING = 1;
-    const ERROR = 2;
-    const CRITICAL = 3;
-
-    /**
-     * @return string
-     */
-    public function getName();
-
-    /**
-     * @param Metric $metric
-     */
-    public function apply(Metric $metric);
-
-    /**
-     * @return integer
-     */
-    public function getLevel();
-
-    /**
-     * @return string
-     */
-    public function getDescription();
-}
diff --git a/src/Hal/Violation/ViolationParser.php b/src/Hal/Violation/ViolationParser.php
deleted file mode 100644
index 0ccc049d..00000000
--- a/src/Hal/Violation/ViolationParser.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-namespace Hal\Violation;
-
-use Hal\Metric\Metrics;
-use Hal\Violation\Class_;
-use Hal\Violation\Package;
-use Hal\Violation\Search\SearchShouldNotBeFoundPrinciple;
-
-class ViolationParser
-{
-    /**
-     * @param Metrics $metrics
-     * @return $this
-     */
-    public function apply(Metrics $metrics)
-    {
-        $violations = [
-            new Class_\Blob(),
-            new Class_\TooComplexClassCode(),
-            new Class_\TooComplexMethodCode(),
-            new Class_\ProbablyBugged(),
-            new Class_\TooLong(),
-            new Class_\TooDependent(),
-            new Package\StableAbstractionsPrinciple(),
-            new Package\StableDependenciesPrinciple(),
-            new SearchShouldNotBeFoundPrinciple(),
-        ];
-
-        foreach ($metrics->all() as $metric) {
-            $metric->set('violations', new Violations());
-
-            foreach ($violations as $violation) {
-                $violation->apply($metric);
-            }
-        }
-
-        return $this;
-    }
-}
diff --git a/src/Hal/Violation/Violations.php b/src/Hal/Violation/Violations.php
deleted file mode 100644
index 91ae0193..00000000
--- a/src/Hal/Violation/Violations.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-namespace Hal\Violation;
-
-/**
- * @package Hal\Violation
- */
-class Violations implements \IteratorAggregate, \Countable
-{
-    /**
-     * @var array
-     */
-    private $data = [];
-
-    /**
-     * @inheritdoc
-     */
-    #[\ReturnTypeWillChange]
-    public function getIterator()
-    {
-        return new \ArrayIterator($this->data);
-    }
-
-    /**
-     * @param Violation $violation
-     */
-    public function add(Violation $violation)
-    {
-        $this->data[] = clone $violation;
-    }
-
-    /**
-     * @return int
-     */
-    #[\ReturnTypeWillChange]
-    public function count()
-    {
-        return count($this->data);
-    }
-
-    /**
-     * @return string
-     */
-    public function __toString()
-    {
-        $string = '';
-        foreach ($this->data as $violation) {
-            $string .= $violation->getName() . ',';
-        }
-        return $string;
-    }
-}
diff --git a/src/functions.php b/src/functions.php
deleted file mode 100644
index 208cd98d..00000000
--- a/src/functions.php
+++ /dev/null
@@ -1,239 +0,0 @@
-<?php
-
-class MyVisitor extends \PhpParser\NodeVisitorAbstract
-{
-    /**
-     * @var
-     */
-    private $callback;
-
-    /**
-     * @param $callback
-     */
-    public function __construct($callback)
-    {
-        $this->callback = $callback;
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function leaveNode(\PhpParser\Node $node)
-    {
-        call_user_func($this->callback, $node);
-    }
-}
-
-/**
- * @param $node
- * @param $callback
- */
-function iterate_over_node($node, $callback)
-{
-    /*
-         // way 2
-         foreach ($node->getSubNodeNames() as $name) {
-             $subNode = $node->$name;
-
-
-
-             if ($subNode instanceof \PhpParser\Node) {
-
-                 return iterate_over_node($node, $callback);
-             }
-
-             if (is_array($subNode)) {
-                 foreach ($subNode as $sub) {
-                     return iterate_over_node($sub, $callback);
-                 }
-             }
-
-                 return $callback($node);
-         }
-
-         return $callback($node);
-    */
-
-    /*
-        // way 1
-        static $traverser;
-        if (!isset($traverser)) {
-            $myVisitor = new MyVisitor($callback);
-            $traverser = new \PhpParser\NodeTraverser();
-            $traverser->addVisitor($myVisitor);
-        }
-        $traverser->traverse(array($node));
-        return;
-    */
-
-    // way 1
-    $myVisitor = new MyVisitor($callback);
-    $traverser = new \PhpParser\NodeTraverser();
-    $traverser->addVisitor($myVisitor);
-    $traverser->traverse([$node]);
-    return;
-}
-
-/**
- * @param $node
- * @return string|null
- */
-function getNameOfNode($node)
-{
-    if (is_string($node)) {
-        return $node;
-    }
-
-    if (isset($node->namespacedName) && null !== $node->namespacedName) {
-        // Return the fully qualified name of the class, interface, or trait
-        return (string) $node->namespacedName;
-    }
-
-    if ($node instanceof \PhpParser\Node\Name\FullyQualified) {
-        return (string) $node;
-    }
-
-    if ($node instanceof \PhpParser\Node\Expr\New_) {
-        return getNameOfNode($node->class);
-    }
-
-    if (isset($node->class)) {
-        return getNameOfNode($node->class);
-    }
-
-    if ($node instanceof \PhpParser\Node\Name) {
-        if(!property_exists($node, 'parts') || null === $node->parts) {
-            return (string) $node->name;
-        }
-        return (string) implode($node->parts);
-    }
-
-    if (isset($node->name) && $node->name instanceof \PhpParser\Node\Expr\Variable) {
-        return getNameOfNode($node->name);
-    }
-
-    if (isset($node->name) && $node->name instanceof \PhpParser\Node\Expr\MethodCall) {
-        return getNameOfNode($node->name);
-    }
-
-    if ($node instanceof \PhpParser\Node\Expr\ArrayDimFetch) {
-        return getNameOfNode($node->var);
-    }
-
-    if (isset($node->name) && $node->name instanceof \PhpParser\Node\Expr\BinaryOp) {
-        return get_class($node->name);
-    }
-
-    if ($node instanceof \PhpParser\Node\Expr\PropertyFetch) {
-        return getNameOfNode($node->var);
-    }
-
-    if (isset($node->name) && !is_string($node->name)) {
-        return getNameOfNode($node->name);
-    }
-
-    // do not use isset here, we want to check if property is set
-    if (property_exists($node, 'name') && null === $node->name) {
-        return 'anonymous@' . spl_object_hash($node);
-    }
-
-    if (isset($node->name)) {
-        return (string) $node->name;
-    }
-
-    return null;
-}
-
-/**
- * @param $src
- * @param $dst
- */
-function recurse_copy($src, $dst)
-{
-    $dir = opendir($src);
-    if (!file_exists($dst)) {
-        mkdir($dst);
-    }
-    while (false !== ($file = readdir($dir))) {
-        if (($file != '.') && ($file != '..')) {
-            if (is_dir($src . '/' . $file)) {
-                recurse_copy($src . '/' . $file, $dst . '/' . $file);
-            } else {
-                copy($src . '/' . $file, $dst . '/' . $file);
-            }
-        }
-    }
-    closedir($dir);
-}
-
-/**
- * @return string
- */
-function getVersion()
-{
-    return 'v2.9.0';
-}
-
-/**
- * @param array $array
- * @param string $attribute
- * @param mixed $currentValue
- * @return false|float
- */
-function gradientAlphaFor($array, $attribute, $currentValue)
-{
-    // memory cache
-    static $caches;
-    if (null === $caches) {
-        $caches = [];
-    }
-
-    if (!isset($caches[$attribute])) {
-        // avoid to iterate over array too many times
-        $max = 0;
-        $min = 1;
-        foreach ($array as $item) {
-            if (!isset($item[$attribute])) {
-                continue;
-            }
-
-            $max = max($max, $item[$attribute]);
-            $min = min($min, $item[$attribute]);
-        }
-
-        $caches[$attribute]['max'] = $max;
-        $caches[$attribute]['min'] = $min;
-    }
-
-    $max = $caches[$attribute]['max'];
-    $min = $caches[$attribute]['min'];
-
-    $percent = (($currentValue - $min) * 100) / (max(1, $max - $min));
-    return round($percent / 100, 2);
-}
-
-/**
- * Style an element according its position in range
- *
- * @param array $array
- * @param string $attribute
- * @param mixed $currentValue
- * @return string
- */
-function gradientStyleFor($array, $attribute, $currentValue)
-{
-    return sprintf(' style="background-color: hsla(203, 82%%, 76%%, %s);"', gradientAlphaFor($array, $attribute, $currentValue));
-}
-
-/**
- * Calculate percentalies
- *
- * @param float[]|int[] $arr
- * @param float $percentile
- * @return mixed
- */
-function percentile($arr, $percentile = 0.95)
-{
-    sort($arr);
-    return $arr[max(round($percentile * count($arr) - 1.0 - $percentile), 0)];
-}
diff --git a/templates/html_report/_footer.php b/templates/html_report/_footer.php
deleted file mode 100644
index c073d117..00000000
--- a/templates/html_report/_footer.php
+++ /dev/null
@@ -1,199 +0,0 @@
-</div>
-
-<!-- Sidebar -->
-<?php if(!isset($fullwidth) || $fullwidth === false) {?>
-<div id="sidebar">
-    <div class="content">
-        <div class="logo">
-            <a href="index.html"><img src="<?php echo $this->assetPath;?>images/phpmetrics-maintenability.png"
-                                                 alt="Logo PhpMetrics"></a>
-            <h1>PhpMetrics</h1>
-        </div>
-        <div class="links">
-            <ul>
-                <li>
-                    <a href="index.html">
-                        <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24"
-                             xmlns="http://www.w3.org/2000/svg">
-                            <path d="M0 0h24v24H0z" fill="none">
-                            <path
-                                d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z">
-                        </svg>
-                        Overview
-                    </a>
-                </li>
-                <li>
-                    <a href="violations.html">
-                        <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
-                            <path d="M0 0h24v24H0z" fill="none">
-                            <path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z">
-                        </svg>
-                        Violations (<?php echo $sum->violations->total;?>)
-                    </a>
-                </li>
-                <?php if($this->isHomePage()) {?>
-                    <li>
-                        <a href="composer.html">
-                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="24px" height="24px"><path d="M0 0h24v24H0z" fill="none"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"></svg>
-                            Composer
-                        </a>
-                    </li>
-                <?php } ?>
-                <?php if($this->isHomePage() && $config->has('junit')) { ?>
-                    <li>
-                        <a href="junit.html">
-                            <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
-                                <path d="M14 5h8v2h-8zm0 5.5h8v2h-8zm0 5.5h8v2h-8zM2 11.5C2 15.08 4.92 18 8.5 18H9v2l3-3-3-3v2h-.5C6.02 16 4 13.98 4 11.5S6.02 7 8.5 7H12V5H8.5C4.92 5 2 7.92 2 11.5z">
-                                <path d="M0 0h24v24H0z" fill="none">
-                            </svg>
-                            Unit testing
-                        </a>
-                    </li>
-                <?php } ?>
-                <li>
-                    <a href="loc.html">
-                        <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24"
-                             xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-                            <defs>
-                                <path d="M0 0h24v24H0z" id="a">
-                            </defs>
-                            <clipPath id="b">
-                                <use overflow="visible" xlink:href="#a">
-                            </clipPath>
-                            <path clip-path="url(#b)"
-                                  d="M11 5.08V2c-5 .5-9 4.81-9 10s4 9.5 9 10v-3.08c-3-.48-6-3.4-6-6.92s3-6.44 6-6.92zM18.97 11H22c-.47-5-4-8.53-9-9v3.08C16 5.51 18.54 8 18.97 11zM13 18.92V22c5-.47 8.53-4 9-9h-3.03c-.43 3-2.97 5.49-5.97 5.92z">
-                        </svg>
-                        Size &amp; volume
-                    </a>
-                </li>
-                <li>
-                    <a href="complexity.html">
-                        <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24"
-                             xmlns="http://www.w3.org/2000/svg">
-                            <path d="M0 0h24v24H0V0z" fill="none">
-                            <path
-                                d="M19.07 4.93l-1.41 1.41C19.1 7.79 20 9.79 20 12c0 4.42-3.58 8-8 8s-8-3.58-8-8c0-4.08 3.05-7.44 7-7.93v2.02C8.16 6.57 6 9.03 6 12c0 3.31 2.69 6 6 6s6-2.69 6-6c0-1.66-.67-3.16-1.76-4.24l-1.41 1.41C15.55 9.9 16 10.9 16 12c0 2.21-1.79 4-4 4s-4-1.79-4-4c0-1.86 1.28-3.41 3-3.86v2.14c-.6.35-1 .98-1 1.72 0 1.1.9 2 2 2s2-.9 2-2c0-.74-.4-1.38-1-1.72V2h-1C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10c0-2.76-1.12-5.26-2.93-7.07z">
-                        </svg>
-                        Complexity &amp; defects
-                    </a>
-                </li>
-                <li>
-                    <a href="oop.html">
-                        <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24"
-                             xmlns="http://www.w3.org/2000/svg">
-                            <path d="M0 0h24v24H0z" fill="none">
-                            <path
-                                d="M17 6c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zM5 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z">
-                        </svg>
-                        Object oriented metrics
-                    </a>
-                </li>
-                <li>
-                    <a href="relations.html">
-                        <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24"
-                             xmlns="http://www.w3.org/2000/svg">
-                            <path d="M0 0h24v24H0z" fill="none">
-                            <path
-                                d="M14 4l2.29 2.29-2.88 2.88 1.42 1.42 2.88-2.88L20 10V4zm-4 0H4v6l2.29-2.29 4.71 4.7V20h2v-8.41l-5.29-5.3z">
-                        </svg>
-                        Object relations
-                    </a>
-                </li>
-                <li>
-                    <a href="coupling.html">
-                        <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24"
-                             xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-                            <defs>
-                                <path d="M0 0h24v24H0V0z" id="a">
-                            </defs>
-                            <clipPath id="b">
-                                <use overflow="visible" xlink:href="#a">
-                            </clipPath>
-                            <path clip-path="url(#b)"
-                                  d="M9.01 14H2v2h7.01v3L13 15l-3.99-4v3zm5.98-1v-3H22V8h-7.01V5L11 9l3.99 4z">
-                        </svg>
-                        Coupling
-                    </a>
-                </li>
-                <li>
-                    <a href="packages.html">
-                        <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24"
-                             xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-                            <path d="M11 9.16V2c-5 .5-9 4.79-9 10s4 9.5 9 10v-7.16c-1-.41-2-1.52-2-2.84s1-2.43 2-2.84zM14.86 11H22c-.48-4.75-4-8.53-9-9v7.16c1 .3 1.52.98 1.86 1.84zM13 14.84V22c5-.47 8.52-4.25 9-9h-7.14c-.34.86-.86 1.54-1.86 1.84z">
-                        </svg>
-                        Package oriented metrics
-                    </a>
-                </li>
-                <li>
-                    <a href="package_relations.html">
-                        <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24"
-                             xmlns="http://www.w3.org/2000/svg">
-                            <path d="M17 20.41L18.41 19 15 15.59 13.59 17 17 20.41zM7.5 8H11v5.59L5.59 19 7 20.41l6-6V8h3.5L12 3.5 7.5 8z">
-                        </svg>
-                        Package relations
-                    </a>
-                </li>
-                <?php if($this->isHomePage() && $config->has('git')) { ?>
-                <li>
-                    <a href="git.html">
-                        <img src="images/logo-git.png" alt="">
-                        Git
-                    </a>
-                </li>
-                <?php } ?>
-                <!--<li>
-                    <a href="all.html">
-                        <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24"
-                             xmlns="http://www.w3.org/2000/svg">
-                            <path d="M3 3v18h18V3H3zm8 16H5v-6h6v6zm0-8H5V5h6v6zm8 8h-6v-6h6v6zm0-8h-6V5h6v6z">
-                            <path d="M0 0h24v24H0z" fill="none">
-                        </svg>
-                        All metrics
-                    </a>
-                </li>-->
-                <!--                <li>-->
-                <!--                    <a href="#">-->
-                <!--                        <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24"-->
-                <!--                             xmlns="http://www.w3.org/2000/svg">-->
-                <!--                            <path-->
-                <!--                                d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z">-->
-                <!--                            <path d="M0 0h24v24H0z" fill="none">-->
-                <!--                        </svg>-->
-                <!--                        Third party-->
-                <!--                    </a>-->
-                <!--                </li>-->
-                <!--<li class="sep">
-                    <a href="panel.html">
-                        <svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
-                            <path d="M0 0h24v24H0z" fill="none">
-                            <path d="M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12z">
-                        </svg>
-                        TV Panel
-                    </a>
-                </li>-->
-            </ul>
-        </div>
-    </div>
-</div>
-<?php } ?>
-</div>
-
-<script src="<?php echo $this->assetPath; ?>js/functions.js?v=<?php echo getVersion(); ?>"></script>
-<script src="<?php echo $this->assetPath; ?>js/d3.v3.js"></script>
-<script src="<?php echo $this->assetPath; ?>js/d3.hexbin.v0.js"></script>
-<script src="<?php echo $this->assetPath; ?>js/sort-table.min.js?v=<?php echo getVersion(); ?>"></script>
-<script src="<?php echo $this->assetPath; ?>js/graph-maintainability.js?v=<?php echo getVersion(); ?>"></script>
-<script src="<?php echo $this->assetPath; ?>js/graph-licenses.js?v=<?php echo getVersion(); ?>"></script>
-<script src="<?php echo $this->assetPath; ?>js/FileSaver.min.js?v=<?php echo getVersion(); ?>"></script>
-
-<script src="<?php echo $this->assetPath; ?>js/clusterize.min.js?v=<?php echo getVersion(); ?>"></script>
-<link rel="stylesheet" href="<?php echo $this->assetPath; ?>css/clusterize.css?v=<?php echo getVersion(); ?>">
-
-<script src="classes.js?v=<?php echo getVersion(); ?>"></script>
-
-<script>
-    var accessibilityEnabled = false;
-</script>
-
-</body>
-</html>
diff --git a/templates/html_report/_header.php b/templates/html_report/_header.php
deleted file mode 100644
index 87baa2da..00000000
--- a/templates/html_report/_header.php
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <title>PhpMetrics report</title>
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="stylesheet" href="<?php echo $this->assetPath; ?>css/milligram.min.css?v=<?php echo getVersion(); ?>">
-    <link rel="stylesheet" href="<?php echo $this->assetPath; ?>css/style.css?v=<?php echo getVersion(); ?>">
-    <link rel="stylesheet" href="<?php echo $this->assetPath; ?>css/roboto.css?v=<?php echo getVersion(); ?>">
-    <link rel="stylesheet" href="<?php echo $this->assetPath; ?>css/normalize.css?v=<?php echo getVersion(); ?>">
-    <link rel="stylesheet" href="<?php echo $this->assetPath; ?>css/material-icons.css?v=<?php echo getVersion(); ?>">
-</head>
-<body>
-
-
-<header class="headerbar">
-    <div class="headerbarInner">
-        <div class="float-left navigation-title">
-            <a href="index.html">
-                <h1 class="title">PhpMetrics</h1>
-                <span class="subtitle">
-                Static analyzer for PHP
-            </span>
-            </a>
-        </div>
-        <ul class="navigation-list float-right">
-            <li class="navigation-item">
-                <a class="navigation-link" href="https://github.com/phpmetrics/phpmetrics">Support</a>
-                <a class="navigation-link" href="https://phpmetrics.github.io/website/">Documentation</a>
-            </li>
-        </ul>
-    </div>
-</header>
-
-<a class="hidden-xs github" href="https://github.com/phpmetrics/phpmetrics"
-   title="PhpMetrics on Github" target="blank">
-    <svg width="80" height="80" viewBox="0 0 250 250" class="github">
-        <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
-        <path
-            d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
-            fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
-        <path
-            d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
-            fill="currentColor" class="octo-body"></path>
-    </svg>
-</a>
-
-
-<div class="page">
-    <div class="content content-first">
-        <div class="report-details">
-            Created at <?php echo date('Y-m-d H:i:s'); ?>
-        , with PHPMetrics <?php echo getVersion(); ?> (<a href="https://twitter.com/Halleck45">Jean-François Lépine</a>).
-        </div>
-
-        <?php if ([] !== $this->groups) {?>
-        <div class="content-full group-tabs">
-            <ul class="tabs">
-                <li class="<?php if(!$this->currentGroup) { echo 'active'; }?>"><a href="<?php echo $this->assetPath;?>index.html">All</a></li>
-                <?php foreach ($this->groups as $group) { ?>
-                    <li class="<?php if ($group->getName() === $this->currentGroup) { echo 'active'; }?> ">
-                        <a href="<?php echo $this->assetPath . $group->getName();?>/index.html"><?php echo $group->getName();?></a>
-                    </li>
-                <?php } ?>
-            </ul>
-        </div>
-        <?php } ?>
diff --git a/templates/html_report/all.php b/templates/html_report/all.php
deleted file mode 100644
index 2a770735..00000000
--- a/templates/html_report/all.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-$fullwidth = true;
-require __DIR__ . '/_header.php'; ?>
-
-<?php
-
-$classesC = [];
-foreach ($classes as $c) {
-    if (!$c['interface']) {
-        unset($c['interface']);
-        $classesC[$c['name']] = $c;
-    }
-}
-
-?>
-
-    <div class="row">
-        <div class="column">
-            <div class="bloc">
-                <table class="js-sort-table" id="table-length">
-                    <thead>
-                    <tr>
-                        <?php foreach ((array) current($classesC) as $k => $v) { ?>
-                            <th class="js-sort-number"><?php echo $k; ?></th>
-                        <?php } ?>
-                    </tr>
-                    </thead>
-                    <tbody>
-                    <?php foreach ($classesC as $class) { ?>
-                        <tr>
-                            <?php foreach ($class as $k => $v) { ?>
-                                <td class="js-sort-number"><?php echo is_array($v) ? count($v) : $v; ?></td>
-                            <?php } ?>
-                        </tr>
-                    <?php } ?>
-                    </tbody>
-                </table>
-            </div>
-        </div>
-    </div>
-<?php require __DIR__ . '/_footer.php'; ?>
-
diff --git a/templates/html_report/complexity.php b/templates/html_report/complexity.php
deleted file mode 100644
index 8eeb41dd..00000000
--- a/templates/html_report/complexity.php
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-require __DIR__ . '/_header.php'; ?>
-
-    <div class="row">
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">Average weighted method count by class <small>(CC)</small></div>
-                <div class="number">
-                    <?php echo $avg->wmc; ?>
-                </div>
-                <?php echo $this->getTrend('avg', 'wmc', true); ?>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">Average cyclomatic complexity by class</div>
-                <div class="number">
-                    <?php echo $avg->ccn; ?>
-                </div>
-                <?php echo $this->getTrend('avg', 'ccn', true); ?>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">Average relative System complexity</div>
-                <div class="number">
-                    <?php echo $avg->relativeSystemComplexity; ?>
-                </div>
-                <?php echo $this->getTrend('avg', 'relativeSystemComplexity', true); ?>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">Average bugs by class<small>(Halstead)</small></div>
-                <div class="number">
-                    <?php echo $avg->bugs; ?>
-                </div>
-                <?php echo $this->getTrend('avg', 'bugs', true); ?>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">average defects by class <small>(Kan)</small></div>
-                <div class="number">
-                    <?php echo $avg->kanDefect; ?>
-                </div>
-                <?php echo $this->getTrend('avg', 'kanDefect', true); ?>
-            </div>
-        </div>
-    </div>
-
-    <div class="row">
-        <div class="column">
-            <div class="bloc">
-                <table class="js-sort-table" id="table-length">
-                    <thead>
-                    <tr>
-                        <th>Class</th>
-                        <th class="js-sort-number">WMC</th>
-                        <th class="js-sort-number">Class cycl.</th>
-                        <th class="js-sort-number">Max method cycl.</th>
-                        <th class="js-sort-number">Relative system complexity</th>
-                        <th class="js-sort-number">Relative data complexity</th>
-                        <th class="js-sort-number">Relative structural complexity</th>
-                        <th class="js-sort-number">Bugs</th>
-                        <th class="js-sort-number">Defects</th>
-                        <?php if ($config->has('junit')) { ?>
-                            <th class="js-sort-number">Unit testsuites calling it</th>
-                        <?php } ?>
-                    </tr>
-                    </thead>
-                    <?php
-                    foreach ($classes as $class) { ?>
-                        <tr>
-                            <td><span class="path"><?php echo $class['name']; ?></span></td>
-                            <?php foreach (['wmc', 'ccn', 'ccnMethodMax', 'relativeSystemComplexity', 'relativeDataComplexity', 'relativeStructuralComplexity', 'bugs', 'kanDefect'] as $attribute) {?>
-                                <td>
-                                    <span class="badge" <?php echo gradientStyleFor($classes, $attribute, $class[$attribute]);?>>
-                                    <?php echo isset($class[$attribute]) ? $class[$attribute] : ''; ?>
-                                    </span>
-                                </td>
-                            <?php } ?>
-                            <?php if ($config->has('junit')) { ?>
-                                <td><?php echo isset($class['numberOfUnitTests']) ? $class['numberOfUnitTests'] : ''; ?></td>
-                            <?php } ?>
-                        </tr>
-                    <?php } ?>
-                </table>
-            </div>
-        </div>
-    </div>
-
-
-<?php require __DIR__ . '/_footer.php'; ?>
diff --git a/templates/html_report/composer.php b/templates/html_report/composer.php
deleted file mode 100644
index e534de78..00000000
--- a/templates/html_report/composer.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-require __DIR__ . '/_header.php';
-
-$packages = isset($project['composer']['packages']) ? $project['composer']['packages'] : [];
-usort($packages, function ($a, $b) {
-    return strcmp($a->name, $b->name);
-});
-if ([] === $packages) {
-    echo '<div class="row"><div class="column"><div class="bloc">No composer.json file found in this project</div></div></div>';
-    require __DIR__ . '/_footer.php';
-    return;
-}
-?>
-
-<div class="row">
-    <div class="column">
-        <div class="bloc">
-            <h4><?php echo count($packages); ?> Composer dependencies</h4>
-
-            <div class="list">
-                <?php foreach ($packages as $package) { ?>
-                    <div class="list-item">
-                        <div class="list-item-title">
-                            <a target="_blank" href="https://packagist.org/packages/<?php echo $package->name; ?>">
-                                <?php echo $package->name; ?>
-                            </a>
-                        </div>
-                        <div class="help">
-                            <div class="help-inner">
-                                <?php if ('outdated' === $package->status) { ?>
-                                    <span class="help-warning" style="position: absolute; right: 10px;">This package should be updated.</span>
-                                <?php } elseif ('unknown' === $package->status) { ?>
-                                    <span class="help-info" style="position: absolute; right: 10px;">This package is private.</span>
-                                <?php } ?>
-                                <span class="badge"><?php echo $package->type; ?></span>
-                                <?php echo $package->description; ?>
-                            </div>
-                        </div>
-
-                        <div class="list-item-content">
-                            <?php $width = sprintf('%d%%', round(100 / 9, 0)); ?>
-                            <table class="table-metrics">
-                                <tr>
-                                    <td width="<?php echo $width; ?>">
-                                        <div class="card-number"><?php echo $package->required; ?></div>
-                                        <div class="card-label">Required version</div>
-                                    </td>
-                                    <td width="<?php echo $width; ?>">
-                                        <div class="card-number"><?php echo $package->installed; ?></div>
-                                        <div class="card-label">Installed</div>
-                                    </td>
-                                    <td width="<?php echo $width; ?>">
-                                        <div class="card-number"><?php echo $package->latest; ?></div>
-                                        <div class="card-label">Latest</div>
-                                    </td>
-                                    <td width="<?php echo $width; ?>">
-                                        <div
-                                            class="card-number"><?php echo number_format($package->github_stars, 0); ?></div>
-                                        <div class="card-label">Github stars</div>
-                                    </td>
-                                    <td width="<?php echo $width; ?>">
-                                        <div
-                                            class="card-number"><?php echo number_format($package->github_forks, 0); ?></div>
-                                        <div class="card-label">Github forks</div>
-                                    </td>
-                                    <td width="<?php echo $width; ?>">
-                                        <div
-                                            class="card-number"><?php echo number_format($package->github_open_issues, 0); ?></div>
-                                        <div class="card-label">Github open issues</div>
-                                    </td>
-                                    <td width="<?php echo $width; ?>">
-                                        <div
-                                            class="card-number"><?php echo number_format($package->download_total, 0); ?></div>
-                                        <div class="card-label">Total downloads</div>
-                                    </td>
-                                    <td width="<?php echo $width; ?>">
-                                        <div
-                                            class="card-number"><?php echo number_format($package->download_monthly, 0); ?></div>
-                                        <div class="card-label">Monthly downloads</div>
-                                    </td>
-                                    <td width="<?php echo $width; ?>">
-                                        <div class="card-number">
-                                            <?php foreach ($package->license as $license) { ?>
-                                                <a target="_blank"
-                                                   href="https://spdx.org/licenses/<?php echo $license; ?>.html"><?php echo $license; ?></a>
-                                            <?php } ?>
-                                        </div>
-                                        <div class="card-label">License(s)</div>
-                                    </td>
-                                </tr>
-                            </table>
-                        </div>
-                    </div>
-                <?php } ?>
-            </div>
-        </div>
-    </div>
-</div>
-
-<?php require __DIR__ . '/_footer.php'; ?>
diff --git a/templates/html_report/coupling.php b/templates/html_report/coupling.php
deleted file mode 100644
index db110bc6..00000000
--- a/templates/html_report/coupling.php
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php require __DIR__ . '/_header.php'; ?>
-
-<div class="row">
-    <div class="column">
-        <div class="bloc">
-            <h4>Coupling</h4>
-
-            <div class="help">
-                <strong>Afferent coupling (AC)</strong> is the number of classes affected by given class.
-                <br><strong>Efferent coupling (EC)</strong> is the number of classes from which given class receives
-                effects.
-            </div>
-
-            <table id="table-relations" class="js-sort-table">
-                <thead>
-                <tr>
-                    <th>Class</th>
-                    <th class="js-sort-number">Afferent coupling</th>
-                    <th class="js-sort-number">Efferent coupling</th>
-                    <th class="js-sort-number">Instability</th>
-                    <th class="js-sort-number">ClassRank</th>
-                </thead>
-                <tbody>
-                <?php foreach ($classes as $class) { ?>
-                    <tr>
-                        <td><span class="path"><?php echo $class['name']; ?></span></td>
-                        <?php foreach (['afferentCoupling', 'efferentCoupling', 'instability', 'pageRank'] as $attribute) {?>
-                            <td>
-                                <span class="badge" <?php echo gradientStyleFor($classes, $attribute, $class[$attribute]);?>>
-                                <?php echo isset($class[$attribute]) ? $class[$attribute] : ''; ?>
-                                </span>
-                            </td>
-                        <?php } ?>
-                    </tr>
-                <?php } ?>
-                </tbody>
-            </table>
-
-        </div>
-    </div>
-
-</div>
-
-<?php require __DIR__ . '/_footer.php'; ?>
-
-
-<script>
-    sortTable(document.getElementById('table-relations'), 1, -1);
-</script>
diff --git a/templates/html_report/css/clusterize.css b/templates/html_report/css/clusterize.css
deleted file mode 100644
index 5db98df4..00000000
--- a/templates/html_report/css/clusterize.css
+++ /dev/null
@@ -1,37 +0,0 @@
-/* max-height - the only parameter in this file that needs to be edited.
- * Change it to suit your needs. The rest is recommended to leave as is.
- */
-.clusterize-scroll{
-  max-height: 200px;
-  overflow: auto;
-}
-
-/**
- * Avoid vertical margins for extra tags
- * Necessary for correct calculations when rows have nonzero vertical margins
- */
-.clusterize-extra-row{
-  margin-top: 0 !important;
-  margin-bottom: 0 !important;
-}
-
-/* By default extra tag .clusterize-keep-parity added to keep parity of rows.
- * Useful when used :nth-child(even/odd)
- */
-.clusterize-extra-row.clusterize-keep-parity{
-  display: none;
-}
-
-/* During initialization clusterize adds tabindex to force the browser to keep focus
- * on the scrolling list, see issue #11
- * Outline removes default browser's borders for focused elements.
- */
-.clusterize-content{
-    outline: 0;
-}
-
-/* Centering message that appears when no data provided
- */
-.clusterize-no-data td{
-  text-align: center;
-}
\ No newline at end of file
diff --git a/templates/html_report/css/material-icons.css b/templates/html_report/css/material-icons.css
deleted file mode 100644
index bf3707e5..00000000
--- a/templates/html_report/css/material-icons.css
+++ /dev/null
@@ -1,20 +0,0 @@
-@font-face {
-  font-family: 'Material Icons';
-  font-style: normal;
-  font-weight: 400;
-  src: url(fonts/material-icons.ttf) format('truetype');
-}
-
-.material-icons {
-  font-family: 'Material Icons';
-  font-weight: normal;
-  font-style: normal;
-  font-size: 24px;
-  line-height: 1;
-  letter-spacing: normal;
-  text-transform: none;
-  display: inline-block;
-  white-space: nowrap;
-  word-wrap: normal;
-  direction: ltr;
-}
diff --git a/templates/html_report/css/milligram.min.css b/templates/html_report/css/milligram.min.css
deleted file mode 100644
index c9d72065..00000000
--- a/templates/html_report/css/milligram.min.css
+++ /dev/null
@@ -1,12 +0,0 @@
-/*!
- * Milligram v1.1.0
- * http://milligram.github.io
- *
- * Copyright (c) 2016 CJ Patoilo
- * Licensed under the MIT license
-*/
-
-
-html{box-sizing:border-box;font-size:62.5%}body{color:#606c76;font-family:"Roboto","Helvetica Neue","Helvetica","Arial",sans-serif;font-size:1.6em;font-weight:300;letter-spacing:.01em;line-height:1.6}*,*:after,*:before{box-sizing:inherit}blockquote{border-left:.3rem solid #d1d1d1;margin-left:0;margin-right:0;padding:1rem 1.5rem}blockquote *:last-child{margin:0}.button,button,input[type='button'],input[type='reset'],input[type='submit']{background-color:#9b4dca;border:.1rem solid #9b4dca;border-radius:.4rem;color:#fff;cursor:pointer;display:inline-block;font-size:1.1rem;font-weight:700;height:3.8rem;letter-spacing:.1rem;line-height:3.8rem;padding:0 3rem;text-align:center;text-decoration:none;text-transform:uppercase;white-space:nowrap}.button:hover,.button:focus,button:hover,button:focus,input[type='button']:hover,input[type='button']:focus,input[type='reset']:hover,input[type='reset']:focus,input[type='submit']:hover,input[type='submit']:focus{background-color:#606c76;border-color:#606c76;color:#fff;outline:0}.button.button-disabled,.button[disabled],button.button-disabled,button[disabled],input[type='button'].button-disabled,input[type='button'][disabled],input[type='reset'].button-disabled,input[type='reset'][disabled],input[type='submit'].button-disabled,input[type='submit'][disabled]{opacity:.5;cursor:default}.button.button-disabled:hover,.button.button-disabled:focus,.button[disabled]:hover,.button[disabled]:focus,button.button-disabled:hover,button.button-disabled:focus,button[disabled]:hover,button[disabled]:focus,input[type='button'].button-disabled:hover,input[type='button'].button-disabled:focus,input[type='button'][disabled]:hover,input[type='button'][disabled]:focus,input[type='reset'].button-disabled:hover,input[type='reset'].button-disabled:focus,input[type='reset'][disabled]:hover,input[type='reset'][disabled]:focus,input[type='submit'].button-disabled:hover,input[type='submit'].button-disabled:focus,input[type='submit'][disabled]:hover,input[type='submit'][disabled]:focus{background-color:#9b4dca;border-color:#9b4dca}.button.button-outline,button.button-outline,input[type='button'].button-outline,input[type='reset'].button-outline,input[type='submit'].button-outline{color:#9b4dca;background-color:transparent}.button.button-outline:hover,.button.button-outline:focus,button.button-outline:hover,button.button-outline:focus,input[type='button'].button-outline:hover,input[type='button'].button-outline:focus,input[type='reset'].button-outline:hover,input[type='reset'].button-outline:focus,input[type='submit'].button-outline:hover,input[type='submit'].button-outline:focus{color:#606c76;background-color:transparent;border-color:#606c76}.button.button-outline.button-disabled:hover,.button.button-outline.button-disabled:focus,.button.button-outline[disabled]:hover,.button.button-outline[disabled]:focus,button.button-outline.button-disabled:hover,button.button-outline.button-disabled:focus,button.button-outline[disabled]:hover,button.button-outline[disabled]:focus,input[type='button'].button-outline.button-disabled:hover,input[type='button'].button-outline.button-disabled:focus,input[type='button'].button-outline[disabled]:hover,input[type='button'].button-outline[disabled]:focus,input[type='reset'].button-outline.button-disabled:hover,input[type='reset'].button-outline.button-disabled:focus,input[type='reset'].button-outline[disabled]:hover,input[type='reset'].button-outline[disabled]:focus,input[type='submit'].button-outline.button-disabled:hover,input[type='submit'].button-outline.button-disabled:focus,input[type='submit'].button-outline[disabled]:hover,input[type='submit'].button-outline[disabled]:focus{color:#9b4dca;border-color:inherit}.button.button-clear,button.button-clear,input[type='button'].button-clear,input[type='reset'].button-clear,input[type='submit'].button-clear{color:#9b4dca;background-color:transparent;border-color:transparent}.button.button-clear:hover,.button.button-clear:focus,button.button-clear:hover,button.button-clear:focus,input[type='button'].button-clear:hover,input[type='button'].button-clear:focus,input[type='reset'].button-clear:hover,input[type='reset'].button-clear:focus,input[type='submit'].button-clear:hover,input[type='submit'].button-clear:focus{color:#606c76;background-color:transparent;border-color:transparent}.button.button-clear.button-disabled:hover,.button.button-clear.button-disabled:focus,.button.button-clear[disabled]:hover,.button.button-clear[disabled]:focus,button.button-clear.button-disabled:hover,button.button-clear.button-disabled:focus,button.button-clear[disabled]:hover,button.button-clear[disabled]:focus,input[type='button'].button-clear.button-disabled:hover,input[type='button'].button-clear.button-disabled:focus,input[type='button'].button-clear[disabled]:hover,input[type='button'].button-clear[disabled]:focus,input[type='reset'].button-clear.button-disabled:hover,input[type='reset'].button-clear.button-disabled:focus,input[type='reset'].button-clear[disabled]:hover,input[type='reset'].button-clear[disabled]:focus,input[type='submit'].button-clear.button-disabled:hover,input[type='submit'].button-clear.button-disabled:focus,input[type='submit'].button-clear[disabled]:hover,input[type='submit'].button-clear[disabled]:focus{color:#9b4dca}code{background:#f4f5f6;border-radius:.4rem;font-size:86%;padding:.2rem .5rem;margin:0 .2rem;white-space:nowrap}pre{background:#f4f5f6;border-left:.3rem solid #9b4dca;font-family:"Menlo","Consolas","Bitstream Vera Sans Mono","DejaVu Sans Mono","Monaco",monospace}pre>code{background:transparent;border-radius:0;display:block;padding:1rem 1.5rem;white-space:pre}hr{border:0;border-top:.1rem solid #f4f5f6;margin-bottom:3.5rem;margin-top:3rem}input[type='email'],input[type='number'],input[type='password'],input[type='search'],input[type='tel'],input[type='text'],input[type='url'],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;border:.1rem solid #d1d1d1;border-radius:.4rem;box-shadow:none;height:3.8rem;padding:.6rem 1rem;width:100%}input[type='email']:focus,input[type='number']:focus,input[type='password']:focus,input[type='search']:focus,input[type='tel']:focus,input[type='text']:focus,input[type='url']:focus,textarea:focus,select:focus{border:.1rem solid #9b4dca;outline:0}select{padding:.6rem 3rem .6rem 1rem;background:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiICAgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMjkgMTQiICAgaGVpZ2h0PSIxNHB4IiAgIGlkPSJMYXllcl8xIiAgIHZlcnNpb249IjEuMSIgICB2aWV3Qm94PSIwIDAgMjkgMTQiICAgd2lkdGg9IjI5cHgiICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ4LjQgcjk5MzkiICAgc29kaXBvZGk6ZG9jbmFtZT0iY2FyZXQtZ3JheS5zdmciPjxtZXRhZGF0YSAgICAgaWQ9Im1ldGFkYXRhMzAzOSI+PHJkZjpSREY+PGNjOldvcmsgICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUgICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+PC9jYzpXb3JrPjwvcmRmOlJERj48L21ldGFkYXRhPjxkZWZzICAgICBpZD0iZGVmczMwMzciIC8+PHNvZGlwb2RpOm5hbWVkdmlldyAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiICAgICBib3JkZXJvcGFjaXR5PSIxIiAgICAgb2JqZWN0dG9sZXJhbmNlPSIxMCIgICAgIGdyaWR0b2xlcmFuY2U9IjEwIiAgICAgZ3VpZGV0b2xlcmFuY2U9IjEwIiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAiICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIiAgICAgaW5rc2NhcGU6d2luZG93LXdpZHRoPSI5MDMiICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI1OTQiICAgICBpZD0ibmFtZWR2aWV3MzAzNSIgICAgIHNob3dncmlkPSJ0cnVlIiAgICAgaW5rc2NhcGU6em9vbT0iMTIuMTM3OTMxIiAgICAgaW5rc2NhcGU6Y3g9Ii00LjExOTMxODJlLTA4IiAgICAgaW5rc2NhcGU6Y3k9IjciICAgICBpbmtzY2FwZTp3aW5kb3cteD0iNTAyIiAgICAgaW5rc2NhcGU6d2luZG93LXk9IjMwMiIgICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjAiICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJMYXllcl8xIj48aW5rc2NhcGU6Z3JpZCAgICAgICB0eXBlPSJ4eWdyaWQiICAgICAgIGlkPSJncmlkMzA0MSIgLz48L3NvZGlwb2RpOm5hbWVkdmlldz48cG9seWdvbiAgICAgcG9pbnRzPSIwLjE1LDAgMTQuNSwxNC4zNSAyOC44NSwwICIgICAgIGlkPSJwb2x5Z29uMzAzMyIgICAgIHRyYW5zZm9ybT0ibWF0cml4KDAuMzU0MTEzODcsMCwwLDAuNDgzMjkxMSw5LjMyNDE1NDUsMy42MjQ5OTkyKSIgICAgIHN0eWxlPSJmaWxsOiNkMWQxZDE7ZmlsbC1vcGFjaXR5OjEiIC8+PC9zdmc+) center right no-repeat}select:focus{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiICAgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMjkgMTQiICAgaGVpZ2h0PSIxNHB4IiAgIGlkPSJMYXllcl8xIiAgIHZlcnNpb249IjEuMSIgICB2aWV3Qm94PSIwIDAgMjkgMTQiICAgd2lkdGg9IjI5cHgiICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ4LjQgcjk5MzkiICAgc29kaXBvZGk6ZG9jbmFtZT0iY2FyZXQuc3ZnIj48bWV0YWRhdGEgICAgIGlkPSJtZXRhZGF0YTMwMzkiPjxyZGY6UkRGPjxjYzpXb3JrICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcyAgICAgaWQ9ImRlZnMzMDM3IiAvPjxzb2RpcG9kaTpuYW1lZHZpZXcgICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIgICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IiAgICAgYm9yZGVyb3BhY2l0eT0iMSIgICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiICAgICBncmlkdG9sZXJhbmNlPSIxMCIgICAgIGd1aWRldG9sZXJhbmNlPSIxMCIgICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIgICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iOTAzIiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iNTk0IiAgICAgaWQ9Im5hbWVkdmlldzMwMzUiICAgICBzaG93Z3JpZD0idHJ1ZSIgICAgIGlua3NjYXBlOnpvb209IjEyLjEzNzkzMSIgICAgIGlua3NjYXBlOmN4PSItNC4xMTkzMTgyZS0wOCIgICAgIGlua3NjYXBlOmN5PSI3IiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjUwMiIgICAgIGlua3NjYXBlOndpbmRvdy15PSIzMDIiICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIwIiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0iTGF5ZXJfMSI+PGlua3NjYXBlOmdyaWQgICAgICAgdHlwZT0ieHlncmlkIiAgICAgICBpZD0iZ3JpZDMwNDEiIC8+PC9zb2RpcG9kaTpuYW1lZHZpZXc+PHBvbHlnb24gICAgIHBvaW50cz0iMjguODUsMCAwLjE1LDAgMTQuNSwxNC4zNSAiICAgICBpZD0icG9seWdvbjMwMzMiICAgICB0cmFuc2Zvcm09Im1hdHJpeCgwLjM1NDExMzg3LDAsMCwwLjQ4MzI5MTEsOS4zMjQxNTUzLDMuNjI1KSIgICAgIHN0eWxlPSJmaWxsOiM5YjRkY2Y7ZmlsbC1vcGFjaXR5OjEiIC8+PC9zdmc+)}textarea{padding-bottom:.6rem;padding-top:.6rem;min-height:6.5rem}label,legend{font-size:1.6rem;font-weight:700;display:block;margin-bottom:.5rem}fieldset{border-width:0;padding:0}input[type='checkbox'],input[type='radio']{display:inline}.label-inline{font-weight:normal;display:inline-block;margin-left:.5rem}.container{margin:0 auto;max-width:112rem;padding:0 2rem;position:relative;width:100%}.row{display:flex;flex-direction:column;padding:0;width:100%}.row .row-wrap{flex-wrap:wrap}.row .row-no-padding{padding:0}.row .row-no-padding>.column{padding:0}.row .row-top{align-items:flex-start}.row .row-bottom{align-items:flex-end}.row .row-center{align-items:center}.row .row-stretch{align-items:stretch}.row .row-baseline{align-items:baseline}.row .column{display:block;flex:1;margin-left:0;max-width:100%;width:100%}.row .column .col-top{align-self:flex-start}.row .column .col-bottom{align-self:flex-end}.row .column .col-center{align-self:center}.row .column.column-offset-10{margin-left:10%}.row .column.column-offset-20{margin-left:20%}.row .column.column-offset-25{margin-left:25%}.row .column.column-offset-33,.row .column.column-offset-34{margin-left:33.3333%}.row .column.column-offset-50{margin-left:50%}.row .column.column-offset-66,.row .column.column-offset-67{margin-left:66.6666%}.row .column.column-offset-75{margin-left:75%}.row .column.column-offset-80{margin-left:80%}.row .column.column-offset-90{margin-left:90%}.row .column.column-10{flex:0 0 10%;max-width:10%}.row .column.column-20{flex:0 0 20%;max-width:20%}.row .column.column-25{flex:0 0 25%;max-width:25%}.row .column.column-33,.row .column.column-34{flex:0 0 33.3333%;max-width:33.3333%}.row .column.column-40{flex:0 0 40%;max-width:40%}.row .column.column-50{flex:0 0 50%;max-width:50%}.row .column.column-60{flex:0 0 60%;max-width:60%}.row .column.column-66,.row .column.column-67{flex:0 0 66.6666%;max-width:66.6666%}.row .column.column-75{flex:0 0 75%;max-width:75%}.row .column.column-80{flex:0 0 80%;max-width:80%}.row .column.column-90{flex:0 0 90%;max-width:90%}@media (min-width: 40rem){.row{flex-direction:row;margin-left:-1rem;width:calc(100% + 2.0rem)}.row .column{margin-bottom:inherit;padding:0 1rem}}a{color:#9b4dca;text-decoration:none}a:hover{color:#606c76}dl,ol,ul{margin-top:0;padding-left:0}dl ul,dl ol,ol ul,ol ol,ul ul,ul ol{font-size:90%;margin:1.5rem 0 1.5rem 3rem}dl{list-style:none}ul{list-style:circle inside}ol{list-style:decimal inside}dt,dd,li{margin-bottom:1rem}.button,button{margin-bottom:1rem}input,textarea,select,fieldset{margin-bottom:1.5rem}pre,blockquote,dl,figure,table,p,ul,ol,form{margin-bottom:2.5rem}table{width:100%}th,td{border-bottom:.1rem solid #e1e1e1;padding:1.2rem 1.5rem;text-align:left}th:first-child,td:first-child{padding-left:0}th:last-child,td:last-child{padding-right:0}p{margin-top:0}h1,h2,h3,h4,h5,h6{font-weight:300;margin-bottom:2rem;margin-top:0}h1{font-size:4rem;letter-spacing:-0.1rem;line-height:1.2}h2{font-size:3.6rem;letter-spacing:-0.1rem;line-height:1.25}h3{font-size:3rem;letter-spacing:-0.1rem;line-height:1.3}h4{font-size:2.4rem;letter-spacing:-0.08rem;line-height:1.35}h5{font-size:1.8rem;letter-spacing:-0.05rem;line-height:1.5}h6{font-size:1.6rem;letter-spacing:0;line-height:1.4}@media (min-width: 40rem){h1{font-size:5rem}h2{font-size:4.2rem}h3{font-size:3.6rem}h4{font-size:3rem}h5{font-size:2.4rem}h6{font-size:1.5rem}}.float-right{float:right}.float-left{float:left}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{content:"";display:table}.clearfix:after{clear:both}
-
-/*# sourceMappingURL=milligram.min.css.map */
\ No newline at end of file
diff --git a/templates/html_report/css/milligram.min.css.map b/templates/html_report/css/milligram.min.css.map
deleted file mode 100644
index 4a28342a..00000000
--- a/templates/html_report/css/milligram.min.css.map
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "version": 3,
-  "sources": [
-    "milligram.min.css"
-  ],
-  "names": [],
-  "mappings": "AAAA;;;;;;EAME;;;AAGF,KAAK,sBAAsB,eAAe,CAAC,KAAK,cAAc,qEAAqE,gBAAgB,gBAAgB,qBAAqB,eAAe,CAAC,mBAAmB,kBAAkB,CAAC,WAAW,gCAAgC,cAAc,eAAe,mBAAmB,CAAC,wBAAwB,QAAQ,CAAC,6EAA6E,yBAAyB,2BAA2B,oBAAoB,WAAW,eAAe,qBAAqB,iBAAiB,gBAAgB,cAAc,qBAAqB,mBAAmB,eAAe,kBAAkB,qBAAqB,yBAAyB,kBAAkB,CAAC,sNAAsN,yBAAyB,qBAAqB,WAAW,SAAS,CAAC,4RAA4R,WAAW,cAAc,CAAC,grBAAgrB,yBAAyB,oBAAoB,CAAC,wJAAwJ,cAAc,4BAA4B,CAAC,4WAA4W,cAAc,6BAA6B,oBAAoB,CAAC,49BAA49B,cAAc,oBAAoB,CAAC,8IAA8I,cAAc,6BAA6B,wBAAwB,CAAC,wVAAwV,cAAc,6BAA6B,wBAAwB,CAAC,o7BAAo7B,aAAa,CAAC,KAAK,mBAAmB,oBAAoB,cAAc,oBAAoB,eAAe,kBAAkB,CAAC,IAAI,mBAAmB,gCAAgC,+FAA+F,CAAC,SAAS,uBAAuB,gBAAgB,cAAc,oBAAoB,eAAe,CAAC,GAAG,SAAS,+BAA+B,qBAAqB,eAAe,CAAC,4JAA4J,wBAAgB,AAAhB,qBAAgB,AAAhB,gBAAgB,6BAA6B,2BAA2B,oBAAoB,gBAAgB,cAAc,mBAAmB,UAAU,CAAC,kNAAkN,2BAA2B,SAAS,CAAC,OAAO,8BAA8B,yvEAAyvE,CAAC,aAAa,4tEAA4tE,CAAC,SAAS,qBAAqB,kBAAkB,iBAAiB,CAAC,aAAa,iBAAiB,gBAAgB,cAAc,mBAAmB,CAAC,SAAS,eAAe,SAAS,CAAC,2CAA2C,cAAc,CAAC,cAAc,mBAAmB,qBAAqB,iBAAiB,CAAC,WAAW,cAAc,iBAAiB,eAAe,kBAAkB,UAAU,CAAC,KAAK,aAAa,sBAAsB,UAAU,UAAU,CAAC,eAAe,cAAc,CAAC,qBAAqB,SAAS,CAAC,6BAA6B,SAAS,CAAC,cAAc,sBAAsB,CAAC,iBAAiB,oBAAoB,CAAC,iBAAiB,kBAAkB,CAAC,kBAAkB,mBAAmB,CAAC,mBAAmB,oBAAoB,CAAC,aAAa,cAAc,OAAO,cAAc,eAAe,UAAU,CAAC,sBAAsB,qBAAqB,CAAC,yBAAyB,mBAAmB,CAAC,yBAAyB,iBAAiB,CAAC,8BAA8B,eAAe,CAAC,8BAA8B,eAAe,CAAC,8BAA8B,eAAe,CAAC,4DAA4D,oBAAoB,CAAC,8BAA8B,eAAe,CAAC,4DAA4D,oBAAoB,CAAC,8BAA8B,eAAe,CAAC,8BAA8B,eAAe,CAAC,8BAA8B,eAAe,CAAC,uBAAuB,aAAa,aAAa,CAAC,uBAAuB,aAAa,aAAa,CAAC,uBAAuB,aAAa,aAAa,CAAC,8CAA8C,kBAAkB,kBAAkB,CAAC,uBAAuB,aAAa,aAAa,CAAC,uBAAuB,aAAa,aAAa,CAAC,uBAAuB,aAAa,aAAa,CAAC,8CAA8C,kBAAkB,kBAAkB,CAAC,uBAAuB,aAAa,aAAa,CAAC,uBAAuB,aAAa,aAAa,CAAC,uBAAuB,aAAa,aAAa,CAAC,0BAA0B,KAAK,mBAAmB,kBAAkB,yBAAyB,CAAC,aAAa,sBAAsB,cAAc,CAAC,CAAC,EAAE,cAAc,oBAAoB,CAAC,QAAQ,aAAa,CAAC,SAAS,aAAa,cAAc,CAAC,oCAAoC,cAAc,2BAA2B,CAAC,GAAG,eAAe,CAAC,GAAG,wBAAwB,CAAC,GAAG,yBAAyB,CAAC,SAAS,kBAAkB,CAAC,eAAe,kBAAkB,CAAC,+BAA+B,oBAAoB,CAAC,4CAA4C,oBAAoB,CAAC,MAAM,UAAU,CAAC,MAAM,kCAAkC,sBAAsB,eAAe,CAAC,8BAA8B,cAAc,CAAC,4BAA4B,eAAe,CAAC,EAAE,YAAY,CAAC,kBAAkB,gBAAgB,mBAAmB,YAAY,CAAC,GAAG,eAAe,uBAAuB,eAAe,CAAC,GAAG,iBAAiB,uBAAuB,gBAAgB,CAAC,GAAG,eAAe,uBAAuB,eAAe,CAAC,GAAG,iBAAiB,wBAAwB,gBAAgB,CAAC,GAAG,iBAAiB,wBAAwB,eAAe,CAAC,GAAG,iBAAiB,iBAAiB,eAAe,CAAC,0BAA0B,GAAG,cAAc,CAAC,GAAG,gBAAgB,CAAC,GAAG,gBAAgB,CAAC,GAAG,cAAc,CAAC,GAAG,gBAAgB,CAAC,GAAG,gBAAgB,CAAC,CAAC,aAAa,WAAW,CAAC,YAAY,UAAU,CAAC,WAAU,MAAO,CAAC,iCAAiC,WAAW,aAAa,CAAC,gBAAgB,UAAU,CAAC",
-  "file": "milligram.min.css",
-  "sourcesContent": [
-    "/*!\n * Milligram v1.1.0\n * http://milligram.github.io\n *\n * Copyright (c) 2016 CJ Patoilo\n * Licensed under the MIT license\n*/\n\n\nhtml{box-sizing:border-box;font-size:62.5%}body{color:#606c76;font-family:\"Roboto\",\"Helvetica Neue\",\"Helvetica\",\"Arial\",sans-serif;font-size:1.6em;font-weight:300;letter-spacing:.01em;line-height:1.6}*,*:after,*:before{box-sizing:inherit}blockquote{border-left:.3rem solid #d1d1d1;margin-left:0;margin-right:0;padding:1rem 1.5rem}blockquote *:last-child{margin:0}.button,button,input[type='button'],input[type='reset'],input[type='submit']{background-color:#9b4dca;border:.1rem solid #9b4dca;border-radius:.4rem;color:#fff;cursor:pointer;display:inline-block;font-size:1.1rem;font-weight:700;height:3.8rem;letter-spacing:.1rem;line-height:3.8rem;padding:0 3rem;text-align:center;text-decoration:none;text-transform:uppercase;white-space:nowrap}.button:hover,.button:focus,button:hover,button:focus,input[type='button']:hover,input[type='button']:focus,input[type='reset']:hover,input[type='reset']:focus,input[type='submit']:hover,input[type='submit']:focus{background-color:#606c76;border-color:#606c76;color:#fff;outline:0}.button.button-disabled,.button[disabled],button.button-disabled,button[disabled],input[type='button'].button-disabled,input[type='button'][disabled],input[type='reset'].button-disabled,input[type='reset'][disabled],input[type='submit'].button-disabled,input[type='submit'][disabled]{opacity:.5;cursor:default}.button.button-disabled:hover,.button.button-disabled:focus,.button[disabled]:hover,.button[disabled]:focus,button.button-disabled:hover,button.button-disabled:focus,button[disabled]:hover,button[disabled]:focus,input[type='button'].button-disabled:hover,input[type='button'].button-disabled:focus,input[type='button'][disabled]:hover,input[type='button'][disabled]:focus,input[type='reset'].button-disabled:hover,input[type='reset'].button-disabled:focus,input[type='reset'][disabled]:hover,input[type='reset'][disabled]:focus,input[type='submit'].button-disabled:hover,input[type='submit'].button-disabled:focus,input[type='submit'][disabled]:hover,input[type='submit'][disabled]:focus{background-color:#9b4dca;border-color:#9b4dca}.button.button-outline,button.button-outline,input[type='button'].button-outline,input[type='reset'].button-outline,input[type='submit'].button-outline{color:#9b4dca;background-color:transparent}.button.button-outline:hover,.button.button-outline:focus,button.button-outline:hover,button.button-outline:focus,input[type='button'].button-outline:hover,input[type='button'].button-outline:focus,input[type='reset'].button-outline:hover,input[type='reset'].button-outline:focus,input[type='submit'].button-outline:hover,input[type='submit'].button-outline:focus{color:#606c76;background-color:transparent;border-color:#606c76}.button.button-outline.button-disabled:hover,.button.button-outline.button-disabled:focus,.button.button-outline[disabled]:hover,.button.button-outline[disabled]:focus,button.button-outline.button-disabled:hover,button.button-outline.button-disabled:focus,button.button-outline[disabled]:hover,button.button-outline[disabled]:focus,input[type='button'].button-outline.button-disabled:hover,input[type='button'].button-outline.button-disabled:focus,input[type='button'].button-outline[disabled]:hover,input[type='button'].button-outline[disabled]:focus,input[type='reset'].button-outline.button-disabled:hover,input[type='reset'].button-outline.button-disabled:focus,input[type='reset'].button-outline[disabled]:hover,input[type='reset'].button-outline[disabled]:focus,input[type='submit'].button-outline.button-disabled:hover,input[type='submit'].button-outline.button-disabled:focus,input[type='submit'].button-outline[disabled]:hover,input[type='submit'].button-outline[disabled]:focus{color:#9b4dca;border-color:inherit}.button.button-clear,button.button-clear,input[type='button'].button-clear,input[type='reset'].button-clear,input[type='submit'].button-clear{color:#9b4dca;background-color:transparent;border-color:transparent}.button.button-clear:hover,.button.button-clear:focus,button.button-clear:hover,button.button-clear:focus,input[type='button'].button-clear:hover,input[type='button'].button-clear:focus,input[type='reset'].button-clear:hover,input[type='reset'].button-clear:focus,input[type='submit'].button-clear:hover,input[type='submit'].button-clear:focus{color:#606c76;background-color:transparent;border-color:transparent}.button.button-clear.button-disabled:hover,.button.button-clear.button-disabled:focus,.button.button-clear[disabled]:hover,.button.button-clear[disabled]:focus,button.button-clear.button-disabled:hover,button.button-clear.button-disabled:focus,button.button-clear[disabled]:hover,button.button-clear[disabled]:focus,input[type='button'].button-clear.button-disabled:hover,input[type='button'].button-clear.button-disabled:focus,input[type='button'].button-clear[disabled]:hover,input[type='button'].button-clear[disabled]:focus,input[type='reset'].button-clear.button-disabled:hover,input[type='reset'].button-clear.button-disabled:focus,input[type='reset'].button-clear[disabled]:hover,input[type='reset'].button-clear[disabled]:focus,input[type='submit'].button-clear.button-disabled:hover,input[type='submit'].button-clear.button-disabled:focus,input[type='submit'].button-clear[disabled]:hover,input[type='submit'].button-clear[disabled]:focus{color:#9b4dca}code{background:#f4f5f6;border-radius:.4rem;font-size:86%;padding:.2rem .5rem;margin:0 .2rem;white-space:nowrap}pre{background:#f4f5f6;border-left:.3rem solid #9b4dca;font-family:\"Menlo\",\"Consolas\",\"Bitstream Vera Sans Mono\",\"DejaVu Sans Mono\",\"Monaco\",monospace}pre>code{background:transparent;border-radius:0;display:block;padding:1rem 1.5rem;white-space:pre}hr{border:0;border-top:.1rem solid #f4f5f6;margin-bottom:3.5rem;margin-top:3rem}input[type='email'],input[type='number'],input[type='password'],input[type='search'],input[type='tel'],input[type='text'],input[type='url'],textarea,select{appearance:none;background-color:transparent;border:.1rem solid #d1d1d1;border-radius:.4rem;box-shadow:none;height:3.8rem;padding:.6rem 1rem;width:100%}input[type='email']:focus,input[type='number']:focus,input[type='password']:focus,input[type='search']:focus,input[type='tel']:focus,input[type='text']:focus,input[type='url']:focus,textarea:focus,select:focus{border:.1rem solid #9b4dca;outline:0}select{padding:.6rem 3rem .6rem 1rem;background:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiICAgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMjkgMTQiICAgaGVpZ2h0PSIxNHB4IiAgIGlkPSJMYXllcl8xIiAgIHZlcnNpb249IjEuMSIgICB2aWV3Qm94PSIwIDAgMjkgMTQiICAgd2lkdGg9IjI5cHgiICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ4LjQgcjk5MzkiICAgc29kaXBvZGk6ZG9jbmFtZT0iY2FyZXQtZ3JheS5zdmciPjxtZXRhZGF0YSAgICAgaWQ9Im1ldGFkYXRhMzAzOSI+PHJkZjpSREY+PGNjOldvcmsgICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUgICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+PC9jYzpXb3JrPjwvcmRmOlJERj48L21ldGFkYXRhPjxkZWZzICAgICBpZD0iZGVmczMwMzciIC8+PHNvZGlwb2RpOm5hbWVkdmlldyAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiICAgICBib3JkZXJvcGFjaXR5PSIxIiAgICAgb2JqZWN0dG9sZXJhbmNlPSIxMCIgICAgIGdyaWR0b2xlcmFuY2U9IjEwIiAgICAgZ3VpZGV0b2xlcmFuY2U9IjEwIiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAiICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIiAgICAgaW5rc2NhcGU6d2luZG93LXdpZHRoPSI5MDMiICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI1OTQiICAgICBpZD0ibmFtZWR2aWV3MzAzNSIgICAgIHNob3dncmlkPSJ0cnVlIiAgICAgaW5rc2NhcGU6em9vbT0iMTIuMTM3OTMxIiAgICAgaW5rc2NhcGU6Y3g9Ii00LjExOTMxODJlLTA4IiAgICAgaW5rc2NhcGU6Y3k9IjciICAgICBpbmtzY2FwZTp3aW5kb3cteD0iNTAyIiAgICAgaW5rc2NhcGU6d2luZG93LXk9IjMwMiIgICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjAiICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJMYXllcl8xIj48aW5rc2NhcGU6Z3JpZCAgICAgICB0eXBlPSJ4eWdyaWQiICAgICAgIGlkPSJncmlkMzA0MSIgLz48L3NvZGlwb2RpOm5hbWVkdmlldz48cG9seWdvbiAgICAgcG9pbnRzPSIwLjE1LDAgMTQuNSwxNC4zNSAyOC44NSwwICIgICAgIGlkPSJwb2x5Z29uMzAzMyIgICAgIHRyYW5zZm9ybT0ibWF0cml4KDAuMzU0MTEzODcsMCwwLDAuNDgzMjkxMSw5LjMyNDE1NDUsMy42MjQ5OTkyKSIgICAgIHN0eWxlPSJmaWxsOiNkMWQxZDE7ZmlsbC1vcGFjaXR5OjEiIC8+PC9zdmc+) center right no-repeat}select:focus{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiICAgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMjkgMTQiICAgaGVpZ2h0PSIxNHB4IiAgIGlkPSJMYXllcl8xIiAgIHZlcnNpb249IjEuMSIgICB2aWV3Qm94PSIwIDAgMjkgMTQiICAgd2lkdGg9IjI5cHgiICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ4LjQgcjk5MzkiICAgc29kaXBvZGk6ZG9jbmFtZT0iY2FyZXQuc3ZnIj48bWV0YWRhdGEgICAgIGlkPSJtZXRhZGF0YTMwMzkiPjxyZGY6UkRGPjxjYzpXb3JrICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcyAgICAgaWQ9ImRlZnMzMDM3IiAvPjxzb2RpcG9kaTpuYW1lZHZpZXcgICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIgICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IiAgICAgYm9yZGVyb3BhY2l0eT0iMSIgICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiICAgICBncmlkdG9sZXJhbmNlPSIxMCIgICAgIGd1aWRldG9sZXJhbmNlPSIxMCIgICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIgICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iOTAzIiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iNTk0IiAgICAgaWQ9Im5hbWVkdmlldzMwMzUiICAgICBzaG93Z3JpZD0idHJ1ZSIgICAgIGlua3NjYXBlOnpvb209IjEyLjEzNzkzMSIgICAgIGlua3NjYXBlOmN4PSItNC4xMTkzMTgyZS0wOCIgICAgIGlua3NjYXBlOmN5PSI3IiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjUwMiIgICAgIGlua3NjYXBlOndpbmRvdy15PSIzMDIiICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIwIiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0iTGF5ZXJfMSI+PGlua3NjYXBlOmdyaWQgICAgICAgdHlwZT0ieHlncmlkIiAgICAgICBpZD0iZ3JpZDMwNDEiIC8+PC9zb2RpcG9kaTpuYW1lZHZpZXc+PHBvbHlnb24gICAgIHBvaW50cz0iMjguODUsMCAwLjE1LDAgMTQuNSwxNC4zNSAiICAgICBpZD0icG9seWdvbjMwMzMiICAgICB0cmFuc2Zvcm09Im1hdHJpeCgwLjM1NDExMzg3LDAsMCwwLjQ4MzI5MTEsOS4zMjQxNTUzLDMuNjI1KSIgICAgIHN0eWxlPSJmaWxsOiM5YjRkY2Y7ZmlsbC1vcGFjaXR5OjEiIC8+PC9zdmc+)}textarea{padding-bottom:.6rem;padding-top:.6rem;min-height:6.5rem}label,legend{font-size:1.6rem;font-weight:700;display:block;margin-bottom:.5rem}fieldset{border-width:0;padding:0}input[type='checkbox'],input[type='radio']{display:inline}.label-inline{font-weight:normal;display:inline-block;margin-left:.5rem}.container{margin:0 auto;max-width:112rem;padding:0 2rem;position:relative;width:100%}.row{display:flex;flex-direction:column;padding:0;width:100%}.row .row-wrap{flex-wrap:wrap}.row .row-no-padding{padding:0}.row .row-no-padding>.column{padding:0}.row .row-top{align-items:flex-start}.row .row-bottom{align-items:flex-end}.row .row-center{align-items:center}.row .row-stretch{align-items:stretch}.row .row-baseline{align-items:baseline}.row .column{display:block;flex:1;margin-left:0;max-width:100%;width:100%}.row .column .col-top{align-self:flex-start}.row .column .col-bottom{align-self:flex-end}.row .column .col-center{align-self:center}.row .column.column-offset-10{margin-left:10%}.row .column.column-offset-20{margin-left:20%}.row .column.column-offset-25{margin-left:25%}.row .column.column-offset-33,.row .column.column-offset-34{margin-left:33.3333%}.row .column.column-offset-50{margin-left:50%}.row .column.column-offset-66,.row .column.column-offset-67{margin-left:66.6666%}.row .column.column-offset-75{margin-left:75%}.row .column.column-offset-80{margin-left:80%}.row .column.column-offset-90{margin-left:90%}.row .column.column-10{flex:0 0 10%;max-width:10%}.row .column.column-20{flex:0 0 20%;max-width:20%}.row .column.column-25{flex:0 0 25%;max-width:25%}.row .column.column-33,.row .column.column-34{flex:0 0 33.3333%;max-width:33.3333%}.row .column.column-40{flex:0 0 40%;max-width:40%}.row .column.column-50{flex:0 0 50%;max-width:50%}.row .column.column-60{flex:0 0 60%;max-width:60%}.row .column.column-66,.row .column.column-67{flex:0 0 66.6666%;max-width:66.6666%}.row .column.column-75{flex:0 0 75%;max-width:75%}.row .column.column-80{flex:0 0 80%;max-width:80%}.row .column.column-90{flex:0 0 90%;max-width:90%}@media (min-width: 40rem){.row{flex-direction:row;margin-left:-1rem;width:calc(100% + 2.0rem)}.row .column{margin-bottom:inherit;padding:0 1rem}}a{color:#9b4dca;text-decoration:none}a:hover{color:#606c76}dl,ol,ul{margin-top:0;padding-left:0}dl ul,dl ol,ol ul,ol ol,ul ul,ul ol{font-size:90%;margin:1.5rem 0 1.5rem 3rem}dl{list-style:none}ul{list-style:circle inside}ol{list-style:decimal inside}dt,dd,li{margin-bottom:1rem}.button,button{margin-bottom:1rem}input,textarea,select,fieldset{margin-bottom:1.5rem}pre,blockquote,dl,figure,table,p,ul,ol,form{margin-bottom:2.5rem}table{width:100%}th,td{border-bottom:.1rem solid #e1e1e1;padding:1.2rem 1.5rem;text-align:left}th:first-child,td:first-child{padding-left:0}th:last-child,td:last-child{padding-right:0}p{margin-top:0}h1,h2,h3,h4,h5,h6{font-weight:300;margin-bottom:2rem;margin-top:0}h1{font-size:4rem;letter-spacing:-0.1rem;line-height:1.2}h2{font-size:3.6rem;letter-spacing:-0.1rem;line-height:1.25}h3{font-size:3rem;letter-spacing:-0.1rem;line-height:1.3}h4{font-size:2.4rem;letter-spacing:-0.08rem;line-height:1.35}h5{font-size:1.8rem;letter-spacing:-0.05rem;line-height:1.5}h6{font-size:1.6rem;letter-spacing:0;line-height:1.4}@media (min-width: 40rem){h1{font-size:5rem}h2{font-size:4.2rem}h3{font-size:3.6rem}h4{font-size:3rem}h5{font-size:2.4rem}h6{font-size:1.5rem}}.float-right{float:right}.float-left{float:left}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{content:\"\";display:table}.clearfix:after{clear:both}\n"
-  ]
-}
\ No newline at end of file
diff --git a/templates/html_report/css/normalize.css b/templates/html_report/css/normalize.css
deleted file mode 100644
index 5e5e3c89..00000000
--- a/templates/html_report/css/normalize.css
+++ /dev/null
@@ -1,424 +0,0 @@
-/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
-
-/**
- * 1. Set default font family to sans-serif.
- * 2. Prevent iOS and IE text size adjust after device orientation change,
- *    without disabling user zoom.
- */
-
-html {
-  font-family: sans-serif; /* 1 */
-  -ms-text-size-adjust: 100%; /* 2 */
-  -webkit-text-size-adjust: 100%; /* 2 */
-}
-
-/**
- * Remove default margin.
- */
-
-body {
-  margin: 0;
-}
-
-/* HTML5 display definitions
-   ========================================================================== */
-
-/**
- * Correct `block` display not defined for any HTML5 element in IE 8/9.
- * Correct `block` display not defined for `details` or `summary` in IE 10/11
- * and Firefox.
- * Correct `block` display not defined for `main` in IE 11.
- */
-
-article,
-aside,
-details,
-figcaption,
-figure,
-footer,
-header,
-hgroup,
-main,
-menu,
-nav,
-section,
-summary {
-  display: block;
-}
-
-/**
- * 1. Correct `inline-block` display not defined in IE 8/9.
- * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
- */
-
-audio,
-canvas,
-progress,
-video {
-  display: inline-block; /* 1 */
-  vertical-align: baseline; /* 2 */
-}
-
-/**
- * Prevent modern browsers from displaying `audio` without controls.
- * Remove excess height in iOS 5 devices.
- */
-
-audio:not([controls]) {
-  display: none;
-  height: 0;
-}
-
-/**
- * Address `[hidden]` styling not present in IE 8/9/10.
- * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
- */
-
-[hidden],
-template {
-  display: none;
-}
-
-/* Links
-   ========================================================================== */
-
-/**
- * Remove the gray background color from active links in IE 10.
- */
-
-a {
-  background-color: transparent;
-}
-
-/**
- * Improve readability of focused elements when they are also in an
- * active/hover state.
- */
-
-a:active,
-a:hover {
-  outline: 0;
-}
-
-/* Text-level semantics
-   ========================================================================== */
-
-/**
- * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
- */
-
-abbr[title] {
-  border-bottom: 1px dotted;
-}
-
-/**
- * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
- */
-
-b,
-strong {
-  font-weight: bold;
-}
-
-/**
- * Address styling not present in Safari and Chrome.
- */
-
-dfn {
-  font-style: italic;
-}
-
-/**
- * Address variable `h1` font-size and margin within `section` and `article`
- * contexts in Firefox 4+, Safari, and Chrome.
- */
-
-h1 {
-  font-size: 2em;
-  margin: 0.67em 0;
-}
-
-/**
- * Address styling not present in IE 8/9.
- */
-
-mark {
-  background: #ff0;
-  color: #000;
-}
-
-/**
- * Address inconsistent and variable font size in all browsers.
- */
-
-small {
-  font-size: 80%;
-}
-
-/**
- * Prevent `sub` and `sup` affecting `line-height` in all browsers.
- */
-
-sub,
-sup {
-  font-size: 75%;
-  line-height: 0;
-  position: relative;
-  vertical-align: baseline;
-}
-
-sup {
-  top: -0.5em;
-}
-
-sub {
-  bottom: -0.25em;
-}
-
-/* Embedded content
-   ========================================================================== */
-
-/**
- * Remove border when inside `a` element in IE 8/9/10.
- */
-
-img {
-  border: 0;
-}
-
-/**
- * Correct overflow not hidden in IE 9/10/11.
- */
-
-svg:not(:root) {
-  overflow: hidden;
-}
-
-/* Grouping content
-   ========================================================================== */
-
-/**
- * Address margin not present in IE 8/9 and Safari.
- */
-
-figure {
-  margin: 1em 40px;
-}
-
-/**
- * Address differences between Firefox and other browsers.
- */
-
-hr {
-  box-sizing: content-box;
-  height: 0;
-}
-
-/**
- * Contain overflow in all browsers.
- */
-
-pre {
-  overflow: auto;
-}
-
-/**
- * Address odd `em`-unit font size rendering in all browsers.
- */
-
-code,
-kbd,
-pre,
-samp {
-  font-family: monospace, monospace;
-  font-size: 1em;
-}
-
-/* Forms
-   ========================================================================== */
-
-/**
- * Known limitation: by default, Chrome and Safari on OS X allow very limited
- * styling of `select`, unless a `border` property is set.
- */
-
-/**
- * 1. Correct color not being inherited.
- *    Known issue: affects color of disabled elements.
- * 2. Correct font properties not being inherited.
- * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
- */
-
-button,
-input,
-optgroup,
-select,
-textarea {
-  color: inherit; /* 1 */
-  font: inherit; /* 2 */
-  margin: 0; /* 3 */
-}
-
-/**
- * Address `overflow` set to `hidden` in IE 8/9/10/11.
- */
-
-button {
-  overflow: visible;
-}
-
-/**
- * Address inconsistent `text-transform` inheritance for `button` and `select`.
- * All other form control elements do not inherit `text-transform` values.
- * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
- * Correct `select` style inheritance in Firefox.
- */
-
-button,
-select {
-  text-transform: none;
-}
-
-/**
- * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
- *    and `video` controls.
- * 2. Correct inability to style clickable `input` types in iOS.
- * 3. Improve usability and consistency of cursor style between image-type
- *    `input` and others.
- */
-
-button,
-html input[type="button"], /* 1 */
-input[type="reset"],
-input[type="submit"] {
-  -webkit-appearance: button; /* 2 */
-  cursor: pointer; /* 3 */
-}
-
-/**
- * Re-set default cursor for disabled elements.
- */
-
-button[disabled],
-html input[disabled] {
-  cursor: default;
-}
-
-/**
- * Remove inner padding and border in Firefox 4+.
- */
-
-button::-moz-focus-inner,
-input::-moz-focus-inner {
-  border: 0;
-  padding: 0;
-}
-
-/**
- * Address Firefox 4+ setting `line-height` on `input` using `!important` in
- * the UA stylesheet.
- */
-
-input {
-  line-height: normal;
-}
-
-/**
- * It's recommended that you don't attempt to style these elements.
- * Firefox's implementation doesn't respect box-sizing, padding, or width.
- *
- * 1. Address box sizing set to `content-box` in IE 8/9/10.
- * 2. Remove excess padding in IE 8/9/10.
- */
-
-input[type="checkbox"],
-input[type="radio"] {
-  box-sizing: border-box; /* 1 */
-  padding: 0; /* 2 */
-}
-
-/**
- * Fix the cursor style for Chrome's increment/decrement buttons. For certain
- * `font-size` values of the `input`, it causes the cursor style of the
- * decrement button to change from `default` to `text`.
- */
-
-input[type="number"]::-webkit-inner-spin-button,
-input[type="number"]::-webkit-outer-spin-button {
-  height: auto;
-}
-
-/**
- * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
- * 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
- */
-
-input[type="search"] {
-  -webkit-appearance: textfield; /* 1 */
-  box-sizing: content-box; /* 2 */
-}
-
-/**
- * Remove inner padding and search cancel button in Safari and Chrome on OS X.
- * Safari (but not Chrome) clips the cancel button when the search input has
- * padding (and `textfield` appearance).
- */
-
-input[type="search"]::-webkit-search-cancel-button,
-input[type="search"]::-webkit-search-decoration {
-  -webkit-appearance: none;
-}
-
-/**
- * Define consistent border, margin, and padding.
- */
-
-fieldset {
-  border: 1px solid #c0c0c0;
-  margin: 0 2px;
-  padding: 0.35em 0.625em 0.75em;
-}
-
-/**
- * 1. Correct `color` not being inherited in IE 8/9/10/11.
- * 2. Remove padding so people aren't caught out if they zero out fieldsets.
- */
-
-legend {
-  border: 0; /* 1 */
-  padding: 0; /* 2 */
-}
-
-/**
- * Remove default vertical scrollbar in IE 8/9/10/11.
- */
-
-textarea {
-  overflow: auto;
-}
-
-/**
- * Don't inherit the `font-weight` (applied by a rule above).
- * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
- */
-
-optgroup {
-  font-weight: bold;
-}
-
-/* Tables
-   ========================================================================== */
-
-/**
- * Remove most spacing between table cells.
- */
-
-table {
-  border-collapse: collapse;
-  border-spacing: 0;
-}
-
-td,
-th {
-  padding: 0;
-}
diff --git a/templates/html_report/css/roboto.css b/templates/html_report/css/roboto.css
deleted file mode 100644
index 7ab7186d..00000000
--- a/templates/html_report/css/roboto.css
+++ /dev/null
@@ -1,12 +0,0 @@
-@font-face {
-  font-family: 'Roboto';
-  font-style: normal;
-  font-weight: 300;
-  src: local('Roboto Light'), local('Roboto-Light'), url(../fonts/roboto-light.ttf) format('truetype');
-}
-@font-face {
-  font-family: 'Roboto';
-  font-style: normal;
-  font-weight: 700;
-  src: local('Roboto Bold'), local('Roboto-Bold'), url(../fonts/roboto-bold.ttf) format('truetype');
-}
diff --git a/templates/html_report/css/style.css b/templates/html_report/css/style.css
deleted file mode 100644
index 442d553b..00000000
--- a/templates/html_report/css/style.css
+++ /dev/null
@@ -1,705 +0,0 @@
-/* ------------- layout -------- */
-body {
-    background: #EAEAEA;
-    padding-top: 80px;
-    font-family: "Roboto", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
-}
-
-.row {
-    margin-bottom: .5em;
-    align-items: stretch;
-}
-
-.headerbar {
-    background-color: #fff;
-    border-bottom:3px solid #E4E4E4;
-    height:80px;
-    line-height:80px;
-    position: fixed;
-    top:0;
-    width: 100%;
-    z-index: 1;
-}
-.headerbarInner {
-    padding: 0 1em;
-}
-.headerbar img {
-    display:inline-block;;
-    vertical-align: middle;
-    height:60px;
-}
-.headerbar .title {
-    display:inline-block;;
-    font-size: 1.2em;
-    font-weight: bold;
-}
-.headerbar .subtitle {
-    display:inline-block;;
-    font-size: 1.2em;
-}
-
-
-
-/* ----------- text ---------- */
-a {
-    color: #4CAF50;
-    cursor: pointer;
-}
-
-
-/* ------------- menu -------- */
-.navigation {
-    left: 0;
-    max-width: 100vw;
-    max-width: 100%;
-    right: 0;
-    top: 0;
-    z-index: 99;
-    margin-bottom: 1em;
-}
-
-/* Re-overiding the width 100% declaration to match size of% based container */
-.navigation .container {
-    padding-bottom: 0;
-    padding-top: 0;
-}
-
-.navigation {
-    background: #f4f5f6;
-    border-bottom: .1rem solid #d1d1d1;
-    display: block;
-    height: 5.2rem;
-    width: 100%;
-}
-.navigation-list {
-    list-style: none;
-    margin-bottom: 0;
-    padding-right: 1.5em;
-}
-
-@media (min-width: 80.0rem) {
-    .navigation-list {
-        margin-right: 0;
-    }
-}
-@media (max-width: 600px) {
-    .navigation-list {
-        display:none
-    }
-}
-
-
-.navigation-item {
-    float: left;
-    margin-bottom: 0;
-    margin-left: 2.5rem;
-    position: relative;
-}
-
-.navigation .img {
-    height: 2.0rem;
-    position: relative;
-    top: .3rem;
-}
-
-.navigation .title,
-.navigation-title a {
-    color: #606c76;
-    display: inline;
-    font-family: 'Gotham Rounded A', 'Gotham Rounded B', 'Helvetica Neue', Arial, sans-serif;
-    font-size: 1.6rem;
-    line-height: 5.2rem;
-    padding: 0;
-    position: relative;
-    text-decoration: none;
-}
-
-.navigation-link {
-    display: inline;
-    font-size: 1.6rem;
-    line-height: 5.2rem;
-    padding: 0;
-    text-decoration: none;
-}
-
-.navigation-link.active {
-    color: #606c76;
-}
-
-/* Github */
-.github {
-    border: 0;
-    color: #f4f5f6;
-    fill: #4CAF50;
-    height: 5.2rem;
-    position: fixed;
-    right: 0;
-    top: 0;
-    width: 5.2rem;
-    z-index: 99;
-}
-
-.github:hover .octo-arm {
-    -webkit-animation: octocat-wave 560ms infinite;
-    animation: octocat-wave 560ms infinite;
-}
-
-@-webkit-keyframes octocat-wave {
-    0%, 50% {
-        -webkit-transform: rotate(0);
-        transform: rotate(0);
-    }
-    25%, 75% {
-        -webkit-transform: rotate(-25deg);
-        transform: rotate(-25deg);
-    }
-}
-
-@keyframes octocat-wave {
-    0%, 50% {
-        -webkit-transform: rotate(0);
-        transform: rotate(0);
-    }
-    25%, 75% {
-        -webkit-transform: rotate(-25deg);
-        transform: rotate(-25deg);
-    }
-}
-
-/* ---------- sidebar ------------- */
-.page {
-    margin-left: 300px;
-}
-.page .content {
-    padding: 2em 2em;
-    position:relative;
-}
-.content-first {
-    margin-top: 80px;
-}
-.content-full {
-    padding: 0;
-}
-.report-details {
-    position: absolute;
-    top:0;
-    right: 3em;
-    color: #666;
-    font-size: 0.8em;
-}
-.report-details a {
-    color: #666;
-    text-decoration: underline;
-}
-@media (max-width: 600px) {
-    .report-details {
-        display: none;
-    }
-}
-
-
-#sidebar {
-    position: fixed;
-    top: 80px;
-    left: 0;
-    background: #4CAF50;
-    width: 300px;
-    height: 92%;
-    overflow: auto;
-    color: #FFF;
-    text-align: left;
-}
-@media (max-width: 600px) {
-    #sidebar {
-        display: none;
-    }
-    .page {
-        margin-left: 0;
-    }
-}
-
-#sidebar .content {
-    padding: 1em;
-}
-
-#sidebar .logo {
-    text-align: center;
-    margin-bottom: 1em;
-}
-
-#sidebar .logo img {
-    width: 150px;
-}
-
-#sidebar .links ul {
-    list-style: none;
-}
-
-#sidebar .links li {
-}
-
-#sidebar .links a {
-    display: block;
-    color: #FFF;
-    line-height: 24px;
-    padding: 10px;
-}
-#sidebar .links .sep {
-    margin-top:1em;
-    padding-top: 1em;
-    border-top:1px solid #81C784;
-}
-
-#sidebar .links svg, #sidebar .links img {
-    vertical-align: top;
-    margin-right: .5em;
-}
-
-#sidebar .links a:hover {
-    background-color: #81C784;
-}
-
-/* ------------- fullwidth -------- */
-.fullwidth #content {
-    margin-left: 0;
-}
-.fullwidth #content, .fullwidth .container, .fullwidth .row, .fullwidth .column {
-    width: auto;
-    max-width:none;
-    flex:auto;
-    float:none;
-
-}
-
-
-/* ------------- text -------- */
-.badge {
-    -webkit-border-radius: 4px;
-    -moz-border-radius: 4px;
-    border-radius: 4px;
-    background-color: #EEE;
-    color: #333;
-    display: inline-block;
-    padding: 1px 5px;
-    margin: 4px auto;
-    font-size: 0.8em;
-}
-
-.badge-score {
-    background-color: #4CAF50;
-    color: #FFF;
-}
-.progress {
-    -webkit-border-radius: 4px;
-    -moz-border-radius: 4px;
-    border-radius: 4px;
-    background-color: #EEE;
-    color: #333;
-    display: inline-block;
-    padding: 1px 5px;
-    font-size: 0.8em;
-    position: absolute;
-    right: 10px;
-    top: 10px;
-}
-.progress svg {
-    vertical-align:middle;;
-}
-.progress-good {
-    background-color: #4CAF50;
-    color: #FFF;
-}
-.progress-bad {
-    background-color: #F44336;
-    color: #FFF;
-}
-.path {
-    font-family: "Menlo", "Consolas", "Bitstream Vera Sans Mono", "DejaVu Sans Mono", "Monaco", monospace;
-    color: #2f855a;
-    background-color: #f0fff4;
-    display: inline-block;
-    padding: 1px 4px;
-}
-a[target="_blank"]::before {
-    content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAQElEQVR42qXKwQkAIAxDUUdxtO6/RBQkQZvSi8I/pL4BoGw/XPkh4XigPmsUgh0626AjRsgxHTkUThsG2T/sIlzdTsp52kSS1wAAAABJRU5ErkJggg==);
-    margin: 0 5px 0 3px;
-}
-
-
-/* ------------ Bloc number ------ */
-.bloc {
-    position: relative;
-    text-align: center;
-    background: #FFF;
-    padding: 15px;
-    border: 0;
-    box-shadow: 0 2px 7px 0 rgba(42, 51, 83, 0.12), 0 5px 15px rgba(0, 0, 0, 0.06);
-    transition: all .15s ease;
-    border-radius: .5rem;
-    border-top: 4px solid #48bb78
-}
-
-.bloc .number {
-    font-size: 2.1em;
-    font-weight: bold;
-    color: #333;
-    text-align: left;
-}
-.bloc .number, .bloc .number-alternate {
-    min-height: 55px;
-}
-.bloc .chart-in-number {
-    margin-top:1em;
-}
-.bloc .bloc-action {
-    background-color: #f3f7fa;
-    text-align: center;
-    padding:10px 0;
-    margin:0 -15px -15px -15px;
-    -webkit-border-bottom-right-radius: 3px;
-    -webkit-border-bottom-left-radius: 3px;
-    -moz-border-radius-bottomright: 3px;
-    -moz-border-radius-bottomleft: 3px;
-    border-bottom-right-radius: 3px;
-    border-bottom-left-radius: 3px;
-    font-size: 0.9em;
-    color: #95999c;
-}
-.bloc .bloc-action a {
-    color: #48566c;
-    text-decoration: none;
-}
-.bloc .bloc-action a:hover {
-    color: #000;
-}
-.bloc .label {
-    color: #333;
-    text-align: left;
-    margin-bottom:.5em;
-    font-weight: 700;
-}
-
-.bloc-number {
-    min-height: 140px;
-}
-.bloc h4 {
-    text-align: left;
-}
-.column.with-help {
-    padding-right:0;
-    padding-bottom:0;
-}
-.column-help .column-help-inner {
-    background-color: #fff;
-    height:100%;
-}
-.help {
-    padding-left:0;
-    color: hsl(0, 0%, 55%);
-    text-align: left;
-    font-size: 0.9em;
-}
-.column.help {
-    align-items: stretch;
-    display: flex;
-}
-.column.help .help-inner {
-    border-left:2px solid #E4E4E4;
-    padding:1em;
-    margin-bottom: 0 !important;
-}
-.column-help {
-    margin-bottom: 0 !important;
-}
-
-/* ----- list ----- */
-.list {
-    text-align: left;
-}
-.list-item {
-    padding:1em;
-    position: relative;
-    -webkit-border-radius: 4px;
-    -moz-border-radius: 4px;
-    border-radius: 4px;
-}
-.list-item-title {
-    font-weight: bold;
-}
-.list-item:hover {
-    background-color: #EBF8FF;
-}
-.table-metrics {
-    margin: 0.5em;
-    text-align: center;
-}
-.table-metrics td {
-    text-align: center;
-}
-.table-metrics .card-number {
-    font-weight: bold;
-}
-.table-metrics .card-label {
-    color: #333;
-    font-size: 0.9em;
-}
-
-/* -------- charts ---------------- */
-.tooltip {
-    position: absolute;
-    background: #333;
-    border-radius: 5px;
-    padding: 5px 15px;
-    box-shadow: 1px 1px 3px;
-    text-align: left;
-    color: #FFF;
-    z-index: 4;
-}
-
-.bar {
-    fill: #4CAF50;
-}
-
-.bar:hover {
-    fill: #81C784;
-}
-
-.axis {
-    font: 10px sans-serif;
-}
-
-.axis path,
-.axis line,
-.scattered-plot path {
-    fill: none;
-    stroke: #000;
-    shape-rendering: crispEdges;
-}
-
-.x.axis path {
-    display: none;
-}
-.scattered-plot .x.axis path {
-    display: block;
-}
-.axis path,
-.axis line {
-    fill: none;
-    stroke: #000;
-    shape-rendering: crispEdges;
-}
-.svg-container {
-    position:relative;
-}
-.btn-save-image {
-    position:absolute;
-    top: 0;
-    left: 0;
-    background:#333;
-    color: #FFF;
-    font-size: 0.8em;
-    line-height: 1em;
-    height: 1em;
-    cursor: pointer;
-    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
-    filter: alpha(opacity=20);
-    -moz-opacity: 0.20;
-    -khtml-opacity: 0.20;
-    opacity: 0.20;
-    transition: opacity .2s ease-out;
-    -moz-transition: opacity .2s ease-out;
-    -webkit-transition: opacity .2s ease-out;
-    -o-transition: opacity .2s ease-out;
-}
-.btn-save-image:hover {
-    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
-    filter: alpha(opacity=100);
-    -moz-opacity: 1;
-    -khtml-opacity: 1;
-    opacity: 1;
-}
-
-/* -------- Table ------------ */
-table tr td {
-    border:none;
-    padding: 4px 0;
-}
-#table-length tbody {
-    font-size: 0.8em;
-}
-
-#table-junit tbody {
-    font-size: 0.8em;
-}
-
-#table-pagerank tbody {
-    font-size: 0.8em;
-}
-
-#table-relations tbody {
-    font-size: 0.8em;
-}
-.table-small {
-    font-size:0.8em;
-}
-
-#pagination a {
-    display: inline-block;
-    padding: 0 .5em;
-    cursor: pointer;
-}
-
-.js-sort-table thead th {
-    cursor: pointer;
-}
-
-/* ---- tabs ---- */
-.tabs {
-    list-style: none;
-    margin: 0;
-    padding: 0;
-}
-.tabs li {
-    list-style: none;
-    display: inline-block;
-    margin:0;
-}
-.tabs li a {
-    text-decoration: none;
-    padding: .5em 1em;
-    display: inline-block;
-    border-top: 4px solid #FFF;
-    border-bottom: 4px solid #FFF;
-}
-.tabs li a:hover, .tabs li.active a  {
-    border-bottom: 4px solid #48bb78;
-}
-.tabs li.active a  {
-    font-weight: bold;
-}
-
-.group-tabs {
-    background-color: #fff;
-    line-height: 2em;
-    margin-bottom: 1em;
-    -webkit-border-radius: 4px;
-    -moz-border-radius: 4px;
-    border-radius: 4px;
-}
-
-/* ---- relations ---- */
-.node {
-    font: 300 11px "Helvetica Neue", Helvetica, Arial, sans-serif;
-    fill: #bbb;
-}
-
-.node:hover {
-    fill: #000;
-}
-
-.link {
-    stroke: steelblue;
-    stroke-opacity: .4;
-    fill: none;
-    pointer-events: none;
-}
-
-.node:hover,
-.node--source,
-.node--target {
-    font-weight: 700;
-}
-
-.node--source {
-    fill: #AE113D;
-}
-
-.node--target {
-    fill: #4617B4;
-}
-
-.link--source,
-.link--target {
-    stroke-opacity: 1;
-    stroke-width: 2px;
-}
-
-.link--source {
-    stroke: #AE113D;
-}
-
-.link--target {
-    stroke: #4617B4;
-}
-
-.relation-source {
-    background-color: #AE113D;
-}
-
-.relation-target {
-    background-color: #4617B4;
-}
-
-/* ---------- footer ---------- */
-.container {
-    padding-bottom: 40px;
-}
-
-footer {
-    position: fixed;
-    bottom: 0;
-    left: 0;
-    width: 100%;
-    background: #FFF;
-    border-top: 1px solid #CCC;
-    padding: 5px 0;
-    text-align: center;
-    font-size: .8em;
-}
-
-
-/* ---------- violations ---------- */
-.violation-list {
-    display: none;
-}
-.violation {
-    padding-left:50px;
-    margin-top: .5em;
-}
-.violation .name {
-    font-weight: bold;
-    margin-top:1em;
-}
-.progress-good {
-    background-color: #4CAF50;
-    color: #FFF;
-}
-.level-critical{
-    background-color: #F44336;
-    color: #FFF;
-}
-.level-error{
-    background-color: #F44336;
-    color: #FFF;
-}
-.level-warning{
-    background-color: darkorange;
-    color: #FFF;
-}
-
-
-/* ------- overrides -------- */
-@media (min-width: 600px) {
-    .clusterize-scroll {
-        max-height: 400px !important;
-    }
-}
-
-
-/* ------ composer ----- */
-.help-warning {
-    background-color: #fbd38d;
-}
-.help-info {
-    background-color:#A7F9FC;
-}
diff --git a/templates/html_report/favicon.ico b/templates/html_report/favicon.ico
deleted file mode 100644
index 36692aec..00000000
Binary files a/templates/html_report/favicon.ico and /dev/null differ
diff --git a/templates/html_report/fonts/material-icons.ttf b/templates/html_report/fonts/material-icons.ttf
deleted file mode 100644
index 691bd26d..00000000
Binary files a/templates/html_report/fonts/material-icons.ttf and /dev/null differ
diff --git a/templates/html_report/fonts/roboto-bold.ttf b/templates/html_report/fonts/roboto-bold.ttf
deleted file mode 100644
index c76118b2..00000000
Binary files a/templates/html_report/fonts/roboto-bold.ttf and /dev/null differ
diff --git a/templates/html_report/fonts/roboto-light.ttf b/templates/html_report/fonts/roboto-light.ttf
deleted file mode 100644
index ef52b760..00000000
Binary files a/templates/html_report/fonts/roboto-light.ttf and /dev/null differ
diff --git a/templates/html_report/git.php b/templates/html_report/git.php
deleted file mode 100644
index fb0adbaf..00000000
--- a/templates/html_report/git.php
+++ /dev/null
@@ -1,202 +0,0 @@
-<?php
-require __DIR__ . '/_header.php'; ?>
-
-
-<?php
-// build d3js json
-$json = [];
-$history = [];
-if (isset($project['git'], $project['git']['history'])) {
-    $history = $project['git']['history'];
-
-    // Sort by key (date)
-    ksort($history);
-
-    // only last 24 weeks
-    $history = array_slice($history, -24);
-    $json = [];
-    foreach ($history as $date => $values) {
-        array_push($json, (object)[
-            'date' => $date,
-            'key' => 'Additions',
-            'value' => abs($values['additions']),
-        ]);
-        array_push($json, (object)[
-            'date' => $date,
-            'key' => 'Removes',
-            'value' => abs($values['removes']),
-        ]);
-    }
-}
-
-// authors
-$authors = [];
-if (isset($project['git'], $project['git']['authors'])) {
-    $authors = $project['git']['authors'];
-}
-?>
-
-<div class="row">
-    <div class="column">
-        <div class="bloc">
-            <h4>Git history
-                <small>(PHP files only)</small>
-            </h4>
-            <div id="chart-git-history" style="height:200px"></div>
-        </div>
-    </div>
-</div>
-
-<div class="row">
-    <div class="column column-60">
-        <div class="bloc">
-            <h4>Most committed PHP files</h4>
-            <table class="js-sort-table table-small" id="table-commits">
-                <thead>
-                <tr>
-                    <th>File</th>
-                    <th class="js-sort-number">Commits</th>
-                </tr>
-                </thead>
-                <tbody>
-                <?php foreach ($files as $file) { ?>
-                    <tr>
-                        <td><?php echo $file['name']; ?></td>
-                        <td><?php echo $file['gitChanges']; ?></td>
-                    </tr>
-                <?php } ?>
-                </tbody>
-            </table>
-        </div>
-    </div>
-    <div class="column">
-        <div class="bloc">
-            <h4>Contributors <small>(PHP only)</small></h4>
-            <table class="js-sort-table table-small" id="table-authors">
-                <thead>
-                <tr>
-                    <th>Name</th>
-                    <th class="js-sort-number">Commits</th>
-                    <th class="js-sort-number">Additions</th>
-                    <th class="js-sort-number">Removes</th>
-                    <th class="js-sort-number">Files</th>
-                </tr>
-                </thead>
-                <tbody>
-                <?php foreach ($authors as $author => $data) { ?>
-                    <tr>
-                        <td><?php echo $author; ?></td>
-                        <td><?php echo $data['commits']; ?></td>
-                        <td><?php echo $data['additions']; ?></td>
-                        <td><?php echo $data['removes']; ?></td>
-                        <td><?php echo $data['nbFiles']; ?></td>
-                    </tr>
-                <?php } ?>
-                </tbody>
-            </table>
-        </div>
-    </div>
-</div>
-
-<?php require __DIR__ . '/_footer.php'; ?>
-
-
-<script>
-    var format = d3.time.format("%Y-%W");
-
-    var margin = {top: 20, right: 0, bottom: 40, left: 40},
-        width = document.getElementById('chart-git-history').offsetWidth - margin.left - margin.right,
-        height = document.getElementById('chart-git-history').offsetHeight - margin.top - margin.bottom;
-
-    var x = d3.time.scale()
-        .range([0, width]);
-
-    var y = d3.scale.linear()
-        .range([height, 0]);
-
-    var z = d3.scale.category20c();
-
-    var xAxis = d3.svg.axis()
-        .scale(x)
-        .orient("bottom")
-        .ticks(d3.time.month);
-
-    var yAxis = d3.svg.axis()
-        .scale(y)
-        .orient("left");
-
-    var stack = d3.layout.stack()
-        .offset("zero")
-        .values(function (d) {
-            return d.values;
-        })
-        .x(function (d) {
-            return d.date;
-        })
-        .y(function (d) {
-            return d.value;
-        });
-
-    var nest = d3.nest()
-        .key(function (d) {
-            return d.key;
-        });
-
-    var area = d3.svg.area()
-        .interpolate("cardinal")
-        .x(function (d) {
-            return x(d.date);
-        })
-        .y0(function (d) {
-            return y(d.y0);
-        })
-        .y1(function (d) {
-            return y(d.y0 + d.y);
-        });
-
-    var svg = d3.select("#chart-git-history").append("svg")
-        .attr("width", width + margin.left + margin.right)
-        .attr("height", height + margin.top + margin.bottom)
-        .append("g")
-        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
-    var data = <?php echo json_encode($json, JSON_PRETTY_PRINT); ?>;
-
-    data.forEach(function (d) {
-        d.date = format.parse(d.date);
-    });
-
-    var layers = stack(nest.entries(data));
-
-    x.domain(d3.extent(data, function (d) {
-        return d.date;
-    }));
-    y.domain([0, d3.max(data, function (d) {
-        return d.y0 + d.y;
-    })]);
-
-    svg.selectAll(".layer")
-        .data(layers)
-        .enter().append("path")
-        .attr("class", "layer")
-        .attr("d", function (d) {
-            return area(d.values);
-        })
-        .style("fill", function (d, i) {
-            return z(i);
-        });
-
-    svg.append("g")
-        .attr("class", "x axis")
-        .attr("transform", "translate(0," + height + ")")
-        .call(xAxis);
-
-    svg.append("g")
-        .attr("class", "y axis")
-        .call(yAxis);
-
-
-    sortTable(document.getElementById('table-commits'), 1, -1);
-    sortTable(document.getElementById('table-authors'), 1, -1);
-
-</script>
diff --git a/templates/html_report/images/logo-git.png b/templates/html_report/images/logo-git.png
deleted file mode 100644
index adf6623a..00000000
Binary files a/templates/html_report/images/logo-git.png and /dev/null differ
diff --git a/templates/html_report/images/logo.png b/templates/html_report/images/logo.png
deleted file mode 100644
index eacdee22..00000000
Binary files a/templates/html_report/images/logo.png and /dev/null differ
diff --git a/templates/html_report/images/phpmetrics-maintenability.png b/templates/html_report/images/phpmetrics-maintenability.png
deleted file mode 100644
index eacdee22..00000000
Binary files a/templates/html_report/images/phpmetrics-maintenability.png and /dev/null differ
diff --git a/templates/html_report/index.php b/templates/html_report/index.php
deleted file mode 100644
index e733473a..00000000
--- a/templates/html_report/index.php
+++ /dev/null
@@ -1,233 +0,0 @@
-<?php
-require __DIR__ . '/_header.php'; ?>
-    <div class="row">
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label"><a href="violations.html">Violations</a> (<?php echo $sum->violations->critical; ?>
-                    criticals, <?php echo $sum->violations->error; ?> errors)
-                </div>
-                <div class="number"><?php echo number_format($sum->violations->total, 0); ?></div>
-                <div class="bloc-action">
-                    <a href="violations.html">View details &gt;</a>
-                </div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <?php echo $this->getTrend('sum', 'loc'); ?>
-                <div class="label"><a href="loc.html">Lines of code</a></div>
-                <div class="number"><?php echo number_format($sum->loc, 0); ?></div>
-                <div class="bloc-action">
-                    <a href="loc.html">View details &gt;</a>
-                </div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <?php echo $this->getTrend('sum', 'nbClasses'); ?>
-                <div class="label"><a href="oop.html">Classes</a></div>
-                <div class="number"><?php echo number_format($sum->nbClasses, 0); ?></div>
-                <div class="bloc-action">
-                    <a href="loc.html">View details &gt;</a>
-                </div>
-            </div>
-        </div>
-    </div>
-
-
-    <div class="row">
-        <div class="column">
-            <div class="bloc bloc-number">
-                <?php echo $this->getTrend('avg', 'ccn', true); ?>
-                <div class="label"><a href="complexity.html">Average cyclomatic complexity by class</a></div>
-                <div class="number"><?php echo number_format($avg->ccn, 2); ?></div>
-                <div class="bloc-action">
-                    <a href="complexity.html">View details &gt;</a>
-                </div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">
-                    <a href="junit.html">Assertions in tests</a>
-                </div>
-                <?php if(isset($project['unitTesting'])) { ?>
-                    <div class="number">
-                        <?php echo $project['unitTesting']['assertions']; ?>
-                    </div>
-                    <div class="bloc-action">
-                        <a href="junit.html">View details &gt;</a>
-                    </div>
-                <?php } else { ?>
-                    <div class="help number-alternate">
-                        <div class="help-inner">
-                            No JUnit report found. Use the --junit=&lt;junit.xml&gt; option to analyse your unit tests.
-                            See <a href="https://phpunit.readthedocs.io/fr/latest/textui.html" target="_blank">documentation of PHPUnit if needed</a>
-                        </div>
-                    </div>
-                    <div class="bloc-action">
-                        No details
-                    </div>
-                <?php } ?>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <?php echo $this->getTrend('avg', 'bugs', true); ?>
-                <div class="label"><a href="complexity.html">Average bugs by class</a></div>
-                <div class="number">
-                    <?php echo number_format($avg->bugs, 2); ?>
-                </div>
-                <div class="bloc-action">
-                    <a href="complexity.html">View details &gt;</a>
-                </div>
-            </div>
-        </div>
-    </div>
-
-    <div class="row">
-        <div class="column column-help">
-            <div class="bloc" style="min-height: 540px;">
-                <div class="column column-help-inner">
-                    <div class="row">
-                        <div class="column with-help">
-                            <div>
-                                <div class="label">
-                                    Maintainability / complexity
-                                    <small><a
-                                            data-current="with-comments"
-                                            onclick="toggleChartMaintainability(this)">
-                                                (with comments)
-                                    </a></small>
-                                </div>
-                                <div id="svg-maintainability" class="svg-container"></div>
-                            </div>
-                        </div>
-                        <div class="column help">
-                            <div class="help-inner">
-                                <p>Each file is symbolized by a circle. Size of the circle represents the Cyclomatic
-                                    complexity.
-                                    Color of the circle represents the Maintainability Index.</p>
-                                <p>Large red circles will be probably hard to maintain.</p>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-
-        <div class="column">
-            <div class="bloc bloc-number" style="min-height: 540px;">
-                <div class="label">ClassRank
-                    <small>(<a href="https://en.wikipedia.org/wiki/PageRank" target="_blank">Google's page rank applied to relations between classes)</a></small>
-                </div>
-                <div class="help">
-                    <div class="help-inner">
-                        <p>
-                            Page Rank is a way to measure the importance of a class. There is no "good" or "bad" page rank. This metric reflects interactions in your code.
-                        </p>
-                    </div>
-                </div>
-                <div class="clusterize small">
-                    <div id="clusterizeClassRank" class="clusterize-scroll">
-                        <table class="table-small">
-                            <thead>
-                            <tr>
-                                <th>ClassRank</th>
-                                <th></th>
-                            </tr>
-                            </thead>
-                            <tbody id="contentClassRank" class="clusterize-content">
-                            <?php
-                            $classesS = $classes;
-                            usort($classesS, static function ($a, $b) {
-                                return strcmp($b['pageRank'], $a['pageRank']);
-                            });
-                            //$classesS = array_slice($classesS, 0, 10);
-                            foreach ($classesS as $class) { ?>
-                                <tr>
-                                    <td>
-                                        <span class="badge" <?php echo gradientStyleFor($classes, 'pageRank', $class['pageRank']);?>><?php echo $class['pageRank']; ?></span>
-                                    </td>
-                                    <td>
-                                        <span class="path"><?php echo $class['name']; ?></span>
-<?php
-    $badgeTitleMIWOC = 'Maintainability Index (w/o comments)';
-    $mIwoC = isset($class['mIwoC']) ? $class['mIwoC'] : '';
-    $badgeTitleMI = 'Maintainability Index';
-    $mi = isset($class['mi']) ? $class['mi'] : '';
-?>
-                                        <span class="badge" title="<?php echo $badgeTitleMI;?>"><?php echo $mi;?></span>
-                                        <span class="badge" title="<?php echo $badgeTitleMIWOC;?>"><?php echo $mIwoC;?></span>
-                                    </td>
-                                </tr>
-                            <?php } ?>
-                            </tbody>
-                        </table>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-
-    <div class="row">
-        <?php if($this->isHomePage()) {?>
-            <div class="column">
-                <div class="bloc bloc-number">
-                    <div class="label">
-                        <a href="composer.html">Composer</a>
-                    </div>
-                    <?php
-                    $packages = isset($project['composer']['packages']) ? $project['composer']['packages'] : [];
-                    $packagesInstalled = isset($project['composer']['packages-installed']) ? $project['composer']['packages-installed'] : [];
-                    if ([] === $packages) { ?>
-                        <div class="help number-alternate"><div class="help-inner">No composer.json file found</div></div>
-                    <?php } else {?>
-                        <div class="number">
-                            <?php echo count($packages);?> dependencies
-                        </div>
-                    <?php } ?>
-
-                    <div id="svg-licenses" class="chart-in-number"></div>
-                    <div class="bloc-action">
-                        <a href="composer.html">View details &gt;</a>
-                    </div>
-                </div>
-            </div>
-        <?php }?>
-        <div class="column"></div>
-        <div class="column"></div>
-    </div>
-
-
-    <script>
-        document.onreadystatechange = function () {
-            if (document.readyState === 'complete') {
-                chartMaintainability();
-
-                new Clusterize({
-                    scrollId: 'clusterizeClassRank',
-                    contentId: 'contentClassRank'
-                });
-
-                // prepare json for packages pie
-                <?php
-                $json = [];
-                $packages = isset($project['composer']['packages']) ? $project['composer']['packages'] : [];
-                foreach ($packages as $package) {
-                    foreach ($package->license as $license) {
-                        if (!isset($json[$license])) {
-                            $json[$license] = new stdClass();
-                            $json[$license]->name = $license;
-                            $json[$license]->value = 0;
-                        }
-                        $json[$license]->value++;
-                    }
-                }
-                ?>
-                chartLicenses(<?php echo json_encode(array_values($json));?>);
-            }
-        };
-    </script>
-
-<?php require __DIR__ . '/_footer.php'; ?>
diff --git a/templates/html_report/js/FileSaver.min.js b/templates/html_report/js/FileSaver.min.js
deleted file mode 100644
index 183d42a1..00000000
--- a/templates/html_report/js/FileSaver.min.js
+++ /dev/null
@@ -1,3 +0,0 @@
-(function(a,b){if("function"==typeof define&&define.amd)define([],b);else if("undefined"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Deprecated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(b,c,d){var e=new XMLHttpRequest;e.open("GET",b),e.responseType="blob",e.onload=function(){a(e.response,c,d)},e.onerror=function(){console.error("could not download file")},e.send()}function d(a){var b=new XMLHttpRequest;b.open("HEAD",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=f.saveAs||("object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(a,b,d,e){if(e=e||open("","_blank"),e&&(e.document.title=e.document.body.innerText="downloading..."),"string"==typeof a)return c(a,b,d);var g="application/octet-stream"===a.type,h=/constructor/i.test(f.HTMLElement)||f.safari,i=/CriOS\/[\d]+/.test(navigator.userAgent);if((i||g&&h)&&"undefined"!=typeof FileReader){var j=new FileReader;j.onloadend=function(){var a=j.result;a=i?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),e?e.location.href=a:location=a,e=null},j.readAsDataURL(a)}else{var k=f.URL||f.webkitURL,l=k.createObjectURL(a);e?e.location=l:location.href=l,e=null,setTimeout(function(){k.revokeObjectURL(l)},4E4)}});f.saveAs=a.saveAs=a,"undefined"!=typeof module&&(module.exports=a)});
-
-//# sourceMappingURL=FileSaver.min.js.map
\ No newline at end of file
diff --git a/templates/html_report/js/FileSaver.min.js.map b/templates/html_report/js/FileSaver.min.js.map
deleted file mode 100644
index 4fbcdd2e..00000000
--- a/templates/html_report/js/FileSaver.min.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../src/FileSaver.js"],"names":[],"mappings":"uLAkBA,QAAS,CAAA,CAAT,CAAc,CAAd,CAAoB,CAApB,CAA0B,OACJ,WAAhB,QAAO,CAAA,CADa,CACS,CAAI,CAAG,CAAE,OAAO,GAAT,CADhB,CAEC,QAAhB,QAAO,CAAA,CAFQ,GAGtB,OAAO,CAAC,IAAR,CAAa,oDAAb,CAHsB,CAItB,CAAI,CAAG,CAAE,OAAO,CAAE,CAAC,CAAZ,CAJe,EASpB,CAAI,CAAC,OAAL,EAAgB,6EAA6E,IAA7E,CAAkF,CAAI,CAAC,IAAvF,CATI,CAUf,GAAI,CAAA,IAAJ,CAAS,UAA8B,CAA9B,CAAT,CAA8C,CAAE,IAAI,CAAE,CAAI,CAAC,IAAb,CAA9C,CAVe,CAYjB,CACR,CAED,QAAS,CAAA,CAAT,CAAmB,CAAnB,CAAwB,CAAxB,CAA8B,CAA9B,CAAoC,CAClC,GAAI,CAAA,CAAG,CAAG,GAAI,CAAA,cAAd,CACA,CAAG,CAAC,IAAJ,CAAS,KAAT,CAAgB,CAAhB,CAFkC,CAGlC,CAAG,CAAC,YAAJ,CAAmB,MAHe,CAIlC,CAAG,CAAC,MAAJ,CAAa,UAAY,CACvB,CAAM,CAAC,CAAG,CAAC,QAAL,CAAe,CAAf,CAAqB,CAArB,CACP,CANiC,CAOlC,CAAG,CAAC,OAAJ,CAAc,UAAY,CACxB,OAAO,CAAC,KAAR,CAAc,yBAAd,CACD,CATiC,CAUlC,CAAG,CAAC,IAAJ,EACD,CAED,QAAS,CAAA,CAAT,CAAsB,CAAtB,CAA2B,CACzB,GAAI,CAAA,CAAG,CAAG,GAAI,CAAA,cAAd,CAEA,CAAG,CAAC,IAAJ,CAAS,MAAT,CAAiB,CAAjB,IAHyB,CAIzB,GAAI,CACF,CAAG,CAAC,IAAJ,EACD,CAAC,MAAO,CAAP,CAAU,CAAE,CACd,MAAqB,IAAd,EAAA,CAAG,CAAC,MAAJ,EAAmC,GAAd,EAAA,CAAG,CAAC,MACjC,CAGD,QAAS,CAAA,CAAT,CAAgB,CAAhB,CAAsB,CACpB,GAAI,CACF,CAAI,CAAC,aAAL,CAAmB,GAAI,CAAA,UAAJ,CAAe,OAAf,CAAnB,CACD,CAAC,MAAO,CAAP,CAAU,CACV,GAAI,CAAA,CAAG,CAAG,QAAQ,CAAC,WAAT,CAAqB,aAArB,CAAV,CACA,CAAG,CAAC,cAAJ,CAAmB,OAAnB,OAAwC,MAAxC,CAAgD,CAAhD,CAAmD,CAAnD,CAAsD,CAAtD,CAAyD,EAAzD,CACsB,EADtB,aACsD,CADtD,CACyD,IADzD,CAFU,CAIV,CAAI,CAAC,aAAL,CAAmB,CAAnB,CACD,CACF,C,GAtDG,CAAA,CAAO,CAAqB,QAAlB,QAAO,CAAA,MAAP,EAA8B,MAAM,CAAC,MAAP,GAAkB,MAAhD,CACV,MADU,CACe,QAAhB,QAAO,CAAA,IAAP,EAA4B,IAAI,CAAC,IAAL,GAAc,IAA1C,CACT,IADS,CACgB,QAAlB,QAAO,CAAA,MAAP,EAA8B,MAAM,CAAC,MAAP,GAAkB,MAAhD,CACP,MADO,O,CAsDP,CAAM,CAAG,CAAO,CAAC,MAAR,GAEQ,QAAlB,QAAO,CAAA,MAAP,EAA8B,MAAM,GAAK,CAA1C,CACI,UAAmB,CAAc,CADrC,CAIE,YAAc,CAAA,iBAAiB,CAAC,SAAhC,CACA,SAAiB,CAAjB,CAAuB,CAAvB,CAA6B,CAA7B,CAAmC,IAC/B,CAAA,CAAG,CAAG,CAAO,CAAC,GAAR,EAAe,CAAO,CAAC,SADE,CAE/B,CAAC,CAAG,QAAQ,CAAC,aAAT,CAAuB,GAAvB,CAF2B,CAGnC,CAAI,CAAG,CAAI,EAAI,CAAI,CAAC,IAAb,EAAqB,UAHO,CAKnC,CAAC,CAAC,QAAF,CAAa,CALsB,CAMnC,CAAC,CAAC,GAAF,CAAQ,UAN2B,CAWf,QAAhB,QAAO,CAAA,CAXwB,EAajC,CAAC,CAAC,IAAF,CAAS,CAbwB,CAc7B,CAAC,CAAC,MAAF,GAAa,QAAQ,CAAC,MAdO,CAmB/B,CAAK,CAAC,CAAD,CAnB0B,CAe/B,CAAW,CAAC,CAAC,CAAC,IAAH,CAAX,CACI,CAAQ,CAAC,CAAD,CAAO,CAAP,CAAa,CAAb,CADZ,CAEI,CAAK,CAAC,CAAD,CAAI,CAAC,CAAC,MAAF,CAAW,QAAf,CAjBsB,GAuBjC,CAAC,CAAC,IAAF,CAAS,CAAG,CAAC,eAAJ,CAAoB,CAApB,CAvBwB,CAwBjC,UAAU,CAAC,UAAY,CAAE,CAAG,CAAC,eAAJ,CAAoB,CAAC,CAAC,IAAtB,CAA6B,CAA5C,CAA8C,GAA9C,CAxBuB,CAyBjC,UAAU,CAAC,UAAY,CAAE,CAAK,CAAC,CAAD,CAAK,CAAzB,CAA2B,CAA3B,CAzBuB,CA2BpC,CA5BC,CA+BA,oBAAsB,CAAA,SAAtB,CACA,SAAiB,CAAjB,CAAuB,CAAvB,CAA6B,CAA7B,CAAmC,CAGnC,GAFA,CAAI,CAAG,CAAI,EAAI,CAAI,CAAC,IAAb,EAAqB,UAE5B,CAAoB,QAAhB,QAAO,CAAA,CAAX,CAUE,SAAS,CAAC,gBAAV,CAA2B,CAAG,CAAC,CAAD,CAAO,CAAP,CAA9B,CAA4C,CAA5C,CAVF,KACE,IAAI,CAAW,CAAC,CAAD,CAAf,CACE,CAAQ,CAAC,CAAD,CAAO,CAAP,CAAa,CAAb,CADV,KAEO,CACL,GAAI,CAAA,CAAC,CAAG,QAAQ,CAAC,aAAT,CAAuB,GAAvB,CAAR,CACA,CAAC,CAAC,IAAF,CAAS,CAFJ,CAGL,CAAC,CAAC,MAAF,CAAW,QAHN,CAIL,UAAU,CAAC,UAAY,CAAE,CAAK,CAAC,CAAD,CAAK,CAAzB,CACX,CAIJ,CAhBC,CAmBA,SAAiB,CAAjB,CAAuB,CAAvB,CAA6B,CAA7B,CAAmC,CAAnC,CAA0C,CAS1C,GANA,CAAK,CAAG,CAAK,EAAI,IAAI,CAAC,EAAD,CAAK,QAAL,CAMrB,CALI,CAKJ,GAJE,CAAK,CAAC,QAAN,CAAe,KAAf,CACA,CAAK,CAAC,QAAN,CAAe,IAAf,CAAoB,SAApB,CAAgC,gBAGlC,EAAoB,QAAhB,QAAO,CAAA,CAAX,CAA8B,MAAO,CAAA,CAAQ,CAAC,CAAD,CAAO,CAAP,CAAa,CAAb,CAAf,CATY,GAWtC,CAAA,CAAK,CAAiB,0BAAd,GAAA,CAAI,CAAC,IAXyB,CAYtC,CAAQ,CAAG,eAAe,IAAf,CAAoB,CAAO,CAAC,WAA5B,GAA4C,CAAO,CAAC,MAZzB,CAatC,CAAW,CAAG,eAAe,IAAf,CAAoB,SAAS,CAAC,SAA9B,CAbwB,CAe1C,GAAI,CAAC,CAAW,EAAK,CAAK,EAAI,CAA1B,GAA8D,WAAtB,QAAO,CAAA,UAAnD,CAA+E,CAE7E,GAAI,CAAA,CAAM,CAAG,GAAI,CAAA,UAAjB,CACA,CAAM,CAAC,SAAP,CAAmB,UAAY,CAC7B,GAAI,CAAA,CAAG,CAAG,CAAM,CAAC,MAAjB,CACA,CAAG,CAAG,CAAW,CAAG,CAAH,CAAS,CAAG,CAAC,OAAJ,CAAY,cAAZ,CAA4B,uBAA5B,CAFG,CAGzB,CAHyB,CAGlB,CAAK,CAAC,QAAN,CAAe,IAAf,CAAsB,CAHJ,CAIxB,QAAQ,CAAG,CAJa,CAK7B,CAAK,CAAG,IACT,CAT4E,CAU7E,CAAM,CAAC,aAAP,CAAqB,CAArB,CACD,CAXD,IAWO,IACD,CAAA,CAAG,CAAG,CAAO,CAAC,GAAR,EAAe,CAAO,CAAC,SAD5B,CAED,CAAG,CAAG,CAAG,CAAC,eAAJ,CAAoB,CAApB,CAFL,CAGD,CAHC,CAGM,CAAK,CAAC,QAAN,CAAiB,CAHvB,CAIA,QAAQ,CAAC,IAAT,CAAgB,CAJhB,CAKL,CAAK,CAAG,IALH,CAML,UAAU,CAAC,UAAY,CAAE,CAAG,CAAC,eAAJ,CAAoB,CAApB,CAA0B,CAAzC,CAA2C,GAA3C,CACX,CACF,CA1FU,C,CA6Fb,CAAO,CAAC,MAAR,CAAiB,CAAM,CAAC,MAAP,CAAgB,C,CAEX,WAAlB,QAAO,CAAA,M,GACT,MAAM,CAAC,OAAP,CAAiB,C","file":"FileSaver.min.js","sourcesContent":["/*\n* FileSaver.js\n* A saveAs() FileSaver implementation.\n*\n* By Eli Grey, http://eligrey.com\n*\n* License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT)\n* source  : http://purl.eligrey.com/github/FileSaver.js\n*/\n\n// The one and only way of getting global scope in all environments\n// https://stackoverflow.com/q/3277182/1008999\nvar _global = typeof window === 'object' && window.window === window\n  ? window : typeof self === 'object' && self.self === self\n  ? self : typeof global === 'object' && global.global === global\n  ? global\n  : this\n\nfunction bom (blob, opts) {\n  if (typeof opts === 'undefined') opts = { autoBom: false }\n  else if (typeof opts !== 'object') {\n    console.warn('Deprecated: Expected third argument to be a object')\n    opts = { autoBom: !opts }\n  }\n\n  // prepend BOM for UTF-8 XML and text/* types (including HTML)\n  // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF\n  if (opts.autoBom && /^\\s*(?:text\\/\\S*|application\\/xml|\\S*\\/\\S*\\+xml)\\s*;.*charset\\s*=\\s*utf-8/i.test(blob.type)) {\n    return new Blob([String.fromCharCode(0xFEFF), blob], { type: blob.type })\n  }\n  return blob\n}\n\nfunction download (url, name, opts) {\n  var xhr = new XMLHttpRequest()\n  xhr.open('GET', url)\n  xhr.responseType = 'blob'\n  xhr.onload = function () {\n    saveAs(xhr.response, name, opts)\n  }\n  xhr.onerror = function () {\n    console.error('could not download file')\n  }\n  xhr.send()\n}\n\nfunction corsEnabled (url) {\n  var xhr = new XMLHttpRequest()\n  // use sync to avoid popup blocker\n  xhr.open('HEAD', url, false)\n  try {\n    xhr.send()\n  } catch (e) {}\n  return xhr.status >= 200 && xhr.status <= 299\n}\n\n// `a.click()` doesn't work for all browsers (#465)\nfunction click (node) {\n  try {\n    node.dispatchEvent(new MouseEvent('click'))\n  } catch (e) {\n    var evt = document.createEvent('MouseEvents')\n    evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80,\n                          20, false, false, false, false, 0, null)\n    node.dispatchEvent(evt)\n  }\n}\n\nvar saveAs = _global.saveAs || (\n  // probably in some web worker\n  (typeof window !== 'object' || window !== _global)\n    ? function saveAs () { /* noop */ }\n\n  // Use download attribute first if possible (#193 Lumia mobile)\n  : 'download' in HTMLAnchorElement.prototype\n  ? function saveAs (blob, name, opts) {\n    var URL = _global.URL || _global.webkitURL\n    var a = document.createElement('a')\n    name = name || blob.name || 'download'\n\n    a.download = name\n    a.rel = 'noopener' // tabnabbing\n\n    // TODO: detect chrome extensions & packaged apps\n    // a.target = '_blank'\n\n    if (typeof blob === 'string') {\n      // Support regular links\n      a.href = blob\n      if (a.origin !== location.origin) {\n        corsEnabled(a.href)\n          ? download(blob, name, opts)\n          : click(a, a.target = '_blank')\n      } else {\n        click(a)\n      }\n    } else {\n      // Support blobs\n      a.href = URL.createObjectURL(blob)\n      setTimeout(function () { URL.revokeObjectURL(a.href) }, 4E4) // 40s\n      setTimeout(function () { click(a) }, 0)\n    }\n  }\n\n  // Use msSaveOrOpenBlob as a second approach\n  : 'msSaveOrOpenBlob' in navigator\n  ? function saveAs (blob, name, opts) {\n    name = name || blob.name || 'download'\n\n    if (typeof blob === 'string') {\n      if (corsEnabled(blob)) {\n        download(blob, name, opts)\n      } else {\n        var a = document.createElement('a')\n        a.href = blob\n        a.target = '_blank'\n        setTimeout(function () { click(a) })\n      }\n    } else {\n      navigator.msSaveOrOpenBlob(bom(blob, opts), name)\n    }\n  }\n\n  // Fallback to using FileReader and a popup\n  : function saveAs (blob, name, opts, popup) {\n    // Open a popup immediately do go around popup blocker\n    // Mostly only available on user interaction and the fileReader is async so...\n    popup = popup || open('', '_blank')\n    if (popup) {\n      popup.document.title =\n      popup.document.body.innerText = 'downloading...'\n    }\n\n    if (typeof blob === 'string') return download(blob, name, opts)\n\n    var force = blob.type === 'application/octet-stream'\n    var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari\n    var isChromeIOS = /CriOS\\/[\\d]+/.test(navigator.userAgent)\n\n    if ((isChromeIOS || (force && isSafari)) && typeof FileReader !== 'undefined') {\n      // Safari doesn't allow downloading of blob URLs\n      var reader = new FileReader()\n      reader.onloadend = function () {\n        var url = reader.result\n        url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;')\n        if (popup) popup.location.href = url\n        else location = url\n        popup = null // reverse-tabnabbing #460\n      }\n      reader.readAsDataURL(blob)\n    } else {\n      var URL = _global.URL || _global.webkitURL\n      var url = URL.createObjectURL(blob)\n      if (popup) popup.location = url\n      else location.href = url\n      popup = null // reverse-tabnabbing #460\n      setTimeout(function () { URL.revokeObjectURL(url) }, 4E4) // 40s\n    }\n  }\n)\n\n_global.saveAs = saveAs.saveAs = saveAs\n\nif (typeof module !== 'undefined') {\n  module.exports = saveAs;\n}\n"]}
\ No newline at end of file
diff --git a/templates/html_report/js/clusterize.min.js b/templates/html_report/js/clusterize.min.js
deleted file mode 100644
index b2d3c8e7..00000000
--- a/templates/html_report/js/clusterize.min.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/*! Clusterize.js - v0.17.6 - 2017-03-05
-* http://NeXTs.github.com/Clusterize.js/
-* Copyright (c) 2015 Denis Lukov; Licensed GPLv3 */
-
-;(function(q,n){"undefined"!=typeof module?module.exports=n():"function"==typeof define&&"object"==typeof define.amd?define(n):this[q]=n()})("Clusterize",function(){function q(b,a,c){return a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent("on"+b,c)}function n(b,a,c){return a.removeEventListener?a.removeEventListener(b,c,!1):a.detachEvent("on"+b,c)}function r(b){return"[object Array]"===Object.prototype.toString.call(b)}function m(b,a){return window.getComputedStyle?window.getComputedStyle(a)[b]:
-a.currentStyle[b]}var l=function(){for(var b=3,a=document.createElement("b"),c=a.all||[];a.innerHTML="\x3c!--[if gt IE "+ ++b+"]><i><![endif]--\x3e",c[0];);return 4<b?b:document.documentMode}(),x=navigator.platform.toLowerCase().indexOf("mac")+1,p=function(b){if(!(this instanceof p))return new p(b);var a=this,c={rows_in_block:50,blocks_in_cluster:4,tag:null,show_no_data_row:!0,no_data_class:"clusterize-no-data",no_data_text:"No data",keep_parity:!0,callbacks:{}};a.options={};for(var d="rows_in_block blocks_in_cluster show_no_data_row no_data_class no_data_text keep_parity tag callbacks".split(" "),
-f=0,h;h=d[f];f++)a.options[h]="undefined"!=typeof b[h]&&null!=b[h]?b[h]:c[h];c=["scroll","content"];for(f=0;d=c[f];f++)if(a[d+"_elem"]=b[d+"Id"]?document.getElementById(b[d+"Id"]):b[d+"Elem"],!a[d+"_elem"])throw Error("Error! Could not find "+d+" element");a.content_elem.hasAttribute("tabindex")||a.content_elem.setAttribute("tabindex",0);var e=r(b.rows)?b.rows:a.fetchMarkup(),g={};b=a.scroll_elem.scrollTop;a.insertToDOM(e,g);a.scroll_elem.scrollTop=b;var k=!1,m=0,l=!1,t=function(){x&&(l||(a.content_elem.style.pointerEvents=
-"none"),l=!0,clearTimeout(m),m=setTimeout(function(){a.content_elem.style.pointerEvents="auto";l=!1},50));k!=(k=a.getClusterNum())&&a.insertToDOM(e,g);a.options.callbacks.scrollingProgress&&a.options.callbacks.scrollingProgress(a.getScrollProgress())},u=0,v=function(){clearTimeout(u);u=setTimeout(a.refresh,100)};q("scroll",a.scroll_elem,t);q("resize",window,v);a.destroy=function(b){n("scroll",a.scroll_elem,t);n("resize",window,v);a.html((b?a.generateEmptyRow():e).join(""))};a.refresh=function(b){(a.getRowsHeight(e)||
-b)&&a.update(e)};a.update=function(b){e=r(b)?b:[];b=a.scroll_elem.scrollTop;e.length*a.options.item_height<b&&(k=a.scroll_elem.scrollTop=0);a.insertToDOM(e,g);a.scroll_elem.scrollTop=b};a.clear=function(){a.update([])};a.getRowsAmount=function(){return e.length};a.getScrollProgress=function(){return this.options.scroll_top/(e.length*this.options.item_height)*100||0};var w=function(b,c){var d=r(c)?c:[];d.length&&(e="append"==b?e.concat(d):d.concat(e),a.insertToDOM(e,g))};a.append=function(a){w("append",
-a)};a.prepend=function(a){w("prepend",a)}};p.prototype={constructor:p,fetchMarkup:function(){for(var b=[],a=this.getChildNodes(this.content_elem);a.length;)b.push(a.shift().outerHTML);return b},exploreEnvironment:function(b,a){var c=this.options;c.content_tag=this.content_elem.tagName.toLowerCase();b.length&&(l&&9>=l&&!c.tag&&(c.tag=b[0].match(/<([^>\s/]*)/)[1].toLowerCase()),1>=this.content_elem.children.length&&(a.data=this.html(b[0]+b[0]+b[0])),c.tag||(c.tag=this.content_elem.children[0].tagName.toLowerCase()),
-this.getRowsHeight(b))},getRowsHeight:function(b){var a=this.options,c=a.item_height;a.cluster_height=0;if(b.length){b=this.content_elem.children;var d=b[Math.floor(b.length/2)];a.item_height=d.offsetHeight;"tr"==a.tag&&"collapse"!=m("borderCollapse",this.content_elem)&&(a.item_height+=parseInt(m("borderSpacing",this.content_elem),10)||0);"tr"!=a.tag&&(b=parseInt(m("marginTop",d),10)||0,d=parseInt(m("marginBottom",d),10)||0,a.item_height+=Math.max(b,d));a.block_height=a.item_height*a.rows_in_block;
-a.rows_in_cluster=a.blocks_in_cluster*a.rows_in_block;a.cluster_height=a.blocks_in_cluster*a.block_height;return c!=a.item_height}},getClusterNum:function(){this.options.scroll_top=this.scroll_elem.scrollTop;return Math.floor(this.options.scroll_top/(this.options.cluster_height-this.options.block_height))||0},generateEmptyRow:function(){var b=this.options;if(!b.tag||!b.show_no_data_row)return[];var a=document.createElement(b.tag),c=document.createTextNode(b.no_data_text),d;a.className=b.no_data_class;
-"tr"==b.tag&&(d=document.createElement("td"),d.colSpan=100,d.appendChild(c));a.appendChild(d||c);return[a.outerHTML]},generate:function(b,a){var c=this.options,d=b.length;if(d<c.rows_in_block)return{top_offset:0,bottom_offset:0,rows_above:0,rows:d?b:this.generateEmptyRow()};var f=Math.max((c.rows_in_cluster-c.rows_in_block)*a,0),h=f+c.rows_in_cluster,e=Math.max(f*c.item_height,0),c=Math.max((d-h)*c.item_height,0),d=[],g=f;for(1>e&&g++;f<h;f++)b[f]&&d.push(b[f]);return{top_offset:e,bottom_offset:c,
-rows_above:g,rows:d}},renderExtraTag:function(b,a){var c=document.createElement(this.options.tag);c.className=["clusterize-extra-row","clusterize-"+b].join(" ");a&&(c.style.height=a+"px");return c.outerHTML},insertToDOM:function(b,a){this.options.cluster_height||this.exploreEnvironment(b,a);var c=this.generate(b,this.getClusterNum()),d=c.rows.join(""),f=this.checkChanges("data",d,a),h=this.checkChanges("top",c.top_offset,a),e=this.checkChanges("bottom",c.bottom_offset,a),g=this.options.callbacks,
-k=[];f||h?(c.top_offset&&(this.options.keep_parity&&k.push(this.renderExtraTag("keep-parity")),k.push(this.renderExtraTag("top-space",c.top_offset))),k.push(d),c.bottom_offset&&k.push(this.renderExtraTag("bottom-space",c.bottom_offset)),g.clusterWillChange&&g.clusterWillChange(),this.html(k.join("")),"ol"==this.options.content_tag&&this.content_elem.setAttribute("start",c.rows_above),g.clusterChanged&&g.clusterChanged()):e&&(this.content_elem.lastChild.style.height=c.bottom_offset+"px")},html:function(b){var a=
-this.content_elem;if(l&&9>=l&&"tr"==this.options.tag){var c=document.createElement("div");for(c.innerHTML="<table><tbody>"+b+"</tbody></table>";b=a.lastChild;)a.removeChild(b);for(c=this.getChildNodes(c.firstChild.firstChild);c.length;)a.appendChild(c.shift())}else a.innerHTML=b},getChildNodes:function(b){b=b.children;for(var a=[],c=0,d=b.length;c<d;c++)a.push(b[c]);return a},checkChanges:function(b,a,c){var d=a!=c[b];c[b]=a;return d}};return p});
\ No newline at end of file
diff --git a/templates/html_report/js/d3.hexbin.v0.js b/templates/html_report/js/d3.hexbin.v0.js
deleted file mode 100644
index 8076834a..00000000
--- a/templates/html_report/js/d3.hexbin.v0.js
+++ /dev/null
@@ -1,110 +0,0 @@
-(function() {
-
-d3.hexbin = function() {
-  var width = 1,
-      height = 1,
-      r,
-      x = d3_hexbinX,
-      y = d3_hexbinY,
-      dx,
-      dy;
-
-  function hexbin(points) {
-    var binsById = {};
-
-    points.forEach(function(point, i) {
-      var py = y.call(hexbin, point, i) / dy, pj = Math.round(py),
-          px = x.call(hexbin, point, i) / dx - (pj & 1 ? .5 : 0), pi = Math.round(px),
-          py1 = py - pj;
-
-      if (Math.abs(py1) * 3 > 1) {
-        var px1 = px - pi,
-            pi2 = pi + (px < pi ? -1 : 1) / 2,
-            pj2 = pj + (py < pj ? -1 : 1),
-            px2 = px - pi2,
-            py2 = py - pj2;
-        if (px1 * px1 + py1 * py1 > px2 * px2 + py2 * py2) pi = pi2 + (pj & 1 ? 1 : -1) / 2, pj = pj2;
-      }
-
-      var id = pi + "-" + pj, bin = binsById[id];
-      if (bin) bin.push(point); else {
-        bin = binsById[id] = [point];
-        bin.i = pi;
-        bin.j = pj;
-        bin.x = (pi + (pj & 1 ? 1 / 2 : 0)) * dx;
-        bin.y = pj * dy;
-      }
-    });
-
-    return d3.values(binsById);
-  }
-
-  function hexagon(radius) {
-    var x0 = 0, y0 = 0;
-    return d3_hexbinAngles.map(function(angle) {
-      var x1 = Math.sin(angle) * radius,
-          y1 = -Math.cos(angle) * radius,
-          dx = x1 - x0,
-          dy = y1 - y0;
-      x0 = x1, y0 = y1;
-      return [dx, dy];
-    });
-  }
-
-  hexbin.x = function(_) {
-    if (!arguments.length) return x;
-    x = _;
-    return hexbin;
-  };
-
-  hexbin.y = function(_) {
-    if (!arguments.length) return y;
-    y = _;
-    return hexbin;
-  };
-
-  hexbin.hexagon = function(radius) {
-    if (arguments.length < 1) radius = r;
-    return "m" + hexagon(radius).join("l") + "z";
-  };
-
-  hexbin.centers = function() {
-    var centers = [];
-    for (var y = 0, odd = false, j = 0; y < height + r; y += dy, odd = !odd, ++j) {
-      for (var x = odd ? dx / 2 : 0, i = 0; x < width + dx / 2; x += dx, ++i) {
-        var center = [x, y];
-        center.i = i;
-        center.j = j;
-        centers.push(center);
-      }
-    }
-    return centers;
-  };
-
-  hexbin.mesh = function() {
-    var fragment = hexagon(r).slice(0, 4).join("l");
-    return hexbin.centers().map(function(p) { return "M" + p + "m" + fragment; }).join("");
-  };
-
-  hexbin.size = function(_) {
-    if (!arguments.length) return [width, height];
-    width = +_[0], height = +_[1];
-    return hexbin;
-  };
-
-  hexbin.radius = function(_) {
-    if (!arguments.length) return r;
-    r = +_;
-    dx = r * 2 * Math.sin(Math.PI / 3);
-    dy = r * 1.5;
-    return hexbin;
-  };
-
-  return hexbin.radius(1);
-};
-
-var d3_hexbinAngles = d3.range(0, 2 * Math.PI, Math.PI / 3),
-    d3_hexbinX = function(d) { return d[0]; },
-    d3_hexbinY = function(d) { return d[1]; };
-
-})();
diff --git a/templates/html_report/js/d3.v3.js b/templates/html_report/js/d3.v3.js
deleted file mode 100644
index aded45c4..00000000
--- a/templates/html_report/js/d3.v3.js
+++ /dev/null
@@ -1,9554 +0,0 @@
-!function() {
-  var d3 = {
-    version: "3.5.17"
-  };
-  var d3_arraySlice = [].slice, d3_array = function(list) {
-    return d3_arraySlice.call(list);
-  };
-  var d3_document = this.document;
-  function d3_documentElement(node) {
-    return node && (node.ownerDocument || node.document || node).documentElement;
-  }
-  function d3_window(node) {
-    return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView);
-  }
-  if (d3_document) {
-    try {
-      d3_array(d3_document.documentElement.childNodes)[0].nodeType;
-    } catch (e) {
-      d3_array = function(list) {
-        var i = list.length, array = new Array(i);
-        while (i--) array[i] = list[i];
-        return array;
-      };
-    }
-  }
-  if (!Date.now) Date.now = function() {
-    return +new Date();
-  };
-  if (d3_document) {
-    try {
-      d3_document.createElement("DIV").style.setProperty("opacity", 0, "");
-    } catch (error) {
-      var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;
-      d3_element_prototype.setAttribute = function(name, value) {
-        d3_element_setAttribute.call(this, name, value + "");
-      };
-      d3_element_prototype.setAttributeNS = function(space, local, value) {
-        d3_element_setAttributeNS.call(this, space, local, value + "");
-      };
-      d3_style_prototype.setProperty = function(name, value, priority) {
-        d3_style_setProperty.call(this, name, value + "", priority);
-      };
-    }
-  }
-  d3.ascending = d3_ascending;
-  function d3_ascending(a, b) {
-    return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
-  }
-  d3.descending = function(a, b) {
-    return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
-  };
-  d3.min = function(array, f) {
-    var i = -1, n = array.length, a, b;
-    if (arguments.length === 1) {
-      while (++i < n) if ((b = array[i]) != null && b >= b) {
-        a = b;
-        break;
-      }
-      while (++i < n) if ((b = array[i]) != null && a > b) a = b;
-    } else {
-      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
-        a = b;
-        break;
-      }
-      while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
-    }
-    return a;
-  };
-  d3.max = function(array, f) {
-    var i = -1, n = array.length, a, b;
-    if (arguments.length === 1) {
-      while (++i < n) if ((b = array[i]) != null && b >= b) {
-        a = b;
-        break;
-      }
-      while (++i < n) if ((b = array[i]) != null && b > a) a = b;
-    } else {
-      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
-        a = b;
-        break;
-      }
-      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
-    }
-    return a;
-  };
-  d3.extent = function(array, f) {
-    var i = -1, n = array.length, a, b, c;
-    if (arguments.length === 1) {
-      while (++i < n) if ((b = array[i]) != null && b >= b) {
-        a = c = b;
-        break;
-      }
-      while (++i < n) if ((b = array[i]) != null) {
-        if (a > b) a = b;
-        if (c < b) c = b;
-      }
-    } else {
-      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
-        a = c = b;
-        break;
-      }
-      while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
-        if (a > b) a = b;
-        if (c < b) c = b;
-      }
-    }
-    return [ a, c ];
-  };
-  function d3_number(x) {
-    return x === null ? NaN : +x;
-  }
-  function d3_numeric(x) {
-    return !isNaN(x);
-  }
-  d3.sum = function(array, f) {
-    var s = 0, n = array.length, a, i = -1;
-    if (arguments.length === 1) {
-      while (++i < n) if (d3_numeric(a = +array[i])) s += a;
-    } else {
-      while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a;
-    }
-    return s;
-  };
-  d3.mean = function(array, f) {
-    var s = 0, n = array.length, a, i = -1, j = n;
-    if (arguments.length === 1) {
-      while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j;
-    } else {
-      while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j;
-    }
-    if (j) return s / j;
-  };
-  d3.quantile = function(values, p) {
-    var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;
-    return e ? v + e * (values[h] - v) : v;
-  };
-  d3.median = function(array, f) {
-    var numbers = [], n = array.length, a, i = -1;
-    if (arguments.length === 1) {
-      while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a);
-    } else {
-      while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a);
-    }
-    if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5);
-  };
-  d3.variance = function(array, f) {
-    var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0;
-    if (arguments.length === 1) {
-      while (++i < n) {
-        if (d3_numeric(a = d3_number(array[i]))) {
-          d = a - m;
-          m += d / ++j;
-          s += d * (a - m);
-        }
-      }
-    } else {
-      while (++i < n) {
-        if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) {
-          d = a - m;
-          m += d / ++j;
-          s += d * (a - m);
-        }
-      }
-    }
-    if (j > 1) return s / (j - 1);
-  };
-  d3.deviation = function() {
-    var v = d3.variance.apply(this, arguments);
-    return v ? Math.sqrt(v) : v;
-  };
-  function d3_bisector(compare) {
-    return {
-      left: function(a, x, lo, hi) {
-        if (arguments.length < 3) lo = 0;
-        if (arguments.length < 4) hi = a.length;
-        while (lo < hi) {
-          var mid = lo + hi >>> 1;
-          if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid;
-        }
-        return lo;
-      },
-      right: function(a, x, lo, hi) {
-        if (arguments.length < 3) lo = 0;
-        if (arguments.length < 4) hi = a.length;
-        while (lo < hi) {
-          var mid = lo + hi >>> 1;
-          if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1;
-        }
-        return lo;
-      }
-    };
-  }
-  var d3_bisect = d3_bisector(d3_ascending);
-  d3.bisectLeft = d3_bisect.left;
-  d3.bisect = d3.bisectRight = d3_bisect.right;
-  d3.bisector = function(f) {
-    return d3_bisector(f.length === 1 ? function(d, x) {
-      return d3_ascending(f(d), x);
-    } : f);
-  };
-  d3.shuffle = function(array, i0, i1) {
-    if ((m = arguments.length) < 3) {
-      i1 = array.length;
-      if (m < 2) i0 = 0;
-    }
-    var m = i1 - i0, t, i;
-    while (m) {
-      i = Math.random() * m-- | 0;
-      t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t;
-    }
-    return array;
-  };
-  d3.permute = function(array, indexes) {
-    var i = indexes.length, permutes = new Array(i);
-    while (i--) permutes[i] = array[indexes[i]];
-    return permutes;
-  };
-  d3.pairs = function(array) {
-    var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n);
-    while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ];
-    return pairs;
-  };
-  d3.transpose = function(matrix) {
-    if (!(n = matrix.length)) return [];
-    for (var i = -1, m = d3.min(matrix, d3_transposeLength), transpose = new Array(m); ++i < m; ) {
-      for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n; ) {
-        row[j] = matrix[j][i];
-      }
-    }
-    return transpose;
-  };
-  function d3_transposeLength(d) {
-    return d.length;
-  }
-  d3.zip = function() {
-    return d3.transpose(arguments);
-  };
-  d3.keys = function(map) {
-    var keys = [];
-    for (var key in map) keys.push(key);
-    return keys;
-  };
-  d3.values = function(map) {
-    var values = [];
-    for (var key in map) values.push(map[key]);
-    return values;
-  };
-  d3.entries = function(map) {
-    var entries = [];
-    for (var key in map) entries.push({
-      key: key,
-      value: map[key]
-    });
-    return entries;
-  };
-  d3.merge = function(arrays) {
-    var n = arrays.length, m, i = -1, j = 0, merged, array;
-    while (++i < n) j += arrays[i].length;
-    merged = new Array(j);
-    while (--n >= 0) {
-      array = arrays[n];
-      m = array.length;
-      while (--m >= 0) {
-        merged[--j] = array[m];
-      }
-    }
-    return merged;
-  };
-  var abs = Math.abs;
-  d3.range = function(start, stop, step) {
-    if (arguments.length < 3) {
-      step = 1;
-      if (arguments.length < 2) {
-        stop = start;
-        start = 0;
-      }
-    }
-    if ((stop - start) / step === Infinity) throw new Error("infinite range");
-    var range = [], k = d3_range_integerScale(abs(step)), i = -1, j;
-    start *= k, stop *= k, step *= k;
-    if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);
-    return range;
-  };
-  function d3_range_integerScale(x) {
-    var k = 1;
-    while (x * k % 1) k *= 10;
-    return k;
-  }
-  function d3_class(ctor, properties) {
-    for (var key in properties) {
-      Object.defineProperty(ctor.prototype, key, {
-        value: properties[key],
-        enumerable: false
-      });
-    }
-  }
-  d3.map = function(object, f) {
-    var map = new d3_Map();
-    if (object instanceof d3_Map) {
-      object.forEach(function(key, value) {
-        map.set(key, value);
-      });
-    } else if (Array.isArray(object)) {
-      var i = -1, n = object.length, o;
-      if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o);
-    } else {
-      for (var key in object) map.set(key, object[key]);
-    }
-    return map;
-  };
-  function d3_Map() {
-    this._ = Object.create(null);
-  }
-  var d3_map_proto = "__proto__", d3_map_zero = "\x00";
-  d3_class(d3_Map, {
-    has: d3_map_has,
-    get: function(key) {
-      return this._[d3_map_escape(key)];
-    },
-    set: function(key, value) {
-      return this._[d3_map_escape(key)] = value;
-    },
-    remove: d3_map_remove,
-    keys: d3_map_keys,
-    values: function() {
-      var values = [];
-      for (var key in this._) values.push(this._[key]);
-      return values;
-    },
-    entries: function() {
-      var entries = [];
-      for (var key in this._) entries.push({
-        key: d3_map_unescape(key),
-        value: this._[key]
-      });
-      return entries;
-    },
-    size: d3_map_size,
-    empty: d3_map_empty,
-    forEach: function(f) {
-      for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]);
-    }
-  });
-  function d3_map_escape(key) {
-    return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key;
-  }
-  function d3_map_unescape(key) {
-    return (key += "")[0] === d3_map_zero ? key.slice(1) : key;
-  }
-  function d3_map_has(key) {
-    return d3_map_escape(key) in this._;
-  }
-  function d3_map_remove(key) {
-    return (key = d3_map_escape(key)) in this._ && delete this._[key];
-  }
-  function d3_map_keys() {
-    var keys = [];
-    for (var key in this._) keys.push(d3_map_unescape(key));
-    return keys;
-  }
-  function d3_map_size() {
-    var size = 0;
-    for (var key in this._) ++size;
-    return size;
-  }
-  function d3_map_empty() {
-    for (var key in this._) return false;
-    return true;
-  }
-  d3.nest = function() {
-    var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
-    function map(mapType, array, depth) {
-      if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
-      var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;
-      while (++i < n) {
-        if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
-          values.push(object);
-        } else {
-          valuesByKey.set(keyValue, [ object ]);
-        }
-      }
-      if (mapType) {
-        object = mapType();
-        setter = function(keyValue, values) {
-          object.set(keyValue, map(mapType, values, depth));
-        };
-      } else {
-        object = {};
-        setter = function(keyValue, values) {
-          object[keyValue] = map(mapType, values, depth);
-        };
-      }
-      valuesByKey.forEach(setter);
-      return object;
-    }
-    function entries(map, depth) {
-      if (depth >= keys.length) return map;
-      var array = [], sortKey = sortKeys[depth++];
-      map.forEach(function(key, keyMap) {
-        array.push({
-          key: key,
-          values: entries(keyMap, depth)
-        });
-      });
-      return sortKey ? array.sort(function(a, b) {
-        return sortKey(a.key, b.key);
-      }) : array;
-    }
-    nest.map = function(array, mapType) {
-      return map(mapType, array, 0);
-    };
-    nest.entries = function(array) {
-      return entries(map(d3.map, array, 0), 0);
-    };
-    nest.key = function(d) {
-      keys.push(d);
-      return nest;
-    };
-    nest.sortKeys = function(order) {
-      sortKeys[keys.length - 1] = order;
-      return nest;
-    };
-    nest.sortValues = function(order) {
-      sortValues = order;
-      return nest;
-    };
-    nest.rollup = function(f) {
-      rollup = f;
-      return nest;
-    };
-    return nest;
-  };
-  d3.set = function(array) {
-    var set = new d3_Set();
-    if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]);
-    return set;
-  };
-  function d3_Set() {
-    this._ = Object.create(null);
-  }
-  d3_class(d3_Set, {
-    has: d3_map_has,
-    add: function(key) {
-      this._[d3_map_escape(key += "")] = true;
-      return key;
-    },
-    remove: d3_map_remove,
-    values: d3_map_keys,
-    size: d3_map_size,
-    empty: d3_map_empty,
-    forEach: function(f) {
-      for (var key in this._) f.call(this, d3_map_unescape(key));
-    }
-  });
-  d3.behavior = {};
-  function d3_identity(d) {
-    return d;
-  }
-  d3.rebind = function(target, source) {
-    var i = 1, n = arguments.length, method;
-    while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
-    return target;
-  };
-  function d3_rebind(target, source, method) {
-    return function() {
-      var value = method.apply(source, arguments);
-      return value === source ? target : value;
-    };
-  }
-  function d3_vendorSymbol(object, name) {
-    if (name in object) return name;
-    name = name.charAt(0).toUpperCase() + name.slice(1);
-    for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
-      var prefixName = d3_vendorPrefixes[i] + name;
-      if (prefixName in object) return prefixName;
-    }
-  }
-  var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ];
-  function d3_noop() {}
-  d3.dispatch = function() {
-    var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
-    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
-    return dispatch;
-  };
-  function d3_dispatch() {}
-  d3_dispatch.prototype.on = function(type, listener) {
-    var i = type.indexOf("."), name = "";
-    if (i >= 0) {
-      name = type.slice(i + 1);
-      type = type.slice(0, i);
-    }
-    if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
-    if (arguments.length === 2) {
-      if (listener == null) for (type in this) {
-        if (this.hasOwnProperty(type)) this[type].on(name, null);
-      }
-      return this;
-    }
-  };
-  function d3_dispatch_event(dispatch) {
-    var listeners = [], listenerByName = new d3_Map();
-    function event() {
-      var z = listeners, i = -1, n = z.length, l;
-      while (++i < n) if (l = z[i].on) l.apply(this, arguments);
-      return dispatch;
-    }
-    event.on = function(name, listener) {
-      var l = listenerByName.get(name), i;
-      if (arguments.length < 2) return l && l.on;
-      if (l) {
-        l.on = null;
-        listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
-        listenerByName.remove(name);
-      }
-      if (listener) listeners.push(listenerByName.set(name, {
-        on: listener
-      }));
-      return dispatch;
-    };
-    return event;
-  }
-  d3.event = null;
-  function d3_eventPreventDefault() {
-    d3.event.preventDefault();
-  }
-  function d3_eventSource() {
-    var e = d3.event, s;
-    while (s = e.sourceEvent) e = s;
-    return e;
-  }
-  function d3_eventDispatch(target) {
-    var dispatch = new d3_dispatch(), i = 0, n = arguments.length;
-    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
-    dispatch.of = function(thiz, argumentz) {
-      return function(e1) {
-        try {
-          var e0 = e1.sourceEvent = d3.event;
-          e1.target = target;
-          d3.event = e1;
-          dispatch[e1.type].apply(thiz, argumentz);
-        } finally {
-          d3.event = e0;
-        }
-      };
-    };
-    return dispatch;
-  }
-  d3.requote = function(s) {
-    return s.replace(d3_requote_re, "\\$&");
-  };
-  var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
-  var d3_subclass = {}.__proto__ ? function(object, prototype) {
-    object.__proto__ = prototype;
-  } : function(object, prototype) {
-    for (var property in prototype) object[property] = prototype[property];
-  };
-  function d3_selection(groups) {
-    d3_subclass(groups, d3_selectionPrototype);
-    return groups;
-  }
-  var d3_select = function(s, n) {
-    return n.querySelector(s);
-  }, d3_selectAll = function(s, n) {
-    return n.querySelectorAll(s);
-  }, d3_selectMatches = function(n, s) {
-    var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")];
-    d3_selectMatches = function(n, s) {
-      return d3_selectMatcher.call(n, s);
-    };
-    return d3_selectMatches(n, s);
-  };
-  if (typeof Sizzle === "function") {
-    d3_select = function(s, n) {
-      return Sizzle(s, n)[0] || null;
-    };
-    d3_selectAll = Sizzle;
-    d3_selectMatches = Sizzle.matchesSelector;
-  }
-  d3.selection = function() {
-    return d3.select(d3_document.documentElement);
-  };
-  var d3_selectionPrototype = d3.selection.prototype = [];
-  d3_selectionPrototype.select = function(selector) {
-    var subgroups = [], subgroup, subnode, group, node;
-    selector = d3_selection_selector(selector);
-    for (var j = -1, m = this.length; ++j < m; ) {
-      subgroups.push(subgroup = []);
-      subgroup.parentNode = (group = this[j]).parentNode;
-      for (var i = -1, n = group.length; ++i < n; ) {
-        if (node = group[i]) {
-          subgroup.push(subnode = selector.call(node, node.__data__, i, j));
-          if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
-        } else {
-          subgroup.push(null);
-        }
-      }
-    }
-    return d3_selection(subgroups);
-  };
-  function d3_selection_selector(selector) {
-    return typeof selector === "function" ? selector : function() {
-      return d3_select(selector, this);
-    };
-  }
-  d3_selectionPrototype.selectAll = function(selector) {
-    var subgroups = [], subgroup, node;
-    selector = d3_selection_selectorAll(selector);
-    for (var j = -1, m = this.length; ++j < m; ) {
-      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
-        if (node = group[i]) {
-          subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
-          subgroup.parentNode = node;
-        }
-      }
-    }
-    return d3_selection(subgroups);
-  };
-  function d3_selection_selectorAll(selector) {
-    return typeof selector === "function" ? selector : function() {
-      return d3_selectAll(selector, this);
-    };
-  }
-  var d3_nsXhtml = "http://www.w3.org/1999/xhtml";
-  var d3_nsPrefix = {
-    svg: "http://www.w3.org/2000/svg",
-    xhtml: d3_nsXhtml,
-    xlink: "http://www.w3.org/1999/xlink",
-    xml: "http://www.w3.org/XML/1998/namespace",
-    xmlns: "http://www.w3.org/2000/xmlns/"
-  };
-  d3.ns = {
-    prefix: d3_nsPrefix,
-    qualify: function(name) {
-      var i = name.indexOf(":"), prefix = name;
-      if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
-      return d3_nsPrefix.hasOwnProperty(prefix) ? {
-        space: d3_nsPrefix[prefix],
-        local: name
-      } : name;
-    }
-  };
-  d3_selectionPrototype.attr = function(name, value) {
-    if (arguments.length < 2) {
-      if (typeof name === "string") {
-        var node = this.node();
-        name = d3.ns.qualify(name);
-        return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
-      }
-      for (value in name) this.each(d3_selection_attr(value, name[value]));
-      return this;
-    }
-    return this.each(d3_selection_attr(name, value));
-  };
-  function d3_selection_attr(name, value) {
-    name = d3.ns.qualify(name);
-    function attrNull() {
-      this.removeAttribute(name);
-    }
-    function attrNullNS() {
-      this.removeAttributeNS(name.space, name.local);
-    }
-    function attrConstant() {
-      this.setAttribute(name, value);
-    }
-    function attrConstantNS() {
-      this.setAttributeNS(name.space, name.local, value);
-    }
-    function attrFunction() {
-      var x = value.apply(this, arguments);
-      if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
-    }
-    function attrFunctionNS() {
-      var x = value.apply(this, arguments);
-      if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
-    }
-    return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
-  }
-  function d3_collapse(s) {
-    return s.trim().replace(/\s+/g, " ");
-  }
-  d3_selectionPrototype.classed = function(name, value) {
-    if (arguments.length < 2) {
-      if (typeof name === "string") {
-        var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1;
-        if (value = node.classList) {
-          while (++i < n) if (!value.contains(name[i])) return false;
-        } else {
-          value = node.getAttribute("class");
-          while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
-        }
-        return true;
-      }
-      for (value in name) this.each(d3_selection_classed(value, name[value]));
-      return this;
-    }
-    return this.each(d3_selection_classed(name, value));
-  };
-  function d3_selection_classedRe(name) {
-    return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
-  }
-  function d3_selection_classes(name) {
-    return (name + "").trim().split(/^|\s+/);
-  }
-  function d3_selection_classed(name, value) {
-    name = d3_selection_classes(name).map(d3_selection_classedName);
-    var n = name.length;
-    function classedConstant() {
-      var i = -1;
-      while (++i < n) name[i](this, value);
-    }
-    function classedFunction() {
-      var i = -1, x = value.apply(this, arguments);
-      while (++i < n) name[i](this, x);
-    }
-    return typeof value === "function" ? classedFunction : classedConstant;
-  }
-  function d3_selection_classedName(name) {
-    var re = d3_selection_classedRe(name);
-    return function(node, value) {
-      if (c = node.classList) return value ? c.add(name) : c.remove(name);
-      var c = node.getAttribute("class") || "";
-      if (value) {
-        re.lastIndex = 0;
-        if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
-      } else {
-        node.setAttribute("class", d3_collapse(c.replace(re, " ")));
-      }
-    };
-  }
-  d3_selectionPrototype.style = function(name, value, priority) {
-    var n = arguments.length;
-    if (n < 3) {
-      if (typeof name !== "string") {
-        if (n < 2) value = "";
-        for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
-        return this;
-      }
-      if (n < 2) {
-        var node = this.node();
-        return d3_window(node).getComputedStyle(node, null).getPropertyValue(name);
-      }
-      priority = "";
-    }
-    return this.each(d3_selection_style(name, value, priority));
-  };
-  function d3_selection_style(name, value, priority) {
-    function styleNull() {
-      this.style.removeProperty(name);
-    }
-    function styleConstant() {
-      this.style.setProperty(name, value, priority);
-    }
-    function styleFunction() {
-      var x = value.apply(this, arguments);
-      if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
-    }
-    return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
-  }
-  d3_selectionPrototype.property = function(name, value) {
-    if (arguments.length < 2) {
-      if (typeof name === "string") return this.node()[name];
-      for (value in name) this.each(d3_selection_property(value, name[value]));
-      return this;
-    }
-    return this.each(d3_selection_property(name, value));
-  };
-  function d3_selection_property(name, value) {
-    function propertyNull() {
-      delete this[name];
-    }
-    function propertyConstant() {
-      this[name] = value;
-    }
-    function propertyFunction() {
-      var x = value.apply(this, arguments);
-      if (x == null) delete this[name]; else this[name] = x;
-    }
-    return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
-  }
-  d3_selectionPrototype.text = function(value) {
-    return arguments.length ? this.each(typeof value === "function" ? function() {
-      var v = value.apply(this, arguments);
-      this.textContent = v == null ? "" : v;
-    } : value == null ? function() {
-      this.textContent = "";
-    } : function() {
-      this.textContent = value;
-    }) : this.node().textContent;
-  };
-  d3_selectionPrototype.html = function(value) {
-    return arguments.length ? this.each(typeof value === "function" ? function() {
-      var v = value.apply(this, arguments);
-      this.innerHTML = v == null ? "" : v;
-    } : value == null ? function() {
-      this.innerHTML = "";
-    } : function() {
-      this.innerHTML = value;
-    }) : this.node().innerHTML;
-  };
-  d3_selectionPrototype.append = function(name) {
-    name = d3_selection_creator(name);
-    return this.select(function() {
-      return this.appendChild(name.apply(this, arguments));
-    });
-  };
-  function d3_selection_creator(name) {
-    function create() {
-      var document = this.ownerDocument, namespace = this.namespaceURI;
-      return namespace === d3_nsXhtml && document.documentElement.namespaceURI === d3_nsXhtml ? document.createElement(name) : document.createElementNS(namespace, name);
-    }
-    function createNS() {
-      return this.ownerDocument.createElementNS(name.space, name.local);
-    }
-    return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create;
-  }
-  d3_selectionPrototype.insert = function(name, before) {
-    name = d3_selection_creator(name);
-    before = d3_selection_selector(before);
-    return this.select(function() {
-      return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
-    });
-  };
-  d3_selectionPrototype.remove = function() {
-    return this.each(d3_selectionRemove);
-  };
-  function d3_selectionRemove() {
-    var parent = this.parentNode;
-    if (parent) parent.removeChild(this);
-  }
-  d3_selectionPrototype.data = function(value, key) {
-    var i = -1, n = this.length, group, node;
-    if (!arguments.length) {
-      value = new Array(n = (group = this[0]).length);
-      while (++i < n) {
-        if (node = group[i]) {
-          value[i] = node.__data__;
-        }
-      }
-      return value;
-    }
-    function bind(group, groupData) {
-      var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;
-      if (key) {
-        var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue;
-        for (i = -1; ++i < n; ) {
-          if (node = group[i]) {
-            if (nodeByKeyValue.has(keyValue = key.call(node, node.__data__, i))) {
-              exitNodes[i] = node;
-            } else {
-              nodeByKeyValue.set(keyValue, node);
-            }
-            keyValues[i] = keyValue;
-          }
-        }
-        for (i = -1; ++i < m; ) {
-          if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) {
-            enterNodes[i] = d3_selection_dataNode(nodeData);
-          } else if (node !== true) {
-            updateNodes[i] = node;
-            node.__data__ = nodeData;
-          }
-          nodeByKeyValue.set(keyValue, true);
-        }
-        for (i = -1; ++i < n; ) {
-          if (i in keyValues && nodeByKeyValue.get(keyValues[i]) !== true) {
-            exitNodes[i] = group[i];
-          }
-        }
-      } else {
-        for (i = -1; ++i < n0; ) {
-          node = group[i];
-          nodeData = groupData[i];
-          if (node) {
-            node.__data__ = nodeData;
-            updateNodes[i] = node;
-          } else {
-            enterNodes[i] = d3_selection_dataNode(nodeData);
-          }
-        }
-        for (;i < m; ++i) {
-          enterNodes[i] = d3_selection_dataNode(groupData[i]);
-        }
-        for (;i < n; ++i) {
-          exitNodes[i] = group[i];
-        }
-      }
-      enterNodes.update = updateNodes;
-      enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
-      enter.push(enterNodes);
-      update.push(updateNodes);
-      exit.push(exitNodes);
-    }
-    var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
-    if (typeof value === "function") {
-      while (++i < n) {
-        bind(group = this[i], value.call(group, group.parentNode.__data__, i));
-      }
-    } else {
-      while (++i < n) {
-        bind(group = this[i], value);
-      }
-    }
-    update.enter = function() {
-      return enter;
-    };
-    update.exit = function() {
-      return exit;
-    };
-    return update;
-  };
-  function d3_selection_dataNode(data) {
-    return {
-      __data__: data
-    };
-  }
-  d3_selectionPrototype.datum = function(value) {
-    return arguments.length ? this.property("__data__", value) : this.property("__data__");
-  };
-  d3_selectionPrototype.filter = function(filter) {
-    var subgroups = [], subgroup, group, node;
-    if (typeof filter !== "function") filter = d3_selection_filter(filter);
-    for (var j = 0, m = this.length; j < m; j++) {
-      subgroups.push(subgroup = []);
-      subgroup.parentNode = (group = this[j]).parentNode;
-      for (var i = 0, n = group.length; i < n; i++) {
-        if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
-          subgroup.push(node);
-        }
-      }
-    }
-    return d3_selection(subgroups);
-  };
-  function d3_selection_filter(selector) {
-    return function() {
-      return d3_selectMatches(this, selector);
-    };
-  }
-  d3_selectionPrototype.order = function() {
-    for (var j = -1, m = this.length; ++j < m; ) {
-      for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {
-        if (node = group[i]) {
-          if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
-          next = node;
-        }
-      }
-    }
-    return this;
-  };
-  d3_selectionPrototype.sort = function(comparator) {
-    comparator = d3_selection_sortComparator.apply(this, arguments);
-    for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);
-    return this.order();
-  };
-  function d3_selection_sortComparator(comparator) {
-    if (!arguments.length) comparator = d3_ascending;
-    return function(a, b) {
-      return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
-    };
-  }
-  d3_selectionPrototype.each = function(callback) {
-    return d3_selection_each(this, function(node, i, j) {
-      callback.call(node, node.__data__, i, j);
-    });
-  };
-  function d3_selection_each(groups, callback) {
-    for (var j = 0, m = groups.length; j < m; j++) {
-      for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
-        if (node = group[i]) callback(node, i, j);
-      }
-    }
-    return groups;
-  }
-  d3_selectionPrototype.call = function(callback) {
-    var args = d3_array(arguments);
-    callback.apply(args[0] = this, args);
-    return this;
-  };
-  d3_selectionPrototype.empty = function() {
-    return !this.node();
-  };
-  d3_selectionPrototype.node = function() {
-    for (var j = 0, m = this.length; j < m; j++) {
-      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
-        var node = group[i];
-        if (node) return node;
-      }
-    }
-    return null;
-  };
-  d3_selectionPrototype.size = function() {
-    var n = 0;
-    d3_selection_each(this, function() {
-      ++n;
-    });
-    return n;
-  };
-  function d3_selection_enter(selection) {
-    d3_subclass(selection, d3_selection_enterPrototype);
-    return selection;
-  }
-  var d3_selection_enterPrototype = [];
-  d3.selection.enter = d3_selection_enter;
-  d3.selection.enter.prototype = d3_selection_enterPrototype;
-  d3_selection_enterPrototype.append = d3_selectionPrototype.append;
-  d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
-  d3_selection_enterPrototype.node = d3_selectionPrototype.node;
-  d3_selection_enterPrototype.call = d3_selectionPrototype.call;
-  d3_selection_enterPrototype.size = d3_selectionPrototype.size;
-  d3_selection_enterPrototype.select = function(selector) {
-    var subgroups = [], subgroup, subnode, upgroup, group, node;
-    for (var j = -1, m = this.length; ++j < m; ) {
-      upgroup = (group = this[j]).update;
-      subgroups.push(subgroup = []);
-      subgroup.parentNode = group.parentNode;
-      for (var i = -1, n = group.length; ++i < n; ) {
-        if (node = group[i]) {
-          subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
-          subnode.__data__ = node.__data__;
-        } else {
-          subgroup.push(null);
-        }
-      }
-    }
-    return d3_selection(subgroups);
-  };
-  d3_selection_enterPrototype.insert = function(name, before) {
-    if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
-    return d3_selectionPrototype.insert.call(this, name, before);
-  };
-  function d3_selection_enterInsertBefore(enter) {
-    var i0, j0;
-    return function(d, i, j) {
-      var group = enter[j].update, n = group.length, node;
-      if (j != j0) j0 = j, i0 = 0;
-      if (i >= i0) i0 = i + 1;
-      while (!(node = group[i0]) && ++i0 < n) ;
-      return node;
-    };
-  }
-  d3.select = function(node) {
-    var group;
-    if (typeof node === "string") {
-      group = [ d3_select(node, d3_document) ];
-      group.parentNode = d3_document.documentElement;
-    } else {
-      group = [ node ];
-      group.parentNode = d3_documentElement(node);
-    }
-    return d3_selection([ group ]);
-  };
-  d3.selectAll = function(nodes) {
-    var group;
-    if (typeof nodes === "string") {
-      group = d3_array(d3_selectAll(nodes, d3_document));
-      group.parentNode = d3_document.documentElement;
-    } else {
-      group = d3_array(nodes);
-      group.parentNode = null;
-    }
-    return d3_selection([ group ]);
-  };
-  d3_selectionPrototype.on = function(type, listener, capture) {
-    var n = arguments.length;
-    if (n < 3) {
-      if (typeof type !== "string") {
-        if (n < 2) listener = false;
-        for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
-        return this;
-      }
-      if (n < 2) return (n = this.node()["__on" + type]) && n._;
-      capture = false;
-    }
-    return this.each(d3_selection_on(type, listener, capture));
-  };
-  function d3_selection_on(type, listener, capture) {
-    var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener;
-    if (i > 0) type = type.slice(0, i);
-    var filter = d3_selection_onFilters.get(type);
-    if (filter) type = filter, wrap = d3_selection_onFilter;
-    function onRemove() {
-      var l = this[name];
-      if (l) {
-        this.removeEventListener(type, l, l.$);
-        delete this[name];
-      }
-    }
-    function onAdd() {
-      var l = wrap(listener, d3_array(arguments));
-      onRemove.call(this);
-      this.addEventListener(type, this[name] = l, l.$ = capture);
-      l._ = listener;
-    }
-    function removeAll() {
-      var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match;
-      for (var name in this) {
-        if (match = name.match(re)) {
-          var l = this[name];
-          this.removeEventListener(match[1], l, l.$);
-          delete this[name];
-        }
-      }
-    }
-    return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;
-  }
-  var d3_selection_onFilters = d3.map({
-    mouseenter: "mouseover",
-    mouseleave: "mouseout"
-  });
-  if (d3_document) {
-    d3_selection_onFilters.forEach(function(k) {
-      if ("on" + k in d3_document) d3_selection_onFilters.remove(k);
-    });
-  }
-  function d3_selection_onListener(listener, argumentz) {
-    return function(e) {
-      var o = d3.event;
-      d3.event = e;
-      argumentz[0] = this.__data__;
-      try {
-        listener.apply(this, argumentz);
-      } finally {
-        d3.event = o;
-      }
-    };
-  }
-  function d3_selection_onFilter(listener, argumentz) {
-    var l = d3_selection_onListener(listener, argumentz);
-    return function(e) {
-      var target = this, related = e.relatedTarget;
-      if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) {
-        l.call(target, e);
-      }
-    };
-  }
-  var d3_event_dragSelect, d3_event_dragId = 0;
-  function d3_event_dragSuppress(node) {
-    var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault);
-    if (d3_event_dragSelect == null) {
-      d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect");
-    }
-    if (d3_event_dragSelect) {
-      var style = d3_documentElement(node).style, select = style[d3_event_dragSelect];
-      style[d3_event_dragSelect] = "none";
-    }
-    return function(suppressClick) {
-      w.on(name, null);
-      if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
-      if (suppressClick) {
-        var off = function() {
-          w.on(click, null);
-        };
-        w.on(click, function() {
-          d3_eventPreventDefault();
-          off();
-        }, true);
-        setTimeout(off, 0);
-      }
-    };
-  }
-  d3.mouse = function(container) {
-    return d3_mousePoint(container, d3_eventSource());
-  };
-  var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0;
-  function d3_mousePoint(container, e) {
-    if (e.changedTouches) e = e.changedTouches[0];
-    var svg = container.ownerSVGElement || container;
-    if (svg.createSVGPoint) {
-      var point = svg.createSVGPoint();
-      if (d3_mouse_bug44083 < 0) {
-        var window = d3_window(container);
-        if (window.scrollX || window.scrollY) {
-          svg = d3.select("body").append("svg").style({
-            position: "absolute",
-            top: 0,
-            left: 0,
-            margin: 0,
-            padding: 0,
-            border: "none"
-          }, "important");
-          var ctm = svg[0][0].getScreenCTM();
-          d3_mouse_bug44083 = !(ctm.f || ctm.e);
-          svg.remove();
-        }
-      }
-      if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, 
-      point.y = e.clientY;
-      point = point.matrixTransform(container.getScreenCTM().inverse());
-      return [ point.x, point.y ];
-    }
-    var rect = container.getBoundingClientRect();
-    return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
-  }
-  d3.touch = function(container, touches, identifier) {
-    if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
-    if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
-      if ((touch = touches[i]).identifier === identifier) {
-        return d3_mousePoint(container, touch);
-      }
-    }
-  };
-  d3.behavior.drag = function() {
-    var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend");
-    function drag() {
-      this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart);
-    }
-    function dragstart(id, position, subject, move, end) {
-      return function() {
-        var that = this, target = d3.event.target.correspondingElement || d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId);
-        if (origin) {
-          dragOffset = origin.apply(that, arguments);
-          dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ];
-        } else {
-          dragOffset = [ 0, 0 ];
-        }
-        dispatch({
-          type: "dragstart"
-        });
-        function moved() {
-          var position1 = position(parent, dragId), dx, dy;
-          if (!position1) return;
-          dx = position1[0] - position0[0];
-          dy = position1[1] - position0[1];
-          dragged |= dx | dy;
-          position0 = position1;
-          dispatch({
-            type: "drag",
-            x: position1[0] + dragOffset[0],
-            y: position1[1] + dragOffset[1],
-            dx: dx,
-            dy: dy
-          });
-        }
-        function ended() {
-          if (!position(parent, dragId)) return;
-          dragSubject.on(move + dragName, null).on(end + dragName, null);
-          dragRestore(dragged);
-          dispatch({
-            type: "dragend"
-          });
-        }
-      };
-    }
-    drag.origin = function(x) {
-      if (!arguments.length) return origin;
-      origin = x;
-      return drag;
-    };
-    return d3.rebind(drag, event, "on");
-  };
-  function d3_behavior_dragTouchId() {
-    return d3.event.changedTouches[0].identifier;
-  }
-  d3.touches = function(container, touches) {
-    if (arguments.length < 2) touches = d3_eventSource().touches;
-    return touches ? d3_array(touches).map(function(touch) {
-      var point = d3_mousePoint(container, touch);
-      point.identifier = touch.identifier;
-      return point;
-    }) : [];
-  };
-  var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π;
-  function d3_sgn(x) {
-    return x > 0 ? 1 : x < 0 ? -1 : 0;
-  }
-  function d3_cross2d(a, b, c) {
-    return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
-  }
-  function d3_acos(x) {
-    return x > 1 ? 0 : x < -1 ? π : Math.acos(x);
-  }
-  function d3_asin(x) {
-    return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x);
-  }
-  function d3_sinh(x) {
-    return ((x = Math.exp(x)) - 1 / x) / 2;
-  }
-  function d3_cosh(x) {
-    return ((x = Math.exp(x)) + 1 / x) / 2;
-  }
-  function d3_tanh(x) {
-    return ((x = Math.exp(2 * x)) - 1) / (x + 1);
-  }
-  function d3_haversin(x) {
-    return (x = Math.sin(x / 2)) * x;
-  }
-  var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4;
-  d3.interpolateZoom = function(p0, p1) {
-    var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S;
-    if (d2 < ε2) {
-      S = Math.log(w1 / w0) / ρ;
-      i = function(t) {
-        return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * t * S) ];
-      };
-    } else {
-      var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
-      S = (r1 - r0) / ρ;
-      i = function(t) {
-        var s = t * S, coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));
-        return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ];
-      };
-    }
-    i.duration = S * 1e3;
-    return i;
-  };
-  d3.behavior.zoom = function() {
-    var view = {
-      x: 0,
-      y: 0,
-      k: 1
-    }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1;
-    if (!d3_behavior_zoomWheel) {
-      d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() {
-        return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
-      }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() {
-        return d3.event.wheelDelta;
-      }, "mousewheel") : (d3_behavior_zoomDelta = function() {
-        return -d3.event.detail;
-      }, "MozMousePixelScroll");
-    }
-    function zoom(g) {
-      g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted);
-    }
-    zoom.event = function(g) {
-      g.each(function() {
-        var dispatch = event.of(this, arguments), view1 = view;
-        if (d3_transitionInheritId) {
-          d3.select(this).transition().each("start.zoom", function() {
-            view = this.__chart__ || {
-              x: 0,
-              y: 0,
-              k: 1
-            };
-            zoomstarted(dispatch);
-          }).tween("zoom:zoom", function() {
-            var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]);
-            return function(t) {
-              var l = i(t), k = dx / l[2];
-              this.__chart__ = view = {
-                x: cx - l[0] * k,
-                y: cy - l[1] * k,
-                k: k
-              };
-              zoomed(dispatch);
-            };
-          }).each("interrupt.zoom", function() {
-            zoomended(dispatch);
-          }).each("end.zoom", function() {
-            zoomended(dispatch);
-          });
-        } else {
-          this.__chart__ = view;
-          zoomstarted(dispatch);
-          zoomed(dispatch);
-          zoomended(dispatch);
-        }
-      });
-    };
-    zoom.translate = function(_) {
-      if (!arguments.length) return [ view.x, view.y ];
-      view = {
-        x: +_[0],
-        y: +_[1],
-        k: view.k
-      };
-      rescale();
-      return zoom;
-    };
-    zoom.scale = function(_) {
-      if (!arguments.length) return view.k;
-      view = {
-        x: view.x,
-        y: view.y,
-        k: null
-      };
-      scaleTo(+_);
-      rescale();
-      return zoom;
-    };
-    zoom.scaleExtent = function(_) {
-      if (!arguments.length) return scaleExtent;
-      scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ];
-      return zoom;
-    };
-    zoom.center = function(_) {
-      if (!arguments.length) return center;
-      center = _ && [ +_[0], +_[1] ];
-      return zoom;
-    };
-    zoom.size = function(_) {
-      if (!arguments.length) return size;
-      size = _ && [ +_[0], +_[1] ];
-      return zoom;
-    };
-    zoom.duration = function(_) {
-      if (!arguments.length) return duration;
-      duration = +_;
-      return zoom;
-    };
-    zoom.x = function(z) {
-      if (!arguments.length) return x1;
-      x1 = z;
-      x0 = z.copy();
-      view = {
-        x: 0,
-        y: 0,
-        k: 1
-      };
-      return zoom;
-    };
-    zoom.y = function(z) {
-      if (!arguments.length) return y1;
-      y1 = z;
-      y0 = z.copy();
-      view = {
-        x: 0,
-        y: 0,
-        k: 1
-      };
-      return zoom;
-    };
-    function location(p) {
-      return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ];
-    }
-    function point(l) {
-      return [ l[0] * view.k + view.x, l[1] * view.k + view.y ];
-    }
-    function scaleTo(s) {
-      view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
-    }
-    function translateTo(p, l) {
-      l = point(l);
-      view.x += p[0] - l[0];
-      view.y += p[1] - l[1];
-    }
-    function zoomTo(that, p, l, k) {
-      that.__chart__ = {
-        x: view.x,
-        y: view.y,
-        k: view.k
-      };
-      scaleTo(Math.pow(2, k));
-      translateTo(center0 = p, l);
-      that = d3.select(that);
-      if (duration > 0) that = that.transition().duration(duration);
-      that.call(zoom.event);
-    }
-    function rescale() {
-      if (x1) x1.domain(x0.range().map(function(x) {
-        return (x - view.x) / view.k;
-      }).map(x0.invert));
-      if (y1) y1.domain(y0.range().map(function(y) {
-        return (y - view.y) / view.k;
-      }).map(y0.invert));
-    }
-    function zoomstarted(dispatch) {
-      if (!zooming++) dispatch({
-        type: "zoomstart"
-      });
-    }
-    function zoomed(dispatch) {
-      rescale();
-      dispatch({
-        type: "zoom",
-        scale: view.k,
-        translate: [ view.x, view.y ]
-      });
-    }
-    function zoomended(dispatch) {
-      if (!--zooming) dispatch({
-        type: "zoomend"
-      }), center0 = null;
-    }
-    function mousedowned() {
-      var that = this, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that);
-      d3_selection_interrupt.call(that);
-      zoomstarted(dispatch);
-      function moved() {
-        dragged = 1;
-        translateTo(d3.mouse(that), location0);
-        zoomed(dispatch);
-      }
-      function ended() {
-        subject.on(mousemove, null).on(mouseup, null);
-        dragRestore(dragged);
-        zoomended(dispatch);
-      }
-    }
-    function touchstarted() {
-      var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that);
-      started();
-      zoomstarted(dispatch);
-      subject.on(mousedown, null).on(touchstart, started);
-      function relocate() {
-        var touches = d3.touches(that);
-        scale0 = view.k;
-        touches.forEach(function(t) {
-          if (t.identifier in locations0) locations0[t.identifier] = location(t);
-        });
-        return touches;
-      }
-      function started() {
-        var target = d3.event.target;
-        d3.select(target).on(touchmove, moved).on(touchend, ended);
-        targets.push(target);
-        var changed = d3.event.changedTouches;
-        for (var i = 0, n = changed.length; i < n; ++i) {
-          locations0[changed[i].identifier] = null;
-        }
-        var touches = relocate(), now = Date.now();
-        if (touches.length === 1) {
-          if (now - touchtime < 500) {
-            var p = touches[0];
-            zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1);
-            d3_eventPreventDefault();
-          }
-          touchtime = now;
-        } else if (touches.length > 1) {
-          var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1];
-          distance0 = dx * dx + dy * dy;
-        }
-      }
-      function moved() {
-        var touches = d3.touches(that), p0, l0, p1, l1;
-        d3_selection_interrupt.call(that);
-        for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {
-          p1 = touches[i];
-          if (l1 = locations0[p1.identifier]) {
-            if (l0) break;
-            p0 = p1, l0 = l1;
-          }
-        }
-        if (l1) {
-          var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0);
-          p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
-          l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
-          scaleTo(scale1 * scale0);
-        }
-        touchtime = null;
-        translateTo(p0, l0);
-        zoomed(dispatch);
-      }
-      function ended() {
-        if (d3.event.touches.length) {
-          var changed = d3.event.changedTouches;
-          for (var i = 0, n = changed.length; i < n; ++i) {
-            delete locations0[changed[i].identifier];
-          }
-          for (var identifier in locations0) {
-            return void relocate();
-          }
-        }
-        d3.selectAll(targets).on(zoomName, null);
-        subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
-        dragRestore();
-        zoomended(dispatch);
-      }
-    }
-    function mousewheeled() {
-      var dispatch = event.of(this, arguments);
-      if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), 
-      translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch);
-      mousewheelTimer = setTimeout(function() {
-        mousewheelTimer = null;
-        zoomended(dispatch);
-      }, 50);
-      d3_eventPreventDefault();
-      scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
-      translateTo(center0, translate0);
-      zoomed(dispatch);
-    }
-    function dblclicked() {
-      var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2;
-      zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1);
-    }
-    return d3.rebind(zoom, event, "on");
-  };
-  var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel;
-  d3.color = d3_color;
-  function d3_color() {}
-  d3_color.prototype.toString = function() {
-    return this.rgb() + "";
-  };
-  d3.hsl = d3_hsl;
-  function d3_hsl(h, s, l) {
-    return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l);
-  }
-  var d3_hslPrototype = d3_hsl.prototype = new d3_color();
-  d3_hslPrototype.brighter = function(k) {
-    k = Math.pow(.7, arguments.length ? k : 1);
-    return new d3_hsl(this.h, this.s, this.l / k);
-  };
-  d3_hslPrototype.darker = function(k) {
-    k = Math.pow(.7, arguments.length ? k : 1);
-    return new d3_hsl(this.h, this.s, k * this.l);
-  };
-  d3_hslPrototype.rgb = function() {
-    return d3_hsl_rgb(this.h, this.s, this.l);
-  };
-  function d3_hsl_rgb(h, s, l) {
-    var m1, m2;
-    h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
-    s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
-    l = l < 0 ? 0 : l > 1 ? 1 : l;
-    m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
-    m1 = 2 * l - m2;
-    function v(h) {
-      if (h > 360) h -= 360; else if (h < 0) h += 360;
-      if (h < 60) return m1 + (m2 - m1) * h / 60;
-      if (h < 180) return m2;
-      if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
-      return m1;
-    }
-    function vv(h) {
-      return Math.round(v(h) * 255);
-    }
-    return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));
-  }
-  d3.hcl = d3_hcl;
-  function d3_hcl(h, c, l) {
-    return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l);
-  }
-  var d3_hclPrototype = d3_hcl.prototype = new d3_color();
-  d3_hclPrototype.brighter = function(k) {
-    return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
-  };
-  d3_hclPrototype.darker = function(k) {
-    return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
-  };
-  d3_hclPrototype.rgb = function() {
-    return d3_hcl_lab(this.h, this.c, this.l).rgb();
-  };
-  function d3_hcl_lab(h, c, l) {
-    if (isNaN(h)) h = 0;
-    if (isNaN(c)) c = 0;
-    return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
-  }
-  d3.lab = d3_lab;
-  function d3_lab(l, a, b) {
-    return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b);
-  }
-  var d3_lab_K = 18;
-  var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
-  var d3_labPrototype = d3_lab.prototype = new d3_color();
-  d3_labPrototype.brighter = function(k) {
-    return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
-  };
-  d3_labPrototype.darker = function(k) {
-    return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
-  };
-  d3_labPrototype.rgb = function() {
-    return d3_lab_rgb(this.l, this.a, this.b);
-  };
-  function d3_lab_rgb(l, a, b) {
-    var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
-    x = d3_lab_xyz(x) * d3_lab_X;
-    y = d3_lab_xyz(y) * d3_lab_Y;
-    z = d3_lab_xyz(z) * d3_lab_Z;
-    return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
-  }
-  function d3_lab_hcl(l, a, b) {
-    return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l);
-  }
-  function d3_lab_xyz(x) {
-    return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
-  }
-  function d3_xyz_lab(x) {
-    return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
-  }
-  function d3_xyz_rgb(r) {
-    return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
-  }
-  d3.rgb = d3_rgb;
-  function d3_rgb(r, g, b) {
-    return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b);
-  }
-  function d3_rgbNumber(value) {
-    return new d3_rgb(value >> 16, value >> 8 & 255, value & 255);
-  }
-  function d3_rgbString(value) {
-    return d3_rgbNumber(value) + "";
-  }
-  var d3_rgbPrototype = d3_rgb.prototype = new d3_color();
-  d3_rgbPrototype.brighter = function(k) {
-    k = Math.pow(.7, arguments.length ? k : 1);
-    var r = this.r, g = this.g, b = this.b, i = 30;
-    if (!r && !g && !b) return new d3_rgb(i, i, i);
-    if (r && r < i) r = i;
-    if (g && g < i) g = i;
-    if (b && b < i) b = i;
-    return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));
-  };
-  d3_rgbPrototype.darker = function(k) {
-    k = Math.pow(.7, arguments.length ? k : 1);
-    return new d3_rgb(k * this.r, k * this.g, k * this.b);
-  };
-  d3_rgbPrototype.hsl = function() {
-    return d3_rgb_hsl(this.r, this.g, this.b);
-  };
-  d3_rgbPrototype.toString = function() {
-    return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
-  };
-  function d3_rgb_hex(v) {
-    return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
-  }
-  function d3_rgb_parse(format, rgb, hsl) {
-    var r = 0, g = 0, b = 0, m1, m2, color;
-    m1 = /([a-z]+)\((.*)\)/.exec(format = format.toLowerCase());
-    if (m1) {
-      m2 = m1[2].split(",");
-      switch (m1[1]) {
-       case "hsl":
-        {
-          return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
-        }
-
-       case "rgb":
-        {
-          return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
-        }
-      }
-    }
-    if (color = d3_rgb_names.get(format)) {
-      return rgb(color.r, color.g, color.b);
-    }
-    if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) {
-      if (format.length === 4) {
-        r = (color & 3840) >> 4;
-        r = r >> 4 | r;
-        g = color & 240;
-        g = g >> 4 | g;
-        b = color & 15;
-        b = b << 4 | b;
-      } else if (format.length === 7) {
-        r = (color & 16711680) >> 16;
-        g = (color & 65280) >> 8;
-        b = color & 255;
-      }
-    }
-    return rgb(r, g, b);
-  }
-  function d3_rgb_hsl(r, g, b) {
-    var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;
-    if (d) {
-      s = l < .5 ? d / (max + min) : d / (2 - max - min);
-      if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;
-      h *= 60;
-    } else {
-      h = NaN;
-      s = l > 0 && l < 1 ? 0 : h;
-    }
-    return new d3_hsl(h, s, l);
-  }
-  function d3_rgb_lab(r, g, b) {
-    r = d3_rgb_xyz(r);
-    g = d3_rgb_xyz(g);
-    b = d3_rgb_xyz(b);
-    var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);
-    return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
-  }
-  function d3_rgb_xyz(r) {
-    return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
-  }
-  function d3_rgb_parseNumber(c) {
-    var f = parseFloat(c);
-    return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
-  }
-  var d3_rgb_names = d3.map({
-    aliceblue: 15792383,
-    antiquewhite: 16444375,
-    aqua: 65535,
-    aquamarine: 8388564,
-    azure: 15794175,
-    beige: 16119260,
-    bisque: 16770244,
-    black: 0,
-    blanchedalmond: 16772045,
-    blue: 255,
-    blueviolet: 9055202,
-    brown: 10824234,
-    burlywood: 14596231,
-    cadetblue: 6266528,
-    chartreuse: 8388352,
-    chocolate: 13789470,
-    coral: 16744272,
-    cornflowerblue: 6591981,
-    cornsilk: 16775388,
-    crimson: 14423100,
-    cyan: 65535,
-    darkblue: 139,
-    darkcyan: 35723,
-    darkgoldenrod: 12092939,
-    darkgray: 11119017,
-    darkgreen: 25600,
-    darkgrey: 11119017,
-    darkkhaki: 12433259,
-    darkmagenta: 9109643,
-    darkolivegreen: 5597999,
-    darkorange: 16747520,
-    darkorchid: 10040012,
-    darkred: 9109504,
-    darksalmon: 15308410,
-    darkseagreen: 9419919,
-    darkslateblue: 4734347,
-    darkslategray: 3100495,
-    darkslategrey: 3100495,
-    darkturquoise: 52945,
-    darkviolet: 9699539,
-    deeppink: 16716947,
-    deepskyblue: 49151,
-    dimgray: 6908265,
-    dimgrey: 6908265,
-    dodgerblue: 2003199,
-    firebrick: 11674146,
-    floralwhite: 16775920,
-    forestgreen: 2263842,
-    fuchsia: 16711935,
-    gainsboro: 14474460,
-    ghostwhite: 16316671,
-    gold: 16766720,
-    goldenrod: 14329120,
-    gray: 8421504,
-    green: 32768,
-    greenyellow: 11403055,
-    grey: 8421504,
-    honeydew: 15794160,
-    hotpink: 16738740,
-    indianred: 13458524,
-    indigo: 4915330,
-    ivory: 16777200,
-    khaki: 15787660,
-    lavender: 15132410,
-    lavenderblush: 16773365,
-    lawngreen: 8190976,
-    lemonchiffon: 16775885,
-    lightblue: 11393254,
-    lightcoral: 15761536,
-    lightcyan: 14745599,
-    lightgoldenrodyellow: 16448210,
-    lightgray: 13882323,
-    lightgreen: 9498256,
-    lightgrey: 13882323,
-    lightpink: 16758465,
-    lightsalmon: 16752762,
-    lightseagreen: 2142890,
-    lightskyblue: 8900346,
-    lightslategray: 7833753,
-    lightslategrey: 7833753,
-    lightsteelblue: 11584734,
-    lightyellow: 16777184,
-    lime: 65280,
-    limegreen: 3329330,
-    linen: 16445670,
-    magenta: 16711935,
-    maroon: 8388608,
-    mediumaquamarine: 6737322,
-    mediumblue: 205,
-    mediumorchid: 12211667,
-    mediumpurple: 9662683,
-    mediumseagreen: 3978097,
-    mediumslateblue: 8087790,
-    mediumspringgreen: 64154,
-    mediumturquoise: 4772300,
-    mediumvioletred: 13047173,
-    midnightblue: 1644912,
-    mintcream: 16121850,
-    mistyrose: 16770273,
-    moccasin: 16770229,
-    navajowhite: 16768685,
-    navy: 128,
-    oldlace: 16643558,
-    olive: 8421376,
-    olivedrab: 7048739,
-    orange: 16753920,
-    orangered: 16729344,
-    orchid: 14315734,
-    palegoldenrod: 15657130,
-    palegreen: 10025880,
-    paleturquoise: 11529966,
-    palevioletred: 14381203,
-    papayawhip: 16773077,
-    peachpuff: 16767673,
-    peru: 13468991,
-    pink: 16761035,
-    plum: 14524637,
-    powderblue: 11591910,
-    purple: 8388736,
-    rebeccapurple: 6697881,
-    red: 16711680,
-    rosybrown: 12357519,
-    royalblue: 4286945,
-    saddlebrown: 9127187,
-    salmon: 16416882,
-    sandybrown: 16032864,
-    seagreen: 3050327,
-    seashell: 16774638,
-    sienna: 10506797,
-    silver: 12632256,
-    skyblue: 8900331,
-    slateblue: 6970061,
-    slategray: 7372944,
-    slategrey: 7372944,
-    snow: 16775930,
-    springgreen: 65407,
-    steelblue: 4620980,
-    tan: 13808780,
-    teal: 32896,
-    thistle: 14204888,
-    tomato: 16737095,
-    turquoise: 4251856,
-    violet: 15631086,
-    wheat: 16113331,
-    white: 16777215,
-    whitesmoke: 16119285,
-    yellow: 16776960,
-    yellowgreen: 10145074
-  });
-  d3_rgb_names.forEach(function(key, value) {
-    d3_rgb_names.set(key, d3_rgbNumber(value));
-  });
-  function d3_functor(v) {
-    return typeof v === "function" ? v : function() {
-      return v;
-    };
-  }
-  d3.functor = d3_functor;
-  d3.xhr = d3_xhrType(d3_identity);
-  function d3_xhrType(response) {
-    return function(url, mimeType, callback) {
-      if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, 
-      mimeType = null;
-      return d3_xhr(url, mimeType, response, callback);
-    };
-  }
-  function d3_xhr(url, mimeType, response, callback) {
-    var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null;
-    if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
-    "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
-      request.readyState > 3 && respond();
-    };
-    function respond() {
-      var status = request.status, result;
-      if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {
-        try {
-          result = response.call(xhr, request);
-        } catch (e) {
-          dispatch.error.call(xhr, e);
-          return;
-        }
-        dispatch.load.call(xhr, result);
-      } else {
-        dispatch.error.call(xhr, request);
-      }
-    }
-    request.onprogress = function(event) {
-      var o = d3.event;
-      d3.event = event;
-      try {
-        dispatch.progress.call(xhr, request);
-      } finally {
-        d3.event = o;
-      }
-    };
-    xhr.header = function(name, value) {
-      name = (name + "").toLowerCase();
-      if (arguments.length < 2) return headers[name];
-      if (value == null) delete headers[name]; else headers[name] = value + "";
-      return xhr;
-    };
-    xhr.mimeType = function(value) {
-      if (!arguments.length) return mimeType;
-      mimeType = value == null ? null : value + "";
-      return xhr;
-    };
-    xhr.responseType = function(value) {
-      if (!arguments.length) return responseType;
-      responseType = value;
-      return xhr;
-    };
-    xhr.response = function(value) {
-      response = value;
-      return xhr;
-    };
-    [ "get", "post" ].forEach(function(method) {
-      xhr[method] = function() {
-        return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));
-      };
-    });
-    xhr.send = function(method, data, callback) {
-      if (arguments.length === 2 && typeof data === "function") callback = data, data = null;
-      request.open(method, url, true);
-      if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
-      if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
-      if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
-      if (responseType != null) request.responseType = responseType;
-      if (callback != null) xhr.on("error", callback).on("load", function(request) {
-        callback(null, request);
-      });
-      dispatch.beforesend.call(xhr, request);
-      request.send(data == null ? null : data);
-      return xhr;
-    };
-    xhr.abort = function() {
-      request.abort();
-      return xhr;
-    };
-    d3.rebind(xhr, dispatch, "on");
-    return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
-  }
-  function d3_xhr_fixCallback(callback) {
-    return callback.length === 1 ? function(error, request) {
-      callback(error == null ? request : null);
-    } : callback;
-  }
-  function d3_xhrHasResponse(request) {
-    var type = request.responseType;
-    return type && type !== "text" ? request.response : request.responseText;
-  }
-  d3.dsv = function(delimiter, mimeType) {
-    var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
-    function dsv(url, row, callback) {
-      if (arguments.length < 3) callback = row, row = null;
-      var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback);
-      xhr.row = function(_) {
-        return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;
-      };
-      return xhr;
-    }
-    function response(request) {
-      return dsv.parse(request.responseText);
-    }
-    function typedResponse(f) {
-      return function(request) {
-        return dsv.parse(request.responseText, f);
-      };
-    }
-    dsv.parse = function(text, f) {
-      var o;
-      return dsv.parseRows(text, function(row, i) {
-        if (o) return o(row, i - 1);
-        var a = new Function("d", "return {" + row.map(function(name, i) {
-          return JSON.stringify(name) + ": d[" + i + "]";
-        }).join(",") + "}");
-        o = f ? function(row, i) {
-          return f(a(row), i);
-        } : a;
-      });
-    };
-    dsv.parseRows = function(text, f) {
-      var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;
-      function token() {
-        if (I >= N) return EOF;
-        if (eol) return eol = false, EOL;
-        var j = I;
-        if (text.charCodeAt(j) === 34) {
-          var i = j;
-          while (i++ < N) {
-            if (text.charCodeAt(i) === 34) {
-              if (text.charCodeAt(i + 1) !== 34) break;
-              ++i;
-            }
-          }
-          I = i + 2;
-          var c = text.charCodeAt(i + 1);
-          if (c === 13) {
-            eol = true;
-            if (text.charCodeAt(i + 2) === 10) ++I;
-          } else if (c === 10) {
-            eol = true;
-          }
-          return text.slice(j + 1, i).replace(/""/g, '"');
-        }
-        while (I < N) {
-          var c = text.charCodeAt(I++), k = 1;
-          if (c === 10) eol = true; else if (c === 13) {
-            eol = true;
-            if (text.charCodeAt(I) === 10) ++I, ++k;
-          } else if (c !== delimiterCode) continue;
-          return text.slice(j, I - k);
-        }
-        return text.slice(j);
-      }
-      while ((t = token()) !== EOF) {
-        var a = [];
-        while (t !== EOL && t !== EOF) {
-          a.push(t);
-          t = token();
-        }
-        if (f && (a = f(a, n++)) == null) continue;
-        rows.push(a);
-      }
-      return rows;
-    };
-    dsv.format = function(rows) {
-      if (Array.isArray(rows[0])) return dsv.formatRows(rows);
-      var fieldSet = new d3_Set(), fields = [];
-      rows.forEach(function(row) {
-        for (var field in row) {
-          if (!fieldSet.has(field)) {
-            fields.push(fieldSet.add(field));
-          }
-        }
-      });
-      return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {
-        return fields.map(function(field) {
-          return formatValue(row[field]);
-        }).join(delimiter);
-      })).join("\n");
-    };
-    dsv.formatRows = function(rows) {
-      return rows.map(formatRow).join("\n");
-    };
-    function formatRow(row) {
-      return row.map(formatValue).join(delimiter);
-    }
-    function formatValue(text) {
-      return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
-    }
-    return dsv;
-  };
-  d3.csv = d3.dsv(",", "text/csv");
-  d3.tsv = d3.dsv("	", "text/tab-separated-values");
-  var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) {
-    setTimeout(callback, 17);
-  };
-  d3.timer = function() {
-    d3_timer.apply(this, arguments);
-  };
-  function d3_timer(callback, delay, then) {
-    var n = arguments.length;
-    if (n < 2) delay = 0;
-    if (n < 3) then = Date.now();
-    var time = then + delay, timer = {
-      c: callback,
-      t: time,
-      n: null
-    };
-    if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer;
-    d3_timer_queueTail = timer;
-    if (!d3_timer_interval) {
-      d3_timer_timeout = clearTimeout(d3_timer_timeout);
-      d3_timer_interval = 1;
-      d3_timer_frame(d3_timer_step);
-    }
-    return timer;
-  }
-  function d3_timer_step() {
-    var now = d3_timer_mark(), delay = d3_timer_sweep() - now;
-    if (delay > 24) {
-      if (isFinite(delay)) {
-        clearTimeout(d3_timer_timeout);
-        d3_timer_timeout = setTimeout(d3_timer_step, delay);
-      }
-      d3_timer_interval = 0;
-    } else {
-      d3_timer_interval = 1;
-      d3_timer_frame(d3_timer_step);
-    }
-  }
-  d3.timer.flush = function() {
-    d3_timer_mark();
-    d3_timer_sweep();
-  };
-  function d3_timer_mark() {
-    var now = Date.now(), timer = d3_timer_queueHead;
-    while (timer) {
-      if (now >= timer.t && timer.c(now - timer.t)) timer.c = null;
-      timer = timer.n;
-    }
-    return now;
-  }
-  function d3_timer_sweep() {
-    var t0, t1 = d3_timer_queueHead, time = Infinity;
-    while (t1) {
-      if (t1.c) {
-        if (t1.t < time) time = t1.t;
-        t1 = (t0 = t1).n;
-      } else {
-        t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;
-      }
-    }
-    d3_timer_queueTail = t0;
-    return time;
-  }
-  function d3_format_precision(x, p) {
-    return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
-  }
-  d3.round = function(x, n) {
-    return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
-  };
-  var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix);
-  d3.formatPrefix = function(value, precision) {
-    var i = 0;
-    if (value = +value) {
-      if (value < 0) value *= -1;
-      if (precision) value = d3.round(value, d3_format_precision(value, precision));
-      i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
-      i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
-    }
-    return d3_formatPrefixes[8 + i / 3];
-  };
-  function d3_formatPrefix(d, i) {
-    var k = Math.pow(10, abs(8 - i) * 3);
-    return {
-      scale: i > 8 ? function(d) {
-        return d / k;
-      } : function(d) {
-        return d * k;
-      },
-      symbol: d
-    };
-  }
-  function d3_locale_numberFormat(locale) {
-    var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) {
-      var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0;
-      while (i > 0 && g > 0) {
-        if (length + g + 1 > width) g = Math.max(1, width - length);
-        t.push(value.substring(i -= g, i + g));
-        if ((length += g + 1) > width) break;
-        g = locale_grouping[j = (j + 1) % locale_grouping.length];
-      }
-      return t.reverse().join(locale_thousands);
-    } : d3_identity;
-    return function(specifier) {
-      var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true;
-      if (precision) precision = +precision.substring(1);
-      if (zfill || fill === "0" && align === "=") {
-        zfill = fill = "0";
-        align = "=";
-      }
-      switch (type) {
-       case "n":
-        comma = true;
-        type = "g";
-        break;
-
-       case "%":
-        scale = 100;
-        suffix = "%";
-        type = "f";
-        break;
-
-       case "p":
-        scale = 100;
-        suffix = "%";
-        type = "r";
-        break;
-
-       case "b":
-       case "o":
-       case "x":
-       case "X":
-        if (symbol === "#") prefix = "0" + type.toLowerCase();
-
-       case "c":
-        exponent = false;
-
-       case "d":
-        integer = true;
-        precision = 0;
-        break;
-
-       case "s":
-        scale = -1;
-        type = "r";
-        break;
-      }
-      if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1];
-      if (type == "r" && !precision) type = "g";
-      if (precision != null) {
-        if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision));
-      }
-      type = d3_format_types.get(type) || d3_format_typeDefault;
-      var zcomma = zfill && comma;
-      return function(value) {
-        var fullSuffix = suffix;
-        if (integer && value % 1) return "";
-        var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign;
-        if (scale < 0) {
-          var unit = d3.formatPrefix(value, precision);
-          value = unit.scale(value);
-          fullSuffix = unit.symbol + suffix;
-        } else {
-          value *= scale;
-        }
-        value = type(value, precision);
-        var i = value.lastIndexOf("."), before, after;
-        if (i < 0) {
-          var j = exponent ? value.lastIndexOf("e") : -1;
-          if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j);
-        } else {
-          before = value.substring(0, i);
-          after = locale_decimal + value.substring(i + 1);
-        }
-        if (!zfill && comma) before = formatGroup(before, Infinity);
-        var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
-        if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity);
-        negative += prefix;
-        value = before + after;
-        return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix;
-      };
-    };
-  }
-  var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;
-  var d3_format_types = d3.map({
-    b: function(x) {
-      return x.toString(2);
-    },
-    c: function(x) {
-      return String.fromCharCode(x);
-    },
-    o: function(x) {
-      return x.toString(8);
-    },
-    x: function(x) {
-      return x.toString(16);
-    },
-    X: function(x) {
-      return x.toString(16).toUpperCase();
-    },
-    g: function(x, p) {
-      return x.toPrecision(p);
-    },
-    e: function(x, p) {
-      return x.toExponential(p);
-    },
-    f: function(x, p) {
-      return x.toFixed(p);
-    },
-    r: function(x, p) {
-      return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));
-    }
-  });
-  function d3_format_typeDefault(x) {
-    return x + "";
-  }
-  var d3_time = d3.time = {}, d3_date = Date;
-  function d3_date_utc() {
-    this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);
-  }
-  d3_date_utc.prototype = {
-    getDate: function() {
-      return this._.getUTCDate();
-    },
-    getDay: function() {
-      return this._.getUTCDay();
-    },
-    getFullYear: function() {
-      return this._.getUTCFullYear();
-    },
-    getHours: function() {
-      return this._.getUTCHours();
-    },
-    getMilliseconds: function() {
-      return this._.getUTCMilliseconds();
-    },
-    getMinutes: function() {
-      return this._.getUTCMinutes();
-    },
-    getMonth: function() {
-      return this._.getUTCMonth();
-    },
-    getSeconds: function() {
-      return this._.getUTCSeconds();
-    },
-    getTime: function() {
-      return this._.getTime();
-    },
-    getTimezoneOffset: function() {
-      return 0;
-    },
-    valueOf: function() {
-      return this._.valueOf();
-    },
-    setDate: function() {
-      d3_time_prototype.setUTCDate.apply(this._, arguments);
-    },
-    setDay: function() {
-      d3_time_prototype.setUTCDay.apply(this._, arguments);
-    },
-    setFullYear: function() {
-      d3_time_prototype.setUTCFullYear.apply(this._, arguments);
-    },
-    setHours: function() {
-      d3_time_prototype.setUTCHours.apply(this._, arguments);
-    },
-    setMilliseconds: function() {
-      d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);
-    },
-    setMinutes: function() {
-      d3_time_prototype.setUTCMinutes.apply(this._, arguments);
-    },
-    setMonth: function() {
-      d3_time_prototype.setUTCMonth.apply(this._, arguments);
-    },
-    setSeconds: function() {
-      d3_time_prototype.setUTCSeconds.apply(this._, arguments);
-    },
-    setTime: function() {
-      d3_time_prototype.setTime.apply(this._, arguments);
-    }
-  };
-  var d3_time_prototype = Date.prototype;
-  function d3_time_interval(local, step, number) {
-    function round(date) {
-      var d0 = local(date), d1 = offset(d0, 1);
-      return date - d0 < d1 - date ? d0 : d1;
-    }
-    function ceil(date) {
-      step(date = local(new d3_date(date - 1)), 1);
-      return date;
-    }
-    function offset(date, k) {
-      step(date = new d3_date(+date), k);
-      return date;
-    }
-    function range(t0, t1, dt) {
-      var time = ceil(t0), times = [];
-      if (dt > 1) {
-        while (time < t1) {
-          if (!(number(time) % dt)) times.push(new Date(+time));
-          step(time, 1);
-        }
-      } else {
-        while (time < t1) times.push(new Date(+time)), step(time, 1);
-      }
-      return times;
-    }
-    function range_utc(t0, t1, dt) {
-      try {
-        d3_date = d3_date_utc;
-        var utc = new d3_date_utc();
-        utc._ = t0;
-        return range(utc, t1, dt);
-      } finally {
-        d3_date = Date;
-      }
-    }
-    local.floor = local;
-    local.round = round;
-    local.ceil = ceil;
-    local.offset = offset;
-    local.range = range;
-    var utc = local.utc = d3_time_interval_utc(local);
-    utc.floor = utc;
-    utc.round = d3_time_interval_utc(round);
-    utc.ceil = d3_time_interval_utc(ceil);
-    utc.offset = d3_time_interval_utc(offset);
-    utc.range = range_utc;
-    return local;
-  }
-  function d3_time_interval_utc(method) {
-    return function(date, k) {
-      try {
-        d3_date = d3_date_utc;
-        var utc = new d3_date_utc();
-        utc._ = date;
-        return method(utc, k)._;
-      } finally {
-        d3_date = Date;
-      }
-    };
-  }
-  d3_time.year = d3_time_interval(function(date) {
-    date = d3_time.day(date);
-    date.setMonth(0, 1);
-    return date;
-  }, function(date, offset) {
-    date.setFullYear(date.getFullYear() + offset);
-  }, function(date) {
-    return date.getFullYear();
-  });
-  d3_time.years = d3_time.year.range;
-  d3_time.years.utc = d3_time.year.utc.range;
-  d3_time.day = d3_time_interval(function(date) {
-    var day = new d3_date(2e3, 0);
-    day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
-    return day;
-  }, function(date, offset) {
-    date.setDate(date.getDate() + offset);
-  }, function(date) {
-    return date.getDate() - 1;
-  });
-  d3_time.days = d3_time.day.range;
-  d3_time.days.utc = d3_time.day.utc.range;
-  d3_time.dayOfYear = function(date) {
-    var year = d3_time.year(date);
-    return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
-  };
-  [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) {
-    i = 7 - i;
-    var interval = d3_time[day] = d3_time_interval(function(date) {
-      (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
-      return date;
-    }, function(date, offset) {
-      date.setDate(date.getDate() + Math.floor(offset) * 7);
-    }, function(date) {
-      var day = d3_time.year(date).getDay();
-      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
-    });
-    d3_time[day + "s"] = interval.range;
-    d3_time[day + "s"].utc = interval.utc.range;
-    d3_time[day + "OfYear"] = function(date) {
-      var day = d3_time.year(date).getDay();
-      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7);
-    };
-  });
-  d3_time.week = d3_time.sunday;
-  d3_time.weeks = d3_time.sunday.range;
-  d3_time.weeks.utc = d3_time.sunday.utc.range;
-  d3_time.weekOfYear = d3_time.sundayOfYear;
-  function d3_locale_timeFormat(locale) {
-    var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths;
-    function d3_time_format(template) {
-      var n = template.length;
-      function format(date) {
-        var string = [], i = -1, j = 0, c, p, f;
-        while (++i < n) {
-          if (template.charCodeAt(i) === 37) {
-            string.push(template.slice(j, i));
-            if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i);
-            if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p);
-            string.push(c);
-            j = i + 1;
-          }
-        }
-        string.push(template.slice(j, i));
-        return string.join("");
-      }
-      format.parse = function(string) {
-        var d = {
-          y: 1900,
-          m: 0,
-          d: 1,
-          H: 0,
-          M: 0,
-          S: 0,
-          L: 0,
-          Z: null
-        }, i = d3_time_parse(d, template, string, 0);
-        if (i != string.length) return null;
-        if ("p" in d) d.H = d.H % 12 + d.p * 12;
-        var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)();
-        if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("W" in d || "U" in d) {
-          if (!("w" in d)) d.w = "W" in d ? 1 : 0;
-          date.setFullYear(d.y, 0, 1);
-          date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7);
-        } else date.setFullYear(d.y, d.m, d.d);
-        date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L);
-        return localZ ? date._ : date;
-      };
-      format.toString = function() {
-        return template;
-      };
-      return format;
-    }
-    function d3_time_parse(date, template, string, j) {
-      var c, p, t, i = 0, n = template.length, m = string.length;
-      while (i < n) {
-        if (j >= m) return -1;
-        c = template.charCodeAt(i++);
-        if (c === 37) {
-          t = template.charAt(i++);
-          p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t];
-          if (!p || (j = p(date, string, j)) < 0) return -1;
-        } else if (c != string.charCodeAt(j++)) {
-          return -1;
-        }
-      }
-      return j;
-    }
-    d3_time_format.utc = function(template) {
-      var local = d3_time_format(template);
-      function format(date) {
-        try {
-          d3_date = d3_date_utc;
-          var utc = new d3_date();
-          utc._ = date;
-          return local(utc);
-        } finally {
-          d3_date = Date;
-        }
-      }
-      format.parse = function(string) {
-        try {
-          d3_date = d3_date_utc;
-          var date = local.parse(string);
-          return date && date._;
-        } finally {
-          d3_date = Date;
-        }
-      };
-      format.toString = local.toString;
-      return format;
-    };
-    d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti;
-    var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths);
-    locale_periods.forEach(function(p, i) {
-      d3_time_periodLookup.set(p.toLowerCase(), i);
-    });
-    var d3_time_formats = {
-      a: function(d) {
-        return locale_shortDays[d.getDay()];
-      },
-      A: function(d) {
-        return locale_days[d.getDay()];
-      },
-      b: function(d) {
-        return locale_shortMonths[d.getMonth()];
-      },
-      B: function(d) {
-        return locale_months[d.getMonth()];
-      },
-      c: d3_time_format(locale_dateTime),
-      d: function(d, p) {
-        return d3_time_formatPad(d.getDate(), p, 2);
-      },
-      e: function(d, p) {
-        return d3_time_formatPad(d.getDate(), p, 2);
-      },
-      H: function(d, p) {
-        return d3_time_formatPad(d.getHours(), p, 2);
-      },
-      I: function(d, p) {
-        return d3_time_formatPad(d.getHours() % 12 || 12, p, 2);
-      },
-      j: function(d, p) {
-        return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3);
-      },
-      L: function(d, p) {
-        return d3_time_formatPad(d.getMilliseconds(), p, 3);
-      },
-      m: function(d, p) {
-        return d3_time_formatPad(d.getMonth() + 1, p, 2);
-      },
-      M: function(d, p) {
-        return d3_time_formatPad(d.getMinutes(), p, 2);
-      },
-      p: function(d) {
-        return locale_periods[+(d.getHours() >= 12)];
-      },
-      S: function(d, p) {
-        return d3_time_formatPad(d.getSeconds(), p, 2);
-      },
-      U: function(d, p) {
-        return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2);
-      },
-      w: function(d) {
-        return d.getDay();
-      },
-      W: function(d, p) {
-        return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2);
-      },
-      x: d3_time_format(locale_date),
-      X: d3_time_format(locale_time),
-      y: function(d, p) {
-        return d3_time_formatPad(d.getFullYear() % 100, p, 2);
-      },
-      Y: function(d, p) {
-        return d3_time_formatPad(d.getFullYear() % 1e4, p, 4);
-      },
-      Z: d3_time_zone,
-      "%": function() {
-        return "%";
-      }
-    };
-    var d3_time_parsers = {
-      a: d3_time_parseWeekdayAbbrev,
-      A: d3_time_parseWeekday,
-      b: d3_time_parseMonthAbbrev,
-      B: d3_time_parseMonth,
-      c: d3_time_parseLocaleFull,
-      d: d3_time_parseDay,
-      e: d3_time_parseDay,
-      H: d3_time_parseHour24,
-      I: d3_time_parseHour24,
-      j: d3_time_parseDayOfYear,
-      L: d3_time_parseMilliseconds,
-      m: d3_time_parseMonthNumber,
-      M: d3_time_parseMinutes,
-      p: d3_time_parseAmPm,
-      S: d3_time_parseSeconds,
-      U: d3_time_parseWeekNumberSunday,
-      w: d3_time_parseWeekdayNumber,
-      W: d3_time_parseWeekNumberMonday,
-      x: d3_time_parseLocaleDate,
-      X: d3_time_parseLocaleTime,
-      y: d3_time_parseYear,
-      Y: d3_time_parseFullYear,
-      Z: d3_time_parseZone,
-      "%": d3_time_parseLiteralPercent
-    };
-    function d3_time_parseWeekdayAbbrev(date, string, i) {
-      d3_time_dayAbbrevRe.lastIndex = 0;
-      var n = d3_time_dayAbbrevRe.exec(string.slice(i));
-      return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
-    }
-    function d3_time_parseWeekday(date, string, i) {
-      d3_time_dayRe.lastIndex = 0;
-      var n = d3_time_dayRe.exec(string.slice(i));
-      return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
-    }
-    function d3_time_parseMonthAbbrev(date, string, i) {
-      d3_time_monthAbbrevRe.lastIndex = 0;
-      var n = d3_time_monthAbbrevRe.exec(string.slice(i));
-      return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
-    }
-    function d3_time_parseMonth(date, string, i) {
-      d3_time_monthRe.lastIndex = 0;
-      var n = d3_time_monthRe.exec(string.slice(i));
-      return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
-    }
-    function d3_time_parseLocaleFull(date, string, i) {
-      return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
-    }
-    function d3_time_parseLocaleDate(date, string, i) {
-      return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
-    }
-    function d3_time_parseLocaleTime(date, string, i) {
-      return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
-    }
-    function d3_time_parseAmPm(date, string, i) {
-      var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase());
-      return n == null ? -1 : (date.p = n, i);
-    }
-    return d3_time_format;
-  }
-  var d3_time_formatPads = {
-    "-": "",
-    _: " ",
-    "0": "0"
-  }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/;
-  function d3_time_formatPad(value, fill, width) {
-    var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length;
-    return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
-  }
-  function d3_time_formatRe(names) {
-    return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i");
-  }
-  function d3_time_formatLookup(names) {
-    var map = new d3_Map(), i = -1, n = names.length;
-    while (++i < n) map.set(names[i].toLowerCase(), i);
-    return map;
-  }
-  function d3_time_parseWeekdayNumber(date, string, i) {
-    d3_time_numberRe.lastIndex = 0;
-    var n = d3_time_numberRe.exec(string.slice(i, i + 1));
-    return n ? (date.w = +n[0], i + n[0].length) : -1;
-  }
-  function d3_time_parseWeekNumberSunday(date, string, i) {
-    d3_time_numberRe.lastIndex = 0;
-    var n = d3_time_numberRe.exec(string.slice(i));
-    return n ? (date.U = +n[0], i + n[0].length) : -1;
-  }
-  function d3_time_parseWeekNumberMonday(date, string, i) {
-    d3_time_numberRe.lastIndex = 0;
-    var n = d3_time_numberRe.exec(string.slice(i));
-    return n ? (date.W = +n[0], i + n[0].length) : -1;
-  }
-  function d3_time_parseFullYear(date, string, i) {
-    d3_time_numberRe.lastIndex = 0;
-    var n = d3_time_numberRe.exec(string.slice(i, i + 4));
-    return n ? (date.y = +n[0], i + n[0].length) : -1;
-  }
-  function d3_time_parseYear(date, string, i) {
-    d3_time_numberRe.lastIndex = 0;
-    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
-    return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1;
-  }
-  function d3_time_parseZone(date, string, i) {
-    return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, 
-    i + 5) : -1;
-  }
-  function d3_time_expandYear(d) {
-    return d + (d > 68 ? 1900 : 2e3);
-  }
-  function d3_time_parseMonthNumber(date, string, i) {
-    d3_time_numberRe.lastIndex = 0;
-    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
-    return n ? (date.m = n[0] - 1, i + n[0].length) : -1;
-  }
-  function d3_time_parseDay(date, string, i) {
-    d3_time_numberRe.lastIndex = 0;
-    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
-    return n ? (date.d = +n[0], i + n[0].length) : -1;
-  }
-  function d3_time_parseDayOfYear(date, string, i) {
-    d3_time_numberRe.lastIndex = 0;
-    var n = d3_time_numberRe.exec(string.slice(i, i + 3));
-    return n ? (date.j = +n[0], i + n[0].length) : -1;
-  }
-  function d3_time_parseHour24(date, string, i) {
-    d3_time_numberRe.lastIndex = 0;
-    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
-    return n ? (date.H = +n[0], i + n[0].length) : -1;
-  }
-  function d3_time_parseMinutes(date, string, i) {
-    d3_time_numberRe.lastIndex = 0;
-    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
-    return n ? (date.M = +n[0], i + n[0].length) : -1;
-  }
-  function d3_time_parseSeconds(date, string, i) {
-    d3_time_numberRe.lastIndex = 0;
-    var n = d3_time_numberRe.exec(string.slice(i, i + 2));
-    return n ? (date.S = +n[0], i + n[0].length) : -1;
-  }
-  function d3_time_parseMilliseconds(date, string, i) {
-    d3_time_numberRe.lastIndex = 0;
-    var n = d3_time_numberRe.exec(string.slice(i, i + 3));
-    return n ? (date.L = +n[0], i + n[0].length) : -1;
-  }
-  function d3_time_zone(d) {
-    var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60;
-    return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2);
-  }
-  function d3_time_parseLiteralPercent(date, string, i) {
-    d3_time_percentRe.lastIndex = 0;
-    var n = d3_time_percentRe.exec(string.slice(i, i + 1));
-    return n ? i + n[0].length : -1;
-  }
-  function d3_time_formatMulti(formats) {
-    var n = formats.length, i = -1;
-    while (++i < n) formats[i][0] = this(formats[i][0]);
-    return function(date) {
-      var i = 0, f = formats[i];
-      while (!f[1](date)) f = formats[++i];
-      return f[0](date);
-    };
-  }
-  d3.locale = function(locale) {
-    return {
-      numberFormat: d3_locale_numberFormat(locale),
-      timeFormat: d3_locale_timeFormat(locale)
-    };
-  };
-  var d3_locale_enUS = d3.locale({
-    decimal: ".",
-    thousands: ",",
-    grouping: [ 3 ],
-    currency: [ "$", "" ],
-    dateTime: "%a %b %e %X %Y",
-    date: "%m/%d/%Y",
-    time: "%H:%M:%S",
-    periods: [ "AM", "PM" ],
-    days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
-    shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
-    months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
-    shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
-  });
-  d3.format = d3_locale_enUS.numberFormat;
-  d3.geo = {};
-  function d3_adder() {}
-  d3_adder.prototype = {
-    s: 0,
-    t: 0,
-    add: function(y) {
-      d3_adderSum(y, this.t, d3_adderTemp);
-      d3_adderSum(d3_adderTemp.s, this.s, this);
-      if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t;
-    },
-    reset: function() {
-      this.s = this.t = 0;
-    },
-    valueOf: function() {
-      return this.s;
-    }
-  };
-  var d3_adderTemp = new d3_adder();
-  function d3_adderSum(a, b, o) {
-    var x = o.s = a + b, bv = x - a, av = x - bv;
-    o.t = a - av + (b - bv);
-  }
-  d3.geo.stream = function(object, listener) {
-    if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {
-      d3_geo_streamObjectType[object.type](object, listener);
-    } else {
-      d3_geo_streamGeometry(object, listener);
-    }
-  };
-  function d3_geo_streamGeometry(geometry, listener) {
-    if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
-      d3_geo_streamGeometryType[geometry.type](geometry, listener);
-    }
-  }
-  var d3_geo_streamObjectType = {
-    Feature: function(feature, listener) {
-      d3_geo_streamGeometry(feature.geometry, listener);
-    },
-    FeatureCollection: function(object, listener) {
-      var features = object.features, i = -1, n = features.length;
-      while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
-    }
-  };
-  var d3_geo_streamGeometryType = {
-    Sphere: function(object, listener) {
-      listener.sphere();
-    },
-    Point: function(object, listener) {
-      object = object.coordinates;
-      listener.point(object[0], object[1], object[2]);
-    },
-    MultiPoint: function(object, listener) {
-      var coordinates = object.coordinates, i = -1, n = coordinates.length;
-      while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]);
-    },
-    LineString: function(object, listener) {
-      d3_geo_streamLine(object.coordinates, listener, 0);
-    },
-    MultiLineString: function(object, listener) {
-      var coordinates = object.coordinates, i = -1, n = coordinates.length;
-      while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
-    },
-    Polygon: function(object, listener) {
-      d3_geo_streamPolygon(object.coordinates, listener);
-    },
-    MultiPolygon: function(object, listener) {
-      var coordinates = object.coordinates, i = -1, n = coordinates.length;
-      while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
-    },
-    GeometryCollection: function(object, listener) {
-      var geometries = object.geometries, i = -1, n = geometries.length;
-      while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
-    }
-  };
-  function d3_geo_streamLine(coordinates, listener, closed) {
-    var i = -1, n = coordinates.length - closed, coordinate;
-    listener.lineStart();
-    while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]);
-    listener.lineEnd();
-  }
-  function d3_geo_streamPolygon(coordinates, listener) {
-    var i = -1, n = coordinates.length;
-    listener.polygonStart();
-    while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
-    listener.polygonEnd();
-  }
-  d3.geo.area = function(object) {
-    d3_geo_areaSum = 0;
-    d3.geo.stream(object, d3_geo_area);
-    return d3_geo_areaSum;
-  };
-  var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder();
-  var d3_geo_area = {
-    sphere: function() {
-      d3_geo_areaSum += 4 * π;
-    },
-    point: d3_noop,
-    lineStart: d3_noop,
-    lineEnd: d3_noop,
-    polygonStart: function() {
-      d3_geo_areaRingSum.reset();
-      d3_geo_area.lineStart = d3_geo_areaRingStart;
-    },
-    polygonEnd: function() {
-      var area = 2 * d3_geo_areaRingSum;
-      d3_geo_areaSum += area < 0 ? 4 * π + area : area;
-      d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
-    }
-  };
-  function d3_geo_areaRingStart() {
-    var λ00, φ00, λ0, cosφ0, sinφ0;
-    d3_geo_area.point = function(λ, φ) {
-      d3_geo_area.point = nextPoint;
-      λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), 
-      sinφ0 = Math.sin(φ);
-    };
-    function nextPoint(λ, φ) {
-      λ *= d3_radians;
-      φ = φ * d3_radians / 2 + π / 4;
-      var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ);
-      d3_geo_areaRingSum.add(Math.atan2(v, u));
-      λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
-    }
-    d3_geo_area.lineEnd = function() {
-      nextPoint(λ00, φ00);
-    };
-  }
-  function d3_geo_cartesian(spherical) {
-    var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);
-    return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];
-  }
-  function d3_geo_cartesianDot(a, b) {
-    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
-  }
-  function d3_geo_cartesianCross(a, b) {
-    return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];
-  }
-  function d3_geo_cartesianAdd(a, b) {
-    a[0] += b[0];
-    a[1] += b[1];
-    a[2] += b[2];
-  }
-  function d3_geo_cartesianScale(vector, k) {
-    return [ vector[0] * k, vector[1] * k, vector[2] * k ];
-  }
-  function d3_geo_cartesianNormalize(d) {
-    var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
-    d[0] /= l;
-    d[1] /= l;
-    d[2] /= l;
-  }
-  function d3_geo_spherical(cartesian) {
-    return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ];
-  }
-  function d3_geo_sphericalEqual(a, b) {
-    return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε;
-  }
-  d3.geo.bounds = function() {
-    var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range;
-    var bound = {
-      point: point,
-      lineStart: lineStart,
-      lineEnd: lineEnd,
-      polygonStart: function() {
-        bound.point = ringPoint;
-        bound.lineStart = ringStart;
-        bound.lineEnd = ringEnd;
-        dλSum = 0;
-        d3_geo_area.polygonStart();
-      },
-      polygonEnd: function() {
-        d3_geo_area.polygonEnd();
-        bound.point = point;
-        bound.lineStart = lineStart;
-        bound.lineEnd = lineEnd;
-        if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90;
-        range[0] = λ0, range[1] = λ1;
-      }
-    };
-    function point(λ, φ) {
-      ranges.push(range = [ λ0 = λ, λ1 = λ ]);
-      if (φ < φ0) φ0 = φ;
-      if (φ > φ1) φ1 = φ;
-    }
-    function linePoint(λ, φ) {
-      var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]);
-      if (p0) {
-        var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal);
-        d3_geo_cartesianNormalize(inflection);
-        inflection = d3_geo_spherical(inflection);
-        var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180;
-        if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
-          var φi = inflection[1] * d3_degrees;
-          if (φi > φ1) φ1 = φi;
-        } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
-          var φi = -inflection[1] * d3_degrees;
-          if (φi < φ0) φ0 = φi;
-        } else {
-          if (φ < φ0) φ0 = φ;
-          if (φ > φ1) φ1 = φ;
-        }
-        if (antimeridian) {
-          if (λ < λ_) {
-            if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
-          } else {
-            if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
-          }
-        } else {
-          if (λ1 >= λ0) {
-            if (λ < λ0) λ0 = λ;
-            if (λ > λ1) λ1 = λ;
-          } else {
-            if (λ > λ_) {
-              if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
-            } else {
-              if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
-            }
-          }
-        }
-      } else {
-        point(λ, φ);
-      }
-      p0 = p, λ_ = λ;
-    }
-    function lineStart() {
-      bound.point = linePoint;
-    }
-    function lineEnd() {
-      range[0] = λ0, range[1] = λ1;
-      bound.point = point;
-      p0 = null;
-    }
-    function ringPoint(λ, φ) {
-      if (p0) {
-        var dλ = λ - λ_;
-        dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
-      } else λ__ = λ, φ__ = φ;
-      d3_geo_area.point(λ, φ);
-      linePoint(λ, φ);
-    }
-    function ringStart() {
-      d3_geo_area.lineStart();
-    }
-    function ringEnd() {
-      ringPoint(λ__, φ__);
-      d3_geo_area.lineEnd();
-      if (abs(dλSum) > ε) λ0 = -(λ1 = 180);
-      range[0] = λ0, range[1] = λ1;
-      p0 = null;
-    }
-    function angle(λ0, λ1) {
-      return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1;
-    }
-    function compareRanges(a, b) {
-      return a[0] - b[0];
-    }
-    function withinRange(x, range) {
-      return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
-    }
-    return function(feature) {
-      φ1 = λ1 = -(λ0 = φ0 = Infinity);
-      ranges = [];
-      d3.geo.stream(feature, bound);
-      var n = ranges.length;
-      if (n) {
-        ranges.sort(compareRanges);
-        for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) {
-          b = ranges[i];
-          if (withinRange(b[0], a) || withinRange(b[1], a)) {
-            if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
-            if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
-          } else {
-            merged.push(a = b);
-          }
-        }
-        var best = -Infinity, dλ;
-        for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) {
-          b = merged[i];
-          if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];
-        }
-      }
-      ranges = range = null;
-      return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ];
-    };
-  }();
-  d3.geo.centroid = function(object) {
-    d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
-    d3.geo.stream(object, d3_geo_centroid);
-    var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z;
-    if (m < ε2) {
-      x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
-      if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;
-      m = x * x + y * y + z * z;
-      if (m < ε2) return [ NaN, NaN ];
-    }
-    return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ];
-  };
-  var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2;
-  var d3_geo_centroid = {
-    sphere: d3_noop,
-    point: d3_geo_centroidPoint,
-    lineStart: d3_geo_centroidLineStart,
-    lineEnd: d3_geo_centroidLineEnd,
-    polygonStart: function() {
-      d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
-    },
-    polygonEnd: function() {
-      d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
-    }
-  };
-  function d3_geo_centroidPoint(λ, φ) {
-    λ *= d3_radians;
-    var cosφ = Math.cos(φ *= d3_radians);
-    d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
-  }
-  function d3_geo_centroidPointXYZ(x, y, z) {
-    ++d3_geo_centroidW0;
-    d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
-    d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
-    d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
-  }
-  function d3_geo_centroidLineStart() {
-    var x0, y0, z0;
-    d3_geo_centroid.point = function(λ, φ) {
-      λ *= d3_radians;
-      var cosφ = Math.cos(φ *= d3_radians);
-      x0 = cosφ * Math.cos(λ);
-      y0 = cosφ * Math.sin(λ);
-      z0 = Math.sin(φ);
-      d3_geo_centroid.point = nextPoint;
-      d3_geo_centroidPointXYZ(x0, y0, z0);
-    };
-    function nextPoint(λ, φ) {
-      λ *= d3_radians;
-      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
-      d3_geo_centroidW1 += w;
-      d3_geo_centroidX1 += w * (x0 + (x0 = x));
-      d3_geo_centroidY1 += w * (y0 + (y0 = y));
-      d3_geo_centroidZ1 += w * (z0 + (z0 = z));
-      d3_geo_centroidPointXYZ(x0, y0, z0);
-    }
-  }
-  function d3_geo_centroidLineEnd() {
-    d3_geo_centroid.point = d3_geo_centroidPoint;
-  }
-  function d3_geo_centroidRingStart() {
-    var λ00, φ00, x0, y0, z0;
-    d3_geo_centroid.point = function(λ, φ) {
-      λ00 = λ, φ00 = φ;
-      d3_geo_centroid.point = nextPoint;
-      λ *= d3_radians;
-      var cosφ = Math.cos(φ *= d3_radians);
-      x0 = cosφ * Math.cos(λ);
-      y0 = cosφ * Math.sin(λ);
-      z0 = Math.sin(φ);
-      d3_geo_centroidPointXYZ(x0, y0, z0);
-    };
-    d3_geo_centroid.lineEnd = function() {
-      nextPoint(λ00, φ00);
-      d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
-      d3_geo_centroid.point = d3_geo_centroidPoint;
-    };
-    function nextPoint(λ, φ) {
-      λ *= d3_radians;
-      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u);
-      d3_geo_centroidX2 += v * cx;
-      d3_geo_centroidY2 += v * cy;
-      d3_geo_centroidZ2 += v * cz;
-      d3_geo_centroidW1 += w;
-      d3_geo_centroidX1 += w * (x0 + (x0 = x));
-      d3_geo_centroidY1 += w * (y0 + (y0 = y));
-      d3_geo_centroidZ1 += w * (z0 + (z0 = z));
-      d3_geo_centroidPointXYZ(x0, y0, z0);
-    }
-  }
-  function d3_geo_compose(a, b) {
-    function compose(x, y) {
-      return x = a(x, y), b(x[0], x[1]);
-    }
-    if (a.invert && b.invert) compose.invert = function(x, y) {
-      return x = b.invert(x, y), x && a.invert(x[0], x[1]);
-    };
-    return compose;
-  }
-  function d3_true() {
-    return true;
-  }
-  function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
-    var subject = [], clip = [];
-    segments.forEach(function(segment) {
-      if ((n = segment.length - 1) <= 0) return;
-      var n, p0 = segment[0], p1 = segment[n];
-      if (d3_geo_sphericalEqual(p0, p1)) {
-        listener.lineStart();
-        for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
-        listener.lineEnd();
-        return;
-      }
-      var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
-      a.o = b;
-      subject.push(a);
-      clip.push(b);
-      a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
-      b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
-      a.o = b;
-      subject.push(a);
-      clip.push(b);
-    });
-    clip.sort(compare);
-    d3_geo_clipPolygonLinkCircular(subject);
-    d3_geo_clipPolygonLinkCircular(clip);
-    if (!subject.length) return;
-    for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
-      clip[i].e = entry = !entry;
-    }
-    var start = subject[0], points, point;
-    while (1) {
-      var current = start, isSubject = true;
-      while (current.v) if ((current = current.n) === start) return;
-      points = current.z;
-      listener.lineStart();
-      do {
-        current.v = current.o.v = true;
-        if (current.e) {
-          if (isSubject) {
-            for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]);
-          } else {
-            interpolate(current.x, current.n.x, 1, listener);
-          }
-          current = current.n;
-        } else {
-          if (isSubject) {
-            points = current.p.z;
-            for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]);
-          } else {
-            interpolate(current.x, current.p.x, -1, listener);
-          }
-          current = current.p;
-        }
-        current = current.o;
-        points = current.z;
-        isSubject = !isSubject;
-      } while (!current.v);
-      listener.lineEnd();
-    }
-  }
-  function d3_geo_clipPolygonLinkCircular(array) {
-    if (!(n = array.length)) return;
-    var n, i = 0, a = array[0], b;
-    while (++i < n) {
-      a.n = b = array[i];
-      b.p = a;
-      a = b;
-    }
-    a.n = b = array[0];
-    b.p = a;
-  }
-  function d3_geo_clipPolygonIntersection(point, points, other, entry) {
-    this.x = point;
-    this.z = points;
-    this.o = other;
-    this.e = entry;
-    this.v = false;
-    this.n = this.p = null;
-  }
-  function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
-    return function(rotate, listener) {
-      var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);
-      var clip = {
-        point: point,
-        lineStart: lineStart,
-        lineEnd: lineEnd,
-        polygonStart: function() {
-          clip.point = pointRing;
-          clip.lineStart = ringStart;
-          clip.lineEnd = ringEnd;
-          segments = [];
-          polygon = [];
-        },
-        polygonEnd: function() {
-          clip.point = point;
-          clip.lineStart = lineStart;
-          clip.lineEnd = lineEnd;
-          segments = d3.merge(segments);
-          var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
-          if (segments.length) {
-            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
-            d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
-          } else if (clipStartInside) {
-            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
-            listener.lineStart();
-            interpolate(null, null, 1, listener);
-            listener.lineEnd();
-          }
-          if (polygonStarted) listener.polygonEnd(), polygonStarted = false;
-          segments = polygon = null;
-        },
-        sphere: function() {
-          listener.polygonStart();
-          listener.lineStart();
-          interpolate(null, null, 1, listener);
-          listener.lineEnd();
-          listener.polygonEnd();
-        }
-      };
-      function point(λ, φ) {
-        var point = rotate(λ, φ);
-        if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ);
-      }
-      function pointLine(λ, φ) {
-        var point = rotate(λ, φ);
-        line.point(point[0], point[1]);
-      }
-      function lineStart() {
-        clip.point = pointLine;
-        line.lineStart();
-      }
-      function lineEnd() {
-        clip.point = point;
-        line.lineEnd();
-      }
-      var segments;
-      var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring;
-      function pointRing(λ, φ) {
-        ring.push([ λ, φ ]);
-        var point = rotate(λ, φ);
-        ringListener.point(point[0], point[1]);
-      }
-      function ringStart() {
-        ringListener.lineStart();
-        ring = [];
-      }
-      function ringEnd() {
-        pointRing(ring[0][0], ring[0][1]);
-        ringListener.lineEnd();
-        var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
-        ring.pop();
-        polygon.push(ring);
-        ring = null;
-        if (!n) return;
-        if (clean & 1) {
-          segment = ringSegments[0];
-          var n = segment.length - 1, i = -1, point;
-          if (n > 0) {
-            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
-            listener.lineStart();
-            while (++i < n) listener.point((point = segment[i])[0], point[1]);
-            listener.lineEnd();
-          }
-          return;
-        }
-        if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
-        segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
-      }
-      return clip;
-    };
-  }
-  function d3_geo_clipSegmentLength1(segment) {
-    return segment.length > 1;
-  }
-  function d3_geo_clipBufferListener() {
-    var lines = [], line;
-    return {
-      lineStart: function() {
-        lines.push(line = []);
-      },
-      point: function(λ, φ) {
-        line.push([ λ, φ ]);
-      },
-      lineEnd: d3_noop,
-      buffer: function() {
-        var buffer = lines;
-        lines = [];
-        line = null;
-        return buffer;
-      },
-      rejoin: function() {
-        if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
-      }
-    };
-  }
-  function d3_geo_clipSort(a, b) {
-    return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]);
-  }
-  var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]);
-  function d3_geo_clipAntimeridianLine(listener) {
-    var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;
-    return {
-      lineStart: function() {
-        listener.lineStart();
-        clean = 1;
-      },
-      point: function(λ1, φ1) {
-        var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0);
-        if (abs(dλ - π) < ε) {
-          listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ);
-          listener.point(sλ0, φ0);
-          listener.lineEnd();
-          listener.lineStart();
-          listener.point(sλ1, φ0);
-          listener.point(λ1, φ0);
-          clean = 0;
-        } else if (sλ0 !== sλ1 && dλ >= π) {
-          if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
-          if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
-          φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
-          listener.point(sλ0, φ0);
-          listener.lineEnd();
-          listener.lineStart();
-          listener.point(sλ1, φ0);
-          clean = 0;
-        }
-        listener.point(λ0 = λ1, φ0 = φ1);
-        sλ0 = sλ1;
-      },
-      lineEnd: function() {
-        listener.lineEnd();
-        λ0 = φ0 = NaN;
-      },
-      clean: function() {
-        return 2 - clean;
-      }
-    };
-  }
-  function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
-    var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
-    return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;
-  }
-  function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
-    var φ;
-    if (from == null) {
-      φ = direction * halfπ;
-      listener.point(-π, φ);
-      listener.point(0, φ);
-      listener.point(π, φ);
-      listener.point(π, 0);
-      listener.point(π, -φ);
-      listener.point(0, -φ);
-      listener.point(-π, -φ);
-      listener.point(-π, 0);
-      listener.point(-π, φ);
-    } else if (abs(from[0] - to[0]) > ε) {
-      var s = from[0] < to[0] ? π : -π;
-      φ = direction * s / 2;
-      listener.point(-s, φ);
-      listener.point(0, φ);
-      listener.point(s, φ);
-    } else {
-      listener.point(to[0], to[1]);
-    }
-  }
-  function d3_geo_pointInPolygon(point, polygon) {
-    var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0;
-    d3_geo_areaRingSum.reset();
-    for (var i = 0, n = polygon.length; i < n; ++i) {
-      var ring = polygon[i], m = ring.length;
-      if (!m) continue;
-      var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1;
-      while (true) {
-        if (j === m) j = 0;
-        point = ring[j];
-        var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ;
-        d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
-        polarAngle += antimeridian ? dλ + sdλ * τ : dλ;
-        if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
-          var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
-          d3_geo_cartesianNormalize(arc);
-          var intersection = d3_geo_cartesianCross(meridianNormal, arc);
-          d3_geo_cartesianNormalize(intersection);
-          var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]);
-          if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) {
-            winding += antimeridian ^ dλ >= 0 ? 1 : -1;
-          }
-        }
-        if (!j++) break;
-        λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;
-      }
-    }
-    return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < -ε) ^ winding & 1;
-  }
-  function d3_geo_clipCircle(radius) {
-    var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
-    return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]);
-    function visible(λ, φ) {
-      return Math.cos(λ) * Math.cos(φ) > cr;
-    }
-    function clipLine(listener) {
-      var point0, c0, v0, v00, clean;
-      return {
-        lineStart: function() {
-          v00 = v0 = false;
-          clean = 1;
-        },
-        point: function(λ, φ) {
-          var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;
-          if (!point0 && (v00 = v0 = v)) listener.lineStart();
-          if (v !== v0) {
-            point2 = intersect(point0, point1);
-            if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
-              point1[0] += ε;
-              point1[1] += ε;
-              v = visible(point1[0], point1[1]);
-            }
-          }
-          if (v !== v0) {
-            clean = 0;
-            if (v) {
-              listener.lineStart();
-              point2 = intersect(point1, point0);
-              listener.point(point2[0], point2[1]);
-            } else {
-              point2 = intersect(point0, point1);
-              listener.point(point2[0], point2[1]);
-              listener.lineEnd();
-            }
-            point0 = point2;
-          } else if (notHemisphere && point0 && smallRadius ^ v) {
-            var t;
-            if (!(c & c0) && (t = intersect(point1, point0, true))) {
-              clean = 0;
-              if (smallRadius) {
-                listener.lineStart();
-                listener.point(t[0][0], t[0][1]);
-                listener.point(t[1][0], t[1][1]);
-                listener.lineEnd();
-              } else {
-                listener.point(t[1][0], t[1][1]);
-                listener.lineEnd();
-                listener.lineStart();
-                listener.point(t[0][0], t[0][1]);
-              }
-            }
-          }
-          if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
-            listener.point(point1[0], point1[1]);
-          }
-          point0 = point1, v0 = v, c0 = c;
-        },
-        lineEnd: function() {
-          if (v0) listener.lineEnd();
-          point0 = null;
-        },
-        clean: function() {
-          return clean | (v00 && v0) << 1;
-        }
-      };
-    }
-    function intersect(a, b, two) {
-      var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b);
-      var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;
-      if (!determinant) return !two && a;
-      var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);
-      d3_geo_cartesianAdd(A, B);
-      var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
-      if (t2 < 0) return;
-      var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu);
-      d3_geo_cartesianAdd(q, A);
-      q = d3_geo_spherical(q);
-      if (!two) return q;
-      var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z;
-      if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;
-      var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε;
-      if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;
-      if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {
-        var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
-        d3_geo_cartesianAdd(q1, A);
-        return [ q, d3_geo_spherical(q1) ];
-      }
-    }
-    function code(λ, φ) {
-      var r = smallRadius ? radius : π - radius, code = 0;
-      if (λ < -r) code |= 1; else if (λ > r) code |= 2;
-      if (φ < -r) code |= 4; else if (φ > r) code |= 8;
-      return code;
-    }
-  }
-  function d3_geom_clipLine(x0, y0, x1, y1) {
-    return function(line) {
-      var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r;
-      r = x0 - ax;
-      if (!dx && r > 0) return;
-      r /= dx;
-      if (dx < 0) {
-        if (r < t0) return;
-        if (r < t1) t1 = r;
-      } else if (dx > 0) {
-        if (r > t1) return;
-        if (r > t0) t0 = r;
-      }
-      r = x1 - ax;
-      if (!dx && r < 0) return;
-      r /= dx;
-      if (dx < 0) {
-        if (r > t1) return;
-        if (r > t0) t0 = r;
-      } else if (dx > 0) {
-        if (r < t0) return;
-        if (r < t1) t1 = r;
-      }
-      r = y0 - ay;
-      if (!dy && r > 0) return;
-      r /= dy;
-      if (dy < 0) {
-        if (r < t0) return;
-        if (r < t1) t1 = r;
-      } else if (dy > 0) {
-        if (r > t1) return;
-        if (r > t0) t0 = r;
-      }
-      r = y1 - ay;
-      if (!dy && r < 0) return;
-      r /= dy;
-      if (dy < 0) {
-        if (r > t1) return;
-        if (r > t0) t0 = r;
-      } else if (dy > 0) {
-        if (r < t0) return;
-        if (r < t1) t1 = r;
-      }
-      if (t0 > 0) line.a = {
-        x: ax + t0 * dx,
-        y: ay + t0 * dy
-      };
-      if (t1 < 1) line.b = {
-        x: ax + t1 * dx,
-        y: ay + t1 * dy
-      };
-      return line;
-    };
-  }
-  var d3_geo_clipExtentMAX = 1e9;
-  d3.geo.clipExtent = function() {
-    var x0, y0, x1, y1, stream, clip, clipExtent = {
-      stream: function(output) {
-        if (stream) stream.valid = false;
-        stream = clip(output);
-        stream.valid = true;
-        return stream;
-      },
-      extent: function(_) {
-        if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
-        clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]);
-        if (stream) stream.valid = false, stream = null;
-        return clipExtent;
-      }
-    };
-    return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]);
-  };
-  function d3_geo_clipExtent(x0, y0, x1, y1) {
-    return function(listener) {
-      var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring;
-      var clip = {
-        point: point,
-        lineStart: lineStart,
-        lineEnd: lineEnd,
-        polygonStart: function() {
-          listener = bufferListener;
-          segments = [];
-          polygon = [];
-          clean = true;
-        },
-        polygonEnd: function() {
-          listener = listener_;
-          segments = d3.merge(segments);
-          var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length;
-          if (inside || visible) {
-            listener.polygonStart();
-            if (inside) {
-              listener.lineStart();
-              interpolate(null, null, 1, listener);
-              listener.lineEnd();
-            }
-            if (visible) {
-              d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
-            }
-            listener.polygonEnd();
-          }
-          segments = polygon = ring = null;
-        }
-      };
-      function insidePolygon(p) {
-        var wn = 0, n = polygon.length, y = p[1];
-        for (var i = 0; i < n; ++i) {
-          for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {
-            b = v[j];
-            if (a[1] <= y) {
-              if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn;
-            } else {
-              if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn;
-            }
-            a = b;
-          }
-        }
-        return wn !== 0;
-      }
-      function interpolate(from, to, direction, listener) {
-        var a = 0, a1 = 0;
-        if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) {
-          do {
-            listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
-          } while ((a = (a + direction + 4) % 4) !== a1);
-        } else {
-          listener.point(to[0], to[1]);
-        }
-      }
-      function pointVisible(x, y) {
-        return x0 <= x && x <= x1 && y0 <= y && y <= y1;
-      }
-      function point(x, y) {
-        if (pointVisible(x, y)) listener.point(x, y);
-      }
-      var x__, y__, v__, x_, y_, v_, first, clean;
-      function lineStart() {
-        clip.point = linePoint;
-        if (polygon) polygon.push(ring = []);
-        first = true;
-        v_ = false;
-        x_ = y_ = NaN;
-      }
-      function lineEnd() {
-        if (segments) {
-          linePoint(x__, y__);
-          if (v__ && v_) bufferListener.rejoin();
-          segments.push(bufferListener.buffer());
-        }
-        clip.point = point;
-        if (v_) listener.lineEnd();
-      }
-      function linePoint(x, y) {
-        x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x));
-        y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y));
-        var v = pointVisible(x, y);
-        if (polygon) ring.push([ x, y ]);
-        if (first) {
-          x__ = x, y__ = y, v__ = v;
-          first = false;
-          if (v) {
-            listener.lineStart();
-            listener.point(x, y);
-          }
-        } else {
-          if (v && v_) listener.point(x, y); else {
-            var l = {
-              a: {
-                x: x_,
-                y: y_
-              },
-              b: {
-                x: x,
-                y: y
-              }
-            };
-            if (clipLine(l)) {
-              if (!v_) {
-                listener.lineStart();
-                listener.point(l.a.x, l.a.y);
-              }
-              listener.point(l.b.x, l.b.y);
-              if (!v) listener.lineEnd();
-              clean = false;
-            } else if (v) {
-              listener.lineStart();
-              listener.point(x, y);
-              clean = false;
-            }
-          }
-        }
-        x_ = x, y_ = y, v_ = v;
-      }
-      return clip;
-    };
-    function corner(p, direction) {
-      return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;
-    }
-    function compare(a, b) {
-      return comparePoints(a.x, b.x);
-    }
-    function comparePoints(a, b) {
-      var ca = corner(a, 1), cb = corner(b, 1);
-      return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];
-    }
-  }
-  function d3_geo_conic(projectAt) {
-    var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1);
-    p.parallels = function(_) {
-      if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ];
-      return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
-    };
-    return p;
-  }
-  function d3_geo_conicEqualArea(φ0, φ1) {
-    var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;
-    function forward(λ, φ) {
-      var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
-      return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];
-    }
-    forward.invert = function(x, y) {
-      var ρ0_y = ρ0 - y;
-      return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];
-    };
-    return forward;
-  }
-  (d3.geo.conicEqualArea = function() {
-    return d3_geo_conic(d3_geo_conicEqualArea);
-  }).raw = d3_geo_conicEqualArea;
-  d3.geo.albers = function() {
-    return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070);
-  };
-  d3.geo.albersUsa = function() {
-    var lower48 = d3.geo.albers();
-    var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]);
-    var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]);
-    var point, pointStream = {
-      point: function(x, y) {
-        point = [ x, y ];
-      }
-    }, lower48Point, alaskaPoint, hawaiiPoint;
-    function albersUsa(coordinates) {
-      var x = coordinates[0], y = coordinates[1];
-      point = null;
-      (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y);
-      return point;
-    }
-    albersUsa.invert = function(coordinates) {
-      var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k;
-      return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates);
-    };
-    albersUsa.stream = function(stream) {
-      var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream);
-      return {
-        point: function(x, y) {
-          lower48Stream.point(x, y);
-          alaskaStream.point(x, y);
-          hawaiiStream.point(x, y);
-        },
-        sphere: function() {
-          lower48Stream.sphere();
-          alaskaStream.sphere();
-          hawaiiStream.sphere();
-        },
-        lineStart: function() {
-          lower48Stream.lineStart();
-          alaskaStream.lineStart();
-          hawaiiStream.lineStart();
-        },
-        lineEnd: function() {
-          lower48Stream.lineEnd();
-          alaskaStream.lineEnd();
-          hawaiiStream.lineEnd();
-        },
-        polygonStart: function() {
-          lower48Stream.polygonStart();
-          alaskaStream.polygonStart();
-          hawaiiStream.polygonStart();
-        },
-        polygonEnd: function() {
-          lower48Stream.polygonEnd();
-          alaskaStream.polygonEnd();
-          hawaiiStream.polygonEnd();
-        }
-      };
-    };
-    albersUsa.precision = function(_) {
-      if (!arguments.length) return lower48.precision();
-      lower48.precision(_);
-      alaska.precision(_);
-      hawaii.precision(_);
-      return albersUsa;
-    };
-    albersUsa.scale = function(_) {
-      if (!arguments.length) return lower48.scale();
-      lower48.scale(_);
-      alaska.scale(_ * .35);
-      hawaii.scale(_);
-      return albersUsa.translate(lower48.translate());
-    };
-    albersUsa.translate = function(_) {
-      if (!arguments.length) return lower48.translate();
-      var k = lower48.scale(), x = +_[0], y = +_[1];
-      lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point;
-      alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
-      hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
-      return albersUsa;
-    };
-    return albersUsa.scale(1070);
-  };
-  var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
-    point: d3_noop,
-    lineStart: d3_noop,
-    lineEnd: d3_noop,
-    polygonStart: function() {
-      d3_geo_pathAreaPolygon = 0;
-      d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
-    },
-    polygonEnd: function() {
-      d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
-      d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);
-    }
-  };
-  function d3_geo_pathAreaRingStart() {
-    var x00, y00, x0, y0;
-    d3_geo_pathArea.point = function(x, y) {
-      d3_geo_pathArea.point = nextPoint;
-      x00 = x0 = x, y00 = y0 = y;
-    };
-    function nextPoint(x, y) {
-      d3_geo_pathAreaPolygon += y0 * x - x0 * y;
-      x0 = x, y0 = y;
-    }
-    d3_geo_pathArea.lineEnd = function() {
-      nextPoint(x00, y00);
-    };
-  }
-  var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1;
-  var d3_geo_pathBounds = {
-    point: d3_geo_pathBoundsPoint,
-    lineStart: d3_noop,
-    lineEnd: d3_noop,
-    polygonStart: d3_noop,
-    polygonEnd: d3_noop
-  };
-  function d3_geo_pathBoundsPoint(x, y) {
-    if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
-    if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
-    if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
-    if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
-  }
-  function d3_geo_pathBuffer() {
-    var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = [];
-    var stream = {
-      point: point,
-      lineStart: function() {
-        stream.point = pointLineStart;
-      },
-      lineEnd: lineEnd,
-      polygonStart: function() {
-        stream.lineEnd = lineEndPolygon;
-      },
-      polygonEnd: function() {
-        stream.lineEnd = lineEnd;
-        stream.point = point;
-      },
-      pointRadius: function(_) {
-        pointCircle = d3_geo_pathBufferCircle(_);
-        return stream;
-      },
-      result: function() {
-        if (buffer.length) {
-          var result = buffer.join("");
-          buffer = [];
-          return result;
-        }
-      }
-    };
-    function point(x, y) {
-      buffer.push("M", x, ",", y, pointCircle);
-    }
-    function pointLineStart(x, y) {
-      buffer.push("M", x, ",", y);
-      stream.point = pointLine;
-    }
-    function pointLine(x, y) {
-      buffer.push("L", x, ",", y);
-    }
-    function lineEnd() {
-      stream.point = point;
-    }
-    function lineEndPolygon() {
-      buffer.push("Z");
-    }
-    return stream;
-  }
-  function d3_geo_pathBufferCircle(radius) {
-    return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z";
-  }
-  var d3_geo_pathCentroid = {
-    point: d3_geo_pathCentroidPoint,
-    lineStart: d3_geo_pathCentroidLineStart,
-    lineEnd: d3_geo_pathCentroidLineEnd,
-    polygonStart: function() {
-      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
-    },
-    polygonEnd: function() {
-      d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
-      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
-      d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
-    }
-  };
-  function d3_geo_pathCentroidPoint(x, y) {
-    d3_geo_centroidX0 += x;
-    d3_geo_centroidY0 += y;
-    ++d3_geo_centroidZ0;
-  }
-  function d3_geo_pathCentroidLineStart() {
-    var x0, y0;
-    d3_geo_pathCentroid.point = function(x, y) {
-      d3_geo_pathCentroid.point = nextPoint;
-      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
-    };
-    function nextPoint(x, y) {
-      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
-      d3_geo_centroidX1 += z * (x0 + x) / 2;
-      d3_geo_centroidY1 += z * (y0 + y) / 2;
-      d3_geo_centroidZ1 += z;
-      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
-    }
-  }
-  function d3_geo_pathCentroidLineEnd() {
-    d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
-  }
-  function d3_geo_pathCentroidRingStart() {
-    var x00, y00, x0, y0;
-    d3_geo_pathCentroid.point = function(x, y) {
-      d3_geo_pathCentroid.point = nextPoint;
-      d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
-    };
-    function nextPoint(x, y) {
-      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
-      d3_geo_centroidX1 += z * (x0 + x) / 2;
-      d3_geo_centroidY1 += z * (y0 + y) / 2;
-      d3_geo_centroidZ1 += z;
-      z = y0 * x - x0 * y;
-      d3_geo_centroidX2 += z * (x0 + x);
-      d3_geo_centroidY2 += z * (y0 + y);
-      d3_geo_centroidZ2 += z * 3;
-      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
-    }
-    d3_geo_pathCentroid.lineEnd = function() {
-      nextPoint(x00, y00);
-    };
-  }
-  function d3_geo_pathContext(context) {
-    var pointRadius = 4.5;
-    var stream = {
-      point: point,
-      lineStart: function() {
-        stream.point = pointLineStart;
-      },
-      lineEnd: lineEnd,
-      polygonStart: function() {
-        stream.lineEnd = lineEndPolygon;
-      },
-      polygonEnd: function() {
-        stream.lineEnd = lineEnd;
-        stream.point = point;
-      },
-      pointRadius: function(_) {
-        pointRadius = _;
-        return stream;
-      },
-      result: d3_noop
-    };
-    function point(x, y) {
-      context.moveTo(x + pointRadius, y);
-      context.arc(x, y, pointRadius, 0, τ);
-    }
-    function pointLineStart(x, y) {
-      context.moveTo(x, y);
-      stream.point = pointLine;
-    }
-    function pointLine(x, y) {
-      context.lineTo(x, y);
-    }
-    function lineEnd() {
-      stream.point = point;
-    }
-    function lineEndPolygon() {
-      context.closePath();
-    }
-    return stream;
-  }
-  function d3_geo_resample(project) {
-    var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16;
-    function resample(stream) {
-      return (maxDepth ? resampleRecursive : resampleNone)(stream);
-    }
-    function resampleNone(stream) {
-      return d3_geo_transformPoint(stream, function(x, y) {
-        x = project(x, y);
-        stream.point(x[0], x[1]);
-      });
-    }
-    function resampleRecursive(stream) {
-      var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0;
-      var resample = {
-        point: point,
-        lineStart: lineStart,
-        lineEnd: lineEnd,
-        polygonStart: function() {
-          stream.polygonStart();
-          resample.lineStart = ringStart;
-        },
-        polygonEnd: function() {
-          stream.polygonEnd();
-          resample.lineStart = lineStart;
-        }
-      };
-      function point(x, y) {
-        x = project(x, y);
-        stream.point(x[0], x[1]);
-      }
-      function lineStart() {
-        x0 = NaN;
-        resample.point = linePoint;
-        stream.lineStart();
-      }
-      function linePoint(λ, φ) {
-        var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);
-        resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
-        stream.point(x0, y0);
-      }
-      function lineEnd() {
-        resample.point = point;
-        stream.lineEnd();
-      }
-      function ringStart() {
-        lineStart();
-        resample.point = ringPoint;
-        resample.lineEnd = ringEnd;
-      }
-      function ringPoint(λ, φ) {
-        linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
-        resample.point = linePoint;
-      }
-      function ringEnd() {
-        resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
-        resample.lineEnd = lineEnd;
-        lineEnd();
-      }
-      return resample;
-    }
-    function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
-      var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;
-      if (d2 > 4 * δ2 && depth--) {
-        var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;
-        if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {
-          resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
-          stream.point(x2, y2);
-          resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
-        }
-      }
-    }
-    resample.precision = function(_) {
-      if (!arguments.length) return Math.sqrt(δ2);
-      maxDepth = (δ2 = _ * _) > 0 && 16;
-      return resample;
-    };
-    return resample;
-  }
-  d3.geo.path = function() {
-    var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream;
-    function path(object) {
-      if (object) {
-        if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
-        if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);
-        d3.geo.stream(object, cacheStream);
-      }
-      return contextStream.result();
-    }
-    path.area = function(object) {
-      d3_geo_pathAreaSum = 0;
-      d3.geo.stream(object, projectStream(d3_geo_pathArea));
-      return d3_geo_pathAreaSum;
-    };
-    path.centroid = function(object) {
-      d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
-      d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
-      return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ];
-    };
-    path.bounds = function(object) {
-      d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
-      d3.geo.stream(object, projectStream(d3_geo_pathBounds));
-      return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ];
-    };
-    path.projection = function(_) {
-      if (!arguments.length) return projection;
-      projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
-      return reset();
-    };
-    path.context = function(_) {
-      if (!arguments.length) return context;
-      contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
-      if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
-      return reset();
-    };
-    path.pointRadius = function(_) {
-      if (!arguments.length) return pointRadius;
-      pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
-      return path;
-    };
-    function reset() {
-      cacheStream = null;
-      return path;
-    }
-    return path.projection(d3.geo.albersUsa()).context(null);
-  };
-  function d3_geo_pathProjectStream(project) {
-    var resample = d3_geo_resample(function(x, y) {
-      return project([ x * d3_degrees, y * d3_degrees ]);
-    });
-    return function(stream) {
-      return d3_geo_projectionRadians(resample(stream));
-    };
-  }
-  d3.geo.transform = function(methods) {
-    return {
-      stream: function(stream) {
-        var transform = new d3_geo_transform(stream);
-        for (var k in methods) transform[k] = methods[k];
-        return transform;
-      }
-    };
-  };
-  function d3_geo_transform(stream) {
-    this.stream = stream;
-  }
-  d3_geo_transform.prototype = {
-    point: function(x, y) {
-      this.stream.point(x, y);
-    },
-    sphere: function() {
-      this.stream.sphere();
-    },
-    lineStart: function() {
-      this.stream.lineStart();
-    },
-    lineEnd: function() {
-      this.stream.lineEnd();
-    },
-    polygonStart: function() {
-      this.stream.polygonStart();
-    },
-    polygonEnd: function() {
-      this.stream.polygonEnd();
-    }
-  };
-  function d3_geo_transformPoint(stream, point) {
-    return {
-      point: point,
-      sphere: function() {
-        stream.sphere();
-      },
-      lineStart: function() {
-        stream.lineStart();
-      },
-      lineEnd: function() {
-        stream.lineEnd();
-      },
-      polygonStart: function() {
-        stream.polygonStart();
-      },
-      polygonEnd: function() {
-        stream.polygonEnd();
-      }
-    };
-  }
-  d3.geo.projection = d3_geo_projection;
-  d3.geo.projectionMutator = d3_geo_projectionMutator;
-  function d3_geo_projection(project) {
-    return d3_geo_projectionMutator(function() {
-      return project;
-    })();
-  }
-  function d3_geo_projectionMutator(projectAt) {
-    var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {
-      x = project(x, y);
-      return [ x[0] * k + δx, δy - x[1] * k ];
-    }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream;
-    function projection(point) {
-      point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
-      return [ point[0] * k + δx, δy - point[1] * k ];
-    }
-    function invert(point) {
-      point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
-      return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];
-    }
-    projection.stream = function(output) {
-      if (stream) stream.valid = false;
-      stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));
-      stream.valid = true;
-      return stream;
-    };
-    projection.clipAngle = function(_) {
-      if (!arguments.length) return clipAngle;
-      preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
-      return invalidate();
-    };
-    projection.clipExtent = function(_) {
-      if (!arguments.length) return clipExtent;
-      clipExtent = _;
-      postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;
-      return invalidate();
-    };
-    projection.scale = function(_) {
-      if (!arguments.length) return k;
-      k = +_;
-      return reset();
-    };
-    projection.translate = function(_) {
-      if (!arguments.length) return [ x, y ];
-      x = +_[0];
-      y = +_[1];
-      return reset();
-    };
-    projection.center = function(_) {
-      if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];
-      λ = _[0] % 360 * d3_radians;
-      φ = _[1] % 360 * d3_radians;
-      return reset();
-    };
-    projection.rotate = function(_) {
-      if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];
-      δλ = _[0] % 360 * d3_radians;
-      δφ = _[1] % 360 * d3_radians;
-      δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
-      return reset();
-    };
-    d3.rebind(projection, projectResample, "precision");
-    function reset() {
-      projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
-      var center = project(λ, φ);
-      δx = x - center[0] * k;
-      δy = y + center[1] * k;
-      return invalidate();
-    }
-    function invalidate() {
-      if (stream) stream.valid = false, stream = null;
-      return projection;
-    }
-    return function() {
-      project = projectAt.apply(this, arguments);
-      projection.invert = project.invert && invert;
-      return reset();
-    };
-  }
-  function d3_geo_projectionRadians(stream) {
-    return d3_geo_transformPoint(stream, function(x, y) {
-      stream.point(x * d3_radians, y * d3_radians);
-    });
-  }
-  function d3_geo_equirectangular(λ, φ) {
-    return [ λ, φ ];
-  }
-  (d3.geo.equirectangular = function() {
-    return d3_geo_projection(d3_geo_equirectangular);
-  }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
-  d3.geo.rotation = function(rotate) {
-    rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);
-    function forward(coordinates) {
-      coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
-      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
-    }
-    forward.invert = function(coordinates) {
-      coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
-      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
-    };
-    return forward;
-  };
-  function d3_geo_identityRotation(λ, φ) {
-    return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
-  }
-  d3_geo_identityRotation.invert = d3_geo_equirectangular;
-  function d3_geo_rotation(δλ, δφ, δγ) {
-    return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation;
-  }
-  function d3_geo_forwardRotationλ(δλ) {
-    return function(λ, φ) {
-      return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
-    };
-  }
-  function d3_geo_rotationλ(δλ) {
-    var rotation = d3_geo_forwardRotationλ(δλ);
-    rotation.invert = d3_geo_forwardRotationλ(-δλ);
-    return rotation;
-  }
-  function d3_geo_rotationφγ(δφ, δγ) {
-    var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);
-    function rotation(λ, φ) {
-      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;
-      return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ];
-    }
-    rotation.invert = function(λ, φ) {
-      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;
-      return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ];
-    };
-    return rotation;
-  }
-  d3.geo.circle = function() {
-    var origin = [ 0, 0 ], angle, precision = 6, interpolate;
-    function circle() {
-      var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];
-      interpolate(null, null, 1, {
-        point: function(x, y) {
-          ring.push(x = rotate(x, y));
-          x[0] *= d3_degrees, x[1] *= d3_degrees;
-        }
-      });
-      return {
-        type: "Polygon",
-        coordinates: [ ring ]
-      };
-    }
-    circle.origin = function(x) {
-      if (!arguments.length) return origin;
-      origin = x;
-      return circle;
-    };
-    circle.angle = function(x) {
-      if (!arguments.length) return angle;
-      interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
-      return circle;
-    };
-    circle.precision = function(_) {
-      if (!arguments.length) return precision;
-      interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
-      return circle;
-    };
-    return circle.angle(90);
-  };
-  function d3_geo_circleInterpolate(radius, precision) {
-    var cr = Math.cos(radius), sr = Math.sin(radius);
-    return function(from, to, direction, listener) {
-      var step = direction * precision;
-      if (from != null) {
-        from = d3_geo_circleAngle(cr, from);
-        to = d3_geo_circleAngle(cr, to);
-        if (direction > 0 ? from < to : from > to) from += direction * τ;
-      } else {
-        from = radius + direction * τ;
-        to = radius - .5 * step;
-      }
-      for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) {
-        listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);
-      }
-    };
-  }
-  function d3_geo_circleAngle(cr, point) {
-    var a = d3_geo_cartesian(point);
-    a[0] -= cr;
-    d3_geo_cartesianNormalize(a);
-    var angle = d3_acos(-a[1]);
-    return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
-  }
-  d3.geo.distance = function(a, b) {
-    var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t;
-    return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);
-  };
-  d3.geo.graticule = function() {
-    var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5;
-    function graticule() {
-      return {
-        type: "MultiLineString",
-        coordinates: lines()
-      };
-    }
-    function lines() {
-      return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) {
-        return abs(x % DX) > ε;
-      }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {
-        return abs(y % DY) > ε;
-      }).map(y));
-    }
-    graticule.lines = function() {
-      return lines().map(function(coordinates) {
-        return {
-          type: "LineString",
-          coordinates: coordinates
-        };
-      });
-    };
-    graticule.outline = function() {
-      return {
-        type: "Polygon",
-        coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]
-      };
-    };
-    graticule.extent = function(_) {
-      if (!arguments.length) return graticule.minorExtent();
-      return graticule.majorExtent(_).minorExtent(_);
-    };
-    graticule.majorExtent = function(_) {
-      if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ];
-      X0 = +_[0][0], X1 = +_[1][0];
-      Y0 = +_[0][1], Y1 = +_[1][1];
-      if (X0 > X1) _ = X0, X0 = X1, X1 = _;
-      if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
-      return graticule.precision(precision);
-    };
-    graticule.minorExtent = function(_) {
-      if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
-      x0 = +_[0][0], x1 = +_[1][0];
-      y0 = +_[0][1], y1 = +_[1][1];
-      if (x0 > x1) _ = x0, x0 = x1, x1 = _;
-      if (y0 > y1) _ = y0, y0 = y1, y1 = _;
-      return graticule.precision(precision);
-    };
-    graticule.step = function(_) {
-      if (!arguments.length) return graticule.minorStep();
-      return graticule.majorStep(_).minorStep(_);
-    };
-    graticule.majorStep = function(_) {
-      if (!arguments.length) return [ DX, DY ];
-      DX = +_[0], DY = +_[1];
-      return graticule;
-    };
-    graticule.minorStep = function(_) {
-      if (!arguments.length) return [ dx, dy ];
-      dx = +_[0], dy = +_[1];
-      return graticule;
-    };
-    graticule.precision = function(_) {
-      if (!arguments.length) return precision;
-      precision = +_;
-      x = d3_geo_graticuleX(y0, y1, 90);
-      y = d3_geo_graticuleY(x0, x1, precision);
-      X = d3_geo_graticuleX(Y0, Y1, 90);
-      Y = d3_geo_graticuleY(X0, X1, precision);
-      return graticule;
-    };
-    return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]);
-  };
-  function d3_geo_graticuleX(y0, y1, dy) {
-    var y = d3.range(y0, y1 - ε, dy).concat(y1);
-    return function(x) {
-      return y.map(function(y) {
-        return [ x, y ];
-      });
-    };
-  }
-  function d3_geo_graticuleY(x0, x1, dx) {
-    var x = d3.range(x0, x1 - ε, dx).concat(x1);
-    return function(y) {
-      return x.map(function(x) {
-        return [ x, y ];
-      });
-    };
-  }
-  function d3_source(d) {
-    return d.source;
-  }
-  function d3_target(d) {
-    return d.target;
-  }
-  d3.geo.greatArc = function() {
-    var source = d3_source, source_, target = d3_target, target_;
-    function greatArc() {
-      return {
-        type: "LineString",
-        coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ]
-      };
-    }
-    greatArc.distance = function() {
-      return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments));
-    };
-    greatArc.source = function(_) {
-      if (!arguments.length) return source;
-      source = _, source_ = typeof _ === "function" ? null : _;
-      return greatArc;
-    };
-    greatArc.target = function(_) {
-      if (!arguments.length) return target;
-      target = _, target_ = typeof _ === "function" ? null : _;
-      return greatArc;
-    };
-    greatArc.precision = function() {
-      return arguments.length ? greatArc : 0;
-    };
-    return greatArc;
-  };
-  d3.geo.interpolate = function(source, target) {
-    return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);
-  };
-  function d3_geo_interpolate(x0, y0, x1, y1) {
-    var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d);
-    var interpolate = d ? function(t) {
-      var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;
-      return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];
-    } : function() {
-      return [ x0 * d3_degrees, y0 * d3_degrees ];
-    };
-    interpolate.distance = d;
-    return interpolate;
-  }
-  d3.geo.length = function(object) {
-    d3_geo_lengthSum = 0;
-    d3.geo.stream(object, d3_geo_length);
-    return d3_geo_lengthSum;
-  };
-  var d3_geo_lengthSum;
-  var d3_geo_length = {
-    sphere: d3_noop,
-    point: d3_noop,
-    lineStart: d3_geo_lengthLineStart,
-    lineEnd: d3_noop,
-    polygonStart: d3_noop,
-    polygonEnd: d3_noop
-  };
-  function d3_geo_lengthLineStart() {
-    var λ0, sinφ0, cosφ0;
-    d3_geo_length.point = function(λ, φ) {
-      λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
-      d3_geo_length.point = nextPoint;
-    };
-    d3_geo_length.lineEnd = function() {
-      d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
-    };
-    function nextPoint(λ, φ) {
-      var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t);
-      d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);
-      λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
-    }
-  }
-  function d3_geo_azimuthal(scale, angle) {
-    function azimuthal(λ, φ) {
-      var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);
-      return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];
-    }
-    azimuthal.invert = function(x, y) {
-      var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);
-      return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ];
-    };
-    return azimuthal;
-  }
-  var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {
-    return Math.sqrt(2 / (1 + cosλcosφ));
-  }, function(ρ) {
-    return 2 * Math.asin(ρ / 2);
-  });
-  (d3.geo.azimuthalEqualArea = function() {
-    return d3_geo_projection(d3_geo_azimuthalEqualArea);
-  }).raw = d3_geo_azimuthalEqualArea;
-  var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {
-    var c = Math.acos(cosλcosφ);
-    return c && c / Math.sin(c);
-  }, d3_identity);
-  (d3.geo.azimuthalEquidistant = function() {
-    return d3_geo_projection(d3_geo_azimuthalEquidistant);
-  }).raw = d3_geo_azimuthalEquidistant;
-  function d3_geo_conicConformal(φ0, φ1) {
-    var cosφ0 = Math.cos(φ0), t = function(φ) {
-      return Math.tan(π / 4 + φ / 2);
-    }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;
-    if (!n) return d3_geo_mercator;
-    function forward(λ, φ) {
-      if (F > 0) {
-        if (φ < -halfπ + ε) φ = -halfπ + ε;
-      } else {
-        if (φ > halfπ - ε) φ = halfπ - ε;
-      }
-      var ρ = F / Math.pow(t(φ), n);
-      return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];
-    }
-    forward.invert = function(x, y) {
-      var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);
-      return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ];
-    };
-    return forward;
-  }
-  (d3.geo.conicConformal = function() {
-    return d3_geo_conic(d3_geo_conicConformal);
-  }).raw = d3_geo_conicConformal;
-  function d3_geo_conicEquidistant(φ0, φ1) {
-    var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0;
-    if (abs(n) < ε) return d3_geo_equirectangular;
-    function forward(λ, φ) {
-      var ρ = G - φ;
-      return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ];
-    }
-    forward.invert = function(x, y) {
-      var ρ0_y = G - y;
-      return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ];
-    };
-    return forward;
-  }
-  (d3.geo.conicEquidistant = function() {
-    return d3_geo_conic(d3_geo_conicEquidistant);
-  }).raw = d3_geo_conicEquidistant;
-  var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {
-    return 1 / cosλcosφ;
-  }, Math.atan);
-  (d3.geo.gnomonic = function() {
-    return d3_geo_projection(d3_geo_gnomonic);
-  }).raw = d3_geo_gnomonic;
-  function d3_geo_mercator(λ, φ) {
-    return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ];
-  }
-  d3_geo_mercator.invert = function(x, y) {
-    return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ];
-  };
-  function d3_geo_mercatorProjection(project) {
-    var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto;
-    m.scale = function() {
-      var v = scale.apply(m, arguments);
-      return v === m ? clipAuto ? m.clipExtent(null) : m : v;
-    };
-    m.translate = function() {
-      var v = translate.apply(m, arguments);
-      return v === m ? clipAuto ? m.clipExtent(null) : m : v;
-    };
-    m.clipExtent = function(_) {
-      var v = clipExtent.apply(m, arguments);
-      if (v === m) {
-        if (clipAuto = _ == null) {
-          var k = π * scale(), t = translate();
-          clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]);
-        }
-      } else if (clipAuto) {
-        v = null;
-      }
-      return v;
-    };
-    return m.clipExtent(null);
-  }
-  (d3.geo.mercator = function() {
-    return d3_geo_mercatorProjection(d3_geo_mercator);
-  }).raw = d3_geo_mercator;
-  var d3_geo_orthographic = d3_geo_azimuthal(function() {
-    return 1;
-  }, Math.asin);
-  (d3.geo.orthographic = function() {
-    return d3_geo_projection(d3_geo_orthographic);
-  }).raw = d3_geo_orthographic;
-  var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {
-    return 1 / (1 + cosλcosφ);
-  }, function(ρ) {
-    return 2 * Math.atan(ρ);
-  });
-  (d3.geo.stereographic = function() {
-    return d3_geo_projection(d3_geo_stereographic);
-  }).raw = d3_geo_stereographic;
-  function d3_geo_transverseMercator(λ, φ) {
-    return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ];
-  }
-  d3_geo_transverseMercator.invert = function(x, y) {
-    return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ];
-  };
-  (d3.geo.transverseMercator = function() {
-    var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate;
-    projection.center = function(_) {
-      return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]);
-    };
-    projection.rotate = function(_) {
-      return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), 
-      [ _[0], _[1], _[2] - 90 ]);
-    };
-    return rotate([ 0, 0, 90 ]);
-  }).raw = d3_geo_transverseMercator;
-  d3.geom = {};
-  function d3_geom_pointX(d) {
-    return d[0];
-  }
-  function d3_geom_pointY(d) {
-    return d[1];
-  }
-  d3.geom.hull = function(vertices) {
-    var x = d3_geom_pointX, y = d3_geom_pointY;
-    if (arguments.length) return hull(vertices);
-    function hull(data) {
-      if (data.length < 3) return [];
-      var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = [];
-      for (i = 0; i < n; i++) {
-        points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]);
-      }
-      points.sort(d3_geom_hullOrder);
-      for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]);
-      var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints);
-      var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = [];
-      for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]);
-      for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]);
-      return polygon;
-    }
-    hull.x = function(_) {
-      return arguments.length ? (x = _, hull) : x;
-    };
-    hull.y = function(_) {
-      return arguments.length ? (y = _, hull) : y;
-    };
-    return hull;
-  };
-  function d3_geom_hullUpper(points) {
-    var n = points.length, hull = [ 0, 1 ], hs = 2;
-    for (var i = 2; i < n; i++) {
-      while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs;
-      hull[hs++] = i;
-    }
-    return hull.slice(0, hs);
-  }
-  function d3_geom_hullOrder(a, b) {
-    return a[0] - b[0] || a[1] - b[1];
-  }
-  d3.geom.polygon = function(coordinates) {
-    d3_subclass(coordinates, d3_geom_polygonPrototype);
-    return coordinates;
-  };
-  var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
-  d3_geom_polygonPrototype.area = function() {
-    var i = -1, n = this.length, a, b = this[n - 1], area = 0;
-    while (++i < n) {
-      a = b;
-      b = this[i];
-      area += a[1] * b[0] - a[0] * b[1];
-    }
-    return area * .5;
-  };
-  d3_geom_polygonPrototype.centroid = function(k) {
-    var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c;
-    if (!arguments.length) k = -1 / (6 * this.area());
-    while (++i < n) {
-      a = b;
-      b = this[i];
-      c = a[0] * b[1] - b[0] * a[1];
-      x += (a[0] + b[0]) * c;
-      y += (a[1] + b[1]) * c;
-    }
-    return [ x * k, y * k ];
-  };
-  d3_geom_polygonPrototype.clip = function(subject) {
-    var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d;
-    while (++i < n) {
-      input = subject.slice();
-      subject.length = 0;
-      b = this[i];
-      c = input[(m = input.length - closed) - 1];
-      j = -1;
-      while (++j < m) {
-        d = input[j];
-        if (d3_geom_polygonInside(d, a, b)) {
-          if (!d3_geom_polygonInside(c, a, b)) {
-            subject.push(d3_geom_polygonIntersect(c, d, a, b));
-          }
-          subject.push(d);
-        } else if (d3_geom_polygonInside(c, a, b)) {
-          subject.push(d3_geom_polygonIntersect(c, d, a, b));
-        }
-        c = d;
-      }
-      if (closed) subject.push(subject[0]);
-      a = b;
-    }
-    return subject;
-  };
-  function d3_geom_polygonInside(p, a, b) {
-    return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
-  }
-  function d3_geom_polygonIntersect(c, d, a, b) {
-    var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
-    return [ x1 + ua * x21, y1 + ua * y21 ];
-  }
-  function d3_geom_polygonClosed(coordinates) {
-    var a = coordinates[0], b = coordinates[coordinates.length - 1];
-    return !(a[0] - b[0] || a[1] - b[1]);
-  }
-  var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = [];
-  function d3_geom_voronoiBeach() {
-    d3_geom_voronoiRedBlackNode(this);
-    this.edge = this.site = this.circle = null;
-  }
-  function d3_geom_voronoiCreateBeach(site) {
-    var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach();
-    beach.site = site;
-    return beach;
-  }
-  function d3_geom_voronoiDetachBeach(beach) {
-    d3_geom_voronoiDetachCircle(beach);
-    d3_geom_voronoiBeaches.remove(beach);
-    d3_geom_voronoiBeachPool.push(beach);
-    d3_geom_voronoiRedBlackNode(beach);
-  }
-  function d3_geom_voronoiRemoveBeach(beach) {
-    var circle = beach.circle, x = circle.x, y = circle.cy, vertex = {
-      x: x,
-      y: y
-    }, previous = beach.P, next = beach.N, disappearing = [ beach ];
-    d3_geom_voronoiDetachBeach(beach);
-    var lArc = previous;
-    while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) {
-      previous = lArc.P;
-      disappearing.unshift(lArc);
-      d3_geom_voronoiDetachBeach(lArc);
-      lArc = previous;
-    }
-    disappearing.unshift(lArc);
-    d3_geom_voronoiDetachCircle(lArc);
-    var rArc = next;
-    while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) {
-      next = rArc.N;
-      disappearing.push(rArc);
-      d3_geom_voronoiDetachBeach(rArc);
-      rArc = next;
-    }
-    disappearing.push(rArc);
-    d3_geom_voronoiDetachCircle(rArc);
-    var nArcs = disappearing.length, iArc;
-    for (iArc = 1; iArc < nArcs; ++iArc) {
-      rArc = disappearing[iArc];
-      lArc = disappearing[iArc - 1];
-      d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
-    }
-    lArc = disappearing[0];
-    rArc = disappearing[nArcs - 1];
-    rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex);
-    d3_geom_voronoiAttachCircle(lArc);
-    d3_geom_voronoiAttachCircle(rArc);
-  }
-  function d3_geom_voronoiAddBeach(site) {
-    var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._;
-    while (node) {
-      dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x;
-      if (dxl > ε) node = node.L; else {
-        dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix);
-        if (dxr > ε) {
-          if (!node.R) {
-            lArc = node;
-            break;
-          }
-          node = node.R;
-        } else {
-          if (dxl > -ε) {
-            lArc = node.P;
-            rArc = node;
-          } else if (dxr > -ε) {
-            lArc = node;
-            rArc = node.N;
-          } else {
-            lArc = rArc = node;
-          }
-          break;
-        }
-      }
-    }
-    var newArc = d3_geom_voronoiCreateBeach(site);
-    d3_geom_voronoiBeaches.insert(lArc, newArc);
-    if (!lArc && !rArc) return;
-    if (lArc === rArc) {
-      d3_geom_voronoiDetachCircle(lArc);
-      rArc = d3_geom_voronoiCreateBeach(lArc.site);
-      d3_geom_voronoiBeaches.insert(newArc, rArc);
-      newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
-      d3_geom_voronoiAttachCircle(lArc);
-      d3_geom_voronoiAttachCircle(rArc);
-      return;
-    }
-    if (!rArc) {
-      newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
-      return;
-    }
-    d3_geom_voronoiDetachCircle(lArc);
-    d3_geom_voronoiDetachCircle(rArc);
-    var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = {
-      x: (cy * hb - by * hc) / d + ax,
-      y: (bx * hc - cx * hb) / d + ay
-    };
-    d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex);
-    newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex);
-    rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex);
-    d3_geom_voronoiAttachCircle(lArc);
-    d3_geom_voronoiAttachCircle(rArc);
-  }
-  function d3_geom_voronoiLeftBreakPoint(arc, directrix) {
-    var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix;
-    if (!pby2) return rfocx;
-    var lArc = arc.P;
-    if (!lArc) return -Infinity;
-    site = lArc.site;
-    var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix;
-    if (!plby2) return lfocx;
-    var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2;
-    if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
-    return (rfocx + lfocx) / 2;
-  }
-  function d3_geom_voronoiRightBreakPoint(arc, directrix) {
-    var rArc = arc.N;
-    if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix);
-    var site = arc.site;
-    return site.y === directrix ? site.x : Infinity;
-  }
-  function d3_geom_voronoiCell(site) {
-    this.site = site;
-    this.edges = [];
-  }
-  d3_geom_voronoiCell.prototype.prepare = function() {
-    var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge;
-    while (iHalfEdge--) {
-      edge = halfEdges[iHalfEdge].edge;
-      if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1);
-    }
-    halfEdges.sort(d3_geom_voronoiHalfEdgeOrder);
-    return halfEdges.length;
-  };
-  function d3_geom_voronoiCloseCells(extent) {
-    var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end;
-    while (iCell--) {
-      cell = cells[iCell];
-      if (!cell || !cell.prepare()) continue;
-      halfEdges = cell.edges;
-      nHalfEdges = halfEdges.length;
-      iHalfEdge = 0;
-      while (iHalfEdge < nHalfEdges) {
-        end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y;
-        start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y;
-        if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) {
-          halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? {
-            x: x0,
-            y: abs(x2 - x0) < ε ? y2 : y1
-          } : abs(y3 - y1) < ε && x1 - x3 > ε ? {
-            x: abs(y2 - y1) < ε ? x2 : x1,
-            y: y1
-          } : abs(x3 - x1) < ε && y3 - y0 > ε ? {
-            x: x1,
-            y: abs(x2 - x1) < ε ? y2 : y0
-          } : abs(y3 - y0) < ε && x3 - x0 > ε ? {
-            x: abs(y2 - y0) < ε ? x2 : x0,
-            y: y0
-          } : null), cell.site, null));
-          ++nHalfEdges;
-        }
-      }
-    }
-  }
-  function d3_geom_voronoiHalfEdgeOrder(a, b) {
-    return b.angle - a.angle;
-  }
-  function d3_geom_voronoiCircle() {
-    d3_geom_voronoiRedBlackNode(this);
-    this.x = this.y = this.arc = this.site = this.cy = null;
-  }
-  function d3_geom_voronoiAttachCircle(arc) {
-    var lArc = arc.P, rArc = arc.N;
-    if (!lArc || !rArc) return;
-    var lSite = lArc.site, cSite = arc.site, rSite = rArc.site;
-    if (lSite === rSite) return;
-    var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by;
-    var d = 2 * (ax * cy - ay * cx);
-    if (d >= -ε2) return;
-    var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by;
-    var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle();
-    circle.arc = arc;
-    circle.site = cSite;
-    circle.x = x + bx;
-    circle.y = cy + Math.sqrt(x * x + y * y);
-    circle.cy = cy;
-    arc.circle = circle;
-    var before = null, node = d3_geom_voronoiCircles._;
-    while (node) {
-      if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) {
-        if (node.L) node = node.L; else {
-          before = node.P;
-          break;
-        }
-      } else {
-        if (node.R) node = node.R; else {
-          before = node;
-          break;
-        }
-      }
-    }
-    d3_geom_voronoiCircles.insert(before, circle);
-    if (!before) d3_geom_voronoiFirstCircle = circle;
-  }
-  function d3_geom_voronoiDetachCircle(arc) {
-    var circle = arc.circle;
-    if (circle) {
-      if (!circle.P) d3_geom_voronoiFirstCircle = circle.N;
-      d3_geom_voronoiCircles.remove(circle);
-      d3_geom_voronoiCirclePool.push(circle);
-      d3_geom_voronoiRedBlackNode(circle);
-      arc.circle = null;
-    }
-  }
-  function d3_geom_voronoiClipEdges(extent) {
-    var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e;
-    while (i--) {
-      e = edges[i];
-      if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) {
-        e.a = e.b = null;
-        edges.splice(i, 1);
-      }
-    }
-  }
-  function d3_geom_voronoiConnectEdge(edge, extent) {
-    var vb = edge.b;
-    if (vb) return true;
-    var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb;
-    if (ry === ly) {
-      if (fx < x0 || fx >= x1) return;
-      if (lx > rx) {
-        if (!va) va = {
-          x: fx,
-          y: y0
-        }; else if (va.y >= y1) return;
-        vb = {
-          x: fx,
-          y: y1
-        };
-      } else {
-        if (!va) va = {
-          x: fx,
-          y: y1
-        }; else if (va.y < y0) return;
-        vb = {
-          x: fx,
-          y: y0
-        };
-      }
-    } else {
-      fm = (lx - rx) / (ry - ly);
-      fb = fy - fm * fx;
-      if (fm < -1 || fm > 1) {
-        if (lx > rx) {
-          if (!va) va = {
-            x: (y0 - fb) / fm,
-            y: y0
-          }; else if (va.y >= y1) return;
-          vb = {
-            x: (y1 - fb) / fm,
-            y: y1
-          };
-        } else {
-          if (!va) va = {
-            x: (y1 - fb) / fm,
-            y: y1
-          }; else if (va.y < y0) return;
-          vb = {
-            x: (y0 - fb) / fm,
-            y: y0
-          };
-        }
-      } else {
-        if (ly < ry) {
-          if (!va) va = {
-            x: x0,
-            y: fm * x0 + fb
-          }; else if (va.x >= x1) return;
-          vb = {
-            x: x1,
-            y: fm * x1 + fb
-          };
-        } else {
-          if (!va) va = {
-            x: x1,
-            y: fm * x1 + fb
-          }; else if (va.x < x0) return;
-          vb = {
-            x: x0,
-            y: fm * x0 + fb
-          };
-        }
-      }
-    }
-    edge.a = va;
-    edge.b = vb;
-    return true;
-  }
-  function d3_geom_voronoiEdge(lSite, rSite) {
-    this.l = lSite;
-    this.r = rSite;
-    this.a = this.b = null;
-  }
-  function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) {
-    var edge = new d3_geom_voronoiEdge(lSite, rSite);
-    d3_geom_voronoiEdges.push(edge);
-    if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va);
-    if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb);
-    d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite));
-    d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite));
-    return edge;
-  }
-  function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) {
-    var edge = new d3_geom_voronoiEdge(lSite, null);
-    edge.a = va;
-    edge.b = vb;
-    d3_geom_voronoiEdges.push(edge);
-    return edge;
-  }
-  function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) {
-    if (!edge.a && !edge.b) {
-      edge.a = vertex;
-      edge.l = lSite;
-      edge.r = rSite;
-    } else if (edge.l === rSite) {
-      edge.b = vertex;
-    } else {
-      edge.a = vertex;
-    }
-  }
-  function d3_geom_voronoiHalfEdge(edge, lSite, rSite) {
-    var va = edge.a, vb = edge.b;
-    this.edge = edge;
-    this.site = lSite;
-    this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y);
-  }
-  d3_geom_voronoiHalfEdge.prototype = {
-    start: function() {
-      return this.edge.l === this.site ? this.edge.a : this.edge.b;
-    },
-    end: function() {
-      return this.edge.l === this.site ? this.edge.b : this.edge.a;
-    }
-  };
-  function d3_geom_voronoiRedBlackTree() {
-    this._ = null;
-  }
-  function d3_geom_voronoiRedBlackNode(node) {
-    node.U = node.C = node.L = node.R = node.P = node.N = null;
-  }
-  d3_geom_voronoiRedBlackTree.prototype = {
-    insert: function(after, node) {
-      var parent, grandpa, uncle;
-      if (after) {
-        node.P = after;
-        node.N = after.N;
-        if (after.N) after.N.P = node;
-        after.N = node;
-        if (after.R) {
-          after = after.R;
-          while (after.L) after = after.L;
-          after.L = node;
-        } else {
-          after.R = node;
-        }
-        parent = after;
-      } else if (this._) {
-        after = d3_geom_voronoiRedBlackFirst(this._);
-        node.P = null;
-        node.N = after;
-        after.P = after.L = node;
-        parent = after;
-      } else {
-        node.P = node.N = null;
-        this._ = node;
-        parent = null;
-      }
-      node.L = node.R = null;
-      node.U = parent;
-      node.C = true;
-      after = node;
-      while (parent && parent.C) {
-        grandpa = parent.U;
-        if (parent === grandpa.L) {
-          uncle = grandpa.R;
-          if (uncle && uncle.C) {
-            parent.C = uncle.C = false;
-            grandpa.C = true;
-            after = grandpa;
-          } else {
-            if (after === parent.R) {
-              d3_geom_voronoiRedBlackRotateLeft(this, parent);
-              after = parent;
-              parent = after.U;
-            }
-            parent.C = false;
-            grandpa.C = true;
-            d3_geom_voronoiRedBlackRotateRight(this, grandpa);
-          }
-        } else {
-          uncle = grandpa.L;
-          if (uncle && uncle.C) {
-            parent.C = uncle.C = false;
-            grandpa.C = true;
-            after = grandpa;
-          } else {
-            if (after === parent.L) {
-              d3_geom_voronoiRedBlackRotateRight(this, parent);
-              after = parent;
-              parent = after.U;
-            }
-            parent.C = false;
-            grandpa.C = true;
-            d3_geom_voronoiRedBlackRotateLeft(this, grandpa);
-          }
-        }
-        parent = after.U;
-      }
-      this._.C = false;
-    },
-    remove: function(node) {
-      if (node.N) node.N.P = node.P;
-      if (node.P) node.P.N = node.N;
-      node.N = node.P = null;
-      var parent = node.U, sibling, left = node.L, right = node.R, next, red;
-      if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right);
-      if (parent) {
-        if (parent.L === node) parent.L = next; else parent.R = next;
-      } else {
-        this._ = next;
-      }
-      if (left && right) {
-        red = next.C;
-        next.C = node.C;
-        next.L = left;
-        left.U = next;
-        if (next !== right) {
-          parent = next.U;
-          next.U = node.U;
-          node = next.R;
-          parent.L = node;
-          next.R = right;
-          right.U = next;
-        } else {
-          next.U = parent;
-          parent = next;
-          node = next.R;
-        }
-      } else {
-        red = node.C;
-        node = next;
-      }
-      if (node) node.U = parent;
-      if (red) return;
-      if (node && node.C) {
-        node.C = false;
-        return;
-      }
-      do {
-        if (node === this._) break;
-        if (node === parent.L) {
-          sibling = parent.R;
-          if (sibling.C) {
-            sibling.C = false;
-            parent.C = true;
-            d3_geom_voronoiRedBlackRotateLeft(this, parent);
-            sibling = parent.R;
-          }
-          if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
-            if (!sibling.R || !sibling.R.C) {
-              sibling.L.C = false;
-              sibling.C = true;
-              d3_geom_voronoiRedBlackRotateRight(this, sibling);
-              sibling = parent.R;
-            }
-            sibling.C = parent.C;
-            parent.C = sibling.R.C = false;
-            d3_geom_voronoiRedBlackRotateLeft(this, parent);
-            node = this._;
-            break;
-          }
-        } else {
-          sibling = parent.L;
-          if (sibling.C) {
-            sibling.C = false;
-            parent.C = true;
-            d3_geom_voronoiRedBlackRotateRight(this, parent);
-            sibling = parent.L;
-          }
-          if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
-            if (!sibling.L || !sibling.L.C) {
-              sibling.R.C = false;
-              sibling.C = true;
-              d3_geom_voronoiRedBlackRotateLeft(this, sibling);
-              sibling = parent.L;
-            }
-            sibling.C = parent.C;
-            parent.C = sibling.L.C = false;
-            d3_geom_voronoiRedBlackRotateRight(this, parent);
-            node = this._;
-            break;
-          }
-        }
-        sibling.C = true;
-        node = parent;
-        parent = parent.U;
-      } while (!node.C);
-      if (node) node.C = false;
-    }
-  };
-  function d3_geom_voronoiRedBlackRotateLeft(tree, node) {
-    var p = node, q = node.R, parent = p.U;
-    if (parent) {
-      if (parent.L === p) parent.L = q; else parent.R = q;
-    } else {
-      tree._ = q;
-    }
-    q.U = parent;
-    p.U = q;
-    p.R = q.L;
-    if (p.R) p.R.U = p;
-    q.L = p;
-  }
-  function d3_geom_voronoiRedBlackRotateRight(tree, node) {
-    var p = node, q = node.L, parent = p.U;
-    if (parent) {
-      if (parent.L === p) parent.L = q; else parent.R = q;
-    } else {
-      tree._ = q;
-    }
-    q.U = parent;
-    p.U = q;
-    p.L = q.R;
-    if (p.L) p.L.U = p;
-    q.R = p;
-  }
-  function d3_geom_voronoiRedBlackFirst(node) {
-    while (node.L) node = node.L;
-    return node;
-  }
-  function d3_geom_voronoi(sites, bbox) {
-    var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle;
-    d3_geom_voronoiEdges = [];
-    d3_geom_voronoiCells = new Array(sites.length);
-    d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree();
-    d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree();
-    while (true) {
-      circle = d3_geom_voronoiFirstCircle;
-      if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) {
-        if (site.x !== x0 || site.y !== y0) {
-          d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site);
-          d3_geom_voronoiAddBeach(site);
-          x0 = site.x, y0 = site.y;
-        }
-        site = sites.pop();
-      } else if (circle) {
-        d3_geom_voronoiRemoveBeach(circle.arc);
-      } else {
-        break;
-      }
-    }
-    if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox);
-    var diagram = {
-      cells: d3_geom_voronoiCells,
-      edges: d3_geom_voronoiEdges
-    };
-    d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null;
-    return diagram;
-  }
-  function d3_geom_voronoiVertexOrder(a, b) {
-    return b.y - a.y || b.x - a.x;
-  }
-  d3.geom.voronoi = function(points) {
-    var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent;
-    if (points) return voronoi(points);
-    function voronoi(data) {
-      var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1];
-      d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) {
-        var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) {
-          var s = e.start();
-          return [ s.x, s.y ];
-        }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : [];
-        polygon.point = data[i];
-      });
-      return polygons;
-    }
-    function sites(data) {
-      return data.map(function(d, i) {
-        return {
-          x: Math.round(fx(d, i) / ε) * ε,
-          y: Math.round(fy(d, i) / ε) * ε,
-          i: i
-        };
-      });
-    }
-    voronoi.links = function(data) {
-      return d3_geom_voronoi(sites(data)).edges.filter(function(edge) {
-        return edge.l && edge.r;
-      }).map(function(edge) {
-        return {
-          source: data[edge.l.i],
-          target: data[edge.r.i]
-        };
-      });
-    };
-    voronoi.triangles = function(data) {
-      var triangles = [];
-      d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) {
-        var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l;
-        while (++j < m) {
-          e0 = e1;
-          s0 = s1;
-          e1 = edges[j].edge;
-          s1 = e1.l === site ? e1.r : e1.l;
-          if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) {
-            triangles.push([ data[i], data[s0.i], data[s1.i] ]);
-          }
-        }
-      });
-      return triangles;
-    };
-    voronoi.x = function(_) {
-      return arguments.length ? (fx = d3_functor(x = _), voronoi) : x;
-    };
-    voronoi.y = function(_) {
-      return arguments.length ? (fy = d3_functor(y = _), voronoi) : y;
-    };
-    voronoi.clipExtent = function(_) {
-      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent;
-      clipExtent = _ == null ? d3_geom_voronoiClipExtent : _;
-      return voronoi;
-    };
-    voronoi.size = function(_) {
-      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1];
-      return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]);
-    };
-    return voronoi;
-  };
-  var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ];
-  function d3_geom_voronoiTriangleArea(a, b, c) {
-    return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y);
-  }
-  d3.geom.delaunay = function(vertices) {
-    return d3.geom.voronoi().triangles(vertices);
-  };
-  d3.geom.quadtree = function(points, x1, y1, x2, y2) {
-    var x = d3_geom_pointX, y = d3_geom_pointY, compat;
-    if (compat = arguments.length) {
-      x = d3_geom_quadtreeCompatX;
-      y = d3_geom_quadtreeCompatY;
-      if (compat === 3) {
-        y2 = y1;
-        x2 = x1;
-        y1 = x1 = 0;
-      }
-      return quadtree(points);
-    }
-    function quadtree(data) {
-      var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_;
-      if (x1 != null) {
-        x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;
-      } else {
-        x2_ = y2_ = -(x1_ = y1_ = Infinity);
-        xs = [], ys = [];
-        n = data.length;
-        if (compat) for (i = 0; i < n; ++i) {
-          d = data[i];
-          if (d.x < x1_) x1_ = d.x;
-          if (d.y < y1_) y1_ = d.y;
-          if (d.x > x2_) x2_ = d.x;
-          if (d.y > y2_) y2_ = d.y;
-          xs.push(d.x);
-          ys.push(d.y);
-        } else for (i = 0; i < n; ++i) {
-          var x_ = +fx(d = data[i], i), y_ = +fy(d, i);
-          if (x_ < x1_) x1_ = x_;
-          if (y_ < y1_) y1_ = y_;
-          if (x_ > x2_) x2_ = x_;
-          if (y_ > y2_) y2_ = y_;
-          xs.push(x_);
-          ys.push(y_);
-        }
-      }
-      var dx = x2_ - x1_, dy = y2_ - y1_;
-      if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy;
-      function insert(n, d, x, y, x1, y1, x2, y2) {
-        if (isNaN(x) || isNaN(y)) return;
-        if (n.leaf) {
-          var nx = n.x, ny = n.y;
-          if (nx != null) {
-            if (abs(nx - x) + abs(ny - y) < .01) {
-              insertChild(n, d, x, y, x1, y1, x2, y2);
-            } else {
-              var nPoint = n.point;
-              n.x = n.y = n.point = null;
-              insertChild(n, nPoint, nx, ny, x1, y1, x2, y2);
-              insertChild(n, d, x, y, x1, y1, x2, y2);
-            }
-          } else {
-            n.x = x, n.y = y, n.point = d;
-          }
-        } else {
-          insertChild(n, d, x, y, x1, y1, x2, y2);
-        }
-      }
-      function insertChild(n, d, x, y, x1, y1, x2, y2) {
-        var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right;
-        n.leaf = false;
-        n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
-        if (right) x1 = xm; else x2 = xm;
-        if (below) y1 = ym; else y2 = ym;
-        insert(n, d, x, y, x1, y1, x2, y2);
-      }
-      var root = d3_geom_quadtreeNode();
-      root.add = function(d) {
-        insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);
-      };
-      root.visit = function(f) {
-        d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_);
-      };
-      root.find = function(point) {
-        return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_);
-      };
-      i = -1;
-      if (x1 == null) {
-        while (++i < n) {
-          insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);
-        }
-        --i;
-      } else data.forEach(root.add);
-      xs = ys = data = d = null;
-      return root;
-    }
-    quadtree.x = function(_) {
-      return arguments.length ? (x = _, quadtree) : x;
-    };
-    quadtree.y = function(_) {
-      return arguments.length ? (y = _, quadtree) : y;
-    };
-    quadtree.extent = function(_) {
-      if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ];
-      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], 
-      y2 = +_[1][1];
-      return quadtree;
-    };
-    quadtree.size = function(_) {
-      if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ];
-      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1];
-      return quadtree;
-    };
-    return quadtree;
-  };
-  function d3_geom_quadtreeCompatX(d) {
-    return d.x;
-  }
-  function d3_geom_quadtreeCompatY(d) {
-    return d.y;
-  }
-  function d3_geom_quadtreeNode() {
-    return {
-      leaf: true,
-      nodes: [],
-      point: null,
-      x: null,
-      y: null
-    };
-  }
-  function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
-    if (!f(node, x1, y1, x2, y2)) {
-      var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;
-      if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);
-      if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);
-      if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);
-      if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);
-    }
-  }
-  function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) {
-    var minDistance2 = Infinity, closestPoint;
-    (function find(node, x1, y1, x2, y2) {
-      if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return;
-      if (point = node.point) {
-        var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy;
-        if (distance2 < minDistance2) {
-          var distance = Math.sqrt(minDistance2 = distance2);
-          x0 = x - distance, y0 = y - distance;
-          x3 = x + distance, y3 = y + distance;
-          closestPoint = point;
-        }
-      }
-      var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym;
-      for (var i = below << 1 | right, j = i + 4; i < j; ++i) {
-        if (node = children[i & 3]) switch (i & 3) {
-         case 0:
-          find(node, x1, y1, xm, ym);
-          break;
-
-         case 1:
-          find(node, xm, y1, x2, ym);
-          break;
-
-         case 2:
-          find(node, x1, ym, xm, y2);
-          break;
-
-         case 3:
-          find(node, xm, ym, x2, y2);
-          break;
-        }
-      }
-    })(root, x0, y0, x3, y3);
-    return closestPoint;
-  }
-  d3.interpolateRgb = d3_interpolateRgb;
-  function d3_interpolateRgb(a, b) {
-    a = d3.rgb(a);
-    b = d3.rgb(b);
-    var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;
-    return function(t) {
-      return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));
-    };
-  }
-  d3.interpolateObject = d3_interpolateObject;
-  function d3_interpolateObject(a, b) {
-    var i = {}, c = {}, k;
-    for (k in a) {
-      if (k in b) {
-        i[k] = d3_interpolate(a[k], b[k]);
-      } else {
-        c[k] = a[k];
-      }
-    }
-    for (k in b) {
-      if (!(k in a)) {
-        c[k] = b[k];
-      }
-    }
-    return function(t) {
-      for (k in i) c[k] = i[k](t);
-      return c;
-    };
-  }
-  d3.interpolateNumber = d3_interpolateNumber;
-  function d3_interpolateNumber(a, b) {
-    a = +a, b = +b;
-    return function(t) {
-      return a * (1 - t) + b * t;
-    };
-  }
-  d3.interpolateString = d3_interpolateString;
-  function d3_interpolateString(a, b) {
-    var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = [];
-    a = a + "", b = b + "";
-    while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) {
-      if ((bs = bm.index) > bi) {
-        bs = b.slice(bi, bs);
-        if (s[i]) s[i] += bs; else s[++i] = bs;
-      }
-      if ((am = am[0]) === (bm = bm[0])) {
-        if (s[i]) s[i] += bm; else s[++i] = bm;
-      } else {
-        s[++i] = null;
-        q.push({
-          i: i,
-          x: d3_interpolateNumber(am, bm)
-        });
-      }
-      bi = d3_interpolate_numberB.lastIndex;
-    }
-    if (bi < b.length) {
-      bs = b.slice(bi);
-      if (s[i]) s[i] += bs; else s[++i] = bs;
-    }
-    return s.length < 2 ? q[0] ? (b = q[0].x, function(t) {
-      return b(t) + "";
-    }) : function() {
-      return b;
-    } : (b = q.length, function(t) {
-      for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
-      return s.join("");
-    });
-  }
-  var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g");
-  d3.interpolate = d3_interpolate;
-  function d3_interpolate(a, b) {
-    var i = d3.interpolators.length, f;
-    while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;
-    return f;
-  }
-  d3.interpolators = [ function(a, b) {
-    var t = typeof b;
-    return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b);
-  } ];
-  d3.interpolateArray = d3_interpolateArray;
-  function d3_interpolateArray(a, b) {
-    var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;
-    for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));
-    for (;i < na; ++i) c[i] = a[i];
-    for (;i < nb; ++i) c[i] = b[i];
-    return function(t) {
-      for (i = 0; i < n0; ++i) c[i] = x[i](t);
-      return c;
-    };
-  }
-  var d3_ease_default = function() {
-    return d3_identity;
-  };
-  var d3_ease = d3.map({
-    linear: d3_ease_default,
-    poly: d3_ease_poly,
-    quad: function() {
-      return d3_ease_quad;
-    },
-    cubic: function() {
-      return d3_ease_cubic;
-    },
-    sin: function() {
-      return d3_ease_sin;
-    },
-    exp: function() {
-      return d3_ease_exp;
-    },
-    circle: function() {
-      return d3_ease_circle;
-    },
-    elastic: d3_ease_elastic,
-    back: d3_ease_back,
-    bounce: function() {
-      return d3_ease_bounce;
-    }
-  });
-  var d3_ease_mode = d3.map({
-    "in": d3_identity,
-    out: d3_ease_reverse,
-    "in-out": d3_ease_reflect,
-    "out-in": function(f) {
-      return d3_ease_reflect(d3_ease_reverse(f));
-    }
-  });
-  d3.ease = function(name) {
-    var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in";
-    t = d3_ease.get(t) || d3_ease_default;
-    m = d3_ease_mode.get(m) || d3_identity;
-    return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1))));
-  };
-  function d3_ease_clamp(f) {
-    return function(t) {
-      return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
-    };
-  }
-  function d3_ease_reverse(f) {
-    return function(t) {
-      return 1 - f(1 - t);
-    };
-  }
-  function d3_ease_reflect(f) {
-    return function(t) {
-      return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));
-    };
-  }
-  function d3_ease_quad(t) {
-    return t * t;
-  }
-  function d3_ease_cubic(t) {
-    return t * t * t;
-  }
-  function d3_ease_cubicInOut(t) {
-    if (t <= 0) return 0;
-    if (t >= 1) return 1;
-    var t2 = t * t, t3 = t2 * t;
-    return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
-  }
-  function d3_ease_poly(e) {
-    return function(t) {
-      return Math.pow(t, e);
-    };
-  }
-  function d3_ease_sin(t) {
-    return 1 - Math.cos(t * halfπ);
-  }
-  function d3_ease_exp(t) {
-    return Math.pow(2, 10 * (t - 1));
-  }
-  function d3_ease_circle(t) {
-    return 1 - Math.sqrt(1 - t * t);
-  }
-  function d3_ease_elastic(a, p) {
-    var s;
-    if (arguments.length < 2) p = .45;
-    if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4;
-    return function(t) {
-      return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p);
-    };
-  }
-  function d3_ease_back(s) {
-    if (!s) s = 1.70158;
-    return function(t) {
-      return t * t * ((s + 1) * t - s);
-    };
-  }
-  function d3_ease_bounce(t) {
-    return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
-  }
-  d3.interpolateHcl = d3_interpolateHcl;
-  function d3_interpolateHcl(a, b) {
-    a = d3.hcl(a);
-    b = d3.hcl(b);
-    var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;
-    if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac;
-    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
-    return function(t) {
-      return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + "";
-    };
-  }
-  d3.interpolateHsl = d3_interpolateHsl;
-  function d3_interpolateHsl(a, b) {
-    a = d3.hsl(a);
-    b = d3.hsl(b);
-    var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al;
-    if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;
-    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
-    return function(t) {
-      return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + "";
-    };
-  }
-  d3.interpolateLab = d3_interpolateLab;
-  function d3_interpolateLab(a, b) {
-    a = d3.lab(a);
-    b = d3.lab(b);
-    var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;
-    return function(t) {
-      return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + "";
-    };
-  }
-  d3.interpolateRound = d3_interpolateRound;
-  function d3_interpolateRound(a, b) {
-    b -= a;
-    return function(t) {
-      return Math.round(a + b * t);
-    };
-  }
-  d3.transform = function(string) {
-    var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
-    return (d3.transform = function(string) {
-      if (string != null) {
-        g.setAttribute("transform", string);
-        var t = g.transform.baseVal.consolidate();
-      }
-      return new d3_transform(t ? t.matrix : d3_transformIdentity);
-    })(string);
-  };
-  function d3_transform(m) {
-    var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
-    if (r0[0] * r1[1] < r1[0] * r0[1]) {
-      r0[0] *= -1;
-      r0[1] *= -1;
-      kx *= -1;
-      kz *= -1;
-    }
-    this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
-    this.translate = [ m.e, m.f ];
-    this.scale = [ kx, ky ];
-    this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
-  }
-  d3_transform.prototype.toString = function() {
-    return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")";
-  };
-  function d3_transformDot(a, b) {
-    return a[0] * b[0] + a[1] * b[1];
-  }
-  function d3_transformNormalize(a) {
-    var k = Math.sqrt(d3_transformDot(a, a));
-    if (k) {
-      a[0] /= k;
-      a[1] /= k;
-    }
-    return k;
-  }
-  function d3_transformCombine(a, b, k) {
-    a[0] += k * b[0];
-    a[1] += k * b[1];
-    return a;
-  }
-  var d3_transformIdentity = {
-    a: 1,
-    b: 0,
-    c: 0,
-    d: 1,
-    e: 0,
-    f: 0
-  };
-  d3.interpolateTransform = d3_interpolateTransform;
-  function d3_interpolateTransformPop(s) {
-    return s.length ? s.pop() + "," : "";
-  }
-  function d3_interpolateTranslate(ta, tb, s, q) {
-    if (ta[0] !== tb[0] || ta[1] !== tb[1]) {
-      var i = s.push("translate(", null, ",", null, ")");
-      q.push({
-        i: i - 4,
-        x: d3_interpolateNumber(ta[0], tb[0])
-      }, {
-        i: i - 2,
-        x: d3_interpolateNumber(ta[1], tb[1])
-      });
-    } else if (tb[0] || tb[1]) {
-      s.push("translate(" + tb + ")");
-    }
-  }
-  function d3_interpolateRotate(ra, rb, s, q) {
-    if (ra !== rb) {
-      if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;
-      q.push({
-        i: s.push(d3_interpolateTransformPop(s) + "rotate(", null, ")") - 2,
-        x: d3_interpolateNumber(ra, rb)
-      });
-    } else if (rb) {
-      s.push(d3_interpolateTransformPop(s) + "rotate(" + rb + ")");
-    }
-  }
-  function d3_interpolateSkew(wa, wb, s, q) {
-    if (wa !== wb) {
-      q.push({
-        i: s.push(d3_interpolateTransformPop(s) + "skewX(", null, ")") - 2,
-        x: d3_interpolateNumber(wa, wb)
-      });
-    } else if (wb) {
-      s.push(d3_interpolateTransformPop(s) + "skewX(" + wb + ")");
-    }
-  }
-  function d3_interpolateScale(ka, kb, s, q) {
-    if (ka[0] !== kb[0] || ka[1] !== kb[1]) {
-      var i = s.push(d3_interpolateTransformPop(s) + "scale(", null, ",", null, ")");
-      q.push({
-        i: i - 4,
-        x: d3_interpolateNumber(ka[0], kb[0])
-      }, {
-        i: i - 2,
-        x: d3_interpolateNumber(ka[1], kb[1])
-      });
-    } else if (kb[0] !== 1 || kb[1] !== 1) {
-      s.push(d3_interpolateTransformPop(s) + "scale(" + kb + ")");
-    }
-  }
-  function d3_interpolateTransform(a, b) {
-    var s = [], q = [];
-    a = d3.transform(a), b = d3.transform(b);
-    d3_interpolateTranslate(a.translate, b.translate, s, q);
-    d3_interpolateRotate(a.rotate, b.rotate, s, q);
-    d3_interpolateSkew(a.skew, b.skew, s, q);
-    d3_interpolateScale(a.scale, b.scale, s, q);
-    a = b = null;
-    return function(t) {
-      var i = -1, n = q.length, o;
-      while (++i < n) s[(o = q[i]).i] = o.x(t);
-      return s.join("");
-    };
-  }
-  function d3_uninterpolateNumber(a, b) {
-    b = (b -= a = +a) || 1 / b;
-    return function(x) {
-      return (x - a) / b;
-    };
-  }
-  function d3_uninterpolateClamp(a, b) {
-    b = (b -= a = +a) || 1 / b;
-    return function(x) {
-      return Math.max(0, Math.min(1, (x - a) / b));
-    };
-  }
-  d3.layout = {};
-  d3.layout.bundle = function() {
-    return function(links) {
-      var paths = [], i = -1, n = links.length;
-      while (++i < n) paths.push(d3_layout_bundlePath(links[i]));
-      return paths;
-    };
-  };
-  function d3_layout_bundlePath(link) {
-    var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];
-    while (start !== lca) {
-      start = start.parent;
-      points.push(start);
-    }
-    var k = points.length;
-    while (end !== lca) {
-      points.splice(k, 0, end);
-      end = end.parent;
-    }
-    return points;
-  }
-  function d3_layout_bundleAncestors(node) {
-    var ancestors = [], parent = node.parent;
-    while (parent != null) {
-      ancestors.push(node);
-      node = parent;
-      parent = parent.parent;
-    }
-    ancestors.push(node);
-    return ancestors;
-  }
-  function d3_layout_bundleLeastCommonAncestor(a, b) {
-    if (a === b) return a;
-    var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;
-    while (aNode === bNode) {
-      sharedNode = aNode;
-      aNode = aNodes.pop();
-      bNode = bNodes.pop();
-    }
-    return sharedNode;
-  }
-  d3.layout.chord = function() {
-    var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;
-    function relayout() {
-      var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;
-      chords = [];
-      groups = [];
-      k = 0, i = -1;
-      while (++i < n) {
-        x = 0, j = -1;
-        while (++j < n) {
-          x += matrix[i][j];
-        }
-        groupSums.push(x);
-        subgroupIndex.push(d3.range(n));
-        k += x;
-      }
-      if (sortGroups) {
-        groupIndex.sort(function(a, b) {
-          return sortGroups(groupSums[a], groupSums[b]);
-        });
-      }
-      if (sortSubgroups) {
-        subgroupIndex.forEach(function(d, i) {
-          d.sort(function(a, b) {
-            return sortSubgroups(matrix[i][a], matrix[i][b]);
-          });
-        });
-      }
-      k = (τ - padding * n) / k;
-      x = 0, i = -1;
-      while (++i < n) {
-        x0 = x, j = -1;
-        while (++j < n) {
-          var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;
-          subgroups[di + "-" + dj] = {
-            index: di,
-            subindex: dj,
-            startAngle: a0,
-            endAngle: a1,
-            value: v
-          };
-        }
-        groups[di] = {
-          index: di,
-          startAngle: x0,
-          endAngle: x,
-          value: groupSums[di]
-        };
-        x += padding;
-      }
-      i = -1;
-      while (++i < n) {
-        j = i - 1;
-        while (++j < n) {
-          var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i];
-          if (source.value || target.value) {
-            chords.push(source.value < target.value ? {
-              source: target,
-              target: source
-            } : {
-              source: source,
-              target: target
-            });
-          }
-        }
-      }
-      if (sortChords) resort();
-    }
-    function resort() {
-      chords.sort(function(a, b) {
-        return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);
-      });
-    }
-    chord.matrix = function(x) {
-      if (!arguments.length) return matrix;
-      n = (matrix = x) && matrix.length;
-      chords = groups = null;
-      return chord;
-    };
-    chord.padding = function(x) {
-      if (!arguments.length) return padding;
-      padding = x;
-      chords = groups = null;
-      return chord;
-    };
-    chord.sortGroups = function(x) {
-      if (!arguments.length) return sortGroups;
-      sortGroups = x;
-      chords = groups = null;
-      return chord;
-    };
-    chord.sortSubgroups = function(x) {
-      if (!arguments.length) return sortSubgroups;
-      sortSubgroups = x;
-      chords = null;
-      return chord;
-    };
-    chord.sortChords = function(x) {
-      if (!arguments.length) return sortChords;
-      sortChords = x;
-      if (chords) resort();
-      return chord;
-    };
-    chord.chords = function() {
-      if (!chords) relayout();
-      return chords;
-    };
-    chord.groups = function() {
-      if (!groups) relayout();
-      return groups;
-    };
-    return chord;
-  };
-  d3.layout.force = function() {
-    var force = {}, event = d3.dispatch("start", "tick", "end"), timer, size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges;
-    function repulse(node) {
-      return function(quad, x1, _, x2) {
-        if (quad.point !== node) {
-          var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy;
-          if (dw * dw / theta2 < dn) {
-            if (dn < chargeDistance2) {
-              var k = quad.charge / dn;
-              node.px -= dx * k;
-              node.py -= dy * k;
-            }
-            return true;
-          }
-          if (quad.point && dn && dn < chargeDistance2) {
-            var k = quad.pointCharge / dn;
-            node.px -= dx * k;
-            node.py -= dy * k;
-          }
-        }
-        return !quad.charge;
-      };
-    }
-    force.tick = function() {
-      if ((alpha *= .99) < .005) {
-        timer = null;
-        event.end({
-          type: "end",
-          alpha: alpha = 0
-        });
-        return true;
-      }
-      var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;
-      for (i = 0; i < m; ++i) {
-        o = links[i];
-        s = o.source;
-        t = o.target;
-        x = t.x - s.x;
-        y = t.y - s.y;
-        if (l = x * x + y * y) {
-          l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
-          x *= l;
-          y *= l;
-          t.x -= x * (k = s.weight + t.weight ? s.weight / (s.weight + t.weight) : .5);
-          t.y -= y * k;
-          s.x += x * (k = 1 - k);
-          s.y += y * k;
-        }
-      }
-      if (k = alpha * gravity) {
-        x = size[0] / 2;
-        y = size[1] / 2;
-        i = -1;
-        if (k) while (++i < n) {
-          o = nodes[i];
-          o.x += (x - o.x) * k;
-          o.y += (y - o.y) * k;
-        }
-      }
-      if (charge) {
-        d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);
-        i = -1;
-        while (++i < n) {
-          if (!(o = nodes[i]).fixed) {
-            q.visit(repulse(o));
-          }
-        }
-      }
-      i = -1;
-      while (++i < n) {
-        o = nodes[i];
-        if (o.fixed) {
-          o.x = o.px;
-          o.y = o.py;
-        } else {
-          o.x -= (o.px - (o.px = o.x)) * friction;
-          o.y -= (o.py - (o.py = o.y)) * friction;
-        }
-      }
-      event.tick({
-        type: "tick",
-        alpha: alpha
-      });
-    };
-    force.nodes = function(x) {
-      if (!arguments.length) return nodes;
-      nodes = x;
-      return force;
-    };
-    force.links = function(x) {
-      if (!arguments.length) return links;
-      links = x;
-      return force;
-    };
-    force.size = function(x) {
-      if (!arguments.length) return size;
-      size = x;
-      return force;
-    };
-    force.linkDistance = function(x) {
-      if (!arguments.length) return linkDistance;
-      linkDistance = typeof x === "function" ? x : +x;
-      return force;
-    };
-    force.distance = force.linkDistance;
-    force.linkStrength = function(x) {
-      if (!arguments.length) return linkStrength;
-      linkStrength = typeof x === "function" ? x : +x;
-      return force;
-    };
-    force.friction = function(x) {
-      if (!arguments.length) return friction;
-      friction = +x;
-      return force;
-    };
-    force.charge = function(x) {
-      if (!arguments.length) return charge;
-      charge = typeof x === "function" ? x : +x;
-      return force;
-    };
-    force.chargeDistance = function(x) {
-      if (!arguments.length) return Math.sqrt(chargeDistance2);
-      chargeDistance2 = x * x;
-      return force;
-    };
-    force.gravity = function(x) {
-      if (!arguments.length) return gravity;
-      gravity = +x;
-      return force;
-    };
-    force.theta = function(x) {
-      if (!arguments.length) return Math.sqrt(theta2);
-      theta2 = x * x;
-      return force;
-    };
-    force.alpha = function(x) {
-      if (!arguments.length) return alpha;
-      x = +x;
-      if (alpha) {
-        if (x > 0) {
-          alpha = x;
-        } else {
-          timer.c = null, timer.t = NaN, timer = null;
-          event.end({
-            type: "end",
-            alpha: alpha = 0
-          });
-        }
-      } else if (x > 0) {
-        event.start({
-          type: "start",
-          alpha: alpha = x
-        });
-        timer = d3_timer(force.tick);
-      }
-      return force;
-    };
-    force.start = function() {
-      var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
-      for (i = 0; i < n; ++i) {
-        (o = nodes[i]).index = i;
-        o.weight = 0;
-      }
-      for (i = 0; i < m; ++i) {
-        o = links[i];
-        if (typeof o.source == "number") o.source = nodes[o.source];
-        if (typeof o.target == "number") o.target = nodes[o.target];
-        ++o.source.weight;
-        ++o.target.weight;
-      }
-      for (i = 0; i < n; ++i) {
-        o = nodes[i];
-        if (isNaN(o.x)) o.x = position("x", w);
-        if (isNaN(o.y)) o.y = position("y", h);
-        if (isNaN(o.px)) o.px = o.x;
-        if (isNaN(o.py)) o.py = o.y;
-      }
-      distances = [];
-      if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance;
-      strengths = [];
-      if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength;
-      charges = [];
-      if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge;
-      function position(dimension, size) {
-        if (!neighbors) {
-          neighbors = new Array(n);
-          for (j = 0; j < n; ++j) {
-            neighbors[j] = [];
-          }
-          for (j = 0; j < m; ++j) {
-            var o = links[j];
-            neighbors[o.source.index].push(o.target);
-            neighbors[o.target.index].push(o.source);
-          }
-        }
-        var candidates = neighbors[i], j = -1, l = candidates.length, x;
-        while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x;
-        return Math.random() * size;
-      }
-      return force.resume();
-    };
-    force.resume = function() {
-      return force.alpha(.1);
-    };
-    force.stop = function() {
-      return force.alpha(0);
-    };
-    force.drag = function() {
-      if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend);
-      if (!arguments.length) return drag;
-      this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag);
-    };
-    function dragmove(d) {
-      d.px = d3.event.x, d.py = d3.event.y;
-      force.resume();
-    }
-    return d3.rebind(force, event, "on");
-  };
-  function d3_layout_forceDragstart(d) {
-    d.fixed |= 2;
-  }
-  function d3_layout_forceDragend(d) {
-    d.fixed &= ~6;
-  }
-  function d3_layout_forceMouseover(d) {
-    d.fixed |= 4;
-    d.px = d.x, d.py = d.y;
-  }
-  function d3_layout_forceMouseout(d) {
-    d.fixed &= ~4;
-  }
-  function d3_layout_forceAccumulate(quad, alpha, charges) {
-    var cx = 0, cy = 0;
-    quad.charge = 0;
-    if (!quad.leaf) {
-      var nodes = quad.nodes, n = nodes.length, i = -1, c;
-      while (++i < n) {
-        c = nodes[i];
-        if (c == null) continue;
-        d3_layout_forceAccumulate(c, alpha, charges);
-        quad.charge += c.charge;
-        cx += c.charge * c.cx;
-        cy += c.charge * c.cy;
-      }
-    }
-    if (quad.point) {
-      if (!quad.leaf) {
-        quad.point.x += Math.random() - .5;
-        quad.point.y += Math.random() - .5;
-      }
-      var k = alpha * charges[quad.point.index];
-      quad.charge += quad.pointCharge = k;
-      cx += k * quad.point.x;
-      cy += k * quad.point.y;
-    }
-    quad.cx = cx / quad.charge;
-    quad.cy = cy / quad.charge;
-  }
-  var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity;
-  d3.layout.hierarchy = function() {
-    var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
-    function hierarchy(root) {
-      var stack = [ root ], nodes = [], node;
-      root.depth = 0;
-      while ((node = stack.pop()) != null) {
-        nodes.push(node);
-        if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) {
-          var n, childs, child;
-          while (--n >= 0) {
-            stack.push(child = childs[n]);
-            child.parent = node;
-            child.depth = node.depth + 1;
-          }
-          if (value) node.value = 0;
-          node.children = childs;
-        } else {
-          if (value) node.value = +value.call(hierarchy, node, node.depth) || 0;
-          delete node.children;
-        }
-      }
-      d3_layout_hierarchyVisitAfter(root, function(node) {
-        var childs, parent;
-        if (sort && (childs = node.children)) childs.sort(sort);
-        if (value && (parent = node.parent)) parent.value += node.value;
-      });
-      return nodes;
-    }
-    hierarchy.sort = function(x) {
-      if (!arguments.length) return sort;
-      sort = x;
-      return hierarchy;
-    };
-    hierarchy.children = function(x) {
-      if (!arguments.length) return children;
-      children = x;
-      return hierarchy;
-    };
-    hierarchy.value = function(x) {
-      if (!arguments.length) return value;
-      value = x;
-      return hierarchy;
-    };
-    hierarchy.revalue = function(root) {
-      if (value) {
-        d3_layout_hierarchyVisitBefore(root, function(node) {
-          if (node.children) node.value = 0;
-        });
-        d3_layout_hierarchyVisitAfter(root, function(node) {
-          var parent;
-          if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0;
-          if (parent = node.parent) parent.value += node.value;
-        });
-      }
-      return root;
-    };
-    return hierarchy;
-  };
-  function d3_layout_hierarchyRebind(object, hierarchy) {
-    d3.rebind(object, hierarchy, "sort", "children", "value");
-    object.nodes = object;
-    object.links = d3_layout_hierarchyLinks;
-    return object;
-  }
-  function d3_layout_hierarchyVisitBefore(node, callback) {
-    var nodes = [ node ];
-    while ((node = nodes.pop()) != null) {
-      callback(node);
-      if ((children = node.children) && (n = children.length)) {
-        var n, children;
-        while (--n >= 0) nodes.push(children[n]);
-      }
-    }
-  }
-  function d3_layout_hierarchyVisitAfter(node, callback) {
-    var nodes = [ node ], nodes2 = [];
-    while ((node = nodes.pop()) != null) {
-      nodes2.push(node);
-      if ((children = node.children) && (n = children.length)) {
-        var i = -1, n, children;
-        while (++i < n) nodes.push(children[i]);
-      }
-    }
-    while ((node = nodes2.pop()) != null) {
-      callback(node);
-    }
-  }
-  function d3_layout_hierarchyChildren(d) {
-    return d.children;
-  }
-  function d3_layout_hierarchyValue(d) {
-    return d.value;
-  }
-  function d3_layout_hierarchySort(a, b) {
-    return b.value - a.value;
-  }
-  function d3_layout_hierarchyLinks(nodes) {
-    return d3.merge(nodes.map(function(parent) {
-      return (parent.children || []).map(function(child) {
-        return {
-          source: parent,
-          target: child
-        };
-      });
-    }));
-  }
-  d3.layout.partition = function() {
-    var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];
-    function position(node, x, dx, dy) {
-      var children = node.children;
-      node.x = x;
-      node.y = node.depth * dy;
-      node.dx = dx;
-      node.dy = dy;
-      if (children && (n = children.length)) {
-        var i = -1, n, c, d;
-        dx = node.value ? dx / node.value : 0;
-        while (++i < n) {
-          position(c = children[i], x, d = c.value * dx, dy);
-          x += d;
-        }
-      }
-    }
-    function depth(node) {
-      var children = node.children, d = 0;
-      if (children && (n = children.length)) {
-        var i = -1, n;
-        while (++i < n) d = Math.max(d, depth(children[i]));
-      }
-      return 1 + d;
-    }
-    function partition(d, i) {
-      var nodes = hierarchy.call(this, d, i);
-      position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
-      return nodes;
-    }
-    partition.size = function(x) {
-      if (!arguments.length) return size;
-      size = x;
-      return partition;
-    };
-    return d3_layout_hierarchyRebind(partition, hierarchy);
-  };
-  d3.layout.pie = function() {
-    var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0;
-    function pie(data) {
-      var n = data.length, values = data.map(function(d, i) {
-        return +value.call(pie, d, i);
-      }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), sum = d3.sum(values), k = sum ? (da - n * pa) / sum : 0, index = d3.range(n), arcs = [], v;
-      if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {
-        return values[j] - values[i];
-      } : function(i, j) {
-        return sort(data[i], data[j]);
-      });
-      index.forEach(function(i) {
-        arcs[i] = {
-          data: data[i],
-          value: v = values[i],
-          startAngle: a,
-          endAngle: a += v * k + pa,
-          padAngle: p
-        };
-      });
-      return arcs;
-    }
-    pie.value = function(_) {
-      if (!arguments.length) return value;
-      value = _;
-      return pie;
-    };
-    pie.sort = function(_) {
-      if (!arguments.length) return sort;
-      sort = _;
-      return pie;
-    };
-    pie.startAngle = function(_) {
-      if (!arguments.length) return startAngle;
-      startAngle = _;
-      return pie;
-    };
-    pie.endAngle = function(_) {
-      if (!arguments.length) return endAngle;
-      endAngle = _;
-      return pie;
-    };
-    pie.padAngle = function(_) {
-      if (!arguments.length) return padAngle;
-      padAngle = _;
-      return pie;
-    };
-    return pie;
-  };
-  var d3_layout_pieSortByValue = {};
-  d3.layout.stack = function() {
-    var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;
-    function stack(data, index) {
-      if (!(n = data.length)) return data;
-      var series = data.map(function(d, i) {
-        return values.call(stack, d, i);
-      });
-      var points = series.map(function(d) {
-        return d.map(function(v, i) {
-          return [ x.call(stack, v, i), y.call(stack, v, i) ];
-        });
-      });
-      var orders = order.call(stack, points, index);
-      series = d3.permute(series, orders);
-      points = d3.permute(points, orders);
-      var offsets = offset.call(stack, points, index);
-      var m = series[0].length, n, i, j, o;
-      for (j = 0; j < m; ++j) {
-        out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
-        for (i = 1; i < n; ++i) {
-          out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
-        }
-      }
-      return data;
-    }
-    stack.values = function(x) {
-      if (!arguments.length) return values;
-      values = x;
-      return stack;
-    };
-    stack.order = function(x) {
-      if (!arguments.length) return order;
-      order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
-      return stack;
-    };
-    stack.offset = function(x) {
-      if (!arguments.length) return offset;
-      offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
-      return stack;
-    };
-    stack.x = function(z) {
-      if (!arguments.length) return x;
-      x = z;
-      return stack;
-    };
-    stack.y = function(z) {
-      if (!arguments.length) return y;
-      y = z;
-      return stack;
-    };
-    stack.out = function(z) {
-      if (!arguments.length) return out;
-      out = z;
-      return stack;
-    };
-    return stack;
-  };
-  function d3_layout_stackX(d) {
-    return d.x;
-  }
-  function d3_layout_stackY(d) {
-    return d.y;
-  }
-  function d3_layout_stackOut(d, y0, y) {
-    d.y0 = y0;
-    d.y = y;
-  }
-  var d3_layout_stackOrders = d3.map({
-    "inside-out": function(data) {
-      var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {
-        return max[a] - max[b];
-      }), top = 0, bottom = 0, tops = [], bottoms = [];
-      for (i = 0; i < n; ++i) {
-        j = index[i];
-        if (top < bottom) {
-          top += sums[j];
-          tops.push(j);
-        } else {
-          bottom += sums[j];
-          bottoms.push(j);
-        }
-      }
-      return bottoms.reverse().concat(tops);
-    },
-    reverse: function(data) {
-      return d3.range(data.length).reverse();
-    },
-    "default": d3_layout_stackOrderDefault
-  });
-  var d3_layout_stackOffsets = d3.map({
-    silhouette: function(data) {
-      var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];
-      for (j = 0; j < m; ++j) {
-        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
-        if (o > max) max = o;
-        sums.push(o);
-      }
-      for (j = 0; j < m; ++j) {
-        y0[j] = (max - sums[j]) / 2;
-      }
-      return y0;
-    },
-    wiggle: function(data) {
-      var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];
-      y0[0] = o = o0 = 0;
-      for (j = 1; j < m; ++j) {
-        for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
-        for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
-          for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
-            s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
-          }
-          s2 += s3 * data[i][j][1];
-        }
-        y0[j] = o -= s1 ? s2 / s1 * dx : 0;
-        if (o < o0) o0 = o;
-      }
-      for (j = 0; j < m; ++j) y0[j] -= o0;
-      return y0;
-    },
-    expand: function(data) {
-      var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];
-      for (j = 0; j < m; ++j) {
-        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
-        if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;
-      }
-      for (j = 0; j < m; ++j) y0[j] = 0;
-      return y0;
-    },
-    zero: d3_layout_stackOffsetZero
-  });
-  function d3_layout_stackOrderDefault(data) {
-    return d3.range(data.length);
-  }
-  function d3_layout_stackOffsetZero(data) {
-    var j = -1, m = data[0].length, y0 = [];
-    while (++j < m) y0[j] = 0;
-    return y0;
-  }
-  function d3_layout_stackMaxIndex(array) {
-    var i = 1, j = 0, v = array[0][1], k, n = array.length;
-    for (;i < n; ++i) {
-      if ((k = array[i][1]) > v) {
-        j = i;
-        v = k;
-      }
-    }
-    return j;
-  }
-  function d3_layout_stackReduceSum(d) {
-    return d.reduce(d3_layout_stackSum, 0);
-  }
-  function d3_layout_stackSum(p, d) {
-    return p + d[1];
-  }
-  d3.layout.histogram = function() {
-    var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;
-    function histogram(data, i) {
-      var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;
-      while (++i < m) {
-        bin = bins[i] = [];
-        bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
-        bin.y = 0;
-      }
-      if (m > 0) {
-        i = -1;
-        while (++i < n) {
-          x = values[i];
-          if (x >= range[0] && x <= range[1]) {
-            bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
-            bin.y += k;
-            bin.push(data[i]);
-          }
-        }
-      }
-      return bins;
-    }
-    histogram.value = function(x) {
-      if (!arguments.length) return valuer;
-      valuer = x;
-      return histogram;
-    };
-    histogram.range = function(x) {
-      if (!arguments.length) return ranger;
-      ranger = d3_functor(x);
-      return histogram;
-    };
-    histogram.bins = function(x) {
-      if (!arguments.length) return binner;
-      binner = typeof x === "number" ? function(range) {
-        return d3_layout_histogramBinFixed(range, x);
-      } : d3_functor(x);
-      return histogram;
-    };
-    histogram.frequency = function(x) {
-      if (!arguments.length) return frequency;
-      frequency = !!x;
-      return histogram;
-    };
-    return histogram;
-  };
-  function d3_layout_histogramBinSturges(range, values) {
-    return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
-  }
-  function d3_layout_histogramBinFixed(range, n) {
-    var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];
-    while (++x <= n) f[x] = m * x + b;
-    return f;
-  }
-  function d3_layout_histogramRange(values) {
-    return [ d3.min(values), d3.max(values) ];
-  }
-  d3.layout.pack = function() {
-    var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius;
-    function pack(d, i) {
-      var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() {
-        return radius;
-      };
-      root.x = root.y = 0;
-      d3_layout_hierarchyVisitAfter(root, function(d) {
-        d.r = +r(d.value);
-      });
-      d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
-      if (padding) {
-        var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2;
-        d3_layout_hierarchyVisitAfter(root, function(d) {
-          d.r += dr;
-        });
-        d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
-        d3_layout_hierarchyVisitAfter(root, function(d) {
-          d.r -= dr;
-        });
-      }
-      d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h));
-      return nodes;
-    }
-    pack.size = function(_) {
-      if (!arguments.length) return size;
-      size = _;
-      return pack;
-    };
-    pack.radius = function(_) {
-      if (!arguments.length) return radius;
-      radius = _ == null || typeof _ === "function" ? _ : +_;
-      return pack;
-    };
-    pack.padding = function(_) {
-      if (!arguments.length) return padding;
-      padding = +_;
-      return pack;
-    };
-    return d3_layout_hierarchyRebind(pack, hierarchy);
-  };
-  function d3_layout_packSort(a, b) {
-    return a.value - b.value;
-  }
-  function d3_layout_packInsert(a, b) {
-    var c = a._pack_next;
-    a._pack_next = b;
-    b._pack_prev = a;
-    b._pack_next = c;
-    c._pack_prev = b;
-  }
-  function d3_layout_packSplice(a, b) {
-    a._pack_next = b;
-    b._pack_prev = a;
-  }
-  function d3_layout_packIntersects(a, b) {
-    var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;
-    return .999 * dr * dr > dx * dx + dy * dy;
-  }
-  function d3_layout_packSiblings(node) {
-    if (!(nodes = node.children) || !(n = nodes.length)) return;
-    var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;
-    function bound(node) {
-      xMin = Math.min(node.x - node.r, xMin);
-      xMax = Math.max(node.x + node.r, xMax);
-      yMin = Math.min(node.y - node.r, yMin);
-      yMax = Math.max(node.y + node.r, yMax);
-    }
-    nodes.forEach(d3_layout_packLink);
-    a = nodes[0];
-    a.x = -a.r;
-    a.y = 0;
-    bound(a);
-    if (n > 1) {
-      b = nodes[1];
-      b.x = b.r;
-      b.y = 0;
-      bound(b);
-      if (n > 2) {
-        c = nodes[2];
-        d3_layout_packPlace(a, b, c);
-        bound(c);
-        d3_layout_packInsert(a, c);
-        a._pack_prev = c;
-        d3_layout_packInsert(c, b);
-        b = a._pack_next;
-        for (i = 3; i < n; i++) {
-          d3_layout_packPlace(a, b, c = nodes[i]);
-          var isect = 0, s1 = 1, s2 = 1;
-          for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
-            if (d3_layout_packIntersects(j, c)) {
-              isect = 1;
-              break;
-            }
-          }
-          if (isect == 1) {
-            for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
-              if (d3_layout_packIntersects(k, c)) {
-                break;
-              }
-            }
-          }
-          if (isect) {
-            if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);
-            i--;
-          } else {
-            d3_layout_packInsert(a, c);
-            b = c;
-            bound(c);
-          }
-        }
-      }
-    }
-    var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;
-    for (i = 0; i < n; i++) {
-      c = nodes[i];
-      c.x -= cx;
-      c.y -= cy;
-      cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));
-    }
-    node.r = cr;
-    nodes.forEach(d3_layout_packUnlink);
-  }
-  function d3_layout_packLink(node) {
-    node._pack_next = node._pack_prev = node;
-  }
-  function d3_layout_packUnlink(node) {
-    delete node._pack_next;
-    delete node._pack_prev;
-  }
-  function d3_layout_packTransform(node, x, y, k) {
-    var children = node.children;
-    node.x = x += k * node.x;
-    node.y = y += k * node.y;
-    node.r *= k;
-    if (children) {
-      var i = -1, n = children.length;
-      while (++i < n) d3_layout_packTransform(children[i], x, y, k);
-    }
-  }
-  function d3_layout_packPlace(a, b, c) {
-    var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;
-    if (db && (dx || dy)) {
-      var da = b.r + c.r, dc = dx * dx + dy * dy;
-      da *= da;
-      db *= db;
-      var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
-      c.x = a.x + x * dx + y * dy;
-      c.y = a.y + x * dy - y * dx;
-    } else {
-      c.x = a.x + db;
-      c.y = a.y;
-    }
-  }
-  d3.layout.tree = function() {
-    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null;
-    function tree(d, i) {
-      var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0);
-      d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z;
-      d3_layout_hierarchyVisitBefore(root1, secondWalk);
-      if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else {
-        var left = root0, right = root0, bottom = root0;
-        d3_layout_hierarchyVisitBefore(root0, function(node) {
-          if (node.x < left.x) left = node;
-          if (node.x > right.x) right = node;
-          if (node.depth > bottom.depth) bottom = node;
-        });
-        var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1);
-        d3_layout_hierarchyVisitBefore(root0, function(node) {
-          node.x = (node.x + tx) * kx;
-          node.y = node.depth * ky;
-        });
-      }
-      return nodes;
-    }
-    function wrapTree(root0) {
-      var root1 = {
-        A: null,
-        children: [ root0 ]
-      }, queue = [ root1 ], node1;
-      while ((node1 = queue.pop()) != null) {
-        for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) {
-          queue.push((children[i] = child = {
-            _: children[i],
-            parent: node1,
-            children: (child = children[i].children) && child.slice() || [],
-            A: null,
-            a: null,
-            z: 0,
-            m: 0,
-            c: 0,
-            s: 0,
-            t: null,
-            i: i
-          }).a = child);
-        }
-      }
-      return root1.children[0];
-    }
-    function firstWalk(v) {
-      var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null;
-      if (children.length) {
-        d3_layout_treeShift(v);
-        var midpoint = (children[0].z + children[children.length - 1].z) / 2;
-        if (w) {
-          v.z = w.z + separation(v._, w._);
-          v.m = v.z - midpoint;
-        } else {
-          v.z = midpoint;
-        }
-      } else if (w) {
-        v.z = w.z + separation(v._, w._);
-      }
-      v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
-    }
-    function secondWalk(v) {
-      v._.x = v.z + v.parent.m;
-      v.m += v.parent.m;
-    }
-    function apportion(v, w, ancestor) {
-      if (w) {
-        var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift;
-        while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
-          vom = d3_layout_treeLeft(vom);
-          vop = d3_layout_treeRight(vop);
-          vop.a = v;
-          shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
-          if (shift > 0) {
-            d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift);
-            sip += shift;
-            sop += shift;
-          }
-          sim += vim.m;
-          sip += vip.m;
-          som += vom.m;
-          sop += vop.m;
-        }
-        if (vim && !d3_layout_treeRight(vop)) {
-          vop.t = vim;
-          vop.m += sim - sop;
-        }
-        if (vip && !d3_layout_treeLeft(vom)) {
-          vom.t = vip;
-          vom.m += sip - som;
-          ancestor = v;
-        }
-      }
-      return ancestor;
-    }
-    function sizeNode(node) {
-      node.x *= size[0];
-      node.y = node.depth * size[1];
-    }
-    tree.separation = function(x) {
-      if (!arguments.length) return separation;
-      separation = x;
-      return tree;
-    };
-    tree.size = function(x) {
-      if (!arguments.length) return nodeSize ? null : size;
-      nodeSize = (size = x) == null ? sizeNode : null;
-      return tree;
-    };
-    tree.nodeSize = function(x) {
-      if (!arguments.length) return nodeSize ? size : null;
-      nodeSize = (size = x) == null ? null : sizeNode;
-      return tree;
-    };
-    return d3_layout_hierarchyRebind(tree, hierarchy);
-  };
-  function d3_layout_treeSeparation(a, b) {
-    return a.parent == b.parent ? 1 : 2;
-  }
-  function d3_layout_treeLeft(v) {
-    var children = v.children;
-    return children.length ? children[0] : v.t;
-  }
-  function d3_layout_treeRight(v) {
-    var children = v.children, n;
-    return (n = children.length) ? children[n - 1] : v.t;
-  }
-  function d3_layout_treeMove(wm, wp, shift) {
-    var change = shift / (wp.i - wm.i);
-    wp.c -= change;
-    wp.s += shift;
-    wm.c += change;
-    wp.z += shift;
-    wp.m += shift;
-  }
-  function d3_layout_treeShift(v) {
-    var shift = 0, change = 0, children = v.children, i = children.length, w;
-    while (--i >= 0) {
-      w = children[i];
-      w.z += shift;
-      w.m += shift;
-      shift += w.s + (change += w.c);
-    }
-  }
-  function d3_layout_treeAncestor(vim, v, ancestor) {
-    return vim.a.parent === v.parent ? vim.a : ancestor;
-  }
-  d3.layout.cluster = function() {
-    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
-    function cluster(d, i) {
-      var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
-      d3_layout_hierarchyVisitAfter(root, function(node) {
-        var children = node.children;
-        if (children && children.length) {
-          node.x = d3_layout_clusterX(children);
-          node.y = d3_layout_clusterY(children);
-        } else {
-          node.x = previousNode ? x += separation(node, previousNode) : 0;
-          node.y = 0;
-          previousNode = node;
-        }
-      });
-      var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;
-      d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) {
-        node.x = (node.x - root.x) * size[0];
-        node.y = (root.y - node.y) * size[1];
-      } : function(node) {
-        node.x = (node.x - x0) / (x1 - x0) * size[0];
-        node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
-      });
-      return nodes;
-    }
-    cluster.separation = function(x) {
-      if (!arguments.length) return separation;
-      separation = x;
-      return cluster;
-    };
-    cluster.size = function(x) {
-      if (!arguments.length) return nodeSize ? null : size;
-      nodeSize = (size = x) == null;
-      return cluster;
-    };
-    cluster.nodeSize = function(x) {
-      if (!arguments.length) return nodeSize ? size : null;
-      nodeSize = (size = x) != null;
-      return cluster;
-    };
-    return d3_layout_hierarchyRebind(cluster, hierarchy);
-  };
-  function d3_layout_clusterY(children) {
-    return 1 + d3.max(children, function(child) {
-      return child.y;
-    });
-  }
-  function d3_layout_clusterX(children) {
-    return children.reduce(function(x, child) {
-      return x + child.x;
-    }, 0) / children.length;
-  }
-  function d3_layout_clusterLeft(node) {
-    var children = node.children;
-    return children && children.length ? d3_layout_clusterLeft(children[0]) : node;
-  }
-  function d3_layout_clusterRight(node) {
-    var children = node.children, n;
-    return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
-  }
-  d3.layout.treemap = function() {
-    var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5));
-    function scale(children, k) {
-      var i = -1, n = children.length, child, area;
-      while (++i < n) {
-        area = (child = children[i]).value * (k < 0 ? 0 : k);
-        child.area = isNaN(area) || area <= 0 ? 0 : area;
-      }
-    }
-    function squarify(node) {
-      var children = node.children;
-      if (children && children.length) {
-        var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;
-        scale(remaining, rect.dx * rect.dy / node.value);
-        row.area = 0;
-        while ((n = remaining.length) > 0) {
-          row.push(child = remaining[n - 1]);
-          row.area += child.area;
-          if (mode !== "squarify" || (score = worst(row, u)) <= best) {
-            remaining.pop();
-            best = score;
-          } else {
-            row.area -= row.pop().area;
-            position(row, u, rect, false);
-            u = Math.min(rect.dx, rect.dy);
-            row.length = row.area = 0;
-            best = Infinity;
-          }
-        }
-        if (row.length) {
-          position(row, u, rect, true);
-          row.length = row.area = 0;
-        }
-        children.forEach(squarify);
-      }
-    }
-    function stickify(node) {
-      var children = node.children;
-      if (children && children.length) {
-        var rect = pad(node), remaining = children.slice(), child, row = [];
-        scale(remaining, rect.dx * rect.dy / node.value);
-        row.area = 0;
-        while (child = remaining.pop()) {
-          row.push(child);
-          row.area += child.area;
-          if (child.z != null) {
-            position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
-            row.length = row.area = 0;
-          }
-        }
-        children.forEach(stickify);
-      }
-    }
-    function worst(row, u) {
-      var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;
-      while (++i < n) {
-        if (!(r = row[i].area)) continue;
-        if (r < rmin) rmin = r;
-        if (r > rmax) rmax = r;
-      }
-      s *= s;
-      u *= u;
-      return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;
-    }
-    function position(row, u, rect, flush) {
-      var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;
-      if (u == rect.dx) {
-        if (flush || v > rect.dy) v = rect.dy;
-        while (++i < n) {
-          o = row[i];
-          o.x = x;
-          o.y = y;
-          o.dy = v;
-          x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);
-        }
-        o.z = true;
-        o.dx += rect.x + rect.dx - x;
-        rect.y += v;
-        rect.dy -= v;
-      } else {
-        if (flush || v > rect.dx) v = rect.dx;
-        while (++i < n) {
-          o = row[i];
-          o.x = x;
-          o.y = y;
-          o.dx = v;
-          y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);
-        }
-        o.z = false;
-        o.dy += rect.y + rect.dy - y;
-        rect.x += v;
-        rect.dx -= v;
-      }
-    }
-    function treemap(d) {
-      var nodes = stickies || hierarchy(d), root = nodes[0];
-      root.x = root.y = 0;
-      if (root.value) root.dx = size[0], root.dy = size[1]; else root.dx = root.dy = 0;
-      if (stickies) hierarchy.revalue(root);
-      scale([ root ], root.dx * root.dy / root.value);
-      (stickies ? stickify : squarify)(root);
-      if (sticky) stickies = nodes;
-      return nodes;
-    }
-    treemap.size = function(x) {
-      if (!arguments.length) return size;
-      size = x;
-      return treemap;
-    };
-    treemap.padding = function(x) {
-      if (!arguments.length) return padding;
-      function padFunction(node) {
-        var p = x.call(treemap, node, node.depth);
-        return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p);
-      }
-      function padConstant(node) {
-        return d3_layout_treemapPad(node, x);
-      }
-      var type;
-      pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], 
-      padConstant) : padConstant;
-      return treemap;
-    };
-    treemap.round = function(x) {
-      if (!arguments.length) return round != Number;
-      round = x ? Math.round : Number;
-      return treemap;
-    };
-    treemap.sticky = function(x) {
-      if (!arguments.length) return sticky;
-      sticky = x;
-      stickies = null;
-      return treemap;
-    };
-    treemap.ratio = function(x) {
-      if (!arguments.length) return ratio;
-      ratio = x;
-      return treemap;
-    };
-    treemap.mode = function(x) {
-      if (!arguments.length) return mode;
-      mode = x + "";
-      return treemap;
-    };
-    return d3_layout_hierarchyRebind(treemap, hierarchy);
-  };
-  function d3_layout_treemapPadNull(node) {
-    return {
-      x: node.x,
-      y: node.y,
-      dx: node.dx,
-      dy: node.dy
-    };
-  }
-  function d3_layout_treemapPad(node, padding) {
-    var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];
-    if (dx < 0) {
-      x += dx / 2;
-      dx = 0;
-    }
-    if (dy < 0) {
-      y += dy / 2;
-      dy = 0;
-    }
-    return {
-      x: x,
-      y: y,
-      dx: dx,
-      dy: dy
-    };
-  }
-  d3.random = {
-    normal: function(µ, σ) {
-      var n = arguments.length;
-      if (n < 2) σ = 1;
-      if (n < 1) µ = 0;
-      return function() {
-        var x, y, r;
-        do {
-          x = Math.random() * 2 - 1;
-          y = Math.random() * 2 - 1;
-          r = x * x + y * y;
-        } while (!r || r > 1);
-        return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
-      };
-    },
-    logNormal: function() {
-      var random = d3.random.normal.apply(d3, arguments);
-      return function() {
-        return Math.exp(random());
-      };
-    },
-    bates: function(m) {
-      var random = d3.random.irwinHall(m);
-      return function() {
-        return random() / m;
-      };
-    },
-    irwinHall: function(m) {
-      return function() {
-        for (var s = 0, j = 0; j < m; j++) s += Math.random();
-        return s;
-      };
-    }
-  };
-  d3.scale = {};
-  function d3_scaleExtent(domain) {
-    var start = domain[0], stop = domain[domain.length - 1];
-    return start < stop ? [ start, stop ] : [ stop, start ];
-  }
-  function d3_scaleRange(scale) {
-    return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
-  }
-  function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
-    var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);
-    return function(x) {
-      return i(u(x));
-    };
-  }
-  function d3_scale_nice(domain, nice) {
-    var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;
-    if (x1 < x0) {
-      dx = i0, i0 = i1, i1 = dx;
-      dx = x0, x0 = x1, x1 = dx;
-    }
-    domain[i0] = nice.floor(x0);
-    domain[i1] = nice.ceil(x1);
-    return domain;
-  }
-  function d3_scale_niceStep(step) {
-    return step ? {
-      floor: function(x) {
-        return Math.floor(x / step) * step;
-      },
-      ceil: function(x) {
-        return Math.ceil(x / step) * step;
-      }
-    } : d3_scale_niceIdentity;
-  }
-  var d3_scale_niceIdentity = {
-    floor: d3_identity,
-    ceil: d3_identity
-  };
-  function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
-    var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;
-    if (domain[k] < domain[0]) {
-      domain = domain.slice().reverse();
-      range = range.slice().reverse();
-    }
-    while (++j <= k) {
-      u.push(uninterpolate(domain[j - 1], domain[j]));
-      i.push(interpolate(range[j - 1], range[j]));
-    }
-    return function(x) {
-      var j = d3.bisect(domain, x, 1, k) - 1;
-      return i[j](u[j](x));
-    };
-  }
-  d3.scale.linear = function() {
-    return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false);
-  };
-  function d3_scale_linear(domain, range, interpolate, clamp) {
-    var output, input;
-    function rescale() {
-      var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
-      output = linear(domain, range, uninterpolate, interpolate);
-      input = linear(range, domain, uninterpolate, d3_interpolate);
-      return scale;
-    }
-    function scale(x) {
-      return output(x);
-    }
-    scale.invert = function(y) {
-      return input(y);
-    };
-    scale.domain = function(x) {
-      if (!arguments.length) return domain;
-      domain = x.map(Number);
-      return rescale();
-    };
-    scale.range = function(x) {
-      if (!arguments.length) return range;
-      range = x;
-      return rescale();
-    };
-    scale.rangeRound = function(x) {
-      return scale.range(x).interpolate(d3_interpolateRound);
-    };
-    scale.clamp = function(x) {
-      if (!arguments.length) return clamp;
-      clamp = x;
-      return rescale();
-    };
-    scale.interpolate = function(x) {
-      if (!arguments.length) return interpolate;
-      interpolate = x;
-      return rescale();
-    };
-    scale.ticks = function(m) {
-      return d3_scale_linearTicks(domain, m);
-    };
-    scale.tickFormat = function(m, format) {
-      return d3_scale_linearTickFormat(domain, m, format);
-    };
-    scale.nice = function(m) {
-      d3_scale_linearNice(domain, m);
-      return rescale();
-    };
-    scale.copy = function() {
-      return d3_scale_linear(domain, range, interpolate, clamp);
-    };
-    return rescale();
-  }
-  function d3_scale_linearRebind(scale, linear) {
-    return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
-  }
-  function d3_scale_linearNice(domain, m) {
-    d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));
-    d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));
-    return domain;
-  }
-  function d3_scale_linearTickRange(domain, m) {
-    if (m == null) m = 10;
-    var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;
-    if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
-    extent[0] = Math.ceil(extent[0] / step) * step;
-    extent[1] = Math.floor(extent[1] / step) * step + step * .5;
-    extent[2] = step;
-    return extent;
-  }
-  function d3_scale_linearTicks(domain, m) {
-    return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
-  }
-  function d3_scale_linearTickFormat(domain, m, format) {
-    var range = d3_scale_linearTickRange(domain, m);
-    if (format) {
-      var match = d3_format_re.exec(format);
-      match.shift();
-      if (match[8] === "s") {
-        var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1])));
-        if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2]));
-        match[8] = "f";
-        format = d3.format(match.join(""));
-        return function(d) {
-          return format(prefix.scale(d)) + prefix.symbol;
-        };
-      }
-      if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range);
-      format = match.join("");
-    } else {
-      format = ",." + d3_scale_linearPrecision(range[2]) + "f";
-    }
-    return d3.format(format);
-  }
-  var d3_scale_linearFormatSignificant = {
-    s: 1,
-    g: 1,
-    p: 1,
-    r: 1,
-    e: 1
-  };
-  function d3_scale_linearPrecision(value) {
-    return -Math.floor(Math.log(value) / Math.LN10 + .01);
-  }
-  function d3_scale_linearFormatPrecision(type, range) {
-    var p = d3_scale_linearPrecision(range[2]);
-    return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2;
-  }
-  d3.scale.log = function() {
-    return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]);
-  };
-  function d3_scale_log(linear, base, positive, domain) {
-    function log(x) {
-      return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base);
-    }
-    function pow(x) {
-      return positive ? Math.pow(base, x) : -Math.pow(base, -x);
-    }
-    function scale(x) {
-      return linear(log(x));
-    }
-    scale.invert = function(x) {
-      return pow(linear.invert(x));
-    };
-    scale.domain = function(x) {
-      if (!arguments.length) return domain;
-      positive = x[0] >= 0;
-      linear.domain((domain = x.map(Number)).map(log));
-      return scale;
-    };
-    scale.base = function(_) {
-      if (!arguments.length) return base;
-      base = +_;
-      linear.domain(domain.map(log));
-      return scale;
-    };
-    scale.nice = function() {
-      var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative);
-      linear.domain(niced);
-      domain = niced.map(pow);
-      return scale;
-    };
-    scale.ticks = function() {
-      var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base;
-      if (isFinite(j - i)) {
-        if (positive) {
-          for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k);
-          ticks.push(pow(i));
-        } else {
-          ticks.push(pow(i));
-          for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k);
-        }
-        for (i = 0; ticks[i] < u; i++) {}
-        for (j = ticks.length; ticks[j - 1] > v; j--) {}
-        ticks = ticks.slice(i, j);
-      }
-      return ticks;
-    };
-    scale.tickFormat = function(n, format) {
-      if (!arguments.length) return d3_scale_logFormat;
-      if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format);
-      var k = Math.max(1, base * n / scale.ticks().length);
-      return function(d) {
-        var i = d / pow(Math.round(log(d)));
-        if (i * base < base - .5) i *= base;
-        return i <= k ? format(d) : "";
-      };
-    };
-    scale.copy = function() {
-      return d3_scale_log(linear.copy(), base, positive, domain);
-    };
-    return d3_scale_linearRebind(scale, linear);
-  }
-  var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = {
-    floor: function(x) {
-      return -Math.ceil(-x);
-    },
-    ceil: function(x) {
-      return -Math.floor(-x);
-    }
-  };
-  d3.scale.pow = function() {
-    return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]);
-  };
-  function d3_scale_pow(linear, exponent, domain) {
-    var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
-    function scale(x) {
-      return linear(powp(x));
-    }
-    scale.invert = function(x) {
-      return powb(linear.invert(x));
-    };
-    scale.domain = function(x) {
-      if (!arguments.length) return domain;
-      linear.domain((domain = x.map(Number)).map(powp));
-      return scale;
-    };
-    scale.ticks = function(m) {
-      return d3_scale_linearTicks(domain, m);
-    };
-    scale.tickFormat = function(m, format) {
-      return d3_scale_linearTickFormat(domain, m, format);
-    };
-    scale.nice = function(m) {
-      return scale.domain(d3_scale_linearNice(domain, m));
-    };
-    scale.exponent = function(x) {
-      if (!arguments.length) return exponent;
-      powp = d3_scale_powPow(exponent = x);
-      powb = d3_scale_powPow(1 / exponent);
-      linear.domain(domain.map(powp));
-      return scale;
-    };
-    scale.copy = function() {
-      return d3_scale_pow(linear.copy(), exponent, domain);
-    };
-    return d3_scale_linearRebind(scale, linear);
-  }
-  function d3_scale_powPow(e) {
-    return function(x) {
-      return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
-    };
-  }
-  d3.scale.sqrt = function() {
-    return d3.scale.pow().exponent(.5);
-  };
-  d3.scale.ordinal = function() {
-    return d3_scale_ordinal([], {
-      t: "range",
-      a: [ [] ]
-    });
-  };
-  function d3_scale_ordinal(domain, ranger) {
-    var index, range, rangeBand;
-    function scale(x) {
-      return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length];
-    }
-    function steps(start, step) {
-      return d3.range(domain.length).map(function(i) {
-        return start + step * i;
-      });
-    }
-    scale.domain = function(x) {
-      if (!arguments.length) return domain;
-      domain = [];
-      index = new d3_Map();
-      var i = -1, n = x.length, xi;
-      while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
-      return scale[ranger.t].apply(scale, ranger.a);
-    };
-    scale.range = function(x) {
-      if (!arguments.length) return range;
-      range = x;
-      rangeBand = 0;
-      ranger = {
-        t: "range",
-        a: arguments
-      };
-      return scale;
-    };
-    scale.rangePoints = function(x, padding) {
-      if (arguments.length < 2) padding = 0;
-      var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, 
-      0) : (stop - start) / (domain.length - 1 + padding);
-      range = steps(start + step * padding / 2, step);
-      rangeBand = 0;
-      ranger = {
-        t: "rangePoints",
-        a: arguments
-      };
-      return scale;
-    };
-    scale.rangeRoundPoints = function(x, padding) {
-      if (arguments.length < 2) padding = 0;
-      var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), 
-      0) : (stop - start) / (domain.length - 1 + padding) | 0;
-      range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step);
-      rangeBand = 0;
-      ranger = {
-        t: "rangeRoundPoints",
-        a: arguments
-      };
-      return scale;
-    };
-    scale.rangeBands = function(x, padding, outerPadding) {
-      if (arguments.length < 2) padding = 0;
-      if (arguments.length < 3) outerPadding = padding;
-      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);
-      range = steps(start + step * outerPadding, step);
-      if (reverse) range.reverse();
-      rangeBand = step * (1 - padding);
-      ranger = {
-        t: "rangeBands",
-        a: arguments
-      };
-      return scale;
-    };
-    scale.rangeRoundBands = function(x, padding, outerPadding) {
-      if (arguments.length < 2) padding = 0;
-      if (arguments.length < 3) outerPadding = padding;
-      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding));
-      range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step);
-      if (reverse) range.reverse();
-      rangeBand = Math.round(step * (1 - padding));
-      ranger = {
-        t: "rangeRoundBands",
-        a: arguments
-      };
-      return scale;
-    };
-    scale.rangeBand = function() {
-      return rangeBand;
-    };
-    scale.rangeExtent = function() {
-      return d3_scaleExtent(ranger.a[0]);
-    };
-    scale.copy = function() {
-      return d3_scale_ordinal(domain, ranger);
-    };
-    return scale.domain(domain);
-  }
-  d3.scale.category10 = function() {
-    return d3.scale.ordinal().range(d3_category10);
-  };
-  d3.scale.category20 = function() {
-    return d3.scale.ordinal().range(d3_category20);
-  };
-  d3.scale.category20b = function() {
-    return d3.scale.ordinal().range(d3_category20b);
-  };
-  d3.scale.category20c = function() {
-    return d3.scale.ordinal().range(d3_category20c);
-  };
-  var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString);
-  var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString);
-  var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString);
-  var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString);
-  d3.scale.quantile = function() {
-    return d3_scale_quantile([], []);
-  };
-  function d3_scale_quantile(domain, range) {
-    var thresholds;
-    function rescale() {
-      var k = 0, q = range.length;
-      thresholds = [];
-      while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
-      return scale;
-    }
-    function scale(x) {
-      if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)];
-    }
-    scale.domain = function(x) {
-      if (!arguments.length) return domain;
-      domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending);
-      return rescale();
-    };
-    scale.range = function(x) {
-      if (!arguments.length) return range;
-      range = x;
-      return rescale();
-    };
-    scale.quantiles = function() {
-      return thresholds;
-    };
-    scale.invertExtent = function(y) {
-      y = range.indexOf(y);
-      return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ];
-    };
-    scale.copy = function() {
-      return d3_scale_quantile(domain, range);
-    };
-    return rescale();
-  }
-  d3.scale.quantize = function() {
-    return d3_scale_quantize(0, 1, [ 0, 1 ]);
-  };
-  function d3_scale_quantize(x0, x1, range) {
-    var kx, i;
-    function scale(x) {
-      return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
-    }
-    function rescale() {
-      kx = range.length / (x1 - x0);
-      i = range.length - 1;
-      return scale;
-    }
-    scale.domain = function(x) {
-      if (!arguments.length) return [ x0, x1 ];
-      x0 = +x[0];
-      x1 = +x[x.length - 1];
-      return rescale();
-    };
-    scale.range = function(x) {
-      if (!arguments.length) return range;
-      range = x;
-      return rescale();
-    };
-    scale.invertExtent = function(y) {
-      y = range.indexOf(y);
-      y = y < 0 ? NaN : y / kx + x0;
-      return [ y, y + 1 / kx ];
-    };
-    scale.copy = function() {
-      return d3_scale_quantize(x0, x1, range);
-    };
-    return rescale();
-  }
-  d3.scale.threshold = function() {
-    return d3_scale_threshold([ .5 ], [ 0, 1 ]);
-  };
-  function d3_scale_threshold(domain, range) {
-    function scale(x) {
-      if (x <= x) return range[d3.bisect(domain, x)];
-    }
-    scale.domain = function(_) {
-      if (!arguments.length) return domain;
-      domain = _;
-      return scale;
-    };
-    scale.range = function(_) {
-      if (!arguments.length) return range;
-      range = _;
-      return scale;
-    };
-    scale.invertExtent = function(y) {
-      y = range.indexOf(y);
-      return [ domain[y - 1], domain[y] ];
-    };
-    scale.copy = function() {
-      return d3_scale_threshold(domain, range);
-    };
-    return scale;
-  }
-  d3.scale.identity = function() {
-    return d3_scale_identity([ 0, 1 ]);
-  };
-  function d3_scale_identity(domain) {
-    function identity(x) {
-      return +x;
-    }
-    identity.invert = identity;
-    identity.domain = identity.range = function(x) {
-      if (!arguments.length) return domain;
-      domain = x.map(identity);
-      return identity;
-    };
-    identity.ticks = function(m) {
-      return d3_scale_linearTicks(domain, m);
-    };
-    identity.tickFormat = function(m, format) {
-      return d3_scale_linearTickFormat(domain, m, format);
-    };
-    identity.copy = function() {
-      return d3_scale_identity(domain);
-    };
-    return identity;
-  }
-  d3.svg = {};
-  function d3_zero() {
-    return 0;
-  }
-  d3.svg.arc = function() {
-    var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle;
-    function arc() {
-      var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1;
-      if (r1 < r0) rc = r1, r1 = r0, r0 = rc;
-      if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z";
-      var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = [];
-      if (ap = (+padAngle.apply(this, arguments) || 0) / 2) {
-        rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments);
-        if (!cw) p1 *= -1;
-        if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap));
-        if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap));
-      }
-      if (r1) {
-        x0 = r1 * Math.cos(a0 + p1);
-        y0 = r1 * Math.sin(a0 + p1);
-        x1 = r1 * Math.cos(a1 - p1);
-        y1 = r1 * Math.sin(a1 - p1);
-        var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1;
-        if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) {
-          var h1 = (a0 + a1) / 2;
-          x0 = r1 * Math.cos(h1);
-          y0 = r1 * Math.sin(h1);
-          x1 = y1 = null;
-        }
-      } else {
-        x0 = y0 = 0;
-      }
-      if (r0) {
-        x2 = r0 * Math.cos(a1 - p0);
-        y2 = r0 * Math.sin(a1 - p0);
-        x3 = r0 * Math.cos(a0 + p0);
-        y3 = r0 * Math.sin(a0 + p0);
-        var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1;
-        if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) {
-          var h0 = (a0 + a1) / 2;
-          x2 = r0 * Math.cos(h0);
-          y2 = r0 * Math.sin(h0);
-          x3 = y3 = null;
-        }
-      } else {
-        x2 = y2 = 0;
-      }
-      if (da > ε && (rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) {
-        cr = r0 < r1 ^ cw ? 0 : 1;
-        var rc1 = rc, rc0 = rc;
-        if (da < π) {
-          var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
-          rc0 = Math.min(rc, (r0 - lc) / (kc - 1));
-          rc1 = Math.min(rc, (r1 - lc) / (kc + 1));
-        }
-        if (x1 != null) {
-          var t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw);
-          if (rc === rc1) {
-            path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]);
-          } else {
-            path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]);
-          }
-        } else {
-          path.push("M", x0, ",", y0);
-        }
-        if (x3 != null) {
-          var t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw);
-          if (rc === rc0) {
-            path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
-          } else {
-            path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
-          }
-        } else {
-          path.push("L", x2, ",", y2);
-        }
-      } else {
-        path.push("M", x0, ",", y0);
-        if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1);
-        path.push("L", x2, ",", y2);
-        if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3);
-      }
-      path.push("Z");
-      return path.join("");
-    }
-    function circleSegment(r1, cw) {
-      return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1;
-    }
-    arc.innerRadius = function(v) {
-      if (!arguments.length) return innerRadius;
-      innerRadius = d3_functor(v);
-      return arc;
-    };
-    arc.outerRadius = function(v) {
-      if (!arguments.length) return outerRadius;
-      outerRadius = d3_functor(v);
-      return arc;
-    };
-    arc.cornerRadius = function(v) {
-      if (!arguments.length) return cornerRadius;
-      cornerRadius = d3_functor(v);
-      return arc;
-    };
-    arc.padRadius = function(v) {
-      if (!arguments.length) return padRadius;
-      padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v);
-      return arc;
-    };
-    arc.startAngle = function(v) {
-      if (!arguments.length) return startAngle;
-      startAngle = d3_functor(v);
-      return arc;
-    };
-    arc.endAngle = function(v) {
-      if (!arguments.length) return endAngle;
-      endAngle = d3_functor(v);
-      return arc;
-    };
-    arc.padAngle = function(v) {
-      if (!arguments.length) return padAngle;
-      padAngle = d3_functor(v);
-      return arc;
-    };
-    arc.centroid = function() {
-      var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ;
-      return [ Math.cos(a) * r, Math.sin(a) * r ];
-    };
-    return arc;
-  };
-  var d3_svg_arcAuto = "auto";
-  function d3_svg_arcInnerRadius(d) {
-    return d.innerRadius;
-  }
-  function d3_svg_arcOuterRadius(d) {
-    return d.outerRadius;
-  }
-  function d3_svg_arcStartAngle(d) {
-    return d.startAngle;
-  }
-  function d3_svg_arcEndAngle(d) {
-    return d.endAngle;
-  }
-  function d3_svg_arcPadAngle(d) {
-    return d && d.padAngle;
-  }
-  function d3_svg_arcSweep(x0, y0, x1, y1) {
-    return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1;
-  }
-  function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) {
-    var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3;
-    if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
-    return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ];
-  }
-  function d3_svg_line(projection) {
-    var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;
-    function line(data) {
-      var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);
-      function segment() {
-        segments.push("M", interpolate(projection(points), tension));
-      }
-      while (++i < n) {
-        if (defined.call(this, d = data[i], i)) {
-          points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
-        } else if (points.length) {
-          segment();
-          points = [];
-        }
-      }
-      if (points.length) segment();
-      return segments.length ? segments.join("") : null;
-    }
-    line.x = function(_) {
-      if (!arguments.length) return x;
-      x = _;
-      return line;
-    };
-    line.y = function(_) {
-      if (!arguments.length) return y;
-      y = _;
-      return line;
-    };
-    line.defined = function(_) {
-      if (!arguments.length) return defined;
-      defined = _;
-      return line;
-    };
-    line.interpolate = function(_) {
-      if (!arguments.length) return interpolateKey;
-      if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
-      return line;
-    };
-    line.tension = function(_) {
-      if (!arguments.length) return tension;
-      tension = _;
-      return line;
-    };
-    return line;
-  }
-  d3.svg.line = function() {
-    return d3_svg_line(d3_identity);
-  };
-  var d3_svg_lineInterpolators = d3.map({
-    linear: d3_svg_lineLinear,
-    "linear-closed": d3_svg_lineLinearClosed,
-    step: d3_svg_lineStep,
-    "step-before": d3_svg_lineStepBefore,
-    "step-after": d3_svg_lineStepAfter,
-    basis: d3_svg_lineBasis,
-    "basis-open": d3_svg_lineBasisOpen,
-    "basis-closed": d3_svg_lineBasisClosed,
-    bundle: d3_svg_lineBundle,
-    cardinal: d3_svg_lineCardinal,
-    "cardinal-open": d3_svg_lineCardinalOpen,
-    "cardinal-closed": d3_svg_lineCardinalClosed,
-    monotone: d3_svg_lineMonotone
-  });
-  d3_svg_lineInterpolators.forEach(function(key, value) {
-    value.key = key;
-    value.closed = /-closed$/.test(key);
-  });
-  function d3_svg_lineLinear(points) {
-    return points.length > 1 ? points.join("L") : points + "Z";
-  }
-  function d3_svg_lineLinearClosed(points) {
-    return points.join("L") + "Z";
-  }
-  function d3_svg_lineStep(points) {
-    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
-    while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]);
-    if (n > 1) path.push("H", p[0]);
-    return path.join("");
-  }
-  function d3_svg_lineStepBefore(points) {
-    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
-    while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
-    return path.join("");
-  }
-  function d3_svg_lineStepAfter(points) {
-    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
-    while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
-    return path.join("");
-  }
-  function d3_svg_lineCardinalOpen(points, tension) {
-    return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension));
-  }
-  function d3_svg_lineCardinalClosed(points, tension) {
-    return points.length < 3 ? d3_svg_lineLinearClosed(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), 
-    points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));
-  }
-  function d3_svg_lineCardinal(points, tension) {
-    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));
-  }
-  function d3_svg_lineHermite(points, tangents) {
-    if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {
-      return d3_svg_lineLinear(points);
-    }
-    var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;
-    if (quad) {
-      path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1];
-      p0 = points[1];
-      pi = 2;
-    }
-    if (tangents.length > 1) {
-      t = tangents[1];
-      p = points[pi];
-      pi++;
-      path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
-      for (var i = 2; i < tangents.length; i++, pi++) {
-        p = points[pi];
-        t = tangents[i];
-        path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
-      }
-    }
-    if (quad) {
-      var lp = points[pi];
-      path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
-    }
-    return path;
-  }
-  function d3_svg_lineCardinalTangents(points, tension) {
-    var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;
-    while (++i < n) {
-      p0 = p1;
-      p1 = p2;
-      p2 = points[i];
-      tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);
-    }
-    return tangents;
-  }
-  function d3_svg_lineBasis(points) {
-    if (points.length < 3) return d3_svg_lineLinear(points);
-    var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
-    points.push(points[n - 1]);
-    while (++i <= n) {
-      pi = points[i];
-      px.shift();
-      px.push(pi[0]);
-      py.shift();
-      py.push(pi[1]);
-      d3_svg_lineBasisBezier(path, px, py);
-    }
-    points.pop();
-    path.push("L", pi);
-    return path.join("");
-  }
-  function d3_svg_lineBasisOpen(points) {
-    if (points.length < 4) return d3_svg_lineLinear(points);
-    var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];
-    while (++i < 3) {
-      pi = points[i];
-      px.push(pi[0]);
-      py.push(pi[1]);
-    }
-    path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
-    --i;
-    while (++i < n) {
-      pi = points[i];
-      px.shift();
-      px.push(pi[0]);
-      py.shift();
-      py.push(pi[1]);
-      d3_svg_lineBasisBezier(path, px, py);
-    }
-    return path.join("");
-  }
-  function d3_svg_lineBasisClosed(points) {
-    var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];
-    while (++i < 4) {
-      pi = points[i % n];
-      px.push(pi[0]);
-      py.push(pi[1]);
-    }
-    path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
-    --i;
-    while (++i < m) {
-      pi = points[i % n];
-      px.shift();
-      px.push(pi[0]);
-      py.shift();
-      py.push(pi[1]);
-      d3_svg_lineBasisBezier(path, px, py);
-    }
-    return path.join("");
-  }
-  function d3_svg_lineBundle(points, tension) {
-    var n = points.length - 1;
-    if (n) {
-      var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;
-      while (++i <= n) {
-        p = points[i];
-        t = i / n;
-        p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
-        p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
-      }
-    }
-    return d3_svg_lineBasis(points);
-  }
-  function d3_svg_lineDot4(a, b) {
-    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
-  }
-  var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];
-  function d3_svg_lineBasisBezier(path, x, y) {
-    path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
-  }
-  function d3_svg_lineSlope(p0, p1) {
-    return (p1[1] - p0[1]) / (p1[0] - p0[0]);
-  }
-  function d3_svg_lineFiniteDifferences(points) {
-    var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);
-    while (++i < j) {
-      m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
-    }
-    m[i] = d;
-    return m;
-  }
-  function d3_svg_lineMonotoneTangents(points) {
-    var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
-    while (++i < j) {
-      d = d3_svg_lineSlope(points[i], points[i + 1]);
-      if (abs(d) < ε) {
-        m[i] = m[i + 1] = 0;
-      } else {
-        a = m[i] / d;
-        b = m[i + 1] / d;
-        s = a * a + b * b;
-        if (s > 9) {
-          s = d * 3 / Math.sqrt(s);
-          m[i] = s * a;
-          m[i + 1] = s * b;
-        }
-      }
-    }
-    i = -1;
-    while (++i <= j) {
-      s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
-      tangents.push([ s || 0, m[i] * s || 0 ]);
-    }
-    return tangents;
-  }
-  function d3_svg_lineMonotone(points) {
-    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
-  }
-  d3.svg.line.radial = function() {
-    var line = d3_svg_line(d3_svg_lineRadial);
-    line.radius = line.x, delete line.x;
-    line.angle = line.y, delete line.y;
-    return line;
-  };
-  function d3_svg_lineRadial(points) {
-    var point, i = -1, n = points.length, r, a;
-    while (++i < n) {
-      point = points[i];
-      r = point[0];
-      a = point[1] - halfπ;
-      point[0] = r * Math.cos(a);
-      point[1] = r * Math.sin(a);
-    }
-    return points;
-  }
-  function d3_svg_area(projection) {
-    var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7;
-    function area(data) {
-      var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {
-        return x;
-      } : d3_functor(x1), fy1 = y0 === y1 ? function() {
-        return y;
-      } : d3_functor(y1), x, y;
-      function segment() {
-        segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z");
-      }
-      while (++i < n) {
-        if (defined.call(this, d = data[i], i)) {
-          points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);
-          points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);
-        } else if (points0.length) {
-          segment();
-          points0 = [];
-          points1 = [];
-        }
-      }
-      if (points0.length) segment();
-      return segments.length ? segments.join("") : null;
-    }
-    area.x = function(_) {
-      if (!arguments.length) return x1;
-      x0 = x1 = _;
-      return area;
-    };
-    area.x0 = function(_) {
-      if (!arguments.length) return x0;
-      x0 = _;
-      return area;
-    };
-    area.x1 = function(_) {
-      if (!arguments.length) return x1;
-      x1 = _;
-      return area;
-    };
-    area.y = function(_) {
-      if (!arguments.length) return y1;
-      y0 = y1 = _;
-      return area;
-    };
-    area.y0 = function(_) {
-      if (!arguments.length) return y0;
-      y0 = _;
-      return area;
-    };
-    area.y1 = function(_) {
-      if (!arguments.length) return y1;
-      y1 = _;
-      return area;
-    };
-    area.defined = function(_) {
-      if (!arguments.length) return defined;
-      defined = _;
-      return area;
-    };
-    area.interpolate = function(_) {
-      if (!arguments.length) return interpolateKey;
-      if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
-      interpolateReverse = interpolate.reverse || interpolate;
-      L = interpolate.closed ? "M" : "L";
-      return area;
-    };
-    area.tension = function(_) {
-      if (!arguments.length) return tension;
-      tension = _;
-      return area;
-    };
-    return area;
-  }
-  d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
-  d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
-  d3.svg.area = function() {
-    return d3_svg_area(d3_identity);
-  };
-  d3.svg.area.radial = function() {
-    var area = d3_svg_area(d3_svg_lineRadial);
-    area.radius = area.x, delete area.x;
-    area.innerRadius = area.x0, delete area.x0;
-    area.outerRadius = area.x1, delete area.x1;
-    area.angle = area.y, delete area.y;
-    area.startAngle = area.y0, delete area.y0;
-    area.endAngle = area.y1, delete area.y1;
-    return area;
-  };
-  d3.svg.chord = function() {
-    var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
-    function chord(d, i) {
-      var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);
-      return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z";
-    }
-    function subgroup(self, f, d, i) {
-      var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ;
-      return {
-        r: r,
-        a0: a0,
-        a1: a1,
-        p0: [ r * Math.cos(a0), r * Math.sin(a0) ],
-        p1: [ r * Math.cos(a1), r * Math.sin(a1) ]
-      };
-    }
-    function equals(a, b) {
-      return a.a0 == b.a0 && a.a1 == b.a1;
-    }
-    function arc(r, p, a) {
-      return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p;
-    }
-    function curve(r0, p0, r1, p1) {
-      return "Q 0,0 " + p1;
-    }
-    chord.radius = function(v) {
-      if (!arguments.length) return radius;
-      radius = d3_functor(v);
-      return chord;
-    };
-    chord.source = function(v) {
-      if (!arguments.length) return source;
-      source = d3_functor(v);
-      return chord;
-    };
-    chord.target = function(v) {
-      if (!arguments.length) return target;
-      target = d3_functor(v);
-      return chord;
-    };
-    chord.startAngle = function(v) {
-      if (!arguments.length) return startAngle;
-      startAngle = d3_functor(v);
-      return chord;
-    };
-    chord.endAngle = function(v) {
-      if (!arguments.length) return endAngle;
-      endAngle = d3_functor(v);
-      return chord;
-    };
-    return chord;
-  };
-  function d3_svg_chordRadius(d) {
-    return d.radius;
-  }
-  d3.svg.diagonal = function() {
-    var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;
-    function diagonal(d, i) {
-      var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {
-        x: p0.x,
-        y: m
-      }, {
-        x: p3.x,
-        y: m
-      }, p3 ];
-      p = p.map(projection);
-      return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
-    }
-    diagonal.source = function(x) {
-      if (!arguments.length) return source;
-      source = d3_functor(x);
-      return diagonal;
-    };
-    diagonal.target = function(x) {
-      if (!arguments.length) return target;
-      target = d3_functor(x);
-      return diagonal;
-    };
-    diagonal.projection = function(x) {
-      if (!arguments.length) return projection;
-      projection = x;
-      return diagonal;
-    };
-    return diagonal;
-  };
-  function d3_svg_diagonalProjection(d) {
-    return [ d.x, d.y ];
-  }
-  d3.svg.diagonal.radial = function() {
-    var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;
-    diagonal.projection = function(x) {
-      return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;
-    };
-    return diagonal;
-  };
-  function d3_svg_diagonalRadialProjection(projection) {
-    return function() {
-      var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ;
-      return [ r * Math.cos(a), r * Math.sin(a) ];
-    };
-  }
-  d3.svg.symbol = function() {
-    var type = d3_svg_symbolType, size = d3_svg_symbolSize;
-    function symbol(d, i) {
-      return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));
-    }
-    symbol.type = function(x) {
-      if (!arguments.length) return type;
-      type = d3_functor(x);
-      return symbol;
-    };
-    symbol.size = function(x) {
-      if (!arguments.length) return size;
-      size = d3_functor(x);
-      return symbol;
-    };
-    return symbol;
-  };
-  function d3_svg_symbolSize() {
-    return 64;
-  }
-  function d3_svg_symbolType() {
-    return "circle";
-  }
-  function d3_svg_symbolCircle(size) {
-    var r = Math.sqrt(size / π);
-    return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z";
-  }
-  var d3_svg_symbols = d3.map({
-    circle: d3_svg_symbolCircle,
-    cross: function(size) {
-      var r = Math.sqrt(size / 5) / 2;
-      return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z";
-    },
-    diamond: function(size) {
-      var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;
-      return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z";
-    },
-    square: function(size) {
-      var r = Math.sqrt(size) / 2;
-      return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z";
-    },
-    "triangle-down": function(size) {
-      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
-      return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z";
-    },
-    "triangle-up": function(size) {
-      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
-      return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z";
-    }
-  });
-  d3.svg.symbolTypes = d3_svg_symbols.keys();
-  var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
-  d3_selectionPrototype.transition = function(name) {
-    var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || {
-      time: Date.now(),
-      ease: d3_ease_cubicInOut,
-      delay: 0,
-      duration: 250
-    };
-    for (var j = -1, m = this.length; ++j < m; ) {
-      subgroups.push(subgroup = []);
-      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
-        if (node = group[i]) d3_transitionNode(node, i, ns, id, transition);
-        subgroup.push(node);
-      }
-    }
-    return d3_transition(subgroups, ns, id);
-  };
-  d3_selectionPrototype.interrupt = function(name) {
-    return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name)));
-  };
-  var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace());
-  function d3_selection_interruptNS(ns) {
-    return function() {
-      var lock, activeId, active;
-      if ((lock = this[ns]) && (active = lock[activeId = lock.active])) {
-        active.timer.c = null;
-        active.timer.t = NaN;
-        if (--lock.count) delete lock[activeId]; else delete this[ns];
-        lock.active += .5;
-        active.event && active.event.interrupt.call(this, this.__data__, active.index);
-      }
-    };
-  }
-  function d3_transition(groups, ns, id) {
-    d3_subclass(groups, d3_transitionPrototype);
-    groups.namespace = ns;
-    groups.id = id;
-    return groups;
-  }
-  var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit;
-  d3_transitionPrototype.call = d3_selectionPrototype.call;
-  d3_transitionPrototype.empty = d3_selectionPrototype.empty;
-  d3_transitionPrototype.node = d3_selectionPrototype.node;
-  d3_transitionPrototype.size = d3_selectionPrototype.size;
-  d3.transition = function(selection, name) {
-    return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection);
-  };
-  d3.transition.prototype = d3_transitionPrototype;
-  d3_transitionPrototype.select = function(selector) {
-    var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node;
-    selector = d3_selection_selector(selector);
-    for (var j = -1, m = this.length; ++j < m; ) {
-      subgroups.push(subgroup = []);
-      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
-        if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {
-          if ("__data__" in node) subnode.__data__ = node.__data__;
-          d3_transitionNode(subnode, i, ns, id, node[ns][id]);
-          subgroup.push(subnode);
-        } else {
-          subgroup.push(null);
-        }
-      }
-    }
-    return d3_transition(subgroups, ns, id);
-  };
-  d3_transitionPrototype.selectAll = function(selector) {
-    var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition;
-    selector = d3_selection_selectorAll(selector);
-    for (var j = -1, m = this.length; ++j < m; ) {
-      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
-        if (node = group[i]) {
-          transition = node[ns][id];
-          subnodes = selector.call(node, node.__data__, i, j);
-          subgroups.push(subgroup = []);
-          for (var k = -1, o = subnodes.length; ++k < o; ) {
-            if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition);
-            subgroup.push(subnode);
-          }
-        }
-      }
-    }
-    return d3_transition(subgroups, ns, id);
-  };
-  d3_transitionPrototype.filter = function(filter) {
-    var subgroups = [], subgroup, group, node;
-    if (typeof filter !== "function") filter = d3_selection_filter(filter);
-    for (var j = 0, m = this.length; j < m; j++) {
-      subgroups.push(subgroup = []);
-      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
-        if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
-          subgroup.push(node);
-        }
-      }
-    }
-    return d3_transition(subgroups, this.namespace, this.id);
-  };
-  d3_transitionPrototype.tween = function(name, tween) {
-    var id = this.id, ns = this.namespace;
-    if (arguments.length < 2) return this.node()[ns][id].tween.get(name);
-    return d3_selection_each(this, tween == null ? function(node) {
-      node[ns][id].tween.remove(name);
-    } : function(node) {
-      node[ns][id].tween.set(name, tween);
-    });
-  };
-  function d3_transition_tween(groups, name, value, tween) {
-    var id = groups.id, ns = groups.namespace;
-    return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) {
-      node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
-    } : (value = tween(value), function(node) {
-      node[ns][id].tween.set(name, value);
-    }));
-  }
-  d3_transitionPrototype.attr = function(nameNS, value) {
-    if (arguments.length < 2) {
-      for (value in nameNS) this.attr(value, nameNS[value]);
-      return this;
-    }
-    var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS);
-    function attrNull() {
-      this.removeAttribute(name);
-    }
-    function attrNullNS() {
-      this.removeAttributeNS(name.space, name.local);
-    }
-    function attrTween(b) {
-      return b == null ? attrNull : (b += "", function() {
-        var a = this.getAttribute(name), i;
-        return a !== b && (i = interpolate(a, b), function(t) {
-          this.setAttribute(name, i(t));
-        });
-      });
-    }
-    function attrTweenNS(b) {
-      return b == null ? attrNullNS : (b += "", function() {
-        var a = this.getAttributeNS(name.space, name.local), i;
-        return a !== b && (i = interpolate(a, b), function(t) {
-          this.setAttributeNS(name.space, name.local, i(t));
-        });
-      });
-    }
-    return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween);
-  };
-  d3_transitionPrototype.attrTween = function(nameNS, tween) {
-    var name = d3.ns.qualify(nameNS);
-    function attrTween(d, i) {
-      var f = tween.call(this, d, i, this.getAttribute(name));
-      return f && function(t) {
-        this.setAttribute(name, f(t));
-      };
-    }
-    function attrTweenNS(d, i) {
-      var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
-      return f && function(t) {
-        this.setAttributeNS(name.space, name.local, f(t));
-      };
-    }
-    return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
-  };
-  d3_transitionPrototype.style = function(name, value, priority) {
-    var n = arguments.length;
-    if (n < 3) {
-      if (typeof name !== "string") {
-        if (n < 2) value = "";
-        for (priority in name) this.style(priority, name[priority], value);
-        return this;
-      }
-      priority = "";
-    }
-    function styleNull() {
-      this.style.removeProperty(name);
-    }
-    function styleString(b) {
-      return b == null ? styleNull : (b += "", function() {
-        var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i;
-        return a !== b && (i = d3_interpolate(a, b), function(t) {
-          this.style.setProperty(name, i(t), priority);
-        });
-      });
-    }
-    return d3_transition_tween(this, "style." + name, value, styleString);
-  };
-  d3_transitionPrototype.styleTween = function(name, tween, priority) {
-    if (arguments.length < 3) priority = "";
-    function styleTween(d, i) {
-      var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name));
-      return f && function(t) {
-        this.style.setProperty(name, f(t), priority);
-      };
-    }
-    return this.tween("style." + name, styleTween);
-  };
-  d3_transitionPrototype.text = function(value) {
-    return d3_transition_tween(this, "text", value, d3_transition_text);
-  };
-  function d3_transition_text(b) {
-    if (b == null) b = "";
-    return function() {
-      this.textContent = b;
-    };
-  }
-  d3_transitionPrototype.remove = function() {
-    var ns = this.namespace;
-    return this.each("end.transition", function() {
-      var p;
-      if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this);
-    });
-  };
-  d3_transitionPrototype.ease = function(value) {
-    var id = this.id, ns = this.namespace;
-    if (arguments.length < 1) return this.node()[ns][id].ease;
-    if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
-    return d3_selection_each(this, function(node) {
-      node[ns][id].ease = value;
-    });
-  };
-  d3_transitionPrototype.delay = function(value) {
-    var id = this.id, ns = this.namespace;
-    if (arguments.length < 1) return this.node()[ns][id].delay;
-    return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
-      node[ns][id].delay = +value.call(node, node.__data__, i, j);
-    } : (value = +value, function(node) {
-      node[ns][id].delay = value;
-    }));
-  };
-  d3_transitionPrototype.duration = function(value) {
-    var id = this.id, ns = this.namespace;
-    if (arguments.length < 1) return this.node()[ns][id].duration;
-    return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
-      node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j));
-    } : (value = Math.max(1, value), function(node) {
-      node[ns][id].duration = value;
-    }));
-  };
-  d3_transitionPrototype.each = function(type, listener) {
-    var id = this.id, ns = this.namespace;
-    if (arguments.length < 2) {
-      var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
-      try {
-        d3_transitionInheritId = id;
-        d3_selection_each(this, function(node, i, j) {
-          d3_transitionInherit = node[ns][id];
-          type.call(node, node.__data__, i, j);
-        });
-      } finally {
-        d3_transitionInherit = inherit;
-        d3_transitionInheritId = inheritId;
-      }
-    } else {
-      d3_selection_each(this, function(node) {
-        var transition = node[ns][id];
-        (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener);
-      });
-    }
-    return this;
-  };
-  d3_transitionPrototype.transition = function() {
-    var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition;
-    for (var j = 0, m = this.length; j < m; j++) {
-      subgroups.push(subgroup = []);
-      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
-        if (node = group[i]) {
-          transition = node[ns][id0];
-          d3_transitionNode(node, i, ns, id1, {
-            time: transition.time,
-            ease: transition.ease,
-            delay: transition.delay + transition.duration,
-            duration: transition.duration
-          });
-        }
-        subgroup.push(node);
-      }
-    }
-    return d3_transition(subgroups, ns, id1);
-  };
-  function d3_transitionNamespace(name) {
-    return name == null ? "__transition__" : "__transition_" + name + "__";
-  }
-  function d3_transitionNode(node, i, ns, id, inherit) {
-    var lock = node[ns] || (node[ns] = {
-      active: 0,
-      count: 0
-    }), transition = lock[id], time, timer, duration, ease, tweens;
-    function schedule(elapsed) {
-      var delay = transition.delay;
-      timer.t = delay + time;
-      if (delay <= elapsed) return start(elapsed - delay);
-      timer.c = start;
-    }
-    function start(elapsed) {
-      var activeId = lock.active, active = lock[activeId];
-      if (active) {
-        active.timer.c = null;
-        active.timer.t = NaN;
-        --lock.count;
-        delete lock[activeId];
-        active.event && active.event.interrupt.call(node, node.__data__, active.index);
-      }
-      for (var cancelId in lock) {
-        if (+cancelId < id) {
-          var cancel = lock[cancelId];
-          cancel.timer.c = null;
-          cancel.timer.t = NaN;
-          --lock.count;
-          delete lock[cancelId];
-        }
-      }
-      timer.c = tick;
-      d3_timer(function() {
-        if (timer.c && tick(elapsed || 1)) {
-          timer.c = null;
-          timer.t = NaN;
-        }
-        return 1;
-      }, 0, time);
-      lock.active = id;
-      transition.event && transition.event.start.call(node, node.__data__, i);
-      tweens = [];
-      transition.tween.forEach(function(key, value) {
-        if (value = value.call(node, node.__data__, i)) {
-          tweens.push(value);
-        }
-      });
-      ease = transition.ease;
-      duration = transition.duration;
-    }
-    function tick(elapsed) {
-      var t = elapsed / duration, e = ease(t), n = tweens.length;
-      while (n > 0) {
-        tweens[--n].call(node, e);
-      }
-      if (t >= 1) {
-        transition.event && transition.event.end.call(node, node.__data__, i);
-        if (--lock.count) delete lock[id]; else delete node[ns];
-        return 1;
-      }
-    }
-    if (!transition) {
-      time = inherit.time;
-      timer = d3_timer(schedule, 0, time);
-      transition = lock[id] = {
-        tween: new d3_Map(),
-        time: time,
-        timer: timer,
-        delay: inherit.delay,
-        duration: inherit.duration,
-        ease: inherit.ease,
-        index: i
-      };
-      inherit = null;
-      ++lock.count;
-    }
-  }
-  d3.svg.axis = function() {
-    var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_;
-    function axis(g) {
-      g.each(function() {
-        var g = d3.select(this);
-        var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy();
-        var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform;
-        var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), 
-        d3.transition(path));
-        tickEnter.append("line");
-        tickEnter.append("text");
-        var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2;
-        if (orient === "bottom" || orient === "top") {
-          tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2";
-          text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle");
-          pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize);
-        } else {
-          tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2";
-          text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start");
-          pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize);
-        }
-        lineEnter.attr(y2, sign * innerTickSize);
-        textEnter.attr(y1, sign * tickSpacing);
-        lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize);
-        textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing);
-        if (scale1.rangeBand) {
-          var x = scale1, dx = x.rangeBand() / 2;
-          scale0 = scale1 = function(d) {
-            return x(d) + dx;
-          };
-        } else if (scale0.rangeBand) {
-          scale0 = scale1;
-        } else {
-          tickExit.call(tickTransform, scale1, scale0);
-        }
-        tickEnter.call(tickTransform, scale0, scale1);
-        tickUpdate.call(tickTransform, scale1, scale1);
-      });
-    }
-    axis.scale = function(x) {
-      if (!arguments.length) return scale;
-      scale = x;
-      return axis;
-    };
-    axis.orient = function(x) {
-      if (!arguments.length) return orient;
-      orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient;
-      return axis;
-    };
-    axis.ticks = function() {
-      if (!arguments.length) return tickArguments_;
-      tickArguments_ = d3_array(arguments);
-      return axis;
-    };
-    axis.tickValues = function(x) {
-      if (!arguments.length) return tickValues;
-      tickValues = x;
-      return axis;
-    };
-    axis.tickFormat = function(x) {
-      if (!arguments.length) return tickFormat_;
-      tickFormat_ = x;
-      return axis;
-    };
-    axis.tickSize = function(x) {
-      var n = arguments.length;
-      if (!n) return innerTickSize;
-      innerTickSize = +x;
-      outerTickSize = +arguments[n - 1];
-      return axis;
-    };
-    axis.innerTickSize = function(x) {
-      if (!arguments.length) return innerTickSize;
-      innerTickSize = +x;
-      return axis;
-    };
-    axis.outerTickSize = function(x) {
-      if (!arguments.length) return outerTickSize;
-      outerTickSize = +x;
-      return axis;
-    };
-    axis.tickPadding = function(x) {
-      if (!arguments.length) return tickPadding;
-      tickPadding = +x;
-      return axis;
-    };
-    axis.tickSubdivide = function() {
-      return arguments.length && axis;
-    };
-    return axis;
-  };
-  var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = {
-    top: 1,
-    right: 1,
-    bottom: 1,
-    left: 1
-  };
-  function d3_svg_axisX(selection, x0, x1) {
-    selection.attr("transform", function(d) {
-      var v0 = x0(d);
-      return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)";
-    });
-  }
-  function d3_svg_axisY(selection, y0, y1) {
-    selection.attr("transform", function(d) {
-      var v0 = y0(d);
-      return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")";
-    });
-  }
-  d3.svg.brush = function() {
-    var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0];
-    function brush(g) {
-      g.each(function() {
-        var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
-        var background = g.selectAll(".background").data([ 0 ]);
-        background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
-        g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move");
-        var resize = g.selectAll(".resize").data(resizes, d3_identity);
-        resize.exit().remove();
-        resize.enter().append("g").attr("class", function(d) {
-          return "resize " + d;
-        }).style("cursor", function(d) {
-          return d3_svg_brushCursor[d];
-        }).append("rect").attr("x", function(d) {
-          return /[ew]$/.test(d) ? -3 : null;
-        }).attr("y", function(d) {
-          return /^[ns]/.test(d) ? -3 : null;
-        }).attr("width", 6).attr("height", 6).style("visibility", "hidden");
-        resize.style("display", brush.empty() ? "none" : null);
-        var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range;
-        if (x) {
-          range = d3_scaleRange(x);
-          backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]);
-          redrawX(gUpdate);
-        }
-        if (y) {
-          range = d3_scaleRange(y);
-          backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]);
-          redrawY(gUpdate);
-        }
-        redraw(gUpdate);
-      });
-    }
-    brush.event = function(g) {
-      g.each(function() {
-        var event_ = event.of(this, arguments), extent1 = {
-          x: xExtent,
-          y: yExtent,
-          i: xExtentDomain,
-          j: yExtentDomain
-        }, extent0 = this.__chart__ || extent1;
-        this.__chart__ = extent1;
-        if (d3_transitionInheritId) {
-          d3.select(this).transition().each("start.brush", function() {
-            xExtentDomain = extent0.i;
-            yExtentDomain = extent0.j;
-            xExtent = extent0.x;
-            yExtent = extent0.y;
-            event_({
-              type: "brushstart"
-            });
-          }).tween("brush:brush", function() {
-            var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y);
-            xExtentDomain = yExtentDomain = null;
-            return function(t) {
-              xExtent = extent1.x = xi(t);
-              yExtent = extent1.y = yi(t);
-              event_({
-                type: "brush",
-                mode: "resize"
-              });
-            };
-          }).each("end.brush", function() {
-            xExtentDomain = extent1.i;
-            yExtentDomain = extent1.j;
-            event_({
-              type: "brush",
-              mode: "resize"
-            });
-            event_({
-              type: "brushend"
-            });
-          });
-        } else {
-          event_({
-            type: "brushstart"
-          });
-          event_({
-            type: "brush",
-            mode: "resize"
-          });
-          event_({
-            type: "brushend"
-          });
-        }
-      });
-    };
-    function redraw(g) {
-      g.selectAll(".resize").attr("transform", function(d) {
-        return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")";
-      });
-    }
-    function redrawX(g) {
-      g.select(".extent").attr("x", xExtent[0]);
-      g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]);
-    }
-    function redrawY(g) {
-      g.select(".extent").attr("y", yExtent[0]);
-      g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]);
-    }
-    function brushstart() {
-      var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset;
-      var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup);
-      if (d3.event.changedTouches) {
-        w.on("touchmove.brush", brushmove).on("touchend.brush", brushend);
-      } else {
-        w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend);
-      }
-      g.interrupt().selectAll("*").interrupt();
-      if (dragging) {
-        origin[0] = xExtent[0] - origin[0];
-        origin[1] = yExtent[0] - origin[1];
-      } else if (resizing) {
-        var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
-        offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ];
-        origin[0] = xExtent[ex];
-        origin[1] = yExtent[ey];
-      } else if (d3.event.altKey) center = origin.slice();
-      g.style("pointer-events", "none").selectAll(".resize").style("display", null);
-      d3.select("body").style("cursor", eventTarget.style("cursor"));
-      event_({
-        type: "brushstart"
-      });
-      brushmove();
-      function keydown() {
-        if (d3.event.keyCode == 32) {
-          if (!dragging) {
-            center = null;
-            origin[0] -= xExtent[1];
-            origin[1] -= yExtent[1];
-            dragging = 2;
-          }
-          d3_eventPreventDefault();
-        }
-      }
-      function keyup() {
-        if (d3.event.keyCode == 32 && dragging == 2) {
-          origin[0] += xExtent[1];
-          origin[1] += yExtent[1];
-          dragging = 0;
-          d3_eventPreventDefault();
-        }
-      }
-      function brushmove() {
-        var point = d3.mouse(target), moved = false;
-        if (offset) {
-          point[0] += offset[0];
-          point[1] += offset[1];
-        }
-        if (!dragging) {
-          if (d3.event.altKey) {
-            if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ];
-            origin[0] = xExtent[+(point[0] < center[0])];
-            origin[1] = yExtent[+(point[1] < center[1])];
-          } else center = null;
-        }
-        if (resizingX && move1(point, x, 0)) {
-          redrawX(g);
-          moved = true;
-        }
-        if (resizingY && move1(point, y, 1)) {
-          redrawY(g);
-          moved = true;
-        }
-        if (moved) {
-          redraw(g);
-          event_({
-            type: "brush",
-            mode: dragging ? "move" : "resize"
-          });
-        }
-      }
-      function move1(point, scale, i) {
-        var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max;
-        if (dragging) {
-          r0 -= position;
-          r1 -= size + position;
-        }
-        min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i];
-        if (dragging) {
-          max = (min += position) + size;
-        } else {
-          if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));
-          if (position < min) {
-            max = min;
-            min = position;
-          } else {
-            max = position;
-          }
-        }
-        if (extent[0] != min || extent[1] != max) {
-          if (i) yExtentDomain = null; else xExtentDomain = null;
-          extent[0] = min;
-          extent[1] = max;
-          return true;
-        }
-      }
-      function brushend() {
-        brushmove();
-        g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null);
-        d3.select("body").style("cursor", null);
-        w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null);
-        dragRestore();
-        event_({
-          type: "brushend"
-        });
-      }
-    }
-    brush.x = function(z) {
-      if (!arguments.length) return x;
-      x = z;
-      resizes = d3_svg_brushResizes[!x << 1 | !y];
-      return brush;
-    };
-    brush.y = function(z) {
-      if (!arguments.length) return y;
-      y = z;
-      resizes = d3_svg_brushResizes[!x << 1 | !y];
-      return brush;
-    };
-    brush.clamp = function(z) {
-      if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null;
-      if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z;
-      return brush;
-    };
-    brush.extent = function(z) {
-      var x0, x1, y0, y1, t;
-      if (!arguments.length) {
-        if (x) {
-          if (xExtentDomain) {
-            x0 = xExtentDomain[0], x1 = xExtentDomain[1];
-          } else {
-            x0 = xExtent[0], x1 = xExtent[1];
-            if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
-            if (x1 < x0) t = x0, x0 = x1, x1 = t;
-          }
-        }
-        if (y) {
-          if (yExtentDomain) {
-            y0 = yExtentDomain[0], y1 = yExtentDomain[1];
-          } else {
-            y0 = yExtent[0], y1 = yExtent[1];
-            if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
-            if (y1 < y0) t = y0, y0 = y1, y1 = t;
-          }
-        }
-        return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];
-      }
-      if (x) {
-        x0 = z[0], x1 = z[1];
-        if (y) x0 = x0[0], x1 = x1[0];
-        xExtentDomain = [ x0, x1 ];
-        if (x.invert) x0 = x(x0), x1 = x(x1);
-        if (x1 < x0) t = x0, x0 = x1, x1 = t;
-        if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ];
-      }
-      if (y) {
-        y0 = z[0], y1 = z[1];
-        if (x) y0 = y0[1], y1 = y1[1];
-        yExtentDomain = [ y0, y1 ];
-        if (y.invert) y0 = y(y0), y1 = y(y1);
-        if (y1 < y0) t = y0, y0 = y1, y1 = t;
-        if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ];
-      }
-      return brush;
-    };
-    brush.clear = function() {
-      if (!brush.empty()) {
-        xExtent = [ 0, 0 ], yExtent = [ 0, 0 ];
-        xExtentDomain = yExtentDomain = null;
-      }
-      return brush;
-    };
-    brush.empty = function() {
-      return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1];
-    };
-    return d3.rebind(brush, event, "on");
-  };
-  var d3_svg_brushCursor = {
-    n: "ns-resize",
-    e: "ew-resize",
-    s: "ns-resize",
-    w: "ew-resize",
-    nw: "nwse-resize",
-    ne: "nesw-resize",
-    se: "nwse-resize",
-    sw: "nesw-resize"
-  };
-  var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ];
-  var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat;
-  var d3_time_formatUtc = d3_time_format.utc;
-  var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ");
-  d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso;
-  function d3_time_formatIsoNative(date) {
-    return date.toISOString();
-  }
-  d3_time_formatIsoNative.parse = function(string) {
-    var date = new Date(string);
-    return isNaN(date) ? null : date;
-  };
-  d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
-  d3_time.second = d3_time_interval(function(date) {
-    return new d3_date(Math.floor(date / 1e3) * 1e3);
-  }, function(date, offset) {
-    date.setTime(date.getTime() + Math.floor(offset) * 1e3);
-  }, function(date) {
-    return date.getSeconds();
-  });
-  d3_time.seconds = d3_time.second.range;
-  d3_time.seconds.utc = d3_time.second.utc.range;
-  d3_time.minute = d3_time_interval(function(date) {
-    return new d3_date(Math.floor(date / 6e4) * 6e4);
-  }, function(date, offset) {
-    date.setTime(date.getTime() + Math.floor(offset) * 6e4);
-  }, function(date) {
-    return date.getMinutes();
-  });
-  d3_time.minutes = d3_time.minute.range;
-  d3_time.minutes.utc = d3_time.minute.utc.range;
-  d3_time.hour = d3_time_interval(function(date) {
-    var timezone = date.getTimezoneOffset() / 60;
-    return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);
-  }, function(date, offset) {
-    date.setTime(date.getTime() + Math.floor(offset) * 36e5);
-  }, function(date) {
-    return date.getHours();
-  });
-  d3_time.hours = d3_time.hour.range;
-  d3_time.hours.utc = d3_time.hour.utc.range;
-  d3_time.month = d3_time_interval(function(date) {
-    date = d3_time.day(date);
-    date.setDate(1);
-    return date;
-  }, function(date, offset) {
-    date.setMonth(date.getMonth() + offset);
-  }, function(date) {
-    return date.getMonth();
-  });
-  d3_time.months = d3_time.month.range;
-  d3_time.months.utc = d3_time.month.utc.range;
-  function d3_time_scale(linear, methods, format) {
-    function scale(x) {
-      return linear(x);
-    }
-    scale.invert = function(x) {
-      return d3_time_scaleDate(linear.invert(x));
-    };
-    scale.domain = function(x) {
-      if (!arguments.length) return linear.domain().map(d3_time_scaleDate);
-      linear.domain(x);
-      return scale;
-    };
-    function tickMethod(extent, count) {
-      var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target);
-      return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) {
-        return d / 31536e6;
-      }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i];
-    }
-    scale.nice = function(interval, skip) {
-      var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval);
-      if (method) interval = method[0], skip = method[1];
-      function skipped(date) {
-        return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length;
-      }
-      return scale.domain(d3_scale_nice(domain, skip > 1 ? {
-        floor: function(date) {
-          while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1);
-          return date;
-        },
-        ceil: function(date) {
-          while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1);
-          return date;
-        }
-      } : interval));
-    };
-    scale.ticks = function(interval, skip) {
-      var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ {
-        range: interval
-      }, skip ];
-      if (method) interval = method[0], skip = method[1];
-      return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip);
-    };
-    scale.tickFormat = function() {
-      return format;
-    };
-    scale.copy = function() {
-      return d3_time_scale(linear.copy(), methods, format);
-    };
-    return d3_scale_linearRebind(scale, linear);
-  }
-  function d3_time_scaleDate(t) {
-    return new Date(t);
-  }
-  var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];
-  var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ];
-  var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) {
-    return d.getMilliseconds();
-  } ], [ ":%S", function(d) {
-    return d.getSeconds();
-  } ], [ "%I:%M", function(d) {
-    return d.getMinutes();
-  } ], [ "%I %p", function(d) {
-    return d.getHours();
-  } ], [ "%a %d", function(d) {
-    return d.getDay() && d.getDate() != 1;
-  } ], [ "%b %d", function(d) {
-    return d.getDate() != 1;
-  } ], [ "%B", function(d) {
-    return d.getMonth();
-  } ], [ "%Y", d3_true ] ]);
-  var d3_time_scaleMilliseconds = {
-    range: function(start, stop, step) {
-      return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate);
-    },
-    floor: d3_identity,
-    ceil: d3_identity
-  };
-  d3_time_scaleLocalMethods.year = d3_time.year;
-  d3_time.scale = function() {
-    return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);
-  };
-  var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) {
-    return [ m[0].utc, m[1] ];
-  });
-  var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) {
-    return d.getUTCMilliseconds();
-  } ], [ ":%S", function(d) {
-    return d.getUTCSeconds();
-  } ], [ "%I:%M", function(d) {
-    return d.getUTCMinutes();
-  } ], [ "%I %p", function(d) {
-    return d.getUTCHours();
-  } ], [ "%a %d", function(d) {
-    return d.getUTCDay() && d.getUTCDate() != 1;
-  } ], [ "%b %d", function(d) {
-    return d.getUTCDate() != 1;
-  } ], [ "%B", function(d) {
-    return d.getUTCMonth();
-  } ], [ "%Y", d3_true ] ]);
-  d3_time_scaleUtcMethods.year = d3_time.year.utc;
-  d3_time.scale.utc = function() {
-    return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat);
-  };
-  d3.text = d3_xhrType(function(request) {
-    return request.responseText;
-  });
-  d3.json = function(url, callback) {
-    return d3_xhr(url, "application/json", d3_json, callback);
-  };
-  function d3_json(request) {
-    return JSON.parse(request.responseText);
-  }
-  d3.html = function(url, callback) {
-    return d3_xhr(url, "text/html", d3_html, callback);
-  };
-  function d3_html(request) {
-    var range = d3_document.createRange();
-    range.selectNode(d3_document.body);
-    return range.createContextualFragment(request.responseText);
-  }
-  d3.xml = d3_xhrType(function(request) {
-    return request.responseXML;
-  });
-  if (typeof define === "function" && define.amd) this.d3 = d3, define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; else this.d3 = d3;
-}();
\ No newline at end of file
diff --git a/templates/html_report/js/functions.js b/templates/html_report/js/functions.js
deleted file mode 100644
index 74d290e6..00000000
--- a/templates/html_report/js/functions.js
+++ /dev/null
@@ -1,40 +0,0 @@
-function loadJSON(filename, callback) {
-
-    var xobj = new XMLHttpRequest();
-    xobj.overrideMimeType("application/json");
-    xobj.open('GET', filename, true);
-    xobj.onreadystatechange = function () {
-        if (xobj.readyState == 4 && xobj.status == "200") {
-            // Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
-            callback(xobj.responseText);
-        }
-    };
-    xobj.send(null);
-}
-
-
-function equalsHeightOf(node1, node2) {
-    var w1 = node1.style.height;
-    node2.style.height = w1 + 'px';
-}
-
-function saveSvgAsImage(svg, name, width, height) {
-    width = width || 600;
-    height = height || 600;
-    var img = new Image(),
-      serializer = new XMLSerializer(),
-      svgStr = serializer.serializeToString(svg);
-
-    img.src = 'data:image/svg+xml;base64,' + window.btoa(svgStr);
-    var canvas = document.createElement("canvas");
-    document.body.appendChild(canvas);
-    canvas.width = width;
-    canvas.height = height;
-    img.onload = function () {
-        canvas.getContext("2d").drawImage(img,0,0, width, height);
-        canvas.toBlob(function (blob) {
-            saveAs(blob, name + ".png");
-        });
-    };
-    canvas.parentNode.removeChild(canvas);
-}
diff --git a/templates/html_report/js/graph-licenses.js b/templates/html_report/js/graph-licenses.js
deleted file mode 100644
index f9066ca5..00000000
--- a/templates/html_report/js/graph-licenses.js
+++ /dev/null
@@ -1,52 +0,0 @@
-function chartLicenses(json) {
-
-    var diameter = document.getElementById('svg-licenses').offsetWidth;
-
-    var svg = d3.select('#svg-licenses').append('svg'),
-        width = 300,//document.getElementById('svg-licenses').offsetWidth,
-        height = 300,//document.getElementById('svg-licenses').offsetWidth,
-        radius = Math.min(width, height) / 2;
-
-    //var r = 300; // outer radius
-
-    var color = d3.scale.ordinal()
-        .range(["#BBDEFB", "#90CAF9", "#64B5F6", "#42A5F5", "#2196F3", "#1E88E5", "#1976D2", "#1565C0", "#0D47A1"]);
-
-    svg
-        .attr("width", width)
-        .attr("height", height);
-
-    var group = svg.append("g")
-        .attr("transform", "translate(" + Math.ceil(width / 2) + ", " + Math.ceil(height / 2) + ")"); // set center of pie
-
-    var arc = d3.svg.arc()
-        .innerRadius(radius - 10)
-        .outerRadius(0);
-
-    var pie = d3.layout.pie()
-        .value(function (d) {
-            return d.value;
-        });
-
-    var arcs = group.selectAll(".arc")
-        .data(pie(json))
-        .enter()
-        .append("g")
-        .attr("class", "arc");
-
-    arcs.append("path")
-        .attr("d", arc) // here the arc function works on every record d of data
-        .attr("fill", function (d) {
-            return color(d.data.value);
-        });
-
-    arcs.append("text")
-        .attr("transform", function (d) {
-            return "translate(" + arc.centroid(d) + ")";
-        })
-        .attr("text-anchor", "middle")
-        .attr('color', '#FFF')
-        .text(function (d) {
-            return d.data.name;
-        });
-}
\ No newline at end of file
diff --git a/templates/html_report/js/graph-maintainability.js b/templates/html_report/js/graph-maintainability.js
deleted file mode 100644
index 223a9fba..00000000
--- a/templates/html_report/js/graph-maintainability.js
+++ /dev/null
@@ -1,124 +0,0 @@
-function chartMaintainability(withoutComment) {
-    var chartId = 'svg-maintainability';
-    withoutComment = typeof (withoutComment) !== 'undefined' ? withoutComment : false;
-    var diameter = document.getElementById(chartId).offsetWidth;
-
-    var json = {
-        name: 'chart',
-        children: classes
-    };
-
-    // if already loaded, removed previous node
-    var previous = d3.select('#' + chartId).select('svg');
-    if (previous) {
-        previous.remove();
-    }
-    previous = d3.select('#' + chartId).select('button');
-    if (previous) {
-        previous.remove();
-    }
-
-    var svg = d3.select('#' + chartId).append('svg')
-        .attr('width', diameter)
-        .attr('height', diameter);
-
-    var bubble = d3.layout.pack()
-        .size([diameter, diameter])
-        .padding(3)
-        .value(function (d) {
-            return d.ccn;
-        });
-
-    var nodes = bubble.nodes(json)
-        .filter(function (d) {
-            return !d.children;
-        }); // filter out the outer bubble*
-
-    var vis = svg.selectAll('circle')
-        .data(nodes, function (d) {
-            return d.name;
-        });
-
-    vis.enter().append('circle')
-        .attr('transform', function (d) {
-            return 'translate(' + d.x + ',' + d.y + ')';
-        })
-        .attr('r', function (d) {
-            return d.r;
-        })
-        .style("fill", function (d) {
-            if (true === withoutComment) {
-                if (d.mIwoC > 65) {
-                    return '#8BC34A';
-                } else if (d.mIwoC > 53) {
-                    return '#FFC107';
-                } else {
-                    return '#F44336';
-                }
-            } else {
-                if (d.mi > 85) {
-                    return '#8BC34A';
-                } else if (d.mi > 69) {
-                    return '#FFC107';
-                } else {
-                    return '#F44336';
-                }
-            }
-        })
-        .on('mouseover', function (d) {
-            var text = '';
-            if (true === withoutComment) {
-                text = '<strong>' + d.name + '</strong>'
-                    + "<br>Cyclomatic Complexity : " + d.ccn
-                    + "<br>Maintainability Index (w/o comments): " + d.mIwoC;
-            } else {
-                text = '<strong>' + d.name + '</strong>'
-                    + "<br>Cyclomatic Complexity : " + d.ccn
-                    + "<br>Maintainability Index: " + d.mi;
-            }
-            d3.select('.tooltip').html(text);
-            d3.select(".tooltip")
-                .style("opacity", 1)
-                .style("z-index", 1);
-        })
-        .on('mousemove', function () {
-            d3.select(".tooltip")
-                .style("left", (d3.event.pageX + 5) + "px")
-                .style("top", (d3.event.pageY + 5) + "px");
-        })
-        .on('mouseout', function () {
-            d3.select(".tooltip")
-                .style("opacity", 0)
-                .style("z-index", -1);
-        });
-
-    d3.select("body")
-        .append("div")
-        .attr("class", "tooltip")
-        .style("opacity", 0);
-
-    // button for saving image
-    var button = d3.select('#' + chartId).append('button');
-    button
-        .classed('btn-save-image', true)
-        .text('download')
-        .on('click', function () {
-            var svg = d3.select('#' + chartId + ' svg')[0][0];
-            var nameImage = (withoutComment)
-                ? 'PhpMetrics maintainability without comments / complexity'
-                : 'PhpMetrics maintainability / complexity';
-            saveSvgAsImage(svg, nameImage, 1900, 1900);
-        });
-}
-
-function toggleChartMaintainability(item) {
-    if (item.getAttribute('data-current') === 'with-comments') {
-        item.setAttribute('data-current', 'without-comments');
-        item.innerHTML = '(without comments)';
-    } else {
-        item.setAttribute('data-current', 'with-comments');
-        item.innerHTML = '(with comments)';
-    }
-
-    chartMaintainability(item.getAttribute('data-current') !== 'with-comments')
-}
diff --git a/templates/html_report/js/sort-table.min.js b/templates/html_report/js/sort-table.min.js
deleted file mode 100644
index ab6a8838..00000000
--- a/templates/html_report/js/sort-table.min.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* Copyright (c) 2006-2013 Tyler Uebele * Released under the MIT license. * latest at https://github.com/tyleruebele/sort-table * minified by Google Closure Compiler */
-function sortTable(a,b,d){var c;sortTable.sortCol=-1;c=a.className.match(/js-sort-\d+/);null!=c&&(sortTable.sortCol=c[0].replace(/js-sort-/,""),a.className=a.className.replace(RegExp(" ?"+c[0]+"\\b"),""));"undefined"===typeof b&&(b=sortTable.sortCol);"undefined"!==typeof d?sortTable.sortDir=-1==d||"desc"==d?-1:1:(c=a.className.match(/js-sort-(a|de)sc/),sortTable.sortDir=null!=c&&sortTable.sortCol==b?"js-sort-asc"==c[0]?-1:1:1);a.className=a.className.replace(/ ?js-sort-(a|de)sc/g,"");a.className+=
-" js-sort-"+b;sortTable.sortCol=b;a.className+=" js-sort-"+(-1==sortTable.sortDir?"desc":"asc");b<a.tHead.rows[a.tHead.rows.length-1].cells.length&&(c=a.tHead.rows[a.tHead.rows.length-1].cells[b].className.match(/js-sort-[-\w]+/));for(d=0;d<a.tHead.rows[a.tHead.rows.length-1].cells.length;d++)b==a.tHead.rows[a.tHead.rows.length-1].cells[d].getAttribute("data-js-sort-colNum")&&(c=a.tHead.rows[a.tHead.rows.length-1].cells[d].className.match(/js-sort-[-\w]+/));sortTable.sortFunc=null!=c?c[0].replace(/js-sort-/,
-""):"string";b=[];a=a.tBodies[0];for(d=0;d<a.rows.length;d++)b[d]=a.rows[d];for(b.sort(sortTable.compareRow);a.firstChild;)a.removeChild(a.firstChild);for(d=0;d<b.length;d++)a.appendChild(b[d])}sortTable.compareRow=function(a,b){var d,c;"function"!=typeof sortTable[sortTable.sortFunc]&&(sortTable.sortFunc="string");d=sortTable[sortTable.sortFunc](a.cells[sortTable.sortCol]);c=sortTable[sortTable.sortFunc](b.cells[sortTable.sortCol]);return d==c?0:sortTable.sortDir*(d>c?1:-1)};
-sortTable.stripTags=function(a){return a.replace(/<\/?[a-z][a-z0-9]*\b[^>]*>/gi,"")};sortTable.date=function(a){return new Date(sortTable.stripTags(a.innerHTML))};sortTable.number=function(a){return Number(sortTable.stripTags(a.innerHTML).replace(/[^-\d.]/g,""))};sortTable.string=function(a){return sortTable.stripTags(a.innerHTML).toLowerCase()};sortTable.last=function(a){return sortTable.stripTags(a.innerHTML).split(" ").pop().toLowerCase()};
-sortTable.input=function(a){for(var b=0;b<a.children.length;b++)if("object"==typeof a.children[b]&&"undefined"!=typeof a.children[b].value)return a.children[b].value.toLowerCase();return sortTable.string(a)};sortTable.getClickHandler=function(a,b){return function(){sortTable(a,b)}};
-sortTable.init=function(){var a,b,d;b=document.querySelectorAll?document.querySelectorAll("table.js-sort-table"):document.getElementsByTagName("table");for(var c=0;c<b.length;c++)if((document.querySelectorAll||null!==b[c].className.match(/\bjs-sort-table\b/))&&!b[c].attributes["data-js-sort-table"]){b[c].tHead?a=b[c].tHead:(a=document.createElement("thead"),a.appendChild(b[c].rows[0]),b[c].insertBefore(a,b[c].children[0]));for(var e=0;e<a.rows.length;e++)for(var f=0,g=0;f<a.rows[e].cells.length;f++)a.rows[e].cells[f].setAttribute("data-js-sort-colNum",
-g),d=sortTable.getClickHandler(b[c],g),window.addEventListener?a.rows[e].cells[f].addEventListener("click",d):window.attachEvent&&a.rows[e].cells[f].attachEvent("onclick",d),g+=a.rows[e].cells[f].colSpan;b[c].setAttribute("data-js-sort-table","true")}};window.addEventListener?window.addEventListener("load",sortTable.init,!1):window.attachEvent&&window.attachEvent("onload",sortTable.init);
diff --git a/templates/html_report/junit.php b/templates/html_report/junit.php
deleted file mode 100644
index 1b517db6..00000000
--- a/templates/html_report/junit.php
+++ /dev/null
@@ -1,302 +0,0 @@
-<?php
-require __DIR__ . '/_header.php'; ?>
-
-<?php
-if (!isset($project['unitTesting'])) {
-    echo '<div class="row"><div class="column">Please use the <code>--junit</code> option to enable this report</div></div>';
-    return;
-}
-
-$unit = $project['unitTesting'];
-$getMetricForClass = function ($classname, $metric) use ($classes) {
-    foreach ($classes as $class) {
-        if ($classname !== $class['name']) {
-            continue;
-        }
-
-        return $class[$metric];
-    }
-
-    return '-';
-};
-?>
-
-
-<div class="row">
-    <div class="column">
-        <div class="bloc bloc-number">
-            <div class="label">Test suites</div>
-            <div class="number">
-                <?php echo $unit['nbSuites']; ?>
-            </div>
-        </div>
-    </div>
-    <div class="column">
-        <div class="bloc bloc-number">
-            <div class="label">Assertions</div>
-            <div class="number">
-                <?php echo $unit['assertions']; ?>
-            </div>
-        </div>
-    </div>
-    <div class="column">
-        <div class="bloc bloc-number">
-            <div class="label">
-                classes never called by tests
-                <small>(<?php echo $unit['percentUncoveredClasses']; ?> %)</small>
-            </div>
-            <div class="number">
-                <?php echo $unit['nbUncoveredClasses']; ?>
-            </div>
-        </div>
-    </div>
-</div>
-
-<div class="row">
-    <div class="column">
-        <div class="bloc">
-            <h4>These classes are never called by tests</h4>
-            <div class="help">
-                <div class="help-inner">
-                    Tests with high Cyclomatic number or high probability of bugs should be covered by unit tests.
-                </div>
-            </div>
-            <div class="clusterize small">
-                <div id="scrollAreaJunitNeverCalled" class="clusterize-scroll">
-                    <table>
-                        <thead>
-                        <tr>
-                            <th>Class</th>
-                            <th class="js-sort-number">Cyclomatic</th>
-                            <th class="js-sort-number">Bugs</th>
-                        </tr>
-                        </thead>
-                        <tbody id="contentAreaJunitNeverCalled" class="clusterize-content">
-                        <?php
-                        foreach ($classes as $class) {
-                            if ($class['numberOfUnitTests'] > 0 || $class['interface']) {
-                                continue;
-                            }
-                            ?>
-                            <tr>
-                                <td><span class="path"><?php echo $class['name']; ?></span></td>
-                                <?php foreach (['ccn', 'bugs'] as $attribute) {?>
-                                    <td>
-                                        <span class="badge" <?php echo gradientStyleFor($classes, $attribute, $class[$attribute]);?>>
-                                        <?php echo isset($class[$attribute]) ? $class[$attribute] : ''; ?>
-                                        </span>
-                                    </td>
-                                <?php } ?>
-                            </tr>
-                            <?php
-                        }
-                        ?>
-                        </tbody>
-                    </table>
-                </div>
-            </div>
-        </div>
-    </div>
-</div>
-
-<div class="row">
-    <div class="column">
-        <div class="bloc">
-            <h4>Execution time of tests</h4>
-
-            <div id="svg-unit-time"></div>
-        </div>
-    </div>
-</div>
-
-<div class="row">
-
-    <div class="column">
-        <div class="bloc">
-            <h4>These classes are called by tests</h4>
-
-            <div class="clusterize small">
-                <div id="scrollAreaJunitCalled" class="clusterize-scroll">
-                    <table>
-                        <thead>
-                        <tr>
-                            <th>TestSuite</th>
-                            <th class="js-sort-number">Called by these classes</th>
-                        </tr>
-                        </thead>
-                        <tbody id="contentAreaJunitCalled" class="clusterize-content">
-                        <?php foreach ($unit['tests'] as $suite) { ?>
-                            <tr>
-                                <td valign="top"><span class="path"><?php echo $suite->classname; ?></span></td>
-                                <td style="padding-bottom: 1em;">
-                                    <?php
-                                    foreach ($suite->externals as $index => $external) { ?>
-                                        <?php echo ($index === 0) ? '' : '<br>'; ?>
-                                        <span class="badge" title="Cyclomatic complexity of class">
-                                            <?php echo $getMetricForClass($external, 'ccn'); ?>
-                                        </span>
-                                        <span class="path"><?php echo $external; ?></span>
-                                    <?php } ?>
-                                </td>
-                            </tr>
-                        <?php } ?>
-                    </table>
-                </div>
-            </div>
-        </div>
-    </div>
-</div>
-    <?php require __DIR__ . '/_footer.php'; ?>
-
-    <script>
-        var clusterize = new Clusterize({
-            scrollId: 'scrollAreaJunitNeverCalled',
-            contentId: 'contentAreaJunitNeverCalled'
-        });
-
-        var clusterize = new Clusterize({
-            scrollId: 'scrollAreaJunitCalled',
-            contentId: 'contentAreaJunitCalled'
-        });
-    </script>
-
-
-    <script>
-
-        function chartTreeUnit() {
-            // from http://bl.ocks.org/masakick/04ad1502068302abbbcb
-            var w = document.getElementById('svg-unit-time').offsetWidth,
-                h = 400,
-                x = d3.scale.linear().range([0, w]),
-                y = d3.scale.linear().range([0, h]),
-                color = d3.scale.category20c(),
-                root,
-                node;
-
-            var treemap = d3.layout.treemap()
-                .round(false)
-                .size([w, h])
-                .sticky(true)
-                //    .value(function(d) { return d["好き度"]; });
-                .value(function (d) {
-                    return d.time;
-                });
-
-            var svg = d3.select('#svg-unit-time').append('div')
-                .attr("class", "chart")
-                .style("width", w + "px")
-                .style("height", h + "px")
-                .append("svg:svg")
-                .attr("width", w)
-                .attr("height", h)
-                .append("svg:g")
-                .attr("transform", "translate(.5,.5)");
-
-
-            <?php
-            // prepare json
-            $unitTimeJson = new stdClass;
-            $unitTimeJson->name = 'Execution time';
-            $unitTimeJson->children = [];
-            foreach ($unit['tests'] as $test) {
-                array_push($unitTimeJson->children, [
-                    'name' => $test->classname,
-                    'time' => (float)$test->time,
-                ]);
-            }
-            ?>
-
-            var json = <?php echo json_encode($unitTimeJson);?>;
-            root = json;
-            var nodes = treemap.nodes(json)
-                .filter(function (d) {
-                    return d.time;
-                    //return d.children;
-                });
-
-            var cell = svg.selectAll("g")
-                    .data(nodes)
-                    .enter().append("svg:g")
-                    .attr("class", "cell")
-                    .attr("transform", function (d) {
-                        return "translate(" + d.x + "," + d.y + ")";
-                    })
-                    .on("click", function (d) {
-                        return zoom(node == root ? d : root);
-                        return zoom(node == d.parent ? root : d.parent);
-                    })
-                ;
-
-            cell.append("svg:rect")
-                .attr("width", function (d) {
-                    return d.dx - 1;
-                })
-                .attr("height", function (d) {
-                    return d.dy - 1;
-                })
-                .style("fill", function (d) {
-                    return '#AED581';
-                })
-            ;
-
-            cell.append("svg:text")
-                .attr("x", function (d) {
-                    return d.dx / 2;
-                })
-                .attr("y", function (d) {
-                    return d.dy / 2;
-                })
-                .attr("dy", ".35em")
-                .attr("text-anchor", "middle")
-                .text(function (d) {
-                    var long = d.name + "\n" + '(' + d.time + ' secs)';
-                    var short = d.name.substr(0, 20) + "...";
-                    return d.dx > d.w ? short : long;
-                })
-                .style("opacity", function (d) {
-                    d.w = this.getComputedTextLength();
-                    return d.dx > d.w ? 1 : 0.2;
-                })
-                .attr('fill', function (d) {
-                    return '#333'
-                });
-
-            //d3.select(window).on("click", function () {
-            //    zoom(root);
-            //});
-            function zoom(d) {
-                var kx = w / d.dx, ky = h / d.dy;
-                x.domain([d.x, d.x + d.dx]);
-                y.domain([d.y, d.y + d.dy]);
-
-                var t = svg.selectAll("g.cell").transition()
-                    .duration(d3.event.altKey ? 7500 : 750)
-                    .attr("transform", function (d) {
-                        return "translate(" + x(d.x) + "," + y(d.y) + ")";
-                    });
-
-                t.select("rect")
-                    .attr("width", function (d) {
-                        return kx * d.dx - 1;
-                    })
-                    .attr("height", function (d) {
-                        return ky * d.dy - 1;
-                    });
-
-                t.select("text")
-                    .attr("x", function (d) {
-                        return kx * d.dx / 2;
-                    })
-                    .attr("y", function (d) {
-                        return ky * d.dy / 2;
-                    })
-                    .style("opacity", function (d) {
-                        return kx * d.dx > d.w ? 1 : 0;
-                    });
-
-                node = d;
-                d3.event.stopPropagation();
-            }
-        }
-        chartTreeUnit();
-    </script>
diff --git a/templates/html_report/loc.php b/templates/html_report/loc.php
deleted file mode 100644
index e860bae3..00000000
--- a/templates/html_report/loc.php
+++ /dev/null
@@ -1,153 +0,0 @@
-<?php require __DIR__ . '/_header.php'; ?>
-
-
-<?php
-
-// 1. build an associative array
-$array = [];
-foreach ($classes as $class) {
-    if (isset($class['lloc'])) {
-        array_push($array, $class['lloc']);
-    }
-}
-
-// 2. percentile map
-$json = [];
-if(count($array) > 1) {
-    $range = range(0.5, 1, .05);
-    foreach ($range as $percentile) {
-        $json[] = (object)[
-            'lloc' => percentile($array, $percentile),
-            'percentile' => round($percentile * 100),
-        ];
-    }
-}
-
-?>
-
-
-<div class="row">
-    <div class="column">
-        <div class="bloc">
-            <h4>Percentile distribution of logical lines of code by class</h4>
-            <div id="lloc-repartition" style="height: 200px"></div>
-            <div class="help" style="text-align: center">Percentile</div>
-        </div>
-    </div>
-</div>
-
-<div class="row">
-    <div class="column">
-        <div class="bloc">
-            <h4>Explore</h4>
-            <table class="js-sort-table" id="table-length">
-                <thead>
-                <tr>
-                    <th>Class</th>
-                    <th class="js-sort-number">LLOC</th>
-                    <th class="js-sort-number">CLOC</th>
-                    <th class="js-sort-number">Volume</th>
-                    <th class="js-sort-number">Intelligent content</th>
-                    <th class="js-sort-number">Comment Weight</th>
-                </tr>
-                </thead>
-                <?php
-                foreach ($classes as $class) { ?>
-                    <tr>
-                        <td><span class="path"><?php echo $class['name']; ?></span></td>
-                        <?php foreach (['lloc', 'cloc', 'volume', 'intelligentContent', 'commentWeight'] as $attribute) {?>
-                            <td>
-                                <span class="badge" <?php echo gradientStyleFor($classes, $attribute, $class[$attribute]);?>>
-                                <?php echo isset($class[$attribute]) ? $class[$attribute] : ''; ?>
-                                </span>
-                            </td>
-                        <?php } ?>
-                    </tr>
-                <?php } ?>
-            </table>
-        </div>
-    </div>
-</div>
-
-
-<?php require __DIR__ . '/_footer.php'; ?>
-
-
-<script>
-
-    // table
-    sortTable(document.getElementById('table-length'), 1, -1);
-
-
-    var margin = {top: 20, right: 20, bottom: 30, left: 40},
-        width = document.getElementById('lloc-repartition').offsetWidth - margin.left - margin.right,
-        height = document.getElementById('lloc-repartition').offsetHeight - margin.top - margin.bottom;
-
-    var x = d3.scale.ordinal()
-        .rangeRoundBands([0, width], .1);
-
-    var y = d3.scale.linear()
-        .range([height, 0]);
-
-    var xAxis = d3.svg.axis()
-        .scale(x)
-        .orient("bottom");
-
-    var yAxis = d3.svg.axis()
-            .scale(y)
-            .orient("left")
-        ;
-
-    var svg = d3.select("#lloc-repartition").append("svg")
-        .attr("width", width + margin.left + margin.right)
-        .attr("height", height + margin.top + margin.bottom)
-        .append("g")
-        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
-    data = <?php echo json_encode($json, JSON_PRETTY_PRINT); ?>;
-
-    x.domain(data.map(function (d) {
-        return d.percentile;
-    }));
-    y.domain([0, d3.max(data, function (d) {
-        return d.lloc;
-    })]);
-
-    svg.append("g")
-        .attr("class", "x axis")
-        .attr("transform", "translate(0," + height + ")")
-        .call(xAxis)
-        .append("text")
-        .style("text-anchor", "end")
-
-    svg.append("g")
-        .attr("class", "y axis")
-        .call(yAxis)
-        .append("text")
-        .attr("transform", "rotate(-90)")
-        .attr("y", 6)
-        .attr("dy", ".71em")
-        .style("text-anchor", "end")
-        .text("Logical lines of code");
-
-    svg.selectAll(".bar")
-        .data(data)
-        .enter().append("rect")
-        .attr("class", "bar")
-        .attr("x", function (d) {
-            return x(d.percentile);
-        })
-        .attr("width", x.rangeBand())
-        .attr("y", function (d) {
-            return y(d.lloc);
-        })
-        .attr("height", function (d) {
-            return height - y(d.lloc);
-        });
-
-    function type(d) {
-        d.lloc = +d.lloc;
-        return d;
-    }
-
-</script>
diff --git a/templates/html_report/oop.php b/templates/html_report/oop.php
deleted file mode 100644
index 5371e0e7..00000000
--- a/templates/html_report/oop.php
+++ /dev/null
@@ -1,93 +0,0 @@
-<?php
-require __DIR__ . '/_header.php'; ?>
-
-<?php
-
-$lcom = [];
-foreach ($classes as $c) {
-    if (!$c['interface']) {
-        array_push($lcom, $c['lcom']);
-    }
-}
-if (count($lcom) > 0) {
-    $lcom = round(array_sum($lcom) / count($lcom), 2);
-} else {
-    $lcom = 0;
-}
-?>
-
-
-    <div class="row">
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">classes <?php echo $this->getTrend('sum', 'nbClasses'); ?></div>
-                <div class="number">
-                    <?php echo $sum->nbClasses; ?>
-                    <small> (<?php echo (count($classes) ? round($sum->nbClasses / count($classes) * 100) : '0'); ?> %)</small>
-                </div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">interfaces <?php echo $this->getTrend('sum', 'nbInterfaces'); ?></div>
-                <div class="number"><?php echo $sum->nbInterfaces; ?>
-                    <small> (<?php echo (count($classes) ? round($sum->nbInterfaces / count($classes) * 100) : '0'); ?> %)</small>
-                </div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">average LCOM <?php echo $this->getTrend('avg', 'lcom', true); ?></div>
-                <div class="number"><?php echo $lcom ?></div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">logical lines of code by class</div>
-                <div class="number"><?php echo $sum->nbClasses ? round($sum->lloc / $sum->nbClasses) : '-'; ?></div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">logical lines of code by method</div>
-                <div class="number"><?php echo $sum->nbMethods ? round($sum->lloc / $sum->nbMethods) : '-'; ?></div>
-            </div>
-        </div>
-    </div>
-
-
-    <div class="row">
-        <div class="column">
-            <div class="bloc">
-                <table class="js-sort-table" id="table-length">
-                    <thead>
-                    <tr>
-                        <th>Class</th>
-                        <th class="js-sort-number">LCOM</th>
-                        <th class="js-sort-number">Volume</th>
-                        <th class="js-sort-number">Class cycl.</th>
-                        <th class="js-sort-number">Max method cycl.</th>
-                        <th class="js-sort-number">Bugs</th>
-                        <th class="js-sort-number">Difficulty</th>
-                    </tr>
-                    </thead>
-                    <?php
-                    foreach ($classes as $class) { ?>
-                        <tr>
-                            <td><span class="path"><?php echo $class['name']; ?></span></td>
-                            <?php foreach (['lcom', 'volume', 'ccn', 'ccnMethodMax', 'bugs', 'difficulty'] as $attribute) {?>
-                                <td>
-                                    <span class="badge" <?php echo gradientStyleFor($classes, $attribute, $class[$attribute]);?>>
-                                    <?php echo isset($class[$attribute]) ? $class[$attribute] : ''; ?>
-                                    </span>
-                                </td>
-                            <?php } ?>
-                        </tr>
-                    <?php } ?>
-                </table>
-            </div>
-        </div>
-    </div>
-
-
-<?php require __DIR__ . '/_footer.php'; ?>
diff --git a/templates/html_report/package_relations.php b/templates/html_report/package_relations.php
deleted file mode 100644
index ae6ed2b4..00000000
--- a/templates/html_report/package_relations.php
+++ /dev/null
@@ -1,222 +0,0 @@
-<?php require __DIR__ . '/_header.php'; ?>
-
-<?php
-$relations = [];
-$getPackageName = function ($name) {
-    return $name === '\\' ? 'global' : substr($name, 0, -1);
-};
-foreach ($packages as $package) {
-    $packageName = $getPackageName($package['name']);
-    $outgoingDependencies = array_map(
-        $getPackageName,
-        isset($package['outgoing_package_dependencies']) ? $package['outgoing_package_dependencies'] : []
-    );
-    $relations[$packageName] = [
-        'name' => $packageName,
-        'size' => 3000,
-        'relations' => $outgoingDependencies,
-    ];
-    // Adding vendor packages
-    foreach ($outgoingDependencies as $each) {
-        if (isset($relations[$each])) {
-            continue;
-        }
-        $relations[$each] = [
-            'name' => $each,
-            'size' => 3000,
-            'relations' => []
-        ];
-    }
-}
-$relations = array_values($relations);
-?>
-
-
-<div class="row">
-    <div class="column">
-        <div class="bloc">
-            <h4>Package relations</h4>
-            <div id="chart-relations"></div>
-        </div>
-    </div>
-</div>
-
-<?php require __DIR__ . '/_footer.php'; ?>
-
-
-<script>
-
-
-    var relations = <?php echo json_encode($relations, JSON_PRETTY_PRINT); ?>;
-
-    /**
-     * Thanks to http://bl.ocks.org/mbostock/raw/7607999/
-     */
-    function updateRelationsChart() {
-
-
-        var diameter = document.getElementById('chart-relations').offsetWidth,
-            radius = diameter / 2,
-            innerRadius = radius - 320;
-
-        var cluster = d3.layout.cluster()
-            .size([360, innerRadius])
-            .sort(null)
-            .value(function (d) {
-                return d.size;
-            });
-
-        var bundle = d3.layout.bundle();
-
-        var line = d3.svg.line.radial()
-            .interpolate("bundle")
-            .tension(.85)
-            .radius(function (d) {
-                return d.y;
-            })
-            .angle(function (d) {
-                return d.x / 180 * Math.PI;
-            });
-
-        var svg = d3.select("#chart-relations").append("svg")
-            .attr("width", diameter)
-            .attr("height", diameter)
-            .append("g")
-            .attr("transform", "translate(" + radius + "," + radius + ")");
-
-        var link = svg.append("g").selectAll(".link"),
-            node = svg.append("g").selectAll(".node");
-
-
-        var nodes = cluster.nodes(packageHierarchy(relations)),
-            links = packageImports(nodes);
-        link = link
-            .data(bundle(links))
-            .enter().append("path")
-            .each(function (d) {
-                d.source = d[0], d.target = d[d.length - 1];
-            })
-            .attr("class", "link")
-            .attr("d", line);
-
-        node = node
-            .data(nodes.filter(function (n) {
-                return !n.children;
-            }))
-            .enter().append("text")
-            .attr("class", "node")
-            .attr("dy", ".31em")
-            .attr("transform", function (d) {
-                return "rotate(" + (d.x - 90) + ")translate(" + (d.y + 8) + ",0)" + (d.x < 180 ? "" : "rotate(180)");
-            })
-            .style("text-anchor", function (d) {
-                return d.x < 180 ? "start" : "end";
-            })
-            .text(function (d) {
-                return d.key;
-            })
-            .on("mouseover", mouseovered)
-            .on("mouseout", mouseouted);
-
-
-//        d3.data(relations);
-
-        function mouseovered(d) {
-            node
-                .each(function (n) {
-                    n.target = n.source = false;
-                });
-
-            link
-                .classed("link--target", function (l) {
-                    if (l.target === d) return l.source.source = true;
-                })
-                .classed("link--source", function (l) {
-                    if (l.source === d) return l.target.target = true;
-                })
-                .filter(function (l) {
-                    return l.target === d || l.source === d;
-                })
-                .each(function () {
-                    this.parentNode.appendChild(this);
-                });
-
-            node
-                .classed("node--target", function (n) {
-                    return n.target;
-                })
-                .classed("node--source", function (n) {
-                    return n.source;
-                });
-        }
-
-        function mouseouted(d) {
-            link
-                .classed("link--target", false)
-                .classed("link--source", false);
-
-            node
-                .classed("node--target", false)
-                .classed("node--source", false);
-        }
-
-        d3.select(self.frameElement).style("height", diameter + "px");
-
-        // Lazily construct the package hierarchy from class names.
-        function packageHierarchy(classes) {
-            var map = {};
-
-            function find(name, data) {
-                name = (data ? name + ' ' : name);
-                var node = map[name];
-                if (!node) {
-                    node = map[name] = data || {name: name, children: []};
-                    if (name.length) {
-                        node.parent = find("");
-                        if (!node.parent.children) {
-                            node.parent.children = []; // fix anomalies
-                        }
-                        node.parent.children.push(node);
-                        node.key = name.trim();
-                    }
-                }
-                return node;
-            }
-
-            classes.forEach(function (d) {
-                find(d.name, d);
-            });
-
-            return map[""];
-        }
-
-        // Return a list of imports for the given array of nodes.
-        function packageImports(nodes) {
-            var map = {},
-                imports = [];
-
-            // Compute a map from name to node.
-            nodes.forEach(function (d) {
-                map[d.name] = d;
-            });
-
-            // For each import, construct a link from the source to target node.
-            nodes.forEach(function (d) {
-                if (d.relations) d.relations.forEach(function (i) {
-                    imports.push({source: map[d.name], target: map[i]});
-                });
-            });
-
-            return imports;
-        }
-
-
-    }
-
-    document.onreadystatechange = function () {
-        if (document.readyState === 'complete') {
-            updateRelationsChart();
-        }
-    };
-
-</script>
diff --git a/templates/html_report/packages.php b/templates/html_report/packages.php
deleted file mode 100644
index 308bda65..00000000
--- a/templates/html_report/packages.php
+++ /dev/null
@@ -1,160 +0,0 @@
-<?php
-require __DIR__ . '/_header.php'; ?>
-
-    <div class="row">
-        <div class="column">
-            <div class="bloc">
-                <h4>Packages</h4>
-
-                <div id="distances" class="scattered-plot"></div>
-
-                <table class="js-sort-table" id="table-length">
-                    <thead>
-                    <tr>
-                        <th>Name</th>
-                        <th class="js-sort-number">Classes</th>
-                        <th class="js-sort-number">Abstraction</th>
-                        <th class="js-sort-number">Instability</th>
-                        <th class="js-sort-number">Distance</th>
-                        <th class="js-sort-number">Outgoing class dep.</th>
-                        <th class="js-sort-number">Outgoing package dep.</th>
-                        <th class="js-sort-number">Incoming class dep.</th>
-                        <th class="js-sort-number">Incoming package dep.</th>
-                    </tr>
-                    </thead>
-                    <?php
-                    foreach ($packages as $package) { ?>
-                        <tr>
-                            <td><span class="path"><?= $package['name'] === '\\' ? 'global' : substr($package['name'], 0, -1); ?></span></td>
-                            <td><?= $package['classes'] ? count($package['classes']) : 0; ?></td>
-                            <td><?= isset($package['abstraction']) ? round($package['abstraction'], 3) : ''; ?></td>
-                            <td><?= isset($package['instability']) ? round($package['instability'], 3) : ''; ?></td>
-                            <td><?= isset($package['normalized_distance']) ? round($package['normalized_distance'], 3) : ''; ?></td>
-                            <td><?= isset($package['outgoing_class_dependencies']) ? count($package['outgoing_class_dependencies']) : 0; ?></td>
-                            <td><?= isset($package['outgoing_package_dependencies']) ? count($package['outgoing_package_dependencies']) : 0; ?></td>
-                            <td><?= isset($package['incoming_class_dependencies']) ? count($package['incoming_class_dependencies']) : 0; ?></td>
-                            <td><?= isset($package['incoming_package_dependencies']) ? count($package['incoming_package_dependencies']) : 0; ?></td>
-                        </tr>
-                    <?php } ?>
-                </table>
-            </div>
-        </div>
-    </div>
-<?php require __DIR__ . '/_footer.php'; ?>
-<?php
-$spots = [];
-foreach ($packages as $each) {
-    if (isset($each['abstraction'], $each['instability'])) {
-        $spots[] = [
-            'name' => $each['name'] === '\\' ? 'global' : substr($each['name'], 0, -1),
-            'abstraction' => $each['abstraction'],
-            'instability' => $each['instability'],
-            'distance' => $each['distance'],
-            'normalizedDistance' => abs($each['normalized_distance']),
-            'classCount' => isset($each['classes']) ? count($each['classes']) : 0
-        ];
-    }
-}
-?>
-<script>
-    /**
-     * Thx to http://bl.ocks.org/weiglemc/6185069
-     */
-    var margin = {top: 20, right: 20, bottom: 20, left: 20},
-        width = 500 - margin.left - margin.right,
-        height = 500 - margin.top - margin.bottom;
-
-    var spots = <?php echo json_encode($spots, JSON_PRETTY_PRINT); ?>;
-
-    /*
-     * value accessor - returns the value to encode for a given data object.
-     * scale - maps value to a visual display encoding, such as a pixel position.
-     * map function - maps from data value to display value
-     * axis - sets up axis
-     */
-
-    // setup x
-    var xValue = function(d) { return d.abstraction;}, // data -> value
-        xScale = d3.scale.linear().range([0, width]), // value -> display
-        xMap = function(d) { return xScale(xValue(d));}, // data -> display
-        xAxis = d3.svg.axis().scale(xScale).orient("bottom");
-
-    // setup y
-    var yValue = function(d) { return d.instability;}, // data -> value
-        yScale = d3.scale.linear().range([height, 0]), // value -> display
-        yMap = function(d) { return yScale(yValue(d));}, // data -> display
-        yAxis = d3.svg.axis().scale(yScale).orient("left");
-
-    // setup fill color
-    var cValue = function(d) { return d.normalizedDistance;},
-        color = d3.scale.linear().domain([0,1])
-            .interpolate(d3.interpolateHcl)
-            .range([d3.rgb("#00FF00"), d3.rgb('#FF0000')])
-
-    // add the graph canvas to #distances
-    var svg = d3.select("#distances").append("svg")
-        .attr("width", width + margin.left + margin.right)
-        .attr("height", height + margin.top + margin.bottom)
-        .append("g")
-        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
-    // add the tooltip area to the webpage
-    var tooltip = d3.select("#distances").append("div")
-        .attr("class", "tooltip")
-        .style("opacity", 0);
-
-    // x-axis
-    svg
-        .append("g")
-            .attr("class", "x axis")
-            .attr("transform", "translate(0," + height + ")")
-            .call(xAxis)
-        .append("text")
-            .attr("class", "label")
-            .attr("x", width)
-            .attr("y", -6)
-            .style("text-anchor", "end")
-            .text("Abstraction");
-
-    // y-axis
-    svg
-        .append("g")
-            .attr("class", "y axis")
-            .call(yAxis)
-        .append("text")
-            .attr("class", "label")
-            .attr("transform", "rotate(-90)")
-            .attr("y", 6)
-            .attr("dy", ".71em")
-            .style("text-anchor", "end")
-            .text("Instability");
-
-    // optimal distance line
-    svg.append("path")
-        .attr("class", "line")
-        .attr("d", (d3.svg.line().x(function (d) { return xScale(d); }).y(function (d) { return yScale(1-d); }))([0, 1]));
-
-    // draw dots
-    svg.selectAll(".dot")
-        .data(spots)
-        .enter().append("circle")
-        .attr("class", "dot")
-        .attr("r", function(d) { return 3.0 + 0.5 * d.classCount; })
-        .attr("cx", xMap)
-        .attr("cy", yMap)
-        .style("fill", function(d) { return color(cValue(d));})
-        .on("mouseover", function(d) {
-            tooltip.transition()
-                .duration(200)
-                .style("opacity", .9);
-            tooltip.html(d.name + "<br> (" + (Math.round(1000 * xValue(d)) / 1000)
-                + ", " + (Math.round(1000 * yValue(d)) / 1000) + ")")
-                .style("left", (d3.event.pageX + 5) + "px")
-                .style("top", (d3.event.pageY - 28) + "px");
-        })
-        .on("mouseout", function(d) {
-            tooltip.transition()
-                .duration(500)
-                .style("opacity", 0);
-        });
-</script>
diff --git a/templates/html_report/panel.php b/templates/html_report/panel.php
deleted file mode 100644
index 391db305..00000000
--- a/templates/html_report/panel.php
+++ /dev/null
@@ -1,137 +0,0 @@
-<?php
-$fullwidth = true;
-require __DIR__ . '/_header.php'; ?>
-
-    <div class="row">
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="number"><?php echo $sum->loc; ?></div>
-                <div class="label">lines of code <?php echo $this->getTrend('sum', 'loc'); ?></div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="number">
-                    <?php echo $sum->nbClasses; ?>
-                    <small> (<?php echo(count($classes) ? round($sum->nbClasses / count($classes) * 100) : '0'); ?>
-                        %)
-                    </small>
-                </div>
-                <div class="label">classes <?php echo $this->getTrend('sum', 'nbClasses'); ?></div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="number"><?php echo $sum->nbInterfaces; ?>
-                    <small> (<?php echo(count($classes) ? round($sum->nbInterfaces / count($classes) * 100) : '0'); ?>
-                        %)
-                    </small>
-                </div>
-                <div class="label">interfaces <?php echo $this->getTrend('sum', 'nbInterfaces'); ?></div>
-            </div>
-        </div>
-
-
-    </div>
-
-    <div class="row">
-
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div
-                    class="number"><?php echo $sum->nbClasses ? round($sum->nbMethods / $sum->nbClasses) : '-'; ?></div>
-                <div class="label">methods by class</div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="number"><?php echo $sum->nbClasses ? round($sum->lloc / $sum->nbClasses) : '-'; ?></div>
-                <div class="label">logical lines of code by class</div>
-            </div>
-        </div>
-
-
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="number"><?php echo $sum->nbMethods ? round($sum->lloc / $sum->nbMethods) : '-'; ?></div>
-                <div class="label">logical lines of code by method</div>
-            </div>
-        </div>
-
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div
-                    class="number"><?php echo $avg->lcom ?></div>
-                <div class="label">average LCOM <?php echo $this->getTrend('avg', 'lcom', true); ?></div>
-            </div>
-        </div>
-    </div>
-
-    <div class="row">
-        <div class="column column-50">
-            <div class="bloc bloc-number">
-                <div class="label">Top 10 ClassRank</div>
-                <table id="table-pagerank">
-                    <thead>
-                    <tr>
-                        <th>Class</th>
-                        <th>ClassRank</th>
-                    </tr>
-                    </thead>
-                    <tbody>
-                    <?php
-                    $classesS = $classes;
-                    usort($classesS, static function ($a, $b) {
-                        return strcmp($b['pageRank'], $a['pageRank']);
-                    });
-                    $classesS = array_slice($classesS, 0, 10);
-                    foreach ($classesS as $class) { ?>
-                        <tr>
-                            <td><?php echo $class['name']; ?>
-                                <?php
-                                $badgeTitleMIWOC = 'Maintainability Index (w/o comments)';
-                                $mIwoC = isset($class['mIwoC']) ? $class['mIwoC'] : '';
-                                $badgeTitleMI = 'Maintainability Index';
-                                $mi = isset($class['mi']) ? $class['mi'] : '';
-                                ?>
-                                <span class="badge" title="<?php echo $badgeTitleMI;?>"><?php echo $mi;?></span>
-                                <span class="badge" title="<?php echo $badgeTitleMIWOC;?>"><?php echo $mIwoC;?></span>
-                            </td>
-                            <td><?php echo $class['pageRank']; ?></td>
-                        </tr>
-                    <?php } ?>
-                    </tbody>
-                </table>
-
-            </div>
-
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="number">
-                    <?php echo $avg->ccn; ?>
-                </div>
-                <div class="label">Average cyclomatic complexity by class <?php echo $this->getTrend('avg', 'ccn',
-                        true); ?></div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc">
-                <div>
-                    <h4>Maintainability / complexity</h4>
-                    <div id="svg-maintainability"></div>
-                </div>
-            </div>
-        </div>
-    </div>
-
-    <script>
-        document.onreadystatechange = function () {
-            if (document.readyState === 'complete') {
-                chartMaintainability();
-            }
-        };
-    </script>
-
-<?php
-require __DIR__ . '/_footer.php'; ?>
diff --git a/templates/html_report/relations.php b/templates/html_report/relations.php
deleted file mode 100644
index 4d4260a4..00000000
--- a/templates/html_report/relations.php
+++ /dev/null
@@ -1,221 +0,0 @@
-<?php require __DIR__ . '/_header.php'; ?>
-
-<?php
-$relations = [];
-$classesCp = [];
-foreach ($classes as $class) {
-
-    $class['name'] = '\\' . $class['name'];
-    $classesCp[$class['name']] = $class;
-    $classesCp[$class['name']]['externals'] = [];
-
-
-    foreach ($class['externals'] as &$ext) {
-        $ext = '\\' . $ext;
-        if (!isset($classes[$ext])) {
-            $classesCp[$ext] = [
-                'name' => $ext,
-                'externals' => [],
-            ];
-        }
-        $classesCp[$class['name']]['externals'][] = $ext;
-    }
-}
-foreach ($classesCp as $class) {
-    array_push($relations, (object)[
-        'name' => $class['name'],
-        'size' => 3000,
-        'relations' => (array)array_values(array_unique($class['externals'])),
-    ]);
-}
-?>
-
-
-<div class="row">
-    <div class="column">
-        <div class="bloc">
-            <h4>Object relations</h4>
-            <div id="chart-relations"></div>
-        </div>
-    </div>
-</div>
-
-<?php require __DIR__ . '/_footer.php'; ?>
-
-
-<script>
-
-
-    var relations = <?php echo json_encode($relations, JSON_PRETTY_PRINT); ?>;
-
-    /**
-     * Thanks to http://bl.ocks.org/mbostock/raw/7607999/
-     */
-    function updateRelationsChart() {
-
-
-        var diameter = document.getElementById('chart-relations').offsetWidth,
-            radius = diameter / 2,
-            innerRadius = radius - 120;
-
-        var cluster = d3.layout.cluster()
-            .size([360, innerRadius])
-            .sort(null)
-            .value(function (d) {
-                return d.size;
-            });
-
-        var bundle = d3.layout.bundle();
-
-        var line = d3.svg.line.radial()
-            .interpolate("bundle")
-            .tension(.85)
-            .radius(function (d) {
-                return d.y;
-            })
-            .angle(function (d) {
-                return d.x / 180 * Math.PI;
-            });
-
-        var svg = d3.select("#chart-relations").append("svg")
-            .attr("width", diameter)
-            .attr("height", diameter)
-            .append("g")
-            .attr("transform", "translate(" + radius + "," + radius + ")");
-
-        var link = svg.append("g").selectAll(".link"),
-            node = svg.append("g").selectAll(".node");
-
-
-        var nodes = cluster.nodes(packageHierarchy(relations)),
-            links = packageImports(nodes);
-        link = link
-            .data(bundle(links))
-            .enter().append("path")
-            .each(function (d) {
-                d.source = d[0], d.target = d[d.length - 1];
-            })
-            .attr("class", "link")
-            .attr("d", line);
-
-        node = node
-            .data(nodes.filter(function (n) {
-                return !n.children;
-            }))
-            .enter().append("text")
-            .attr("class", "node")
-            .attr("dy", ".31em")
-            .attr("transform", function (d) {
-                return "rotate(" + (d.x - 90) + ")translate(" + (d.y + 8) + ",0)" + (d.x < 180 ? "" : "rotate(180)");
-            })
-            .style("text-anchor", function (d) {
-                return d.x < 180 ? "start" : "end";
-            })
-            .text(function (d) {
-                return d.key;
-            })
-            .on("mouseover", mouseovered)
-            .on("mouseout", mouseouted);
-
-
-//        d3.data(relations);
-
-        function mouseovered(d) {
-            node
-                .each(function (n) {
-                    n.target = n.source = false;
-                });
-
-            link
-                .classed("link--target", function (l) {
-                    if (l.target === d) return l.source.source = true;
-                })
-                .classed("link--source", function (l) {
-                    if (l.source === d) return l.target.target = true;
-                })
-                .filter(function (l) {
-                    return l.target === d || l.source === d;
-                })
-                .each(function () {
-                    this.parentNode.appendChild(this);
-                });
-
-            node
-                .classed("node--target", function (n) {
-                    return n.target;
-                })
-                .classed("node--source", function (n) {
-                    return n.source;
-                });
-        }
-
-        function mouseouted(d) {
-            link
-                .classed("link--target", false)
-                .classed("link--source", false);
-
-            node
-                .classed("node--target", false)
-                .classed("node--source", false);
-        }
-
-        d3.select(self.frameElement).style("height", diameter + "px");
-
-        // Lazily construct the package hierarchy from class names.
-        function packageHierarchy(classes) {
-            var map = {};
-
-            function find(name, data) {
-                name = (data ? name + ' ' : name);
-                var node = map[name], i;
-                if (!node) {
-                    node = map[name] = data || {name: name, children: []};
-                    if (name.length) {
-                        node.parent = find(name.substring(0, i = name.lastIndexOf("\\")));
-                        if (!node.parent.children) {
-                            node.parent.children = []; // fix anomalies
-                        }
-                        node.parent.children.push(node);
-                        node.key = name;//name.substring(i + 1);
-                    }
-                }
-                return node;
-            }
-
-            classes.forEach(function (d) {
-                find(d.name, d);
-            });
-
-            return map[""];
-        }
-
-        // Return a list of imports for the given array of nodes.
-        function packageImports(nodes) {
-            var map = {},
-                imports = [];
-
-            // Compute a map from name to node.
-            nodes.forEach(function (d) {
-                map[d.name] = d;
-            });
-
-            // For each import, construct a link from the source to target node.
-            nodes.forEach(function (d) {
-                if (d.relations) d.relations.forEach(function (i) {
-                    imports.push({source: map[d.name], target: map[i]});
-                });
-            });
-
-            return imports;
-        }
-
-
-    }
-
-    document.onreadystatechange = function () {
-        if (document.readyState === 'complete') {
-            updateRelationsChart();
-        }
-    };
-
-</script>
diff --git a/templates/html_report/violations.php b/templates/html_report/violations.php
deleted file mode 100644
index 44cc2db8..00000000
--- a/templates/html_report/violations.php
+++ /dev/null
@@ -1,165 +0,0 @@
-<?php require __DIR__ . '/_header.php'; ?>
-
-<?php
-$map = [
-    \Hal\Violation\Violation::INFO => 'information',
-    \Hal\Violation\Violation::WARNING => 'warning',
-    \Hal\Violation\Violation::ERROR => 'error',
-    \Hal\Violation\Violation::CRITICAL => 'critical',
-];
-?>
-
-    <div class="row">
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">Violations</div>
-                <div class="number"><?php echo $sum->violations->total; ?></div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">Information</div>
-                <div class="number"><?php echo $sum->violations->information; ?></div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">Warnings</div>
-                <div class="number"><?php echo $sum->violations->warning; ?></div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">Errors</div>
-                <div class="number"><?php echo $sum->violations->error; ?></div>
-            </div>
-        </div>
-        <div class="column">
-            <div class="bloc bloc-number">
-                <div class="label">Criticals</div>
-                <div class="number"><?php echo $sum->violations->critical; ?></div>
-            </div>
-        </div>
-    </div>
-
-<?php if ($sum->violations->total > 0) { ?>
-    <div class="row">
-        <div class="column">
-            <div class="bloc">
-                <h4>Class Violations</h4>
-                <table class="table-pagerank table-small">
-                    <thead>
-                    <tr>
-                        <th>Class</th>
-                        <th>Violations</th>
-                    </tr>
-                    </thead>
-                    <tbody>
-                    <?php foreach ($classes as $class) {
-                        if (count($class['violations']) > 0) {
-                            $currentId = 'bloc-' . uniqid('', true);
-                            ?>
-
-                            <tr>
-                                <td>
-                                    <a onclick="return toggle('<?php echo $currentId; ?>');">
-                                        <span class="path"><?php echo $class['name']; ?></span>
-                                    </a>
-                                    <div class="violation-list" id="<?php echo $currentId; ?>">
-                                        <?php foreach ($class['violations'] as $violation) { ?>
-                                            <div class="violation">
-                                                <div class="name">
-                                                    <?php echo $violation->getName(); ?>
-                                                    <span
-                                                        class="badge level level-<?php echo $map[$violation->getLevel()]; ?>"><?php echo $map[$violation->getLevel()]; ?></span>
-
-                                                </div>
-                                                <div
-                                                    class="description"><?php echo nl2br($violation->getDescription()); ?></div>
-
-                                            </div>
-                                        <?php } ?>
-                                    </div>
-                                </td>
-
-                                <td valign="top">
-                                    <?php foreach ($class['violations'] as $violation) { ?>
-                                        <span
-                                            class="badge level level-<?php echo $map[$violation->getLevel()]; ?>"> <?php echo $violation->getName(); ?></span>
-                                    <?php } ?>
-                                </td>
-                            </tr>
-                        <?php }
-                    } ?>
-                    </tbody>
-                </table>
-            </div>
-        </div>
-    </div>
-    <div class="row">
-        <div class="column">
-            <div class="bloc">
-                <h4>Package Violations</h4>
-                <table class="table-pagerank table-small">
-                    <thead>
-                    <tr>
-                        <th>Package</th>
-                        <th>Violations</th>
-                    </tr>
-                    </thead>
-                    <tbody>
-                    <?php foreach ($packages as $package) {
-                        if (count($package['violations']) > 0) {
-                            $currentId = 'bloc-' . uniqid();
-                            ?>
-
-                            <tr>
-                                <td>
-                                    <a onclick="return toggle('<?php echo $currentId; ?>');">
-                                        <span class="path"><?php echo substr($package['name'], 0, -1); ?></span>
-                                    </a>
-                                    <div class="violation-list" id="<?php echo $currentId; ?>">
-                                        <?php foreach ($package['violations'] as $violation) { ?>
-                                            <div class="violation">
-                                                <div class="name">
-                                                    <?php echo $violation->getName(); ?>
-                                                    <span
-                                                            class="badge level level-<?php echo $map[$violation->getLevel()]; ?>"><?php echo $map[$violation->getLevel()]; ?></span>
-
-                                                </div>
-                                                <div
-                                                        class="description"><?php echo nl2br($violation->getDescription()); ?></div>
-
-                                            </div>
-                                        <?php } ?>
-                                    </div>
-                                </td>
-
-                                <td valign="top">
-                                    <?php foreach ($package['violations'] as $violation) { ?>
-                                        <span
-                                                class="badge level level-<?php echo $map[$violation->getLevel()]; ?>"> <?php echo $violation->getName(); ?></span>
-                                    <?php } ?>
-                                </td>
-                            </tr>
-                        <?php }
-                    } ?>
-                    </tbody>
-                </table>
-            </div>
-        </div>
-    </div>
-<?php } ?>
-
-    <script>
-        function toggle(id) {
-            var div = document.getElementById(id);
-            if (div.style.display === 'block') {
-                div.style.display = 'none';
-            }
-            else {
-                div.style.display = 'block';
-            }
-        }
-    </script>
-<?php require __DIR__ . '/_footer.php'; ?>
diff --git a/tests/Application/Config/File/ConfigFileReaderTest.php b/tests/Application/Config/File/ConfigFileReaderTest.php
deleted file mode 100644
index e843d766..00000000
--- a/tests/Application/Config/File/ConfigFileReaderTest.php
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-
-namespace Test\Hal\Application\Config\File;
-
-use Hal\Application\Config\Config;
-use Hal\Application\Config\File\ConfigFileReaderFactory;
-use Hal\Search\Searches;
-
-/**
- * @group config
- */
-class ConfigFileReaderTest extends \PHPUnit\Framework\TestCase
-{
-    public function testICanParseBasicJsonFIle(): void
-    {
-        $filename = __DIR__ . '/examples/config.json';
-
-        $config = new Config();
-
-        $reader = ConfigFileReaderFactory::createFromFileName($filename);
-        $reader->read($config);
-
-        $this->assertEquals($this->getExpectedData(), $config->all());
-    }
-
-    private function getExpectedData()
-    {
-        return [
-            'exclude' => 'tests',
-            'report-html' => __DIR__ . '/examples/tmp/report/',
-            'report-json' => '/tmp/report.json',
-            'report-csv' => '/tmp/report.csv',
-            'report-violations' => '/tmp/violations.xml',
-            'extensions' => 'php,php8',
-            'git' => 'git',
-            'junit' => '/tmp/junit.xml',
-            'files' => [
-                __DIR__ . '/examples/src/Hal/Component'
-            ],
-            'groups' => [
-                [
-                    "name" => "Controllers",
-                    "match" => "!component!i"
-                ],
-                [
-                    "name" => "Domain",
-                    "match" => "!app!i"
-                ],
-                [
-                    "name" => "Models",
-                    "match" => "!app!i"
-                ]
-            ],
-            'searches' => new Searches()
-        ];
-    }
-
-    public function testICanParseConfigWithSearch(): void
-    {
-        $filename = __DIR__ . '/examples/config-with-search.json';
-
-        $config = new Config();
-
-        $reader = ConfigFileReaderFactory::createFromFileName($filename);
-        $reader->read($config);
-
-        $this->assertInstanceOf(Searches::class, $config->get('searches'));
-        $searches = $config->get('searches');
-        $this->assertEquals('my-search1', $searches->get('my-search1')->getName());
-        $this->assertEquals('my-search2', $searches->get('my-search2')->getName());
-        $this->assertFalse($searches->has('my-searchNOT_FOUND'));
-    }
-}
diff --git a/tests/Application/Config/File/examples/config-with-search.json b/tests/Application/Config/File/examples/config-with-search.json
deleted file mode 100644
index 7e0c492e..00000000
--- a/tests/Application/Config/File/examples/config-with-search.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "searches": {
-        "my-search1": {
-            "type": "class"
-        },
-        "my-search2": {
-            "type": "interface"
-        }
-    }
-}
diff --git a/tests/Application/Config/File/examples/config.ini b/tests/Application/Config/File/examples/config.ini
deleted file mode 100644
index 69d6e423..00000000
--- a/tests/Application/Config/File/examples/config.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-exclude = test1
-report-html = test2
\ No newline at end of file
diff --git a/tests/Application/Config/File/examples/config.json b/tests/Application/Config/File/examples/config.json
deleted file mode 100644
index 2d6ea729..00000000
--- a/tests/Application/Config/File/examples/config.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
-  "includes": [
-      "src/Hal/Component"
-  ],
-  "excludes": [
-      "tests"
-  ],
-  "extensions": [
-      "php",
-      "php8"
-  ],
-  "report": {
-      "html": "tmp/report/",
-      "csv": "/tmp/report.csv",
-      "json": "/tmp/report.json",
-      "violations": "/tmp/violations.xml"
-  },
-  "groups": [
-      {
-          "name": "Controllers",
-          "match": "!component!i"
-      },
-      {
-          "name": "Domain",
-          "match": "!app!i"
-      },
-      {
-          "name": "Models",
-          "match": "!app!i"
-      }
-  ],
-  "plugins": {
-      "git": {
-          "binary": "git"
-      },
-      "junit": {
-          "report": "/tmp/junit.xml"
-      }
-  }
-}
diff --git a/tests/Application/Config/ParserTest.php b/tests/Application/Config/ParserTest.php
deleted file mode 100644
index aa4cfbcf..00000000
--- a/tests/Application/Config/ParserTest.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-namespace Test\Hal\Application\Config;
-
-use Hal\Application\Config\Parser;
-use PHPUnit\Framework\Attributes\DataProvider;
-
-/**
- * @group application
- * @group config
- */
-class ParserTest extends \PHPUnit\Framework\TestCase
-{
-    /**
-     * @dataProvider providesExample
-     */
-    #[DataProvider('providesExample')]
-    public function testICanParseArguments($argv, $expected): void
-    {
-        $parser = new Parser();
-        $config = $parser->parse($argv);
-        $this->assertEquals($expected, $config->all());
-    }
-
-    public static function providesExample()
-    {
-        return [
-            [
-                ['--report-html=./build'],
-                ['report-html' => './build']
-            ],
-            [
-                ['--report-html ./build'],
-                []
-            ],
-            [
-                ['--argument'],
-                ['argument' => true]
-            ],
-            [
-                ['--argument1', '--argument2=abc'],
-                ['argument1' => true, 'argument2' => 'abc']
-            ],
-            [
-                [],
-                []
-            ],
-            [
-                ['--argument', 'myFolder'],
-                ['argument' => true, 'files' => ['myFolder']]
-            ],
-            [
-                ['--exclude=""', 'myFolder'],
-                ['exclude' => "", 'files' => ['myFolder']]
-            ]
-        ];
-    }
-}
diff --git a/tests/Component/Ast/NodeTraverserTest.php b/tests/Component/Ast/NodeTraverserTest.php
deleted file mode 100644
index 601db156..00000000
--- a/tests/Component/Ast/NodeTraverserTest.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-namespace Test\Hal\Component\Ast;
-
-use Hal\Component\Ast\NodeTraverser;
-use PhpParser\NodeTraverser as BaseTraverser;
-use PHPUnit\Framework\TestCase;
-
-class NodeTraverserTest extends TestCase
-{
-    public function testItCanBeInstantiated(): void
-    {
-        $this->assertInstanceOf(BaseTraverser::class, new NodeTraverser());
-    }
-}
diff --git a/tests/Component/Ast/SupportedVersionTest.php b/tests/Component/Ast/SupportedVersionTest.php
deleted file mode 100644
index 3d9ea49b..00000000
--- a/tests/Component/Ast/SupportedVersionTest.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-
-namespace Test\Hal\Component\Ast;
-
-use Hal\Metric\ClassMetric;
-use PHPUnit\Framework\Attributes\DataProvider;
-use PHPUnit\Framework\Attributes\Group;
-use PHPUnit\Framework\TestCase;
-use Test\Hal\PhpUnit\WithAnalyzer;
-
-#[Group('ast')]
-class SupportedVersionTest extends TestCase
-{
-    use WithAnalyzer;
-
-    /**
-     * @dataProvider providesCases
-     */
-    #[DataProvider('providesCases')]
-    public function testClassForPhpVersionIsCorrectlyParsed($filename, $classname, array $expected): void
-    {
-        $metrics = $this->analyze([__DIR__ . '/dataset/' . $filename . '.php']);
-
-        /** @var ClassMetric $class */
-        $class = $metrics->get($classname);
-        $this->assertInstanceOf(ClassMetric::class, $class);
-        foreach ($expected as $key => $value) {
-            $this->assertEquals($value, $class->get($key), "[PHP $filename] Class $classname metric $key does not match expected value");
-        }
-    }
-
-    public static function providesCases()
-    {
-        // for php < 7.0, the class is not supported
-        if (version_compare(PHP_VERSION, '7.0.0', '<')) {
-            return [];
-        }
-
-        $cases = [];
-        if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
-            $cases['php7.1.void'] = ['php7.1.void', 'Foo', ['nbMethods' => 1, 'number_operands_unique' => 1]];
-        }
-        if (version_compare(PHP_VERSION, '7.2.0', '>=')) {
-            $cases['php7.2.trailcomma'] = ['php7.2.trailcomma', 'Foo', ['nbMethods' => 1, 'number_operands_unique' => 2]];
-        }
-        if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
-            $cases['php7.3.heredoc'] = ['php7.3.heredoc', 'Foo', ['nbMethods' => 1, 'number_operands_unique' => 2]];
-        }
-        if (version_compare(PHP_VERSION, '7.4.0', '>=')) {
-            $cases['php7.4.typedprop'] = ['php7.4.typedprop', 'Foo', ['nbMethods' => 1, 'number_operands_unique' => 1]];
-        }
-        if (version_compare(PHP_VERSION, '8.0.0', '>=')) {
-            $cases['php8.0.uniontype'] = ['php8.0.uniontype', 'Foo', ['nbMethods' => 1, 'number_operands_unique' => 1]];
-        }
-        if (version_compare(PHP_VERSION, '8.1.0', '>=')) {
-            $cases['php8.1.readonlyproperty'] = ['php8.1.readonlyproperty', 'Foo', ['nbMethods' => 0, 'number_operands_unique' => 2]];
-        }
-        if (version_compare(PHP_VERSION, '8.2.0', '>=')) {
-            $cases['php8.2.truetype'] = ['php8.2.truetype', 'Foo', ['nbMethods' => 1, 'number_operands_unique' => 1]];
-        }
-        if (version_compare(PHP_VERSION, '8.3.0', '>=')) {
-            $cases['php8.3.jsonconst'] = ['php8.3.jsonconst', 'Foo', ['nbMethods' => 1, 'number_operands_unique' => 1]];
-        }
-        if (version_compare(PHP_VERSION, '8.4.0', '>=')) {
-            $cases['php8.4.propertyhook'] = ['php8.4.propertyhook', 'Foo', ['nbMethods' => 0, 'number_operands_unique' => 2]];
-        }
-
-        return $cases;
-    }
-}
diff --git a/tests/Component/Ast/dataset/php7.0.coalesce.php b/tests/Component/Ast/dataset/php7.0.coalesce.php
deleted file mode 100644
index 3bf68d37..00000000
--- a/tests/Component/Ast/dataset/php7.0.coalesce.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php
-
-class Foo
-{
-    public function bar($a, $b = null)
-    {
-        return $a ?? $b ?? 3;
-    }
-}
diff --git a/tests/Component/Ast/dataset/php7.1.void.php b/tests/Component/Ast/dataset/php7.1.void.php
deleted file mode 100644
index e5e94afd..00000000
--- a/tests/Component/Ast/dataset/php7.1.void.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php
-
-class Foo
-{
-    public function bar($a): void
-    {
-        return;
-    }
-}
diff --git a/tests/Component/Ast/dataset/php7.2.trailcomma.php b/tests/Component/Ast/dataset/php7.2.trailcomma.php
deleted file mode 100644
index 7249316c..00000000
--- a/tests/Component/Ast/dataset/php7.2.trailcomma.php
+++ /dev/null
@@ -1,2 +0,0 @@
-<?php
-class Foo { public function bar($a, $b,) {} }
diff --git a/tests/Component/Ast/dataset/php7.3.heredoc.php b/tests/Component/Ast/dataset/php7.3.heredoc.php
deleted file mode 100644
index 5dec4602..00000000
--- a/tests/Component/Ast/dataset/php7.3.heredoc.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php
-
-class Foo
-{
-    public function bar()
-    {
-        $a = <<<TXT
-heredoc
-TXT;
-    }
-}
diff --git a/tests/Component/Ast/dataset/php7.4.typedprop.php b/tests/Component/Ast/dataset/php7.4.typedprop.php
deleted file mode 100644
index e85f1daa..00000000
--- a/tests/Component/Ast/dataset/php7.4.typedprop.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-
-class Foo
-{
-    public int $bar;
-
-    public function baz($bar)
-    {
-    }
-}
diff --git a/tests/Component/Ast/dataset/php8.0.uniontype.php b/tests/Component/Ast/dataset/php8.0.uniontype.php
deleted file mode 100644
index 870e0477..00000000
--- a/tests/Component/Ast/dataset/php8.0.uniontype.php
+++ /dev/null
@@ -1,2 +0,0 @@
-<?php
-class Foo { public function bar(int|string $a) {} }
diff --git a/tests/Component/Ast/dataset/php8.1.readonlyproperty.php b/tests/Component/Ast/dataset/php8.1.readonlyproperty.php
deleted file mode 100644
index 1a7979ef..00000000
--- a/tests/Component/Ast/dataset/php8.1.readonlyproperty.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php
-
-class Foo
-{
-    public readonly int $bar;
-
-    public function __construct(int $bar)
-    {
-        $this->bar = $bar;
-    }
-}
diff --git a/tests/Component/Ast/dataset/php8.2.truetype.php b/tests/Component/Ast/dataset/php8.2.truetype.php
deleted file mode 100644
index 24857d33..00000000
--- a/tests/Component/Ast/dataset/php8.2.truetype.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-class Foo
-{
-    function alwaysReturnsFalse($a): false {
-        return false;
-    }
-}
diff --git a/tests/Component/Ast/dataset/php8.3.jsonconst.php b/tests/Component/Ast/dataset/php8.3.jsonconst.php
deleted file mode 100644
index b852122d..00000000
--- a/tests/Component/Ast/dataset/php8.3.jsonconst.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-
-class Foo
-{
-    public const JSON = JSON_THROW_ON_ERROR;
-
-    public function bar($a)
-    {
-    }
-}
diff --git a/tests/Component/Ast/dataset/php8.4.propertyhook.php b/tests/Component/Ast/dataset/php8.4.propertyhook.php
deleted file mode 100644
index 72d2706c..00000000
--- a/tests/Component/Ast/dataset/php8.4.propertyhook.php
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php
-
-class Foo
-{
-    public string $languageCode;
-
-    public string $countryCode
-    {
-        set (string $countryCode) {
-            $this->countryCode = strtoupper($countryCode);
-        }
-    }
-}
diff --git a/tests/Component/File/FinderTest.php b/tests/Component/File/FinderTest.php
deleted file mode 100644
index ae971b0b..00000000
--- a/tests/Component/File/FinderTest.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-namespace Test\Hal\Component\File;
-
-use Hal\Component\File\Finder;
-use PHPUnit\Framework\TestCase;
-
-/**
- * @group file
- */
-class FinderTest extends TestCase
-{
-    public function testPathsGivenAreRecoveredOverExcluded(): void
-    {
-        $exampleRoot = __DIR__ . DIRECTORY_SEPARATOR . 'examples';
-
-        $extensions = ['php', 'inc', 'phtml'];
-        $excludedDirs = [
-            'excluded', //Simple string name
-            '.excluded', //Name containing a special regex character (".")
-        ];
-
-        $inputFiles = [$exampleRoot];
-
-        $finder = new Finder($extensions, $excludedDirs);
-        $files = $finder->fetch($inputFiles);
-
-        $expected = [
-            $exampleRoot . DIRECTORY_SEPARATOR . 'included' . DIRECTORY_SEPARATOR . 'includedFile.php',
-            $exampleRoot . DIRECTORY_SEPARATOR . 'includedFile.php.inc',
-        ];
-
-        //Sorting the expected and the actual array values to assert both array are same.
-        \sort($expected);
-        \sort($files);
-
-        static::assertSame($expected, $files);
-    }
-
-    public function testGivenPathsAreIgnoredRegardingExclusion(): void
-    {
-        $exampleRoot = __DIR__ . DIRECTORY_SEPARATOR . 'examples';
-        $actualFoundFiles = (new Finder(['php'], ['tests']))->fetch([$exampleRoot]);
-        $expectedFoundFiles = [
-            $exampleRoot . DIRECTORY_SEPARATOR . 'excluded' . DIRECTORY_SEPARATOR . 'excludedFile.php',
-            $exampleRoot . DIRECTORY_SEPARATOR . 'included' . DIRECTORY_SEPARATOR . 'includedFile.php',
-        ];
-        sort($actualFoundFiles);
-        sort($expectedFoundFiles);
-        $this->assertSame($expectedFoundFiles, $actualFoundFiles);
-    }
-}
diff --git a/tests/Component/File/examples/.excluded/.excludedFile.phtml.inc b/tests/Component/File/examples/.excluded/.excludedFile.phtml.inc
deleted file mode 100644
index e69de29b..00000000
diff --git a/tests/Component/File/examples/.excludedFile.phtml b/tests/Component/File/examples/.excludedFile.phtml
deleted file mode 100644
index e69de29b..00000000
diff --git a/tests/Component/File/examples/excluded/excludedFile.php b/tests/Component/File/examples/excluded/excludedFile.php
deleted file mode 100644
index e69de29b..00000000
diff --git a/tests/Component/File/examples/excludedFile.php.inc b/tests/Component/File/examples/excludedFile.php.inc
deleted file mode 100644
index e69de29b..00000000
diff --git a/tests/Component/File/examples/included/includedFile.php b/tests/Component/File/examples/included/includedFile.php
deleted file mode 100644
index e69de29b..00000000
diff --git a/tests/Component/File/examples/includedFile.php.inc b/tests/Component/File/examples/includedFile.php.inc
deleted file mode 100644
index e69de29b..00000000
diff --git a/tests/Component/Issuer/IssuerTest.php b/tests/Component/Issuer/IssuerTest.php
deleted file mode 100644
index bfd830fc..00000000
--- a/tests/Component/Issuer/IssuerTest.php
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-
-namespace Test\Hal\Component\Issue;
-
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Component\Issue\Issuer;
-use Hal\Component\Output\TestOutput;
-use PhpParser\ParserFactory;
-use PHPUnit\Framework\Attributes\RequiresPhp;
-use Polyfill\TestCaseCompatible;
-
-/**
- * @group issue
- */
-class IssuerTest extends \PHPUnit\Framework\TestCase
-{
-    use TestCaseCompatible;
-    /**
-     * @requires PHP < 7.0
-     */
-    #[RequiresPhp('< 7.0')]
-    public function testICanEnableIssuerPhp5(): void
-    {
-        $output = new TestOutput();
-        $issuer = (new TestIssuer($output))->enable();
-        $issuer->set('Firstname', 'Jean-François');
-
-        try {
-            trigger_error('Object of class stdClass could not be converted to string', E_USER_WARNING);
-        } catch (\Exception $e) {
-        }
-
-        $this->assertStringContainsString('Object of class stdClass could not be converted to string', $issuer->log);
-        $this->assertStringContainsString('Operating System', $issuer->log);
-        $this->assertStringContainsString('Details', $issuer->log);
-        $this->assertStringContainsString('https://github.com/phpmetrics/PhpMetrics/issues/new', $output->output);
-        $this->assertStringContainsString('Firstname: Jean-François', $issuer->log);
-        $this->assertStringContainsString('IssuerTest.php (line 29)', $issuer->log);
-        $issuer->disable();
-    }
-
-    /**
-     * @requires PHP < 7.0
-     */
-    public function testIssuerDisplayStatements(): void
-    {
-        $output = new TestOutput();
-        $issuer = (new TestIssuer($output))->enable();
-        $code = <<<EOT
-<?php
-class A{
-   public function foo() {
-
-   }
-}
-EOT;
-
-        $parser = (new ParserFactoryBridge())->create();
-        $stmt = $parser->parse($code);
-        $issuer->set('code', $stmt);
-
-        try {
-            trigger_error('Object of class stdClass could not be converted to string', E_USER_ERROR);
-        } catch (\Exception $e) {
-        }
-
-        $issuer->disable();
-        $this->assertStringContainsString('class A', $issuer->log);
-    }
-}
-
-class TestIssuer extends Issuer
-{
-    public $log;
-
-    protected function terminate($status)
-    {
-        throw new \RuntimeException('Terminated: ' . $status);
-    }
-
-    protected function log($logfile, $log)
-    {
-        $this->log = $log;
-    }
-}
diff --git a/tests/Component/Tree/GraphDeduplicatedTest.php b/tests/Component/Tree/GraphDeduplicatedTest.php
deleted file mode 100644
index 03ee7563..00000000
--- a/tests/Component/Tree/GraphDeduplicatedTest.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-namespace Test;
-
-use Hal\Component\Tree\Graph;
-use Hal\Component\Tree\GraphDeduplicated;
-use Hal\Component\Tree\Node;
-
-/**
- * @group tree
- */
-class GraphDeduplicatedTest extends \PHPUnit\Framework\TestCase
-{
-
-    public function testEdgeDeduplication(): void
-    {
-        $graph = new GraphDeduplicated();
-        $a = new Node('A');
-        $b = new Node('B');
-        $graph->insert($a);
-        $graph->insert($b);
-
-        $graph->addEdge($a, $b);
-        $graph->addEdge($a, $b);
-        $this->assertCount(1, $graph->getEdges());
-
-        $graph->addEdge($b, $a);
-        $this->assertCount(2, $graph->getEdges());
-    }
-}
diff --git a/tests/Component/Tree/GraphTest.php b/tests/Component/Tree/GraphTest.php
deleted file mode 100644
index 1f8aabfc..00000000
--- a/tests/Component/Tree/GraphTest.php
+++ /dev/null
@@ -1,125 +0,0 @@
-<?php
-
-namespace Test;
-
-use Hal\Component\Tree\Graph;
-use Hal\Component\Tree\Node;
-
-/**
- * @group tree
- */
-class GraphTest extends \PHPUnit\Framework\TestCase
-{
-    public function testICanAddEdge(): void
-    {
-        $graph = new Graph();
-        $a = new Node('node_a');
-        $b = new Node('node_b');
-
-        $graph->insert($a)->insert($b);
-        $graph->addEdge($a, $b);
-        $this->assertCount(1, $a->getEdges());
-        $this->assertSame($a, $a->getEdges()[0]->getFrom());
-        $this->assertSame($b, $a->getEdges()[0]->getTo());
-
-        $this->assertCount(1, $b->getEdges());
-        $this->assertSame($a, $a->getEdges()[0]->getFrom());
-        $this->assertSame($b, $a->getEdges()[0]->getTo());
-    }
-
-    public function testICanAddEdgeWithUnexistantFromNode(): void
-    {
-        $this->expectException(\LogicException::class);
-        $graph = new Graph();
-        $a = new Node('A');
-        $b = new Node('B');
-
-        $graph->insert($a);
-        $graph->addEdge($a, $b);
-    }
-
-    public function testICanAddEdgeWithUnexistantToNode(): void
-    {
-        $this->expectException(\LogicException::class);
-        $graph = new Graph();
-        $a = new Node('A');
-        $b = new Node('B');
-
-        $graph->insert($b);
-        $graph->addEdge($a, $b);
-    }
-
-    public function testICanInsertSameNodeTwice(): void
-    {
-        $this->expectException(\LogicException::class);
-        $graph = new Graph();
-        $node = new Node('A');
-        $graph->insert($node);
-        $graph->insert($node);
-    }
-
-    public function testICanListEdges(): void
-    {
-        $graph = new Graph();
-        $a = new Node('A');
-        $b = new Node('B');
-        $graph->insert($a);
-        $graph->insert($b);
-
-        $this->assertCount(0, $graph->getEdges());
-        $graph->addEdge($a, $b);
-        $this->assertCount(1, $graph->getEdges());
-    }
-
-    public function testEdgeIsAddedToFromAndToNode(): void
-    {
-        $graph = new Graph();
-        $a = new Node('A');
-        $b = new Node('B');
-        $c = new Node('C');
-        $graph->insert($a);
-        $graph->insert($b);
-        $graph->insert($c);
-
-        $graph->addEdge($a, $b);
-        $graph->addEdge($b, $c);
-
-        $this->assertCount(1, $a->getEdges());
-        $this->assertCount(2, $b->getEdges());
-        $this->assertCount(1, $c->getEdges());
-    }
-
-
-    public function testICanListRootNodes(): void
-    {
-        $graph = new Graph();
-        $a = new Node('A'); // root
-        $b = new Node('B');
-        $c = new Node('C');
-        $d = new Node('D');
-        $e = new Node('E'); // root
-        $graph->insert($a);
-        $graph->insert($b);
-        $graph->insert($c);
-        $graph->insert($d);
-        $graph->insert($e);
-
-        $graph->addEdge($a, $b); // A -> B
-        $graph->addEdge($b, $c); // B -> C
-        $graph->addEdge($a, $d); // A -> D
-
-        $roots = $graph->getRootNodes();
-        $this->assertCount(2, $roots);
-
-        $rootsFound = [
-            'A' => false,
-            'E' => false,
-        ];
-        foreach ($roots as $node) {
-            $rootsFound[$node->getKey()] = true;
-        }
-
-        $this->assertTrue($rootsFound['A']);
-        $this->assertTrue($rootsFound['E']);
-    }
-}
diff --git a/tests/Component/Tree/HashMapTest.php b/tests/Component/Tree/HashMapTest.php
deleted file mode 100644
index b37d5779..00000000
--- a/tests/Component/Tree/HashMapTest.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-namespace Test;
-
-use Hal\Component\Tree\HashMap;
-use Hal\Component\Tree\Node;
-
-/**
- * @group tree
- */
-class HashMapTest extends \PHPUnit\Framework\TestCase
-{
-
-    public function testICanWorkWithHashMap(): void
-    {
-        $hash = new HashMap;
-        $hash
-            ->attach($node1 = new Node('A', 'value1'))
-            ->attach($node2 = new Node('B', 'value2'))
-            ->attach(new Node('C', 'value3'));
-
-        $this->assertCount(3, $hash);
-        $this->assertTrue($hash->has('A'));
-        $this->assertTrue($hash->has('B'));
-        $this->assertFalse($hash->has('Not'));
-
-        $this->assertEquals($node1, $hash->get('A'));
-        $this->assertEquals($node2, $hash->get('B'));
-    }
-
-    public function testICanIterateThroughHashMap(): void
-    {
-        $hash = new HashMap;
-        $hash
-            ->attach(new Node('A', 'value1'))
-            ->attach(new Node('B', 'value2'))
-            ->attach(new Node('C', 'value3'));
-        $i = 0;
-        foreach ($hash as $item) {
-            $i++;
-        }
-        $this->assertEquals(3, $i);
-    }
-}
diff --git a/tests/Component/Tree/NodeTest.php b/tests/Component/Tree/NodeTest.php
deleted file mode 100644
index 588c368f..00000000
--- a/tests/Component/Tree/NodeTest.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-namespace Test;
-
-use Hal\Component\Tree\Edge;
-use Hal\Component\Tree\Node;
-
-/**
- * @group tree
- */
-class NodeTest extends \PHPUnit\Framework\TestCase
-{
-    public function testICanWorkWithNode(): void
-    {
-        $node = new Node('A');
-        $to = new Node('B');
-        $edge = new Edge($node, $to);
-        $node->addEdge($edge);
-        $node->setData('value1');
-
-        $this->assertEquals('value1', $node->getData());
-        $this->assertEquals(['B' => $to], $node->getAdjacents());
-        $this->assertEquals('A', $node->getKey());
-    }
-}
diff --git a/tests/Component/Tree/Operator/CycleDetectorTest.php b/tests/Component/Tree/Operator/CycleDetectorTest.php
deleted file mode 100644
index 87f5be52..00000000
--- a/tests/Component/Tree/Operator/CycleDetectorTest.php
+++ /dev/null
@@ -1,145 +0,0 @@
-<?php
-
-namespace Test;
-
-use Hal\Component\Tree\Graph;
-use Hal\Component\Tree\Node;
-use Hal\Component\Tree\Operator\CycleDetector;
-
-/**
- * @group tree
- */
-class CycleDetectorTest extends \PHPUnit\Framework\TestCase
-{
-    public function testCycleIsDetected(): void
-    {
-        $graph = new Graph();
-        $a = new Node('A');
-        $b = new Node('B');
-        $c = new Node('C');
-        $d = new Node('D');
-        $e = new Node('E');
-        $f = new Node('F');
-
-        $graph->insert($a)->insert($b)->insert($c)->insert($d)->insert($e)->insert($f);
-
-        // cyclic
-        $graph->addEdge($a, $b); // A -> B
-        $graph->addEdge($b, $c); // B -> C
-        $graph->addEdge($c, $d); // C -> D
-        $graph->addEdge($d, $a); // D -> A
-
-        // not cyclic
-        $graph->addEdge($e, $a); // E -> A
-        $graph->addEdge($f, $a); // F -> A
-
-        $cycleDetector = new CycleDetector();
-        $isCyclic = $cycleDetector->isCyclic($graph);
-
-        $this->assertTrue($isCyclic);
-        $this->assertTrue($a->cyclic);
-        $this->assertTrue($b->cyclic);
-        $this->assertTrue($c->cyclic);
-        $this->assertTrue($d->cyclic);
-        $this->assertFalse($e->cyclic);
-        $this->assertFalse($f->cyclic);
-    }
-
-    public function testAllCyclesAreFound(): void
-    {
-        $graph = new Graph();
-        $a = new Node('A');
-        $b = new Node('B');
-        $c = new Node('C');
-        $d = new Node('D');
-        $e = new Node('E');
-        $f = new Node('F');
-
-        $graph->insert($a)->insert($b)->insert($c)->insert($d)->insert($e)->insert($f);
-
-        // cyclic
-        $graph->addEdge($a, $b); // A -> B
-        $graph->addEdge($b, $c); // B -> C
-        $graph->addEdge($c, $d); // C -> D
-        $graph->addEdge($d, $a); // D -> A
-
-        // cyclic
-        $graph->addEdge($e, $f); // E -> F
-        $graph->addEdge($f, $e); // F -> E
-
-        $cycleDetector = new CycleDetector();
-        $isCyclic = $cycleDetector->isCyclic($graph);
-
-        $this->assertTrue($isCyclic);
-        $this->assertTrue($a->cyclic);
-        $this->assertTrue($b->cyclic);
-        $this->assertTrue($c->cyclic);
-        $this->assertTrue($d->cyclic);
-        $this->assertTrue($e->cyclic);
-        $this->assertTrue($f->cyclic);
-    }
-
-    public function testCycleIsNotDetected(): void
-    {
-        $graph = new Graph();
-        $a = new Node('A');
-        $b = new Node('B');
-        $c = new Node('C');
-        $d = new Node('D');
-        $e = new Node('E');
-        $f = new Node('F');
-
-        $graph->insert($a)->insert($b)->insert($c)->insert($d)->insert($e)->insert($f);
-
-        // not cyclic
-        $graph->addEdge($a, $b); // A -> B
-        $graph->addEdge($b, $c); // B -> C
-        $graph->addEdge($c, $d); // C -> D
-
-        // not cyclic
-        $graph->addEdge($d, $e); // D -> E
-        $graph->addEdge($e, $f); // E -> F
-
-        $cycleDetector = new CycleDetector();
-        $isCyclic = $cycleDetector->isCyclic($graph);
-
-        $this->assertFalse($isCyclic);
-        $this->assertFalse($a->cyclic);
-        $this->assertFalse($b->cyclic);
-        $this->assertFalse($c->cyclic);
-        $this->assertFalse($d->cyclic);
-        $this->assertFalse($e->cyclic);
-        $this->assertFalse($f->cyclic);
-    }
-
-    public function testPartCycleIsDetected(): void
-    {
-        $graph = new Graph();
-        $a = new Node('A');
-        $b = new Node('B');
-        $c = new Node('C');
-        $d = new Node('D');
-        $e = new Node('E');
-
-        $graph->insert($a)->insert($b)->insert($c)->insert($d)->insert($e);
-
-        // cyclic
-        $graph->addEdge($a, $b); // A -> B
-        $graph->addEdge($b, $c); // B -> C
-        $graph->addEdge($c, $a); // C -> A
-
-        // not cyclic
-        $graph->addEdge($d, $e); // D -> E
-        $graph->addEdge($e, $a); // E -> A
-
-        $cycleDetector = new CycleDetector();
-        $isCyclic = $cycleDetector->isCyclic($graph);
-
-        $this->assertTrue($isCyclic);
-        $this->assertTrue($a->cyclic);
-        $this->assertTrue($b->cyclic);
-        $this->assertTrue($c->cyclic);
-        $this->assertFalse($d->cyclic);
-        $this->assertTrue($e->cyclic);
-    }
-}
diff --git a/tests/Component/Tree/Operator/SizeOfTreeTest.php b/tests/Component/Tree/Operator/SizeOfTreeTest.php
deleted file mode 100644
index 3db8befd..00000000
--- a/tests/Component/Tree/Operator/SizeOfTreeTest.php
+++ /dev/null
@@ -1,123 +0,0 @@
-<?php
-
-namespace Test;
-
-use Hal\Component\Tree\Graph;
-use Hal\Component\Tree\GraphFactory;
-use Hal\Component\Tree\Node;
-use Hal\Component\Tree\Operator\SizeOfTree;
-
-/**
- * @group tree
- */
-class SizeOfTreeTest extends \PHPUnit\Framework\TestCase
-{
-
-    public function testICannotGetInfoAboutGraphWhenItIsCyclic(): void
-    {
-        $this->expectException(\LogicException::class);
-        $this->expectExceptionMessage('Cannot get size informations of cyclic graph');
-        $graph = new Graph();
-        $a = new Node('A');
-        $b = new Node('B');
-
-        $graph->insert($a)->insert($b);
-
-        // case 1
-        $graph->addEdge($a, $b); // A -> B
-        $graph->addEdge($b, $a); // B -> C
-
-        $size = new SizeOfTree($graph);
-    }
-
-    public function testICanGetDepthOfNode(): void
-    {
-        $graph = new Graph();
-        $a = new Node('A');
-        $b = new Node('B');
-        $c = new Node('C');
-        $d = new Node('D');
-        $e = new Node('E');
-
-        $graph->insert($a)->insert($b)->insert($c)->insert($d)->insert($e);
-
-        // case 1
-        $graph->addEdge($a, $b); // A -> B
-        $graph->addEdge($b, $c); // B -> C
-        $graph->addEdge($c, $d); // C -> D
-        $graph->addEdge($a, $e); // A -> E  (node with multiple childs)
-
-        $size = new SizeOfTree($graph);
-
-        $this->assertEquals(0, $size->getDepthOfNode($a));
-        $this->assertEquals(1, $size->getDepthOfNode($b));
-        $this->assertEquals(2, $size->getDepthOfNode($c));
-        $this->assertEquals(3, $size->getDepthOfNode($d));
-        $this->assertEquals(1, $size->getDepthOfNode($e));
-    }
-
-    public function testICanGetNbChildsOfNode(): void
-    {
-        $graph = new Graph();
-        $a = new Node('A');
-        $b = new Node('B');
-        $c = new Node('C');
-        $d = new Node('D');
-        $e = new Node('E');
-
-        $graph->insert($a)->insert($b)->insert($c)->insert($d)->insert($e);
-
-        // case 1
-        $graph->addEdge($a, $b); // A -> B
-        $graph->addEdge($b, $c); // B -> C
-        $graph->addEdge($c, $d); // C -> D
-        $graph->addEdge($a, $e); // A -> E  (node with multiple childs)
-
-        $size = new SizeOfTree($graph);
-
-        $this->assertEquals(4, $size->getNumberOfChilds($a));
-        $this->assertEquals(2, $size->getNumberOfChilds($b));
-        $this->assertEquals(1, $size->getNumberOfChilds($c));
-        $this->assertEquals(0, $size->getNumberOfChilds($d));
-        $this->assertEquals(0, $size->getNumberOfChilds($e));
-    }
-
-    public function testICanGetInfoAboutAverageHeightOfTree(): void
-    {
-        $graph = new Graph();
-        $a = new Node('A');
-        $b = new Node('B');
-        $c = new Node('C');
-        $d = new Node('D');
-        $e = new Node('E');
-        $f = new Node('F');
-        $g = new Node('G');
-        $x = new Node('X');
-        $y = new Node('Y');
-        $z = new Node('Z');
-
-        $graph->insert($a)->insert($b)->insert($c)->insert($d)->insert($e)->insert($f)->insert($g);
-        $graph->insert($x)->insert($y)->insert($z);
-
-        // case 1
-        $graph->addEdge($a, $b); // A -> B
-        $graph->addEdge($b, $c); // B -> C
-        $graph->addEdge($c, $d); // C -> D
-        $graph->addEdge($c, $f); // C -> F
-        $graph->addEdge($f, $g); // F -> G
-        $graph->addEdge($a, $e); // A -> E
-        $graph->addEdge($x, $y); // X -> Y
-
-        // longest branch A = 5      A -> B -> C -> F -> G
-        // longest branch X = 2      X -> Y
-        // longest branch Z = 1      Z
-
-        $size = new SizeOfTree($graph);
-
-        $this->assertEquals(5, $size->getLongestBranch($a));
-        $this->assertEquals(2, $size->getLongestBranch($x));
-        $this->assertEquals(1, $size->getLongestBranch($z));
-
-        $this->assertEquals(2.67, $size->getAverageHeightOfGraph());
-    }
-}
diff --git a/tests/Functions/GetNameOfNodeTest.php b/tests/Functions/GetNameOfNodeTest.php
deleted file mode 100644
index fc53d4b4..00000000
--- a/tests/Functions/GetNameOfNodeTest.php
+++ /dev/null
@@ -1,86 +0,0 @@
-<?php
-
-namespace Functions;
-
-use Hal\Component\Ast\NodeTraverser;
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Component\Ast\ParserTraverserVisitorsAssigner;
-use PhpParser\Node\Stmt\Class_;
-use PhpParser\NodeVisitor\NameResolver;
-use PHPUnit\Framework\TestCase;
-use Polyfill\TestCaseCompatible;
-
-/**
- * @group name
- */
-class GetNameOfNodeTest extends TestCase
-{
-    use TestCaseCompatible;
-
-    public function testNameIsCorrect(): void
-    {
-        $code = '<?php class Foo {}';
-        $parser = (new ParserFactoryBridge())->create();
-        $stmts = $parser->parse($code);
-
-        $traverser = new NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new NameResolver()
-        ]);
-        $traverser->traverse($stmts);
-
-        $node = $stmts[0];
-        $name = getNameOfNode($node);
-        $this->assertEquals('Foo', $name);
-    }
-
-    public function testNameInNamespaceIsCorrect(): void
-    {
-        $code = '<?php namespace Bar; class Foo {}';
-        $parser = (new ParserFactoryBridge())->create();
-        $stmts = $parser->parse($code);
-
-        $traverser = new NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new NameResolver()
-        ]);
-        $traverser->traverse($stmts);
-
-        // namespace
-        $node = $stmts[0];
-        $name = getNameOfNode($node);
-        $this->assertEquals('Bar', $name);
-
-        // class
-        $node = $node->stmts[0];
-        $this->assertInstanceOf(Class_::class, $node);
-        $name = getNameOfNode($node);
-        $this->assertEquals('Bar\\Foo', $name);
-    }
-    public function testItCanNameAnonymousClass() : void
-    {
-        $code = '<?php class Foo { public function bar() { return new class {}; } }';
-        $parser = (new ParserFactoryBridge())->create();
-        $stmts = $parser->parse($code);
-
-        $traverser = new NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new NameResolver()
-        ]);
-        $traverser->traverse($stmts);
-
-        // class
-        $node = $stmts[0];
-        $name = getNameOfNode($node);
-        $this->assertEquals('Foo', $name);
-
-        // anonymous class
-        $node = $node->stmts[0]->stmts[0]->expr->class;
-
-        if(method_exists($this, 'assertMatchesRegularExpression')) {
-            $this->assertMatchesRegularExpression('/^anonymous/', getNameOfNode($node));
-        } else {
-            $this->assertRegExp('/^anonymous/', getNameOfNode($node));;
-        }
-    }
-}
diff --git a/tests/Metric/Class_/ClassEnumVisitorTest.php b/tests/Metric/Class_/ClassEnumVisitorTest.php
deleted file mode 100644
index b44654fc..00000000
--- a/tests/Metric/Class_/ClassEnumVisitorTest.php
+++ /dev/null
@@ -1,163 +0,0 @@
-<?php
-namespace Test\Hal\Metric\Class_;
-
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Metric\Class_\ClassEnumVisitor;
-use Hal\Metric\Metrics;
-use PhpParser\NodeTraverser;
-use PhpParser\NodeVisitor\NameResolver;
-use PhpParser\ParserFactory;
-use PHPUnit\Framework\Attributes\DataProvider;
-
-/**
- * @group class
- */
-class ClassEnumVisitorTest extends \PHPUnit\Framework\TestCase
-{
-    /**
-     * @dataProvider provideExamples
-     */
-    #[DataProvider('provideExamples')]
-    public function testMethodsAreFoundAndCountedAccordingTheirRole(
-        $example,
-        $classname,
-        $nbMethods,
-        $nbMethodsPrivate,
-        $nbMethodsPublic,
-        $nbMethodsIncludingGettersSetters
-    ): void {
-        $code = file_get_contents($example);
-        $metrics = $this->analyzeCode($code);
-
-        $this->assertSame(
-            $nbMethods,
-            $metrics->get($classname)->get('nbMethods'),
-            "Expected $nbMethods methods (without getters and setters) but found {$metrics->get($classname)->get('nbMethods')}"
-        );
-        $this->assertSame(
-            $nbMethodsPrivate,
-            $metrics->get($classname)->get('nbMethodsPrivate'),
-            "Expected $nbMethodsPrivate private methods but got {$metrics->get($classname)->get('nbMethodsPrivate')}"
-        );
-        $this->assertSame(
-            $nbMethodsPublic,
-            $metrics->get($classname)->get('nbMethodsPublic'),
-            "Expected $nbMethodsPublic public methods but got {$metrics->get($classname)->get('nbMethodsPublic')}"
-        );
-        $this->assertSame(
-            $nbMethodsIncludingGettersSetters,
-            $metrics->get($classname)->get('nbMethodsIncludingGettersSetters'),
-            "Expected $nbMethodsPrivate methods including getters and setters but got {$metrics->get($classname)->get('nbMethodsIncludingGettersSetters')}"
-        );
-    }
-
-    public static function provideExamples()
-    {
-        return [
-            [__DIR__ . '/../examples/nbmethods1.php', 'A', 3, 1, 2, 7],
-        ];
-    }
-
-    /**
-     * @param string $code
-     * @return Metrics
-     */
-    private function analyzeCode($code)
-    {
-        $metrics = new Metrics();
-        $parser = (new ParserFactoryBridge())->create();
-        $traverser = new NodeTraverser();
-        $traverser->addVisitor(new NameResolver());
-        $traverser->addVisitor(new ClassEnumVisitor($metrics));
-
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        return $metrics;
-    }
-
-    public function testAnonymousClassIsHandledCorrectly(): void
-    {
-        $code = '<?php new class {};';
-        $metrics = $this->analyzeCode($code);
-
-        $this->assertCount(1, $metrics->all());
-    }
-
-    /**
-     * @link https://github.com/phpmetrics/PhpMetrics/issues/238
-     */
-    public function testDynamicAttributeClassIsHandledCorrectly(): void
-    {
-        $code = '
-class A {
-    public function foo() {
-        $reflection = new \ReflectionObject($this);
-
-        foreach ($reflection->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
-            $return[$property->name] = $this->{$property->name};
-        }
-    }
-}
-';
-        $metrics = $this->analyzeCode($code);
-        $this->assertInstanceOf(Metrics::class, $metrics);
-    }
-
-
-    /**
-     * @link https://github.com/phpmetrics/PhpMetrics/issues/238#issuecomment-292466274
-     */
-    public function testDynamicAttributeClassIsHandledCorrectly2(): void
-    {
-        $code = '<?php
-namespace Blackprism\CouchbaseODM\Observer;
-/**
- * Interface NotifyPropertyChangedInterface
- */
-interface NotifyPropertyChangedInterface
-{
-    /**
-     * Enable tracking on object.
-     */
-    public function track();
-    /**
-     * Check if object is tracked.
-     *
-     * @return bool
-     */
-    public function isTracked(): bool;
-}';
-
-        $metrics = $this->analyzeCode($code);
-        $this->assertInstanceOf(Metrics::class, $metrics);
-    }
-
-    public function testItDoesNotMarkClassesAsAbstract(): void
-    {
-        $code = '<?php class Foo {}';
-        $metrics = $this->analyzeCode($code);
-        $this->assertFalse($metrics->get('Foo')->get('abstract'));
-    }
-
-    public function testItMarksAbstractClassesAsAbstract(): void
-    {
-        $code = '<?php abstract class Foo {}';
-        $metrics = $this->analyzeCode($code);
-        $this->assertTrue($metrics->get('Foo')->get('abstract'));
-    }
-
-    public function testItMarksInterfacesAsAbstract(): void
-    {
-        $code = '<?php interface Foo {}';
-        $metrics = $this->analyzeCode($code);
-        $this->assertTrue($metrics->get('Foo')->get('abstract'));
-    }
-
-    public function testItMarksTraitsAsAbstract(): void
-    {
-        $code = '<?php trait Foo {}';
-        $metrics = $this->analyzeCode($code);
-        $this->assertTrue($metrics->get('Foo')->get('abstract'));
-    }
-}
diff --git a/tests/Metric/Class_/Complexity/CyclomaticComplexityVisitorTest.php b/tests/Metric/Class_/Complexity/CyclomaticComplexityVisitorTest.php
deleted file mode 100644
index be7fd42c..00000000
--- a/tests/Metric/Class_/Complexity/CyclomaticComplexityVisitorTest.php
+++ /dev/null
@@ -1,120 +0,0 @@
-<?php
-namespace Test\Hal\Metric\Class_\Coupling;
-
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Component\Ast\ParserTraverserVisitorsAssigner;
-use Hal\Metric\Class_\ClassEnumVisitor;
-use Hal\Metric\Class_\Complexity\CyclomaticComplexityVisitor;
-use Hal\Metric\Metrics;
-use PhpParser\NodeTraverser;
-use PhpParser\NodeVisitor\NameResolver;
-use PhpParser\ParserFactory;
-use PHPUnit\Framework\Attributes\DataProvider;
-
-class CyclomaticComplexityVisitorTest extends \PHPUnit\Framework\TestCase
-{
-    /**
-     * @dataProvider provideExamplesForCcn
-     */
-    #[DataProvider('provideExamplesForCcn')]
-    public function testCcnOfClassesIsWellCalculated($example, $classname, $expectedCcn): void
-    {
-        $metrics = new Metrics();
-
-        $parser = (new ParserFactoryBridge())->create();
-        $traverser = new NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new NameResolver(),
-            new ClassEnumVisitor($metrics),
-            new CyclomaticComplexityVisitor($metrics),
-        ]);
-
-        $code = file_get_contents($example);
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        $this->assertSame($expectedCcn, $metrics->get($classname)->get('ccn'));
-    }
-
-    /**
-     * @dataProvider provideExamplesForWmc
-     */
-    #[DataProvider('provideExamplesForWmc')]
-    public function testWeightedMethodCountOfClassesIsWellCalculated($example, $classname, $expectedWmc): void
-    {
-        $metrics = new Metrics();
-
-        $parser = (new ParserFactoryBridge)->create();
-        $traverser = new NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new NameResolver(),
-            new ClassEnumVisitor($metrics),
-            new CyclomaticComplexityVisitor($metrics),
-        ]);
-
-        $code = file_get_contents($example);
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        $this->assertSame($expectedWmc, $metrics->get($classname)->get('wmc'));
-    }
-
-    /**
-     * @dataProvider provideExamplesForMaxCc
-     */
-    #[DataProvider('provideExamplesForMaxCc')]
-    public function testMaximalCyclomaticComplexityOfMethodsIsWellCalculated($example, $classname, $expectedCcnMethodMax): void
-    {
-        $metrics = new Metrics();
-
-        $parser = (new ParserFactoryBridge)->create();
-        $traverser = new NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new NameResolver(),
-            new ClassEnumVisitor($metrics),
-            new CyclomaticComplexityVisitor($metrics),
-        ]);
-
-        $code = file_get_contents($example);
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        $this->assertSame($expectedCcnMethodMax, $metrics->get($classname)->get('ccnMethodMax'));
-    }
-
-    public static function provideExamplesForWmc()
-    {
-        return [
-            'A' => [__DIR__ . '/../../examples/cyclomatic1.php', 'A', 10],
-            'B' => [__DIR__ . '/../../examples/cyclomatic1.php', 'B', 4],
-            'Foo\\C' => [__DIR__ . '/../../examples/cyclomatic_anon.php', 'Foo\\C', 1],
-            'SwitchCase' => [__DIR__ . '/../../examples/cyclomatic_full.php', 'SwitchCase', 4],
-            'IfElseif' => [__DIR__ . '/../../examples/cyclomatic_full.php', 'IfElseif', 7],
-            'Loops' => [__DIR__ . '/../../examples/cyclomatic_full.php', 'Loops', 5],
-            'CatchIt' => [__DIR__ . '/../../examples/cyclomatic_full.php', 'CatchIt', 3],
-            'Logical' => [__DIR__ . '/../../examples/cyclomatic_full.php', 'Logical', 11],
-        ];
-    }
-
-    public static function provideExamplesForCcn()
-    {
-        return [
-            'A' => [__DIR__ . '/../../examples/cyclomatic1.php', 'A', 8],
-            'B' => [__DIR__ . '/../../examples/cyclomatic1.php', 'B', 4],
-            'Foo\\C' => [__DIR__ . '/../../examples/cyclomatic_anon.php', 'Foo\\C', 1],
-            'SwitchCase' => [__DIR__ . '/../../examples/cyclomatic_full.php', 'SwitchCase', 4],
-            'IfElseif' => [__DIR__ . '/../../examples/cyclomatic_full.php', 'IfElseif', 7],
-            'Loops' => [__DIR__ . '/../../examples/cyclomatic_full.php', 'Loops', 5],
-            'CatchIt' => [__DIR__ . '/../../examples/cyclomatic_full.php', 'CatchIt', 3],
-            'Logical' => [__DIR__ . '/../../examples/cyclomatic_full.php', 'Logical', 11],
-        ];
-    }
-
-    public static function provideExamplesForMaxCc()
-    {
-        return [
-            [__DIR__ . '/../../examples/cyclomatic1.php', 'A', 6],
-            [__DIR__ . '/../../examples/cyclomatic1.php', 'B', 4],
-        ];
-    }
-}
diff --git a/tests/Metric/Class_/Complexity/KanDefectVisitorTest.php b/tests/Metric/Class_/Complexity/KanDefectVisitorTest.php
deleted file mode 100644
index d39b072f..00000000
--- a/tests/Metric/Class_/Complexity/KanDefectVisitorTest.php
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-namespace Test\Hal\Metric\Class_\Coupling;
-
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Component\Ast\ParserTraverserVisitorsAssigner;
-use Hal\Metric\Class_\ClassEnumVisitor;
-use Hal\Metric\Class_\Complexity\KanDefectVisitor;
-use Hal\Metric\Metrics;
-use PhpParser\NodeVisitor\NameResolver;
-use PhpParser\ParserFactory;
-use PHPUnit\Framework\Attributes\DataProvider;
-
-/**
- * @group metric
- * @group kan
- * @group defect
- */
-class KanDefectVisitorTest extends \PHPUnit\Framework\TestCase
-{
-    /**
-     * @dataProvider provideExamples
-     */
-    #[DataProvider('provideExamples')]
-    public function testLackOfCohesionOfMethodsIsWellCalculated($example, $classname, $expected): void
-    {
-        $metrics = new Metrics();
-
-        $parser = (new ParserFactoryBridge())->create();
-        $traverser = new \PhpParser\NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new NameResolver(),
-            new ClassEnumVisitor($metrics),
-            new KanDefectVisitor($metrics)
-        ]);
-
-        $code = file_get_contents($example);
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        $this->assertSame($expected, $metrics->get($classname)->get('kanDefect'));
-    }
-
-    public static function provideExamples()
-    {
-        return [
-            [ __DIR__ . '/../../examples/kan1.php', 'A', .89],
-        ];
-    }
-}
diff --git a/tests/Metric/Class_/Complexity/SystemComplexityVisitorTest.php b/tests/Metric/Class_/Complexity/SystemComplexityVisitorTest.php
deleted file mode 100644
index b4266d9a..00000000
--- a/tests/Metric/Class_/Complexity/SystemComplexityVisitorTest.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-namespace Test\Hal\Metric\Class_\Coupling;
-
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Component\Ast\ParserTraverserVisitorsAssigner;
-use Hal\Metric\Class_\ClassEnumVisitor;
-use Hal\Metric\Class_\Structural\SystemComplexityVisitor;
-use Hal\Metric\Metrics;
-use PhpParser\NodeVisitor\NameResolver;
-use PhpParser\ParserFactory;
-use PHPUnit\Framework\Attributes\DataProvider;
-
-/**
- * @group metric
- * @group complexity
- * @group defect
- */
-class SystemComplexityVisitorTest extends \PHPUnit\Framework\TestCase
-{
-    /**
-     * @dataProvider provideExamples
-     */
-    #[DataProvider('provideExamples')]
-    public function testLackOfCohesionOfMethodsIsWellCalculated($filename, $class, $rdc, $rsc, $rsysc): void
-    {
-        $metrics = new Metrics();
-
-        $parser = (new ParserFactoryBridge())->create();
-        $traverser = new \PhpParser\NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new NameResolver(),
-            new ClassEnumVisitor($metrics),
-            new SystemComplexityVisitor($metrics),
-        ]);
-
-        $code = file_get_contents($filename);
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        $this->assertSame($rdc, $metrics->get('A')->get('relativeDataComplexity'));
-        $this->assertSame($rsc, $metrics->get('A')->get('relativeStructuralComplexity'));
-        $this->assertSame($rsysc, $metrics->get('A')->get('relativeSystemComplexity'));
-    }
-
-    public static function provideExamples()
-    {
-        return [
-            [ __DIR__ . '/../../examples/systemcomplexity1.php', 'A', 0.5, 36.0, 36.5],
-        ];
-    }
-}
diff --git a/tests/Metric/Class_/Component/MaintainabilityIndexVisitorTest.php b/tests/Metric/Class_/Component/MaintainabilityIndexVisitorTest.php
deleted file mode 100644
index 3b2a0e77..00000000
--- a/tests/Metric/Class_/Component/MaintainabilityIndexVisitorTest.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-namespace Test\Hal\Metric\Class_\Structural;
-
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Component\Ast\ParserTraverserVisitorsAssigner;
-use Hal\Metric\Class_\Component\MaintainabilityIndexVisitor;
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metrics;
-use PhpParser\ParserFactory;
-use PHPUnit\Framework\Attributes\DataProvider;
-
-/**
- * @group metric
- * @group mi
- * @group complex
- */
-class MaintainabilityIndexVisitorTest extends \PHPUnit\Framework\TestCase
-{
-    /**
-     * @dataProvider provideValues
-     */
-    #[DataProvider('provideValues')]
-    public function testLackOfCohesionOfMethodsIsWellCalculated($ccn, $lloc, $cloc, $volume, $mIwoC, $mi, $commentWeight): void
-    {
-        $metrics = new Metrics();
-        $classMetrics = new ClassMetric('A');
-        $classMetrics->set('lloc', $lloc);
-        $classMetrics->set('loc', $lloc + $cloc);
-        $classMetrics->set('ccn', $ccn);
-        $classMetrics->set('cloc', $cloc);
-        $classMetrics->set('volume', $volume);
-        $metrics->attach($classMetrics);
-
-        $parser = (new ParserFactoryBridge())->create();
-        $traverser = new \PhpParser\NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new \PhpParser\NodeVisitor\NameResolver(),
-            new MaintainabilityIndexVisitor($metrics)
-        ]);
-
-        $code = <<<EOT
-    <?php class A {
-        public function foo() {
-
-        }
-    }
-EOT;
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        // And now, mi, mIwoC and commentWeight should be set
-        $this->assertEquals($mi, $classMetrics->get('mi'));
-        $this->assertEquals($mIwoC, $classMetrics->get('mIwoC'));
-        $this->assertEquals($commentWeight, $classMetrics->get('commentWeight'));
-    }
-
-    public static function provideValues()
-    {
-        return [
-            //    CC    LLOC    CLOC        Volume      MIwoC      mi          commentWeight
-            [5     , 50    , 20       , 10         , 55.26,   92.1,      36.83 ],
-            [11    , 45   , 26       , 1777.49    , 39.7,     80.01,      40.3 ]
-        ];
-    }
-}
diff --git a/tests/Metric/Class_/Coupling/ExternalsVisitorTest.php b/tests/Metric/Class_/Coupling/ExternalsVisitorTest.php
deleted file mode 100644
index ce9a45d3..00000000
--- a/tests/Metric/Class_/Coupling/ExternalsVisitorTest.php
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-namespace Test\Hal\Metric\Class_\Coupling;
-
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Component\Ast\ParserTraverserVisitorsAssigner;
-use Hal\Metric\Class_\ClassEnumVisitor;
-use Hal\Metric\Class_\Coupling\ExternalsVisitor;
-use Hal\Metric\Metrics;
-use PhpParser\ParserFactory;
-use PHPUnit\Framework\Attributes\DataProvider;
-
-/**
- * @group metric
- * @group externals
- * @group coupling
- */
-class ExternalsVisitorTest extends \PHPUnit\Framework\TestCase
-{
-    /**
-     * @dataProvider provideExamples
-     */
-    #[DataProvider('provideExamples')]
-    public function testDependenciesAreFound($example, $classname, $expected): void
-    {
-        $metrics = new Metrics();
-
-        $parser = (new ParserFactoryBridge())->create();
-        $traverser = new \PhpParser\NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new \PhpParser\NodeVisitor\NameResolver(),
-            new ClassEnumVisitor($metrics),
-            new ExternalsVisitor($metrics)
-        ]);
-
-        $code = file_get_contents($example);
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        $this->assertSame($expected, $metrics->get($classname)->get('externals'));
-    }
-
-    public static function provideExamples()
-    {
-        $cases = [
-            [ __DIR__ . '/../../examples/externals1.php', 'A', ['H', 'C', 'B', 'D']],
-            [ __DIR__ . '/../../examples/externals1.php', 'B', []],
-            [ __DIR__ . '/../../examples/externals1.php', 'C', []],
-            [ __DIR__ . '/../../examples/externals1.php', 'D', []],
-            [ __DIR__ . '/../../examples/externals1.php', 'E', ['D', 'F', 'G']],
-            [ __DIR__ . '/../../examples/externals1.php', 'F', ['G', 'H']],
-            [ __DIR__ . '/../../examples/externals1.php', 'G', []],
-            [ __DIR__ . '/../../examples/externals1.php', 'H', []],
-            [ __DIR__ . '/../../examples/externals1.php', 'NS1\\A', ['NS2\\B']],
-        ];
-
-        // at least php 8.4:
-        if (version_compare(PHP_VERSION, '8.0.0', '>=')) {
-            $cases[] = [ __DIR__ . '/../../examples/php8.4.dereferencing_new.php', 'A', ['NS1\\B']];
-        }
-
-        return $cases;
-    }
-
-
-    /**
-     * @dataProvider provideExamplesAnnotation
-     */
-    #[DataProvider('provideExamplesAnnotation')]
-    public function testDependenciesAreFoundEvenInAnnotation($example, $classname, $expected): void
-    {
-        $metrics = new Metrics();
-
-        $parser = (new ParserFactoryBridge())->create();
-        $traverser = new \PhpParser\NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new \PhpParser\NodeVisitor\NameResolver(),
-            new ClassEnumVisitor($metrics),
-            new ExternalsVisitor($metrics)
-        ]);
-
-        $code = file_get_contents($example);
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        $this->assertSame($expected, $metrics->get($classname)->get('externals'));
-    }
-
-    public static function provideExamplesAnnotation()
-    {
-        return [
-            [ __DIR__ . '/../../examples/annotations1.php', 'C\\A', ['A\\Route', 'B\\Json']],
-        ];
-    }
-}
diff --git a/tests/Metric/Class_/Structural/LcomVisitorTest.php b/tests/Metric/Class_/Structural/LcomVisitorTest.php
deleted file mode 100644
index ad77e921..00000000
--- a/tests/Metric/Class_/Structural/LcomVisitorTest.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-namespace Test\Hal\Metric\Class_\Structural;
-
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Component\Ast\ParserTraverserVisitorsAssigner;
-use Hal\Metric\Class_\ClassEnumVisitor;
-use Hal\Metric\Class_\Coupling\ExternalsVisitor;
-use Hal\Metric\Class_\Structural\LcomVisitor;
-use Hal\Metric\Metrics;
-use PhpParser\ParserFactory;
-use PHPUnit\Framework\Attributes\DataProvider;
-
-class LcomVisitorTest extends \PHPUnit\Framework\TestCase
-{
-    /**
-     * @dataProvider provideExamples
-     */
-    #[DataProvider('provideExamples')]
-    public function testLackOfCohesionOfMethodsIsWellCalculated($example, $classname, $expected): void
-    {
-        $metrics = new Metrics();
-
-        $parser = (new ParserFactoryBridge())->create();
-        $traverser = new \PhpParser\NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new \PhpParser\NodeVisitor\NameResolver(),
-            new ClassEnumVisitor($metrics),
-            new LcomVisitor($metrics),
-        ]);
-
-        $code = file_get_contents($example);
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        $this->assertEquals($expected, $metrics->get($classname)->get('lcom'));
-    }
-
-    public static function provideExamples()
-    {
-        return [
-            [ __DIR__ . '/../../examples/lcom1.php', 'MyClassA', 2]
-        ];
-    }
-}
diff --git a/tests/Metric/Class_/Text/HalsteadVisitorTest.php b/tests/Metric/Class_/Text/HalsteadVisitorTest.php
deleted file mode 100644
index bff16fa7..00000000
--- a/tests/Metric/Class_/Text/HalsteadVisitorTest.php
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-namespace Test\Hal\Metric\Class_\Structural;
-
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Metric\Class_\ClassEnumVisitor;
-use Hal\Metric\Class_\Text\HalsteadVisitor;
-use Hal\Metric\Metrics;
-use PhpParser\ParserFactory;
-use PHPUnit\Framework\Attributes\DataProvider;
-
-/**
- * @group halstead
- * @group metric
- */
-class HalsteadVisitorTest extends \PHPUnit\Framework\TestCase
-{
-    /**
-     * @dataProvider provideExamples
-     */
-    #[DataProvider('provideExamples')]
-    public function testLackOfCohesionOfMethodsIsWellCalculated($example, $functionName, $nbOperators, $nbOperands, $difficulty): void
-    {
-        $metrics = new Metrics();
-
-        $parser = (new ParserFactoryBridge())->create();
-        $traverser = new \PhpParser\NodeTraverser();
-        $traverser->addVisitor(new \PhpParser\NodeVisitor\NameResolver());
-        $traverser->addVisitor(new ClassEnumVisitor($metrics));
-        $traverser->addVisitor(new HalsteadVisitor($metrics));
-
-        $code = file_get_contents($example);
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        $this->assertEquals(
-            $nbOperands,
-            $metrics->get($functionName)->get('number_operands'),
-            "Expected $nbOperands operands but got {$metrics->get($functionName)->get('number_operands')}"
-        );
-        $this->assertEquals(
-            $nbOperators,
-            $metrics->get($functionName)->get('number_operators'),
-            "Expected $nbOperators operators but got {$metrics->get($functionName)->get('number_operators')}"
-        );
-        $this->assertEquals(
-            $difficulty,
-            $metrics->get($functionName)->get('difficulty'),
-            "Expected difficulty $difficulty but got {$metrics->get($functionName)->get('difficulty')}"
-        );
-    }
-
-    public static function provideExamples()
-    {
-        return [
-            [ __DIR__ . '/../../examples/halstead1.php', 'twice', 2, 3, 1.5],
-            [ __DIR__ . '/../../examples/halstead2.php', 'maxi', 4, 6, 4.5],
-            [ __DIR__ . '/../../examples/halstead3.php', 'f_switch', 3, 9, 1.29],
-            [ __DIR__ . '/../../examples/halstead4.php', 'f_while', 9, 13, 10.4],
-        ];
-    }
-}
diff --git a/tests/Metric/Class_/Text/LengthVisitorTest.php b/tests/Metric/Class_/Text/LengthVisitorTest.php
deleted file mode 100644
index 91801ec0..00000000
--- a/tests/Metric/Class_/Text/LengthVisitorTest.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-namespace Test\Hal\Metric\Class_\Structural;
-
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Component\Ast\ParserTraverserVisitorsAssigner;
-use Hal\Metric\Class_\ClassEnumVisitor;
-use Hal\Metric\Class_\Coupling\ExternalsVisitor;
-use Hal\Metric\Class_\Text\LengthVisitor;
-use Hal\Metric\Metrics;
-use PhpParser\ParserFactory;
-use PHPUnit\Framework\Attributes\DataProvider;
-
-/**
- * @group loc
- * @group metric
- */
-class LengthVisitorTest extends \PHPUnit\Framework\TestCase
-{
-    /**
-     * @dataProvider provideExamples
-     */
-    #[DataProvider('provideExamples')]
-    public function testLineCountsAreWellCalculated($example, $functionName, $loc, $lloc, $cloc): void
-    {
-        $metrics = new Metrics();
-
-        $parser = (new ParserFactoryBridge())->create();
-        $traverser = new \PhpParser\NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new \PhpParser\NodeVisitor\NameResolver(),
-            new ClassEnumVisitor($metrics),
-            new LengthVisitor($metrics)
-        ]);
-
-        $code = file_get_contents($example);
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        $this->assertEquals($lloc, $metrics->get($functionName)->get('lloc'));
-        $this->assertEquals($cloc, $metrics->get($functionName)->get('cloc'));
-        $this->assertEquals($loc, $metrics->get($functionName)->get('loc'));
-    }
-
-    public static function provideExamples()
-    {
-        return [
-            [ __DIR__ . '/../../examples/loc1.php', 'A', 21, 13, 8],
-        ];
-    }
-}
diff --git a/tests/Metric/Helper/RoleOfMethodDetectorTest.php b/tests/Metric/Helper/RoleOfMethodDetectorTest.php
deleted file mode 100644
index 3a39b9e6..00000000
--- a/tests/Metric/Helper/RoleOfMethodDetectorTest.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-namespace Test\Hal\Metric\Helper;
-
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Metric\Helper\RoleOfMethodDetector;
-use PhpParser\Node\Stmt\Class_;
-use PhpParser\Node\Stmt\ClassMethod;
-use PhpParser\ParserFactory;
-use PHPUnit\Framework\Attributes\DataProvider;
-
-/**
- * @group method
- * @group helper
- * @group parsing
- */
-class RoleOfMethodDetectorTest extends \PHPUnit\Framework\TestCase
-{
-    /**
-     * @dataProvider provideExamples
-     */
-    #[DataProvider('provideExamples')]
-    public function testICanDetectRoleOfMethod($expected, $code): void
-    {
-        $parser = (new ParserFactoryBridge())->create();
-        $stmt = $parser->parse($code);
-
-        $helper = new RoleOfMethodDetector();
-
-        foreach ($stmt as $node) {
-            if ($node instanceof Class_) {
-                foreach ($node->stmts as $sub) {
-                    if ($sub instanceof ClassMethod) {
-                        $type = $helper->detects($sub);
-                        $this->assertEquals($expected, $type);
-                    }
-                }
-            }
-        }
-    }
-
-    public static function provideExamples()
-    {
-        $examples = [
-            'getter' => ['getter', '<?php class A { function getName(){ return $this->name; } }  ?>'],
-            'getter with string cast' => ['getter', '<?php class A { function getName(){ return (string) $this->name; } }  ?>'],
-            'getter with int cast' => ['getter', '<?php class A { function getName(){ return (int) $this->name; } }  ?>'],
-            'setter' => ['setter', '<?php class A { function setName($string){ $this->name = $name; } } ?>'],
-            'setter with string cast' => ['setter', '<?php class A { function setName($string){ $this->name = (string) $name; } } ?>'],
-            'setter with $this return' => ['setter', '<?php class A { function setName($string){ $this->name = (string) $name; return $this; } } ?>'],
-            'neither setter nor getter' => [null, '<?php class A { function foo($string){ $this->name = (string) $name * 3; } } ?>'],
-        ];
-        if (version_compare(PHP_VERSION, '7.0.0') >= 0) {
-            $examples['getter with return scalar'] = ['getter', '<?php class A { function getName(): string { return $this->name; } }'];
-            $examples['setter with scalar hint and return void'] = ['setter', '<?php class A { function setName(string $name): void { $this->name = $name; } }'];
-            $examples['getter with return object'] = ['getter', '<?php class A { function getName(): Name { return $this->name; } }'];
-            $examples['setter with object hint and return void'] = ['setter', '<?php class A { function setName(Name $name): void { $this->name = $name; } }'];
-            $examples['getter with return optional'] = ['getter', '<?php class A { function isOk(): ?bool { return $this->isOk; } }'];
-            $examples['setter fluent with param optional'] = ['setter', '<?php class A { function setOk(?bool $ok): self { $this->isOk = $ok; return $this; } }'];
-            $examples['setter fluent non typed with param optional'] = ['setter', '<?php class A { function setOk(?bool $ok) { $this->isOk = $ok; return $this; } }'];
-            $examples['setter with param optional'] = ['setter', '<?php class A { function setOk(?bool $ok) { $this->isOk = $ok; } }'];
-        }
-        return $examples;
-    }
-}
diff --git a/tests/Metric/Package/PackageAbstractionTest.php b/tests/Metric/Package/PackageAbstractionTest.php
deleted file mode 100644
index e51ab369..00000000
--- a/tests/Metric/Package/PackageAbstractionTest.php
+++ /dev/null
@@ -1,92 +0,0 @@
-<?php
-
-namespace Test\Hal\Metric\Package;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metric;
-use Hal\Metric\Metrics;
-use Hal\Metric\Package\PackageAbstraction;
-use Hal\Metric\PackageMetric;
-use PHPUnit\Framework\TestCase;
-
-/**
- * @group metric
- * @group package
- */
-class PackageAbstractionTest extends TestCase
-{
-    public function testItCalculatesTheAbstractionOfEachPackage(): void
-    {
-        $metrics = $this->metricsOf([
-            $this->aPackage('SemiAbstract\\', [
-                $this->aClass('SemiAbstract\\Class_'),
-                $this->anAbstractClass('SemiAbstract\\AbstractClass'),
-            ]),
-            $this->aPackage('Abstract\\', [
-                $this->anAbstractClass('Abstract\\AbstractClass'),
-            ]),
-            $this->aPackage('Concrete\\', [
-                $this->aClass('Stable\\Class_'),
-            ])
-        ]);
-
-        $object = new PackageAbstraction();
-        $object->calculate($metrics);
-
-        $this->assertSame(0.5, $metrics->get('SemiAbstract\\')->getAbstraction());
-        $this->assertSame(1.0, $metrics->get('Abstract\\')->getAbstraction());
-        $this->assertSame(0.0, $metrics->get('Concrete\\')->getAbstraction());
-    }
-
-    /**
-     * @param Metric[][] $metrics
-     * @return Metrics
-     */
-    private function metricsOf(array $metrics)
-    {
-        $result = new Metrics();
-        foreach ($metrics as $eachMetrics) {
-            foreach ($eachMetrics as $eachMetric) {
-                $result->attach($eachMetric);
-            }
-        }
-        return $result;
-    }
-
-    /**
-     * @param ClassMetric[] $classes
-     * @return Metric[] $metrics
-     */
-    private function aPackage($packageName, array $classes)
-    {
-        $packageMetric = new PackageMetric($packageName);
-        foreach ($classes as $each) {
-            $packageMetric->addClass($each->getName());
-        }
-        $result = $classes;
-        $result[] = $packageMetric;
-        return $result;
-    }
-
-    /**
-     * @param string $className
-     * @return ClassMetric
-     */
-    private function anAbstractClass($className)
-    {
-        $metric = new ClassMetric($className);
-        $metric->set('abstract', true);
-        return $metric;
-    }
-
-    /**
-     * @param string $className
-     * @return ClassMetric
-     */
-    private function aClass($className)
-    {
-        $metric = new ClassMetric($className);
-        $metric->set('abstract', false);
-        return $metric;
-    }
-}
diff --git a/tests/Metric/Package/PackageCollectingVisitorTest.php b/tests/Metric/Package/PackageCollectingVisitorTest.php
deleted file mode 100644
index 942f143b..00000000
--- a/tests/Metric/Package/PackageCollectingVisitorTest.php
+++ /dev/null
@@ -1,97 +0,0 @@
-<?php
-
-namespace Test\Hal\Metric\Package;
-
-use Hal\Component\Ast\ParserFactoryBridge;
-use Hal\Component\Ast\ParserTraverserVisitorsAssigner;
-use Hal\Metric\Class_\ClassEnumVisitor;
-use Hal\Metric\Metrics;
-use Hal\Metric\Package\PackageCollectingVisitor;
-use Hal\Metric\PackageMetric;
-use PhpParser\NodeTraverser;
-use PhpParser\NodeVisitor\NameResolver;
-use PhpParser\ParserFactory;
-use PHPUnit\Framework\TestCase;
-
-/**
- * @group metric
- * @group package
- */
-class PackageCollectingVisitorTest extends TestCase
-{
-    public function testItUsesThePackageAndTheSubpackageAnnotationAsPackageName(): void
-    {
-        $metrics = $this->analyzeCode(<<<'CODE'
-<?php
-namespace PackageA;
-
-/**
- * @package PackA
- * @subpackage SubA
- */
-class ClassA
-{
-}
-CODE
-        );
-        $this->assertInstanceOf(PackageMetric::class, $metrics->get('PackA\\SubA\\'));
-        $this->assertSame(['PackageA\\ClassA'], $metrics->get('PackA\\SubA\\')->getClasses());
-        $this->assertSame('PackA\\SubA\\', $metrics->get('PackageA\\ClassA')->get('package'));
-    }
-
-    public function testItUsesThePackageAnnotationAsPackageNameIfNoSubpackageAnnotationExist(): void
-    {
-        $metrics = $this->analyzeCode(<<<'CODE'
-<?php
-namespace PackageA;
-
-/**
- * @package PackA
- */
-class ClassA
-{
-}
-CODE
-        );
-        $this->assertInstanceOf(PackageMetric::class, $metrics->get('PackA\\'));
-        $this->assertSame(['PackageA\\ClassA'], $metrics->get('PackA\\')->getClasses());
-        $this->assertSame('PackA\\', $metrics->get('PackageA\\ClassA')->get('package'));
-    }
-
-    public function testItUsesTheNamespaceAsPackageNameIfNoPackageAnnotationAreAvailable(): void
-    {
-        $metrics = $this->analyzeCode(<<<'CODE'
-<?php
-namespace PackageA;
-
-class ClassA
-{
-}
-CODE
-        );
-        $this->assertInstanceOf(PackageMetric::class, $metrics->get('PackageA\\'));
-        $this->assertSame(['PackageA\\ClassA'], $metrics->get('PackageA\\')->getClasses());
-        $this->assertSame('PackageA\\', $metrics->get('PackageA\\ClassA')->get('package'));
-    }
-
-    /**
-     * @param string $code
-     * @return Metrics
-     */
-    private function analyzeCode($code)
-    {
-        $metrics = new Metrics();
-        $parser = (new ParserFactoryBridge())->create();
-        $traverser = new NodeTraverser();
-        (new ParserTraverserVisitorsAssigner())->assign($traverser, [
-            new \PhpParser\NodeVisitor\NameResolver(),
-            new ClassEnumVisitor($metrics),
-            new PackageCollectingVisitor($metrics)
-        ]);
-
-        $stmts = $parser->parse($code);
-        $traverser->traverse($stmts);
-
-        return $metrics;
-    }
-}
diff --git a/tests/Metric/Package/PackageDependenciesTest.php b/tests/Metric/Package/PackageDependenciesTest.php
deleted file mode 100644
index 6a217b09..00000000
--- a/tests/Metric/Package/PackageDependenciesTest.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-namespace Test\Hal\Metric\Package;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metrics;
-use Hal\Metric\Package\PackageDependencies;
-use Hal\Metric\PackageMetric;
-use PHPUnit\Framework\TestCase;
-
-/**
- * @group metric
- * @group package
- */
-class PackageDependenciesTest extends TestCase
-{
-    public function testItCollectsAllIncomingAndOutgoingPackageDependencies(): void
-    {
-        $packageA = new PackageMetric('PackageA\\');
-        $packageB = new PackageMetric('PackageB\\');
-
-        $classWithExternalsOfB = new ClassMetric('PackageA\\AnotherClass');
-        $classWithExternalsOfB->set('package', 'PackageA\\');
-        $classWithExternalsOfB->set('externals', ['ClassB', 'PackageB\\ClassB']);
-
-        $classWithGlobalExternal = new ClassMetric('ClassA');
-        $classWithGlobalExternal->set('package', 'PackageA\\');
-        $classWithGlobalExternal->set('externals', ['stdClass']);
-
-        $metrics = new Metrics();
-        $metrics->attach($packageA);
-        $metrics->attach($packageB);
-
-        $metrics->attach($classWithGlobalExternal);
-        $metrics->attach($classWithExternalsOfB);
-
-        $metrics->attach((new ClassMetric('ClassB'))->set('package', 'PackageB\\'));
-        $metrics->attach(new ClassMetric('PackageB\\ClassB'));
-
-        (new PackageDependencies())->calculate($metrics);
-
-        $this->assertSame(['stdClass', 'ClassB', 'PackageB\\ClassB'], $packageA->getOutgoingClassDependencies());
-        $this->assertSame(['\\', 'PackageB\\'], $packageA->getOutgoingPackageDependencies());
-        $this->assertSame(['PackageA\\AnotherClass'], $packageB->getIncomingClassDependencies());
-        $this->assertSame(['PackageA\\'], $packageB->getIncomingPackageDependencies());
-    }
-
-    public function testItSkipsClassesThatHasNoDependencies(): void
-    {
-        $classMetric = (new ClassMetric('OneClass'))->set('package', 'PackageA\\');
-        $metrics = $this->getMockBuilder(Metrics::class)->disableOriginalConstructor()->getMock();
-        $metrics
-            ->expects($this->once())
-            ->method('all')
-            ->willReturn([$classMetric]);
-
-        (new PackageDependencies())->calculate($metrics);
-    }
-
-    public function testItSkipsClassesThatHasNoPackage(): void
-    {
-        $classMetric = (new ClassMetric('OneClass'))->set('externals', ['AnotherClass']);
-        $metrics = $this->getMockBuilder(Metrics::class)->disableOriginalConstructor()->getMock();
-        $metrics
-            ->expects($this->once())
-            ->method('all')
-            ->willReturn([$classMetric]);
-
-        (new PackageDependencies())->calculate($metrics);
-    }
-}
diff --git a/tests/Metric/Package/PackageDistanceTest.php b/tests/Metric/Package/PackageDistanceTest.php
deleted file mode 100644
index 3099ec75..00000000
--- a/tests/Metric/Package/PackageDistanceTest.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-namespace Test\Hal\Metric\Package;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\Metrics;
-use Hal\Metric\Package\PackageDistance;
-use Hal\Metric\PackageMetric;
-use PHPUnit\Framework\Attributes\DataProvider;
-use \PHPUnit\Framework\TestCase;
-
-/**
- * @group metric
- * @group package
- */
-class PackageDistanceTest extends TestCase
-{
-    /**
-     * @dataProvider provideExamples
-     */
-    #[DataProvider('provideExamples')]
-    public function testItCalculatesTheNormalizedDistanceOfAllPackages($instability, $abstraction, $expectedDistance): void
-    {
-        $metrics = new Metrics();
-        $metrics->attach(new ClassMetric('Ignored'));
-
-        $package = new PackageMetric('MyPackage\\');
-        $package->setInstability($instability);
-        $package->setAbstraction($abstraction);
-
-        $metrics->attach($package);
-
-        (new PackageDistance())->calculate($metrics);
-
-        $this->assertSame($expectedDistance, $package->getNormalizedDistance());
-    }
-
-    public static function provideExamples()
-    {
-        return [
-            'missing instability and abstraction' => [null, null, null],
-            'missing instability' => [null, 1.0, null],
-            'missing abstraction' => [1.0, null, null],
-            'abstract and stable' => [1.0, 0.0, 0.0],
-            'concrete and instable' => [0.0, 1.0, 0.0],
-            'abstract and instable' => [1.0, 1.0, 1.0],
-            'concrete and stable' => [0.0, 0.0, 1.0],
-        ];
-    }
-}
diff --git a/tests/Metric/Package/PackageInstabilityTest.php b/tests/Metric/Package/PackageInstabilityTest.php
deleted file mode 100644
index 70b7514a..00000000
--- a/tests/Metric/Package/PackageInstabilityTest.php
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-
-namespace Test\Hal\Metric\Package;
-
-use Hal\Metric\Metrics;
-use Hal\Metric\Package\PackageInstability;
-use Hal\Metric\PackageMetric;
-use \PHPUnit\Framework\TestCase;
-
-/**
- * @group metric
- * @group package
- */
-class PackageInstabilityTest extends TestCase
-{
-    public function testItCalculatesTheInstabilityOfEachPackage(): void
-    {
-        $packageA = new PackageMetric('PackageA\\');
-        $packageB = new PackageMetric('PackageB\\');
-        $packageC = new PackageMetric('PackageC\\');
-
-        $packageB->addOutgoingClassDependency('ClassA', $packageA->getName());
-        $packageA->addIncomingClassDependency('ClassB', $packageB->getName());
-
-        $packageA->addOutgoingClassDependency('ClassC', $packageC->getName());
-        $packageC->addIncomingClassDependency('ClassA', $packageA->getName());
-
-        $metrics = new Metrics();
-        $metrics->attach($packageA);
-        $metrics->attach($packageB);
-        $metrics->attach($packageC);
-
-        (new PackageInstability())->calculate($metrics);
-
-        $this->assertSame(0.5, $packageA->getInstability());
-        $this->assertSame(1.0, $packageB->getInstability());
-        $this->assertSame(0.0, $packageC->getInstability());
-    }
-
-    public function testItStoresTheInstabilityOfTheDependentPackagesOfEachPackage(): void
-    {
-        $packageA = new PackageMetric('PackageA\\');
-        $packageB = new PackageMetric('PackageB\\');
-        $packageC = new PackageMetric('PackageC\\');
-
-        $packageB->addOutgoingClassDependency('ClassA', $packageA->getName());
-        $packageA->addIncomingClassDependency('ClassB', $packageB->getName());
-
-        $packageA->addOutgoingClassDependency('ClassC', $packageC->getName());
-        $packageC->addIncomingClassDependency('ClassA', $packageA->getName());
-
-        $metrics = new Metrics();
-        $metrics->attach($packageA);
-        $metrics->attach($packageB);
-        $metrics->attach($packageC);
-
-        (new PackageInstability())->calculate($metrics);
-
-        $this->assertSame([$packageC->getName() => 0.0], $packageA->getDependentInstabilities());
-        $this->assertSame([$packageA->getName() => 0.5], $packageB->getDependentInstabilities());
-        $this->assertSame([], $packageC->getDependentInstabilities());
-    }
-
-    public function testItDoesNotCrashIfOnePackageHasNoIncomingAndNoOutgoingDependencies(): void
-    {
-        $package = new PackageMetric('PackageA\\');
-
-        $metrics = new Metrics();
-        $metrics->attach($package);
-
-        (new PackageInstability())->calculate($metrics);
-
-        $this->assertNull($package->getInstability());
-    }
-}
diff --git a/tests/Metric/PackageMetricTest.php b/tests/Metric/PackageMetricTest.php
deleted file mode 100644
index 422953bc..00000000
--- a/tests/Metric/PackageMetricTest.php
+++ /dev/null
@@ -1,138 +0,0 @@
-<?php
-
-namespace Test\Hal\Metric;
-
-use Hal\Metric\Metric;
-use Hal\Metric\PackageMetric;
-use PHPUnit\Framework\TestCase;
-
-class PackageMetricTest extends TestCase
-{
-    public function testItIsAMetric(): void
-    {
-        $this->assertInstanceOf(Metric::class, new PackageMetric('PackageName\\'));
-    }
-
-    public function testItAppendsClasses(): void
-    {
-        $metric = new PackageMetric('PackageName\\');
-
-        $this->assertSame([], $metric->getClasses());
-
-        $metric->addClass('Foo');
-        $this->assertSame(['Foo'], $metric->getClasses());
-
-        $metric->addClass('Bar');
-        $this->assertSame(['Foo', 'Bar'], $metric->getClasses());
-    }
-
-    public function testItMayHasAnAbstraction(): void
-    {
-        $metric = new PackageMetric('PackageName\\');
-        $this->assertNull($metric->getAbstraction());
-
-        $metric->setAbstraction(0.8);
-        $this->assertSame(0.8, $metric->getAbstraction());
-    }
-
-    public function testItMayHasAnInstability(): void
-    {
-        $metric = new PackageMetric('PackageName\\');
-        $this->assertNull($metric->getInstability());
-
-        $metric->setInstability(0.8);
-        $this->assertSame(0.8, $metric->getInstability());
-    }
-
-    public function testItHasAUniqueListOfOutgoingClassDependencies(): void
-    {
-        $metric = new PackageMetric('PackageName\\');
-        $this->assertSame([], $metric->getOutgoingClassDependencies());
-
-        $metric->addOutgoingClassDependency('PackageA\\AnyClass', 'PackageA\\');
-        $metric->addOutgoingClassDependency('PackageA\\AnyClass', 'PackageA\\');
-
-        $this->assertSame(['PackageA\\AnyClass'], $metric->getOutgoingClassDependencies());
-    }
-
-    public function testItDoesNotAddClassesOfItselfAsOutgoingClassDependencies(): void
-    {
-        $metric = new PackageMetric('PackageA\\');
-        $metric->addOutgoingClassDependency('PackageA\\AnyClass', 'PackageA\\');
-        $this->assertSame([], $metric->getOutgoingClassDependencies());
-    }
-
-    public function testItHasAUniqueListOfOutgoingPackageDependencies(): void
-    {
-        $metric = new PackageMetric('PackageName\\');
-        $this->assertSame([], $metric->getOutgoingPackageDependencies());
-
-        $metric->addOutgoingClassDependency('PackageA\\AnyClass', 'PackageA\\');
-        $metric->addOutgoingClassDependency('PackageA\\AnotherClass', 'PackageA\\');
-
-        $this->assertSame(['PackageA\\'], $metric->getOutgoingPackageDependencies());
-    }
-
-    public function testItDoesNotAddItselfAsOutgoingClassDependencies(): void
-    {
-        $metric = new PackageMetric('PackageA\\');
-        $metric->addOutgoingClassDependency('PackageA\\AnyClass', 'PackageA\\');
-        $this->assertSame([], $metric->getOutgoingPackageDependencies());
-    }
-
-    public function testItHasAUniqueListOfIncomingClassDependencies(): void
-    {
-        $metric = new PackageMetric('PackageName\\');
-        $this->assertSame([], $metric->getOutgoingClassDependencies());
-
-        $metric->addIncomingClassDependency('PackageA\\AnyClass', 'PackageA\\');
-        $metric->addIncomingClassDependency('PackageA\\AnyClass', 'PackageA\\');
-
-        $this->assertSame(['PackageA\\AnyClass'], $metric->getIncomingClassDependencies());
-    }
-
-    public function testItDoesNotAddClassesOfItselfAsIncomingClassDependencies(): void
-    {
-        $metric = new PackageMetric('PackageA\\');
-        $metric->addIncomingClassDependency('PackageA\\AnyClass', 'PackageA\\');
-        $this->assertSame([], $metric->getIncomingClassDependencies());
-    }
-
-    public function testItHasAUniqueListOfIncomingPackageDependencies(): void
-    {
-        $metric = new PackageMetric('PackageName\\');
-        $this->assertSame([], $metric->getIncomingPackageDependencies());
-
-        $metric->addIncomingClassDependency('PackageA\\AnyClass', 'PackageA\\');
-        $metric->addIncomingClassDependency('PackageA\\AnotherClass', 'PackageA\\');
-
-        $this->assertSame(['PackageA\\'], $metric->getIncomingPackageDependencies());
-    }
-
-    public function testItDoesNotAddItselfAsIncomingClassDependencies(): void
-    {
-        $metric = new PackageMetric('PackageA\\');
-        $metric->addIncomingClassDependency('PackageA\\AnyClass', 'PackageA\\');
-        $this->assertSame([], $metric->getIncomingPackageDependencies());
-    }
-
-    public function testItMayHasADistanceAndANormalizedDistance(): void
-    {
-        $metric = new PackageMetric('PackageA\\');
-        $this->assertNull($metric->getDistance());
-        $this->assertNull($metric->getNormalizedDistance());
-
-        $metric->setNormalizedDistance(1);
-        $this->assertSame(1, $metric->getNormalizedDistance());
-        $this->assertSame(1/sqrt(2), $metric->getDistance());
-    }
-
-    public function testItMyaHasDependentInstabilities(): void
-    {
-        $metric = new PackageMetric('PackageB\\');
-        $this->assertSame([], $metric->getDependentInstabilities());
-
-        $metric->setDependentInstabilities(['PackageA\\' => 0.04, 'PackageC\\' => 0.5]);
-        $this->assertSame(['PackageA\\' => 0.04, 'PackageC\\' => 0.5], $metric->getDependentInstabilities());
-    }
-}
diff --git a/tests/Metric/System/UnitTesting/UnitTestingTest.php b/tests/Metric/System/UnitTesting/UnitTestingTest.php
deleted file mode 100644
index 0b80bacd..00000000
--- a/tests/Metric/System/UnitTesting/UnitTestingTest.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-namespace Test\Hal\Metric\System\UnitTesting;
-
-use Hal\Application\Config\Config;
-use Hal\Metric\Metrics;
-use Hal\Metric\System\UnitTesting\UnitTesting;
-
-/**
- * @group unit
- */
-class UnitTestingTest extends \PHPUnit\Framework\TestCase
-{
-
-    public function testICanParseJunitXmlFile(): void
-    {
-        $config = new Config();
-        $config->set('junit', __DIR__ . '/xml/junit1.xml');
-        $unit = new UnitTesting($config, []);
-        $metrics = new Metrics();
-        $unit->calculate($metrics);
-
-        $this->assertEquals(2, $metrics->get('unitTesting')->get('nbSuites'));
-        $this->assertCount(2, $metrics->get('unitTesting')->get('tests'));
-
-        $tests = $metrics->get('unitTesting')->get('tests');
-        $this->assertArrayHasKey('Test\Hal\Application\Config\ParserTest', $tests);
-        $this->assertEquals(7, $tests['Test\Hal\Application\Config\ParserTest']->assertions);
-
-        $tests = $metrics->get('unitTesting')->get('tests');
-        $this->assertArrayHasKey('Test\Hal\Component\Issue\IssuerTest', $tests);
-        $this->assertEquals(6, $tests['Test\Hal\Component\Issue\IssuerTest']->assertions);
-    }
-
-    public function testExceptionIsThrownIfJunitFileDoesNotExist(): void
-    {
-        $this->expectException(\Hal\Application\Config\ConfigException::class);
-        $config = new Config();
-        $config->set('junit', __DIR__ . '/xml/junit-not-found.xml');
-        $unit = new UnitTesting($config, []);
-        $metrics = new Metrics();
-        $unit->calculate($metrics);
-    }
-
-    public function testICanParseCodeceptionFile(): void
-    {
-        $config = new Config();
-        $config->set('junit', __DIR__ . '/xml/codeception1.xml');
-        $unit = new UnitTesting($config, []);
-        $metrics = new Metrics();
-        $unit->calculate($metrics);
-
-        $this->assertEquals(3, $metrics->get('unitTesting')->get('nbSuites'));
-        $this->assertEquals(27, $metrics->get('unitTesting')->get('assertions'));
-    }
-}
diff --git a/tests/Metric/System/UnitTesting/examples/1.php b/tests/Metric/System/UnitTesting/examples/1.php
deleted file mode 100644
index 32c232cf..00000000
--- a/tests/Metric/System/UnitTesting/examples/1.php
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php
-namespace MyProject\AccessToken\Repository {
-    class MongoDbAccessTokenRepositoryTest {
-
-    }
-}
\ No newline at end of file
diff --git a/tests/Metric/System/UnitTesting/examples/2.php b/tests/Metric/System/UnitTesting/examples/2.php
deleted file mode 100644
index 252a930d..00000000
--- a/tests/Metric/System/UnitTesting/examples/2.php
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php
-namespace MyProject\Client\Repository;
-
-class PhpArrayClientRepositoryTest {
-
-}
diff --git a/tests/Metric/System/UnitTesting/examples/3.php b/tests/Metric/System/UnitTesting/examples/3.php
deleted file mode 100644
index d4ae27a8..00000000
--- a/tests/Metric/System/UnitTesting/examples/3.php
+++ /dev/null
@@ -1,5 +0,0 @@
-<?php
-namespace MyProject\RefreshToken\Repository;
-class MongoDbRefreshTokenRepositoryTest {
-
-}
\ No newline at end of file
diff --git a/tests/Metric/System/UnitTesting/xml/codeception1.xml b/tests/Metric/System/UnitTesting/xml/codeception1.xml
deleted file mode 100644
index 134e1c25..00000000
--- a/tests/Metric/System/UnitTesting/xml/codeception1.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<testsuites>
-    <testsuite name="MyProject.unit" tests="20" assertions="27" failures="0" errors="0" time="0.325358">
-        <testcase name="testGetNewToken" class="MyProject\AccessToken\Repository\MongoDbAccessTokenRepositoryTest" file="tests/Metric/System/UnitTesting/examples/1.php"/>
-        <testcase name="testRevokeAccessToken" class="MyProject\AccessToken\Repository\MongoDbAccessTokenRepositoryTest" file="tests/Metric/System/UnitTesting/examples/1.php"/>
-        <testcase name="testIsAccessTokenRevoked with data set #0" class="MyProject\AccessToken\Repository\MongoDbAccessTokenRepositoryTest" file="tests/Metric/System/UnitTesting/examples/1.php"/>
-        <testcase name="testIsAccessTokenRevoked with data set #1" class="MyProject\AccessToken\Repository\MongoDbAccessTokenRepositoryTest" file="tests/Metric/System/UnitTesting/examples/1.php"/>
-        <testcase name="testGetClientEntity" class="MyProject\Client\Repository\PhpArrayClientRepositoryTest" file="tests/Metric/System/UnitTesting/examples/2.php"/>
-        <testcase name="testGetClientEntityWithoutValidatingSecret" class="MyProject\Client\Repository\PhpArrayClientRepositoryTest" file="tests/Metric/System/UnitTesting/examples/2.php"/>
-        <testcase name="testGetClientEntityWithUnknownIdentifier" class="MyProject\Client\Repository\PhpArrayClientRepositoryTest" file="tests/Metric/System/UnitTesting/examples/2.php"/>
-        <testcase name="testGetClientEntityWithNotAllowedGrantType" class="MyProject\Client\Repository\PhpArrayClientRepositoryTest" file="tests/Metric/System/UnitTesting/examples/2.php"/>
-        <testcase name="testGetClientEntityWithInvalidClientSecret" class="MyProject\Client\Repository\PhpArrayClientRepositoryTest" file="tests/Metric/System/UnitTesting/examples/2.php"/>
-        <testcase name="testGetNewRefreshToken" class="MyProject\RefreshToken\Repository\MongoDbRefreshTokenRepositoryTest" file="tests/Metric/System/UnitTesting/examples/3.php"/>
-        <testcase name="testRevokeRefreshToken" class="MyProject\RefreshToken\Repository\MongoDbRefreshTokenRepositoryTest" file="tests/Metric/System/UnitTesting/examples/3.php"/>
-        <testcase name="testIsRefreshTokenRevoked with data set #0" class="MyProject\RefreshToken\Repository\MongoDbRefreshTokenRepositoryTest" file="tests/Metric/System/UnitTesting/examples/3.php"/>
-        <testcase name="testIsRefreshTokenRevoked with data set #1" class="MyProject\RefreshToken\Repository\MongoDbRefreshTokenRepositoryTest" file="tests/Metric/System/UnitTesting/examples/3.php"/>
-    </testsuite>
-</testsuites>
\ No newline at end of file
diff --git a/tests/Metric/System/UnitTesting/xml/junit1.xml b/tests/Metric/System/UnitTesting/xml/junit1.xml
deleted file mode 100644
index 6f9149a4..00000000
--- a/tests/Metric/System/UnitTesting/xml/junit1.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<testsuites>
-    <testsuite name="PhpMetrics Suite" tests="56" assertions="113" failures="0" errors="0" time="0.241833">
-        <testsuite name="Test\Hal\Application\Config\ParserTest"
-                   file="tests/Application/Config/ParserTest.php" tests="7"
-                   assertions="7" failures="0" errors="0" time="0.005405">
-            <testsuite name="Test\Hal\Application\Config\ParserTest::testICanParseArguments" tests="7" assertions="7"
-                       failures="0" errors="0" time="0.005405">
-                <testcase name="testICanParseArguments with data set #0" assertions="1" time="0.001322"/>
-                <testcase name="testICanParseArguments with data set #1" assertions="1" time="0.000134"/>
-                <testcase name="testICanParseArguments with data set #2" assertions="1" time="0.000113"/>
-                <testcase name="testICanParseArguments with data set #3" assertions="1" time="0.003494"/>
-                <testcase name="testICanParseArguments with data set #4" assertions="1" time="0.000103"/>
-                <testcase name="testICanParseArguments with data set #5" assertions="1" time="0.000121"/>
-                <testcase name="testICanParseArguments with data set #6" assertions="1" time="0.000118"/>
-            </testsuite>
-        </testsuite>
-        <testsuite name="Test\Hal\Component\Issue\IssuerTest"
-                   file="tests/Component/Issuer/IssuerTest.php" tests="2"
-                   assertions="6" failures="0" errors="0" time="0.024517">
-            <testcase name="testICanEnableIssuer" class="Test\Hal\Component\Issue\IssuerTest"
-                      file="tests/Component/Issuer/IssuerTest.php" line="15"
-                      assertions="5" time="0.002145"/>
-            <testcase name="testIssuerDisplayStatements" class="Test\Hal\Component\Issue\IssuerTest"
-                      file="tests/Component/Issuer/IssuerTest.php" line="35"
-                      assertions="1" time="0.022372"/>
-        </testsuite>
-    </testsuite>
-</testsuites>
\ No newline at end of file
diff --git a/tests/Metric/examples/annotations1.php b/tests/Metric/examples/annotations1.php
deleted file mode 100644
index 9f333c3a..00000000
--- a/tests/Metric/examples/annotations1.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-namespace A {
-
-    class Route
-    {
-    }
-}
-
-namespace B {
-
-    class Json
-    {
-
-    }
-
-    class Nothing {
-
-    }
-}
-namespace C {
-
-    use A\Route;
-    use B\Json;
-
-    class A
-    {
-        /**
-         * @Route
-         * @Nohing
-         * @Json("xyz")
-         */
-        public function fooAction()
-        {
-
-        }
-
-    }
-}
\ No newline at end of file
diff --git a/tests/Metric/examples/cyclomatic1.php b/tests/Metric/examples/cyclomatic1.php
deleted file mode 100644
index 8b87dfa7..00000000
--- a/tests/Metric/examples/cyclomatic1.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-class A {
-    public function foo1()
-    {
-        if(true) {
-            if(false) {
-
-            }
-        }
-    }
-
-    public function foo2()
-    {
-        if(true) {
-
-        } else {
-	        if (true) {
-
-	        } else if (true) {
-
-	        } elseif (true) {
-
-	        } elseif (true) {
-
-	        }
-        }
-    }
-
-    public function foo3()
-    {
-    }
-}
-
-class B {
-    public function foo()
-    {
-        if(true) {
-
-        }
-
-        foreach([] as $foo) {
-            if(false) {
-                continue;
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/tests/Metric/examples/cyclomatic_anon.php b/tests/Metric/examples/cyclomatic_anon.php
deleted file mode 100644
index fc5d267a..00000000
--- a/tests/Metric/examples/cyclomatic_anon.php
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php
-
-namespace Foo;
-
-class C
-{
-    public function foo1()
-    {
-        return new class
-        {
-        };
-    }
-}
diff --git a/tests/Metric/examples/cyclomatic_full.php b/tests/Metric/examples/cyclomatic_full.php
deleted file mode 100644
index d122b771..00000000
--- a/tests/Metric/examples/cyclomatic_full.php
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-class SwitchCase // ccn2: 4
-{
-    function __invoke()
-    {
-        switch ('abc') {
-            case 'abc':
-            case 'def':
-            case 'hij':
-                break;
-            default:
-        }
-    }
-}
-
-class IfElseif // ccn2: 7
-{
-    function __invoke()
-    {
-        if (true) {
-            if (true) {
-            } elseif (true) {
-            } else {
-            }
-        } elseif (true) {
-            if (false) {
-            }
-        }
-
-        if (true) {
-        }
-    }
-}
-
-class Loops // ccn2: 5
-{
-    function __invoke()
-    {
-        while (true) {
-            do {
-            } while (false);
-        }
-        foreach ([] as $each) {
-            for ($i = 0; $i < 0; ++$i) {
-            }
-        }
-    }
-}
-
-class CatchIt // ccn2: 3
-{
-    function __invoke()
-    {
-        try {
-        } catch (Exception $e) {
-        } catch (Throwable $e) {
-        } finally {
-        }
-    }
-}
-
-class Logical // ccn2: 11
-{
-    function __invoke()
-    {
-        $a = (true || false) && (false && true) || (true xor false);
-        $b = $a ? 1 : 2;
-        $c = $b ?: 0;
-        $d = $b ?? $c;
-        $e = $b <=> $d;
-    }
-}
diff --git a/tests/Metric/examples/externals1.php b/tests/Metric/examples/externals1.php
deleted file mode 100644
index c1ad6c12..00000000
--- a/tests/Metric/examples/externals1.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-namespace {
-    class A {
-        public function foo($foo, C $c) : H
-        {
-             $x = new B;
-            D::foo();
-        }
-    }
-    class B {
-        public function baz(array $array)
-        {
-
-        }
-    }
-    class C {
-        public static function create()
-        {
-            return new self();
-        }
-    }
-    class D {
-
-    }
-    class E extends D implements F, G {
-        public function __construct()
-        {
-            parent::__construct();
-        }
-    }
-    interface F extends G, H {
-
-    }
-    interface G {
-
-    }
-    interface H {
-
-    }
-}
-
-namespace NS1 {
-    use NS2\B;
-    class A {
-        public function foo()
-        {
-            $a = new B;
-        }
-    }
-}
-namespace NS2 {
-    class B {
-
-    }
-}
\ No newline at end of file
diff --git a/tests/Metric/examples/halstead1.php b/tests/Metric/examples/halstead1.php
deleted file mode 100644
index 5436ee42..00000000
--- a/tests/Metric/examples/halstead1.php
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-function twice($a) {
-    return 2 * $a;
-}
\ No newline at end of file
diff --git a/tests/Metric/examples/halstead2.php b/tests/Metric/examples/halstead2.php
deleted file mode 100644
index 95563162..00000000
--- a/tests/Metric/examples/halstead2.php
+++ /dev/null
@@ -1,5 +0,0 @@
-<?php
-function maxi ($a, $b){
-    if ($a > $b) return $a;
-    return $b;
-}
\ No newline at end of file
diff --git a/tests/Metric/examples/halstead3.php b/tests/Metric/examples/halstead3.php
deleted file mode 100644
index c4891ca6..00000000
--- a/tests/Metric/examples/halstead3.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-function f_switch($a){
-    switch ($a){
-        case 0 :
-            printf("zero");
-        case 10 :
-            printf("an even number");
-            break;
-        default:
-            printf("I don't know that one");
-            return -1;
-            break;
-    }
-    return 0;
-}
\ No newline at end of file
diff --git a/tests/Metric/examples/halstead4.php b/tests/Metric/examples/halstead4.php
deleted file mode 100644
index 817673ec..00000000
--- a/tests/Metric/examples/halstead4.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-function f_while($a){
-    $i = 2;
-    if ($a < 0) return 0;
-    while ($a > 0){
-        $a -= 100;
-        $i *= 2;
-    }
-    return $i;
-}
\ No newline at end of file
diff --git a/tests/Metric/examples/kan1.php b/tests/Metric/examples/kan1.php
deleted file mode 100644
index f682efe1..00000000
--- a/tests/Metric/examples/kan1.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-class A {
-    public function foo()
-    {
-        if(true) {
-
-        }
-
-        switch(true) {
-            case false:
-                break;
-        }
-
-        switch(true) {
-            case false:
-                break;
-        }
-
-
-        while(false) {
-
-        }
-
-    }
-}
\ No newline at end of file
diff --git a/tests/Metric/examples/lcom1.php b/tests/Metric/examples/lcom1.php
deleted file mode 100644
index 97207694..00000000
--- a/tests/Metric/examples/lcom1.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-class MyClassA {
-
-    private $a;
-
-    public function a()
-    {
-        $this->b();
-    }
-
-    public function b()
-    {
-        $this->x = 1;
-    }
-
-    public function c()
-    {
-        $this->x = 2;
-    }
-
-
-    public function z()
-    {
-        $this->y();
-    }
-
-    public function y()
-    {
-
-    }
-}
\ No newline at end of file
diff --git a/tests/Metric/examples/loc1.php b/tests/Metric/examples/loc1.php
deleted file mode 100644
index 133b7150..00000000
--- a/tests/Metric/examples/loc1.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-class A {
-
-    /**
-     * This a long comment
-     *
-     * @return int
-     */
-    public function x()
-    {
-        // any comment
-        // another comment
-        $x = 1 + 1;
-        $x = 1 + 1;
-        $x = 1 + 1;
-        $x = 1 + 1; // a command in a line
-        echo 'http://www.phpmetrics.org/';
-        return $x;
-    }
-}
-
-/**
- * Class B
- * @package Foo
- */
-class B {
-
-    public function x()
-    {
-        $x = 1 + 1;
-        return $x;
-    }
-}
diff --git a/tests/Metric/examples/nbmethods1.php b/tests/Metric/examples/nbmethods1.php
deleted file mode 100644
index 47dc7829..00000000
--- a/tests/Metric/examples/nbmethods1.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-class A
-{
-    private $a;
-
-    private $b;
-
-    public function foo($a)
-    {
-        return $a + 1;
-    }
-
-    public function bar()
-    {
-        $this->a = null;
-    }
-
-    private function baz()
-    {
-        $this->b = $this->b * 3;
-    }
-
-    public function getA()
-    {
-        return $this->a;
-    }
-
-    public function setA($a)
-    {
-        $this->a = $a;
-    }
-
-    public function getB()
-    {
-        return $this->b;
-    }
-
-    public function setB($b)
-    {
-        $this->b = (string)$b;
-        return $this;
-    }
-
-}
\ No newline at end of file
diff --git a/tests/Metric/examples/php8.4.dereferencing_new.php b/tests/Metric/examples/php8.4.dereferencing_new.php
deleted file mode 100644
index b3a4036c..00000000
--- a/tests/Metric/examples/php8.4.dereferencing_new.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-namespace {
-    class A {
-        public function foo()
-        {
-             new \NS1\B()->foo();
-        }
-    }
-}
-
-namespace NS1 {
-    class B {
-        public function foo()
-        {
-
-        }
-    }
-}
diff --git a/tests/Metric/examples/systemcomplexity1.php b/tests/Metric/examples/systemcomplexity1.php
deleted file mode 100644
index 16ecc2ab..00000000
--- a/tests/Metric/examples/systemcomplexity1.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-class A {
-
-    public function foo($a, $b, $c)
-    {
-        if(true) {
-            return $c;
-        } else {
-            return $b;
-        }
-
-        self::bar();
-        static::bar();
-        $this->foo();
-
-        (new B)->bar();
-        $B = new B;
-        $B->bar();
-        (new C)->bar();
-
-        $B::foo();
-        B::foo();
-        C::foo();
-    }
-
-    public static function bar()
-    {
-
-    }
-}
-
-class B {
-
-    public function bar()
-    {
-
-    }
-
-    public static function foo()
-    {
-
-    }
-}
-
-class C {
-
-    public function bar()
-    {
-
-    }
-
-    public static function foo()
-    {
-
-    }
-}
diff --git a/tests/PhpUnit/WithAnalyzer.php b/tests/PhpUnit/WithAnalyzer.php
deleted file mode 100644
index cf29f49f..00000000
--- a/tests/PhpUnit/WithAnalyzer.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-
-namespace Test\Hal\PhpUnit;
-
-use Hal\Application\Analyze;
-use Hal\Application\Config\Config;
-use Hal\Component\File\Finder;
-use Hal\Component\Issue\Issuer;
-use Hal\Component\Output\TestOutput;
-use Hal\Metric\Metrics;
-
-trait WithAnalyzer
-{
-    public function analyze(array $filesToAnalyze = [])
-    {
-        $finder = new Finder();
-        $config = new Config();
-        $files = $finder->fetch($filesToAnalyze);
-
-        // disable composer
-        $config->set('composer', false);
-
-        $output = new TestOutput();
-        $issuer = new Issuer($output);
-        return (new Analyze($config, $output, $issuer))->run($files);
-    }
-}
diff --git a/tests/Polyfill/TestCaseCompatible.php b/tests/Polyfill/TestCaseCompatible.php
deleted file mode 100644
index 08a6d0bb..00000000
--- a/tests/Polyfill/TestCaseCompatible.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-
-namespace Polyfill;
-
-if (!method_exists(\PHPUnit\Framework\Assert::class, 'assertStringContainsString')) {
-    trait TestCaseCompatible
-    {
-        public function assertStringContainsString($needle, $haystack, $message = '')
-        {
-            $this->assertContains($needle, $haystack, $message);
-        }
-
-        public function assertMatchesRegularExpression($pattern, $string, $message = '')
-        {
-            $this->assertRegExp($pattern, $string, $message);
-        }
-    }
-} else {
-    trait TestCaseCompatible
-    {
-    }
-}
-
-
diff --git a/tests/Polyfill/each.php b/tests/Polyfill/each.php
deleted file mode 100644
index bfc53169..00000000
--- a/tests/Polyfill/each.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-
-//
-// This code is a copy of https://github.com/ChristiaanBye/polyfill-each
-// @see https://github.com/ChristiaanBye/polyfill-each/blob/master/LICENSE
-//
-// @licence MIT
-// @author ChristiaanBye
-//
-if (!function_exists('each')) {
-    /**
-     * @param array $array Although the actual function accepted objects, it was discouraged to pass them. Hence for the
-     *                     shim only an array is supported.
-     *
-     * @return array|false
-     */
-    function each(array &$array)
-    {
-        $key   = key($array);
-        $value = current($array);
-
-        if ($key === null) {
-            // key() returns null if the array pointer is beyond the list of element or if the array is empty. If the
-            // same scenario occurred in the each() function, a false was returned instead. Hence returning false here
-            return false;
-        }
-
-        // Advance the array pointer before returning
-        next($array);
-
-        return array(
-            1       => $value,
-            'value' => $value,
-            0       => $key,
-            'key'   => $key
-        );
-    }
-}
diff --git a/tests/Polyfill/testcase.php b/tests/Polyfill/testcase.php
deleted file mode 100644
index 0a8727ca..00000000
--- a/tests/Polyfill/testcase.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-/**
- * Polyfill for PHPUnit\Framework\TestCase vs PHPUnit_Framework_TestCase
- */
-if (!class_exists('PHPUnit\Framework\TestCase') && class_exists('PHPUnit_Framework_TestCase')) {
-    class_alias('PHPUnit_Framework_TestCase', 'PHPUnit\Framework\TestCase');
-}
diff --git a/tests/Report/Html/ComplexityReportRegressionTest.php b/tests/Report/Html/ComplexityReportRegressionTest.php
deleted file mode 100644
index 9e60892a..00000000
--- a/tests/Report/Html/ComplexityReportRegressionTest.php
+++ /dev/null
@@ -1,105 +0,0 @@
-<?php
-
-namespace Test\Hal\Reporter\Html;
-
-use DOMNode;
-use Hal\Application\Config\Config;
-use Hal\Component\Output\TestOutput;
-use Hal\Metric\Group\Group;
-use Hal\Metric\Metrics;
-use Hal\Report\Html\Reporter;
-use PHPUnit\Framework\Attributes\DataProvider;
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\DomCrawler\Crawler;
-
-/**
- * @group reporter
- * @group html
- */
-class ComplexityReportRegressionTest extends TestCase
-{
-    /**
-     * @dataProvider tableHeaderDataProvider
-     */
-    #[DataProvider('tableHeaderDataProvider')]
-    public function testComplexityHtmlReportContainsCorrectOrderOfTableColumns($junitEnabled, $expectedTableHeader): void
-    {
-        $config = new Config();
-        $output = new TestOutput();
-        $reporter = new Reporter($config, $output);
-
-        // prepares data for report
-        $groups = [];
-        $groups[] = new Group('group', '.*');
-        $config->set('groups', $groups);
-
-        if ($junitEnabled) {
-            $config->set('junit', ['file' => '/tmp/junit.xml']);
-        }
-
-        // prepares destination
-        $destination = implode(DIRECTORY_SEPARATOR, [
-            sys_get_temp_dir(),
-            'phpmetrics-html' . uniqid('', true)
-        ]);
-
-        $config->set('report-html', $destination);
-
-        // generates report
-        $metrics = new Metrics();
-        $reporter->generate($metrics);
-
-        // ensure complexity report contains expected table header columns
-        $content = file_get_contents(sprintf('%s/complexity.html', $destination));
-        $actualTableHeader = $this->getActualTableHeader($content);
-
-        $this->assertEquals($expectedTableHeader, $actualTableHeader);
-    }
-
-    public static function tableHeaderDataProvider()
-    {
-        $defaultTableHeader = [
-            'Class',
-            'WMC',
-            'Class cycl.',
-            'Max method cycl.',
-            'Relative system complexity',
-            'Relative data complexity',
-            'Relative structural complexity',
-            'Bugs',
-            'Defects',
-        ];
-
-        $junitTableHeader = array_merge($defaultTableHeader, [
-            'Unit testsuites calling it'
-        ]);
-
-        return [
-            'junit disabled' => [false, $defaultTableHeader],
-            'junit enabled' => [true, $junitTableHeader],
-        ];
-    }
-
-    private function getActualTableHeader($content)
-    {
-        $dom = new \DOMDocument();
-        @$dom->loadHTML($content);
-
-        $xpath = new \DOMXPath($dom);
-        $rows = $xpath->query('//table[contains(concat(" ",normalize-space(@class)," ")," js-sort-table ")]/thead/tr');
-
-        if ($rows->length === 0) {
-            return [];
-        }
-
-        $headerRow = $rows->item(0);
-        $headers = [];
-        foreach ($headerRow->childNodes as $node) {
-            if ($node->nodeType === XML_ELEMENT_NODE) {
-                $headers[] = $node->textContent;
-            }
-        }
-
-        return $headers;
-    }
-}
diff --git a/tests/Report/Html/ReporterTest.php b/tests/Report/Html/ReporterTest.php
deleted file mode 100644
index 42d8bedb..00000000
--- a/tests/Report/Html/ReporterTest.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-
-namespace Test\Hal\Reporter\Html;
-
-use Hal\Application\Config\Config;
-use Hal\Component\Output\TestOutput;
-use Hal\Metric\Group\Group;
-use Hal\Metric\Metrics;
-use Hal\Report\Html\Reporter;
-use PHPUnit\Framework\TestCase;
-use Polyfill\TestCaseCompatible;
-
-/**
- * @group reporter
- * @group html
- */
-class ReporterTest extends TestCase
-{
-    use TestCaseCompatible;
-
-    public function testICanGenerateHtmlReport(): void
-    {
-        $config = new Config();
-        $output = new TestOutput();
-        $reporter = new Reporter($config, $output);
-
-        // prepares data for report
-        $groups = [];
-        $groups[] = new Group('group1', '.*');
-        $groups[] = new Group('group2', '.*');
-        $config->set('groups', $groups);
-
-        // prepares destination
-        $destination = implode(DIRECTORY_SEPARATOR, [
-            sys_get_temp_dir(),
-            'phpmetrics-html' . uniqid('', true)
-        ]);
-
-        $config->set('report-html', $destination);
-
-        // generates report
-        $metrics = new Metrics();
-        $reporter->generate($metrics);
-
-        // ensure files are generated
-        $this->assertFileExists(sprintf('%s/index.html', $destination));
-        $this->assertFileExists(sprintf('%s/coupling.html', $destination));
-        $this->assertFileExists(sprintf('%s/css/style.css', $destination));
-
-        // ensure basic content is generated
-        $content = file_get_contents(sprintf('%s/index.html', $destination));
-        $this->assertStringContainsString('PhpMetrics report', $content);
-    }
-}
diff --git a/tests/Search/SearchFactoryTest.php b/tests/Search/SearchFactoryTest.php
deleted file mode 100644
index 68a7c0e6..00000000
--- a/tests/Search/SearchFactoryTest.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-namespace Test\Hal\Search;
-
-use Hal\Search\SearchesFactory;
-use PHPUnit\Framework\TestCase;
-
-/**
- * @group search
- */
-class SearchFactoryTest extends TestCase
-{
-
-    public function testIShoulBeAbleToFactorySearches(): void
-    {
-        $config = [
-            'search1' => [
-                'type' => 'class'
-            ],
-            'search2' => [
-                'type' => 'interface'
-            ]
-        ];
-        $factory = new SearchesFactory();
-        $searches = $factory->factory($config);
-
-        $this->assertCount(2, $searches->all());
-        $this->assertEquals('class', $searches->get('search1')->getConfig()->type);
-        $this->assertEquals('interface', $searches->get('search2')->getConfig()->type);
-        $this->assertTrue($searches->has('search1'));
-        $this->assertFalse($searches->has('searchNO'));
-    }
-}
diff --git a/tests/Search/SearchTest.php b/tests/Search/SearchTest.php
deleted file mode 100644
index 9ff43c9e..00000000
--- a/tests/Search/SearchTest.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-
-namespace Test\Hal\Search;
-
-use Hal\Metric\ClassMetric;
-use Hal\Metric\InterfaceMetric;
-use Hal\Metric\Metric;
-use Hal\Search\Search;
-use PHPUnit\Framework\Attributes\DataProvider;
-use PHPUnit\Framework\TestCase;
-
-/**
- * @group search
- */
-class SearchTest extends TestCase
-{
-
-    public function testSearchCanReduceSearchByName(): void
-    {
-        $config = [
-            'nameMatches' => 'awesome'
-        ];
-
-        $metric = $this->getMockBuilder(Metric::class)->getMock();
-        $metric
-            ->expects($this->once())
-            ->method('getName')
-            ->willReturn('My\\AwesomeClass');
-
-        $search = new Search('my-search', $config);
-
-        $this->assertTrue($search->matches($metric));
-    }
-
-    public function testSearchCanReduceSearchByType(): void
-    {
-        $config = [
-            'type' => 'class'
-        ];
-
-        $classMetric = $this->getMockBuilder(ClassMetric::class)->disableOriginalConstructor()->getMock();
-        $interfaceMetric = $this->getMockBuilder(InterfaceMetric::class)->disableOriginalConstructor()->getMock();
-
-        $search = new Search('my-search', $config);
-
-        $this->assertTrue($search->matches($classMetric));
-        $this->assertFalse($search->matches($interfaceMetric));
-    }
-
-    /**
-     * @dataProvider providesMetrics
-     */
-    #[DataProvider('providesMetrics')]
-    public function testSearchCanReduceSearchByMetric($searchExpression, $value, $expected): void
-    {
-        $config = [
-            'ccn' => $searchExpression
-        ];
-
-        $metric = $this->getMockBuilder(Metric::class)->getMock();
-        $metric
-            ->expects($this->once())
-            ->method('get')
-            ->willReturn($value);
-
-        $search = new Search('my-search', $config);
-
-        $this->assertEquals($expected, $search->matches($metric));
-    }
-
-    public static function providesMetrics()
-    {
-        return [
-            ['>=2.5', 6, true],
-            ['>=2.5', 2.5, true],
-            ['>=2.5', 2.4, false],
-            ['>=2.5', 1, false],
-            ['>=2.5', .3, false],
-            ['<3', 2, true],
-            ['<3', 3, false],
-            ['<=3', 3, true],
-            ['=3', 3, true],
-            ['3', 3, true],
-            ['=2', 3, false],
-        ];
-    }
-}
diff --git a/tests/Violation/Class_/BlobTest.php b/tests/Violation/Class_/BlobTest.php
deleted file mode 100644
index 457f70ff..00000000
--- a/tests/Violation/Class_/BlobTest.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
-namespace Test\Hal\Violation\Class_;
-
-use Hal\Metric\ClassMetric;
-use Hal\Violation\Class_\Blob;
-use Hal\Violation\Violations;
-use PHPUnit\Framework\Attributes\DataProvider;
-
-/**
- * @group violation
- */
-class BlobTest extends \PHPUnit\Framework\TestCase
-{
-    /**
-     * @dataProvider provideExamples
-     */
-    #[DataProvider('provideExamples')]
-    public function testGlobIsFound($expected, $nbMethodsPublic, $lcom, $nbExternals): void
-    {
-        $class = $this->getMockBuilder(ClassMetric::class)->disableOriginalConstructor()->getMock();
-
-        $violations = new Violations();
-        $class->method('get')->willReturnCallback(function ($param) use (
-            $violations,
-            $nbMethodsPublic,
-            $lcom,
-            $nbExternals
-        ) {
-            switch ($param) {
-                case 'nbMethodsPublic':
-                    return $nbMethodsPublic;
-                case 'lcom':
-                    return $lcom;
-                case 'externals':
-                    return array_pad([], $nbExternals, '');
-                case 'violations':
-                    return $violations;
-            }
-        });
-
-        $object = new Blob();
-        $object->apply($class);
-        $this->assertEquals($expected, $class->get('violations')->count());
-    }
-
-    public static function provideExamples()
-    {
-        return [
-            [1, 9, 3, 10],
-            [0, 9, 3, 5],
-            [0, 9, 1.4, 10],
-            [0, 3, 3, 10],
-        ];
-    }
-}
diff --git a/tests/Violation/Package/StableAbstractionsPrincipleTest.php b/tests/Violation/Package/StableAbstractionsPrincipleTest.php
deleted file mode 100644
index 2475dc6a..00000000
--- a/tests/Violation/Package/StableAbstractionsPrincipleTest.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-
-namespace Violation\Package;
-
-use Hal\Metric\Metric;
-use Hal\Metric\PackageMetric;
-use Hal\Violation\Package\StableAbstractionsPrinciple;
-use Hal\Violation\Violations;
-use PHPUnit\Framework\Attributes\DataProvider;
-use \PHPUnit\Framework\TestCase;
-
-/**
- * @group violation
- */
-class StableAbstractionsPrincipleTest extends TestCase
-{
-    public function testItIgnoresNonPackageMetrics(): void
-    {
-        $metric = $this->getMockBuilder(Metric::class)
-            ->disableOriginalConstructor()
-            ->getMock();
-
-        $metric->expects($this->never())
-            ->method('get')
-            ->with('violations');
-
-        $object = new StableAbstractionsPrinciple();
-
-        $object->apply($metric);
-    }
-
-    /**
-     * @dataProvider provideExamples
-     */
-    #[DataProvider('provideExamples')]
-    public function testItAddsViolationsIfAPackageIsEitherStableAndConcreteOrInstableAndAbstract($abstractness, $instability, $expectedViolationCount): void
-    {
-        $metric = new PackageMetric('package');
-        $metric->set('violations', new Violations());
-        $metric->setNormalizedDistance($abstractness + $instability - 1);
-
-        $object = new StableAbstractionsPrinciple();
-
-        $object->apply($metric);
-
-        $this->assertSame($expectedViolationCount, $metric->get('violations')->count());
-    }
-
-    public static function provideExamples()
-    {
-        return [
-            'highly instable and highly concrete' => [1, 0, 0],
-            'highly stable and highly abstract' => [0, 1, 0],
-            'highly instable and highly abstract' => [1, 1, 1],
-            'highly stable and highly concrete' => [0, 0, 1],
-            'instable and concrete' => [0.76, 0.24, 0],
-            'stable and abstract' => [0.24, 0.76, 0],
-            'instable and abstract' => [0.76, 0.76, 1],
-            'stable and concrete' => [0.24, 0.24, 1],
-        ];
-    }
-}
diff --git a/tests/Violation/Package/StableDependenciesPrincipleTest.php b/tests/Violation/Package/StableDependenciesPrincipleTest.php
deleted file mode 100644
index 6e4cbce3..00000000
--- a/tests/Violation/Package/StableDependenciesPrincipleTest.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-namespace Violation\Package;
-
-use Hal\Metric\Metric;
-use Hal\Metric\PackageMetric;
-use Hal\Violation\Package\StableDependenciesPrinciple;
-use Hal\Violation\Violations;
-use PHPUnit\Framework\Attributes\DataProvider;
-use \PHPUnit\Framework\TestCase;
-
-/**
- * @group violation
- */
-class StableDependenciesPrincipleTest extends TestCase
-{
-    public function testItIgnoresNonPackageMetrics(): void
-    {
-        $metric = $this->getMockBuilder(Metric::class)->getMock();
-        $metric->expects($this->never())->method('get');
-        $object = new StableDependenciesPrinciple();
-
-        $object->apply($metric);
-    }
-
-    /**
-     * @dataProvider provideExamples
-     */
-    #[DataProvider('provideExamples')]
-    public function testItAddsViolationsIfOneDependentPackageIsMoreUnstableOrAsUnstableAsThePackageItself(
-        $packageInstability,
-        array $dependentInstabilities,
-        $expectedViolationCount
-    ): void {
-        $violations = new Violations();
-        $metric = $this->getMockBuilder(PackageMetric::class)->disableOriginalConstructor()->getMock();
-        $metric->method('getInstability')->willReturn($packageInstability);
-        $metric->method('getDependentInstabilities')->willReturn($dependentInstabilities);
-        $metric->method('get')->willReturn($violations);
-
-        $object = new StableDependenciesPrinciple();
-
-        $object->apply($metric);
-
-        $this->assertSame($expectedViolationCount, $violations->count());
-    }
-
-    public static function provideExamples()
-    {
-        return [
-            'no dependents' => [2.2, [], 0],
-            'dependents with a lower instability' => [2.2, [2.0], 0],
-            'dependents with the same instability' => [2.2, [2.2], 1],
-            'dependents with a bigger instability' => [2.2, [2.3], 1],
-            'multiple dependents with a bigger instability' => [2.5, [2.2, 3.0, 2.5, 4.5], 1],
-        ];
-    }
-}
diff --git a/tests/Violation/examples/godobject.php b/tests/Violation/examples/godobject.php
deleted file mode 100644
index e7121e18..00000000
--- a/tests/Violation/examples/godobject.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-class IAmBlob {
-    private $a;
-    private $b;
-    private $c;
-    private $d;
-
-    public function flow1_A()
-    {
-        $this->a = 1;
-    }
-
-    public function flow1_B()
-    {
-        return $this->a * 3 + $this->b;
-    }
-
-    public function flow1_C()
-    {
-        $this->b = 1;
-    }
-
-    public function flow2_A()
-    {
-        $this->c = 1;
-        $a = new A;
-        $b = new B;
-    }
-
-    public function flow3_A()
-    {
-        $this->d = 1;
-        $a = new C;
-        $b = new D;
-    }
-
-    public function flow3_B()
-    {
-        return $this->d  * 3;
-    }
-
-    public function flow3_C()
-    {
-        return $this->d  * 4;
-        $a = new E;
-        $b = new F;
-    }
-
-    public function flow3_D()
-    {
-        return $this->d  * 5;
-    }
-
-    public function flow3_E()
-    {
-        return $this->d  * 6;
-    }
-}
-
-class IAmGood {
-    public function foo($x)
-    {
-        return $x * 3;
-    }
-}
\ No newline at end of file
diff --git a/tests/Violation/examples/singleton.php b/tests/Violation/examples/singleton.php
deleted file mode 100644
index 922c5280..00000000
--- a/tests/Violation/examples/singleton.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-class MySingleton {
-    private function __construct() {}
-
-    public static function foo() {
-        return new self;
-    }
-}
\ No newline at end of file
diff --git a/tests/binary/BinTest.php b/tests/binary/BinTest.php
deleted file mode 100644
index 839d4154..00000000
--- a/tests/binary/BinTest.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-namespace Test\Binary;
-
-use PHPUnit\Framework\Attributes\Group;
-use Polyfill\TestCaseCompatible;
-
-/**
- * @group binary
- */
-#[Group('binary')]
-class BinTest extends \PHPUnit\Framework\TestCase
-{
-    use TestCaseCompatible;
-
-    private $phar;
-
-    public function setUp(): void
-    {
-        parent::setUp();
-        $this->phar = __DIR__ . '/../../bin/phpmetrics';
-    }
-
-    public function testICanRunBinFile(): void
-    {
-        $command = sprintf('%s --version', $this->phar);
-        $r = shell_exec($command);
-        $this->assertStringContainsString('PhpMetrics', $r);
-    }
-
-    public function testICanProvideOneDirectoryToParse(): void
-    {
-        $command = sprintf('%s --exclude="" %s 2>&1', $this->phar, __DIR__ . '/examples/1');
-        $r = shell_exec($command);
-        $this->assertStringContainsString('Object oriented programming', $r);
-        $this->assertStringContainsString('LOC', $r);
-        $this->assertMatchesRegularExpression('!Classes\s+2!', $r);
-    }
-
-    public function testICanProvideMultipleDirectoriesToParse(): void
-    {
-        $command = sprintf(
-            '%s --exclude="" %s,%s  2>&1',
-            $this->phar,
-            __DIR__ . '/examples/1',
-            __DIR__ . '/examples/2'
-        );
-        $r = shell_exec($command);
-        $this->assertStringContainsString('Object oriented programming', $r);
-        $this->assertStringContainsString('LOC', $r);
-        $this->assertMatchesRegularExpression('!Classes\s+4!', $r);
-    }
-}
diff --git a/tests/binary/PharTest.php b/tests/binary/PharTest.php
deleted file mode 100644
index a56835e3..00000000
--- a/tests/binary/PharTest.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-namespace Test\Binary;
-
-use PHPUnit\Framework\Attributes\Group;
-use Polyfill\TestCaseCompatible;
-
-/**
- * @group binary
- */
-#[Group('binary')]
-class PharTest extends \PHPUnit\Framework\TestCase
-{
-
-    use TestCaseCompatible;
-
-    private $phar;
-
-    public function setUp(): void
-    {
-        parent::setUp();
-        $this->phar = __DIR__ . '/../../releases/phpmetrics.phar';
-    }
-
-    public function testICanRunPhar(): void
-    {
-        $command = sprintf('%s --version', $this->phar);
-        $r = shell_exec($command);
-        $this->assertStringContainsString('PhpMetrics', $r);
-    }
-
-    public function testICanProvideOneDirectoryToParse(): void
-    {
-        $command = sprintf('%s --exclude="" %s 2>&1', $this->phar, __DIR__ . '/examples/1');
-        $r = shell_exec($command);
-        $this->assertStringContainsString('Object oriented programming', $r);
-        $this->assertStringContainsString('LOC', $r);
-        $this->assertMatchesRegularExpression('!Classes\s+2!', $r);
-    }
-
-    public function testICanProvideMultipleDirectoriesToParse(): void
-    {
-        $command = sprintf(
-            '%s --exclude="" %s,%s  2>&1',
-            $this->phar,
-            __DIR__ . '/examples/1',
-            __DIR__ . '/examples/2'
-        );
-        $r = shell_exec($command);
-        $this->assertStringContainsString('Object oriented programming', $r);
-        $this->assertStringContainsString('LOC', $r);
-        $this->assertMatchesRegularExpression('!Classes\s+4!', $r);
-    }
-}
diff --git a/tests/binary/ReportTest.php b/tests/binary/ReportTest.php
deleted file mode 100644
index 2a6b10d8..00000000
--- a/tests/binary/ReportTest.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-namespace Test\Binary;
-
-use PHPUnit\Framework\Attributes\Group;
-use Polyfill\TestCaseCompatible;
-
-/**
- * @group binary
- */
-#[Group('binary')]
-class BinReportTest extends \PHPUnit\Framework\TestCase
-{
-    use TestCaseCompatible;
-
-    private $phar;
-
-    public function setUp(): void
-    {
-        parent::setUp();
-        $this->phar = __DIR__ . '/../../bin/phpmetrics';
-    }
-
-    public function testICanRunBinFile(): void
-    {
-        $command = sprintf('%s --version', $this->phar);
-        $r = shell_exec($command);
-        $this->assertStringContainsString('PhpMetrics', $r);
-    }
-
-    public function testICanProvideOneDirectoryToParse(): void
-    {
-        $command = sprintf('%s --exclude="" %s 2>&1', $this->phar, __DIR__ . '/examples/1');
-        $r = shell_exec($command);
-        $this->assertStringContainsString('Object oriented programming', $r);
-        $this->assertStringContainsString('LOC', $r);
-        $this->assertMatchesRegularExpression('!Classes\s+2!', $r);
-    }
-
-    public function testICanProvideMultipleDirectoriesToParse(): void
-    {
-        $command = sprintf(
-            '%s --exclude="" %s,%s  2>&1',
-            $this->phar,
-            __DIR__ . '/examples/1',
-            __DIR__ . '/examples/2'
-        );
-        $r = shell_exec($command);
-        $this->assertStringContainsString('Object oriented programming', $r);
-        $this->assertStringContainsString('LOC', $r);
-        $this->assertMatchesRegularExpression('!Classes\s+4!', $r);
-    }
-
-    public function testICanGenerateCsvReport(): void
-    {
-        $destination = '/tmp/report.csv';
-        if (file_exists($destination)) {
-            unlink($destination);
-        }
-        $command = sprintf(
-            '%s --report-csv="%s" %s,%s  2>&1',
-            $this->phar,
-            $destination,
-            __DIR__ . '/examples/1',
-            __DIR__ . '/examples/2'
-        );
-        shell_exec($command);
-        $this->assertFileExists($destination);
-    }
-
-    public function testICanGenerateJsonReport(): void
-    {
-        $destination = '/tmp/report.json';
-        if (file_exists($destination)) {
-            unlink($destination);
-        }
-        $command = sprintf(
-            '%s --report-json="%s" %s,%s  2>&1',
-            $this->phar,
-            $destination,
-            __DIR__ . '/examples/1',
-            __DIR__ . '/examples/2'
-        );
-        shell_exec($command);
-        $this->assertFileExists($destination);
-        $this->assertJson(file_get_contents($destination));
-    }
-}
diff --git a/tests/binary/StandaloneTest.php b/tests/binary/StandaloneTest.php
deleted file mode 100644
index 5d6d6448..00000000
--- a/tests/binary/StandaloneTest.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-namespace Test\Hal\binary;
-
-use PHPUnit\Framework\Attributes\Group;
-use Polyfill\TestCaseCompatible;
-
-/**
- * @group binary
- */
-#[Group('binary')]
-class StandaloneTest extends \PHPUnit\Framework\TestCase
-{
-
-    use TestCaseCompatible;
-
-    private $binary;
-
-    public function setUp(): void
-    {
-        parent::setUp();
-        $this->binary = __DIR__ . '/../../releases/phpmetrics-linux-x86_64';
-    }
-
-    public function testICanRunStandaloneBinary(): void
-    {
-        $command = sprintf('%s --version', $this->binary);
-        $r = shell_exec($command);
-        $this->assertStringContainsString('PhpMetrics', $r);
-    }
-
-    public function testICanProvideOneDirectoryToParse(): void
-    {
-        $command = sprintf('%s --exclude="" %s 2>&1', $this->binary, __DIR__ . '/examples/1');
-        $r = shell_exec($command);
-        $this->assertStringContainsString('Object oriented programming', $r);
-        $this->assertStringContainsString('LOC', $r);
-        $this->assertMatchesRegularExpression('!Classes\s+2!', $r);
-    }
-
-    public function testICanProvideMultipleDirectoriesToParse(): void
-    {
-        $command = sprintf(
-            '%s --exclude="" %s,%s  2>&1',
-            $this->binary,
-            __DIR__ . '/examples/1',
-            __DIR__ . '/examples/2'
-        );
-        $r = shell_exec($command);
-        $this->assertStringContainsString('Object oriented programming', $r);
-        $this->assertStringContainsString('LOC', $r);
-        $this->assertMatchesRegularExpression('!Classes\s+4!', $r);
-    }
-}
diff --git a/tests/binary/examples/1/file1.php b/tests/binary/examples/1/file1.php
deleted file mode 100644
index c1b40f5e..00000000
--- a/tests/binary/examples/1/file1.php
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-class A {
-
-}
-class B {
-
-}
diff --git a/tests/binary/examples/2/file1.php b/tests/binary/examples/2/file1.php
deleted file mode 100644
index 2011c7ec..00000000
--- a/tests/binary/examples/2/file1.php
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-class C {
-
-}
-class D {
-    
-}
\ No newline at end of file
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
deleted file mode 100644
index dc2a6a2a..00000000
--- a/tests/bootstrap.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-require_once __DIR__ . '/../vendor/autoload.php';
-
-// polyfill for methods of phpunit
-require_once __DIR__ . '/Polyfill/TestCaseCompatible.php';
-
-// polyfill for each() function
-require_once __DIR__ . '/Polyfill/each.php';
-
-// polyfill for \PHPUnit\Framework\TestCase vs \PHPUnit_Framework_TestCase
-require_once __DIR__ . '/Polyfill/testcase.php';
diff --git a/tooling/README.md b/tooling/README.md
deleted file mode 100644
index 7daa4e64..00000000
--- a/tooling/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Tooling
-
-This folder contains external dependencies used for building and testing the project only.
-
-It allows avoiding conflicts with the main project dependencies and to keep the project clean.
diff --git a/tooling/composer.json b/tooling/composer.json
deleted file mode 100644
index fe7409db..00000000
--- a/tooling/composer.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "name": "phpmetrics/tooling",
-    "license": "MIT",
-    "autoload": {
-        "psr-4": {
-            "Phpmetrics\\Tooling\\": "src/"
-        }
-    },
-    "authors": [
-        {
-            "name": "Jean-François Lépine"
-        }
-    ],
-    "require-dev": {
-        "rector/rector": "^2.1"
-    }
-}
