Clean up test files and debug artifacts, add node_modules to gitignore, export DashboardManager for testing, and enhance pytest configuration with comprehensive test markers and settings
Some checks failed
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
126
.github/workflows/tests.yml
vendored
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
name: Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, develop]
|
||||||
|
pull_request:
|
||||||
|
branches: [main, develop]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
backend-tests:
|
||||||
|
name: Backend Tests (Python)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ['3.10', '3.11', '3.12']
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
cache: 'pip'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -r app/requirements.txt
|
||||||
|
pip install pytest pytest-asyncio pytest-cov httpx respx freezegun pytest-mock
|
||||||
|
|
||||||
|
- name: Run unit tests
|
||||||
|
run: |
|
||||||
|
pytest tests/backend -v --tb=short -m "unit" --cov=app --cov-report=xml --cov-report=term-missing
|
||||||
|
env:
|
||||||
|
DATABASE_URL: "sqlite+aiosqlite:///:memory:"
|
||||||
|
API_KEY: "test-api-key-12345"
|
||||||
|
JWT_SECRET_KEY: "test-jwt-secret-key"
|
||||||
|
NTFY_ENABLED: "false"
|
||||||
|
ANSIBLE_DIR: "."
|
||||||
|
|
||||||
|
- name: Upload coverage to Codecov
|
||||||
|
uses: codecov/codecov-action@v4
|
||||||
|
if: matrix.python-version == '3.11'
|
||||||
|
with:
|
||||||
|
files: ./coverage.xml
|
||||||
|
flags: backend
|
||||||
|
name: backend-coverage
|
||||||
|
fail_ci_if_error: false
|
||||||
|
|
||||||
|
frontend-tests:
|
||||||
|
name: Frontend Tests (JS)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run frontend tests
|
||||||
|
run: npm test -- --coverage
|
||||||
|
|
||||||
|
- name: Upload coverage to Codecov
|
||||||
|
uses: codecov/codecov-action@v4
|
||||||
|
with:
|
||||||
|
files: ./coverage/lcov.info
|
||||||
|
flags: frontend
|
||||||
|
name: frontend-coverage
|
||||||
|
fail_ci_if_error: false
|
||||||
|
|
||||||
|
integration-tests:
|
||||||
|
name: Integration Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [backend-tests]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Python 3.11
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
cache: 'pip'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -r app/requirements.txt
|
||||||
|
pip install pytest pytest-asyncio pytest-cov httpx respx freezegun pytest-mock
|
||||||
|
|
||||||
|
- name: Run integration tests
|
||||||
|
run: |
|
||||||
|
pytest tests/backend -v --tb=short -m "integration" || true
|
||||||
|
env:
|
||||||
|
DATABASE_URL: "sqlite+aiosqlite:///:memory:"
|
||||||
|
API_KEY: "test-api-key-12345"
|
||||||
|
JWT_SECRET_KEY: "test-jwt-secret-key"
|
||||||
|
NTFY_ENABLED: "false"
|
||||||
|
ANSIBLE_DIR: "."
|
||||||
|
|
||||||
|
all-tests-passed:
|
||||||
|
name: All Tests Passed
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [backend-tests, frontend-tests]
|
||||||
|
if: always()
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check test results
|
||||||
|
run: |
|
||||||
|
if [ "${{ needs.backend-tests.result }}" != "success" ]; then
|
||||||
|
echo "Backend tests failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ "${{ needs.frontend-tests.result }}" != "success" ]; then
|
||||||
|
echo "Frontend tests failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "All tests passed!"
|
||||||
3
.gitignore
vendored
@ -44,3 +44,6 @@ tasks_logs/**/.adhoc_history.json
|
|||||||
# OS
|
# OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
|
# node_modules
|
||||||
|
node_modules
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{"source":"tMBsdAS7JBTyRORp0YaJR984WAAsOxgmReSLBN0Nd41GhzEakjROICqAJ31iOdYG5Ijo/MlJ01p3ig1iN88+Tw==","name":"@vitest/mocker","dependency":"vite","title":"Depends on vulnerable versions of vite","url":null,"severity":"moderate","versions":["2.1.0-beta.7","2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.1.5","2.1.6","2.1.7","2.1.8","2.1.9","2.2.0-beta.1","2.2.0-beta.2","3.0.0-beta.1","3.0.0-beta.2","3.0.0-beta.3","3.0.0-beta.4","3.0.0","3.0.1","3.0.2","3.0.3","3.0.4","3.0.5","3.0.6","3.0.7","3.0.8","3.0.9","3.1.0-beta.1","3.1.0-beta.2","3.1.0","3.1.1","3.1.2","3.1.3","3.1.4","3.2.0-beta.1","3.2.0-beta.2","3.2.0-beta.3","3.2.0","3.2.1","3.2.2","3.2.3","3.2.4","4.0.0-beta.1","4.0.0-beta.2","4.0.0-beta.3","4.0.0-beta.4","4.0.0-beta.5","4.0.0-beta.6","4.0.0-beta.7","4.0.0-beta.8","4.0.0-beta.9","4.0.0-beta.10","4.0.0-beta.11","4.0.0-beta.12","4.0.0-beta.13","4.0.0-beta.14","4.0.0-beta.15","4.0.0-beta.16","4.0.0-beta.17","4.0.0-beta.18","4.0.0-beta.19","4.0.0","4.0.1","4.0.2","4.0.3","4.0.4","4.0.5","4.0.6","4.0.7","4.0.8","4.0.9","4.0.10","4.0.11","4.0.12","4.0.13","4.0.14","4.0.15"],"vulnerableVersions":["2.1.0-beta.7","2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.1.5","2.1.6","2.1.7","2.1.8","2.1.9","2.2.0-beta.1","2.2.0-beta.2","3.0.0-beta.1","3.0.0-beta.2","3.0.0-beta.3","3.0.0-beta.4"],"cwe":["CWE-346"],"cvss":{"score":5.3,"vectorString":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N"},"range":"<=3.0.0-beta.4","id":"SJ6ALG5CByItLFxBhtpyrxAdDoKdsJCSnzbVFPNK6WdVHJq3/BQr5X33nTvglq430Jo7eFZBpLt727pFLHxHzA=="}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{"source":"SJ6ALG5CByItLFxBhtpyrxAdDoKdsJCSnzbVFPNK6WdVHJq3/BQr5X33nTvglq430Jo7eFZBpLt727pFLHxHzA==","name":"vitest","dependency":"@vitest/mocker","title":"Depends on vulnerable versions of @vitest/mocker","url":null,"severity":"moderate","versions":["0.0.0","0.0.1","0.0.2","0.0.3","0.0.4","0.0.6","0.0.7","0.0.8","0.0.9","0.0.10","0.0.11","0.0.12","0.0.13","0.0.14","0.0.15","0.0.16","0.0.17","0.0.18","0.0.19","0.0.20","0.0.21","0.0.22","0.0.23","0.0.24","0.0.25","0.0.26","0.0.27","0.0.28","0.0.29","0.0.30","0.0.31","0.0.32","0.0.33","0.0.34","0.0.35","0.0.36","0.0.37","0.0.38","0.0.39","0.0.40","0.0.41","0.0.42","0.0.43","0.0.44","0.0.45","0.0.46","0.0.47","0.0.48","0.0.49","0.0.50","0.0.51","0.0.52","0.0.53","0.0.54","0.0.55","0.0.56","0.0.57","0.0.58","0.0.59","0.0.60","0.0.61","0.0.62","0.0.63","0.0.64","0.0.65","0.0.66","0.0.67","0.0.68","0.0.69","0.0.70","0.0.71","0.0.72","0.0.73","0.0.74","0.0.75","0.0.76","0.0.77","0.0.78","0.0.79","0.0.80","0.0.81","0.0.82","0.0.83","0.0.84","0.0.85","0.0.87","0.0.88","0.0.89","0.0.90","0.0.91","0.0.92","0.0.93","0.0.94","0.0.95","0.0.96","0.0.97","0.0.98","0.0.99","0.0.100","0.0.101","0.0.102","0.0.103","0.0.104","0.0.105","0.0.106","0.0.107","0.0.108","0.0.109","0.0.110","0.0.111","0.0.112","0.0.113","0.0.114","0.0.115","0.0.116","0.0.117","0.0.118","0.0.119","0.0.120","0.0.121","0.0.122","0.0.123","0.0.124","0.0.125","0.0.126","0.0.127","0.0.128","0.0.129","0.0.130","0.0.131","0.0.132","0.0.133","0.0.134","0.0.135","0.0.136","0.0.137","0.0.138","0.0.139","0.0.140","0.0.141","0.0.142","0.1.0","0.1.12","0.1.13","0.1.14","0.1.15","0.1.16","0.1.17","0.1.18","0.1.19","0.1.20","0.1.21","0.1.23","0.1.24","0.1.25","0.1.26","0.1.27","0.2.0","0.2.1","0.2.2","0.2.3","0.2.4","0.2.5","0.2.6","0.2.7","0.2.8","0.3.0","0.3.1","0.3.2","0.3.3","0.3.4","0.3.5","0.3.6","0.4.0","0.4.1","0.4.2","0.4.3","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.5.5","0.5.6","0.5.7","0.5.8","0.5.9","0.6.0","0.6.1","0.6.3","0.7.0","0.7.1","0.7.2","0.7.3","0.7.4","0.7.5","0.7.6","0.7.7","0.7.8","0.7.9","0.7.10","0.7.11","0.7.12","0.7.13","0.8.0","0.8.1","0.8.2","0.8.3","0.8.4","0.8.5","0.9.0","0.9.1","0.9.2","0.9.3","0.9.4","0.10.0","0.10.1","0.10.2","0.10.3","0.10.4","0.10.5","0.11.0","0.12.0","0.12.1","0.12.2","0.12.3","0.12.4","0.12.5","0.12.6","0.12.7","0.12.8","0.12.9","0.12.10","0.13.0","0.13.1","0.14.0","0.14.1","0.14.2","0.15.0","0.15.1","0.15.2","0.16.0","0.17.0","0.17.1","0.18.0","0.18.1","0.19.0","0.19.1","0.20.0","0.20.1","0.20.2","0.20.3","0.21.0","0.21.1","0.22.0","0.22.1","0.23.0","0.23.1","0.23.2","0.23.4","0.24.0","0.24.1","0.24.2","0.24.3","0.24.4","0.24.5","0.25.0","0.25.1","0.25.2","0.25.3","0.25.4","0.25.5","0.25.6","0.25.7","0.25.8","0.26.0","0.26.1","0.26.2","0.26.3","0.27.0","0.27.1","0.27.2","0.27.3","0.28.0","0.28.1","0.28.2","0.28.3","0.28.4","0.28.5","0.29.0","0.29.1","0.29.2","0.29.3","0.29.4","0.29.5","0.29.6","0.29.7","0.29.8","0.30.0","0.30.1","0.31.0","0.31.1","0.31.2","0.31.3","0.31.4","0.32.0","0.32.1","0.32.2","0.32.3","0.32.4","0.33.0","0.34.0","0.34.1","0.34.2","0.34.3","0.34.4","0.34.5","0.34.6","1.0.0-beta.0","1.0.0-beta.1","1.0.0-beta.2","1.0.0-beta.3","1.0.0-beta.4","1.0.0-beta.5","1.0.0-beta.6","1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.1","1.2.2","1.3.0","1.3.1","1.4.0","1.5.0","1.5.1","1.5.2","1.5.3","1.6.0","1.6.1","2.0.0-beta.1","2.0.0-beta.2","2.0.0-beta.3","2.0.0-beta.5","2.0.0-beta.6","2.0.0-beta.7","2.0.0-beta.8","2.0.0-beta.9","2.0.0-beta.10","2.0.0-beta.11","2.0.0-beta.12","2.0.0-beta.13","2.0.0","2.0.1","2.0.2","2.0.3","2.0.4","2.0.5","2.1.0-beta.1","2.1.0-beta.2","2.1.0-beta.3","2.1.0-beta.4","2.1.0-beta.5","2.1.0-beta.6","2.1.0-beta.7","2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.1.5","2.1.6","2.1.7","2.1.8","2.1.9","2.2.0-beta.1","2.2.0-beta.2","3.0.0-beta.1","3.0.0-beta.2","3.0.0-beta.3","3.0.0-beta.4","3.0.0","3.0.1","3.0.2","3.0.3","3.0.4","3.0.5","3.0.6","3.0.7","3.0.8","3.0.9","3.1.0-beta.1","3.1.0-beta.2","3.1.0","3.1.1","3.1.2","3.1.3","3.1.4","3.2.0-beta.1","3.2.0-beta.2","3.2.0-beta.3","3.2.0","3.2.1","3.2.2","3.2.3","3.2.4","4.0.0-beta.1","4.0.0-beta.2","4.0.0-beta.3","4.0.0-beta.4","4.0.0-beta.5","4.0.0-beta.6","4.0.0-beta.7","4.0.0-beta.8","4.0.0-beta.9","4.0.0-beta.10","4.0.0-beta.11","4.0.0-beta.12","4.0.0-beta.13","4.0.0-beta.14","4.0.0-beta.15","4.0.0-beta.16","4.0.0-beta.17","4.0.0-beta.18","4.0.0-beta.19","4.0.0","4.0.1","4.0.2","4.0.3","4.0.4","4.0.5","4.0.6","4.0.7","4.0.8","4.0.9","4.0.10","4.0.11","4.0.12","4.0.13","4.0.14","4.0.15"],"vulnerableVersions":["2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.1.5","2.1.6","2.1.7","2.1.8","2.1.9","2.2.0-beta.1","2.2.0-beta.2","3.0.0-beta.1","3.0.0-beta.2","3.0.0-beta.3","3.0.0-beta.4"],"cwe":["CWE-346"],"cvss":{"score":5.3,"vectorString":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N"},"range":"2.1.0-beta.1 - 3.0.0-beta.4","id":"BSMf7BHi5iZnvIquFfRkjWP6a8w6U34XKSRTgPQahAegm6GPZJH2KxXV9Lykl5yaU1n6yOYaeIOzMIn67rnZBA=="}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{"source":"XRC5FYn4BgxTqFRmBvXrbhEb/XwDQF7aS38Di6r7Pv9zY1oGG9mQ2VYohi/Jc8TchbgRdRy0c0xiUZ9w83+tUA==","name":"@vitest/ui","dependency":"vitest","title":"Depends on vulnerable versions of vitest","url":null,"severity":"moderate","versions":["0.0.119","0.0.120","0.0.121","0.0.122","0.0.123","0.0.124","0.0.125","0.0.126","0.0.127","0.0.128","0.0.129","0.0.130","0.0.131","0.0.132","0.0.133","0.0.134","0.0.135","0.0.136","0.0.137","0.0.138","0.0.139","0.0.140","0.0.141","0.0.142","0.1.0","0.1.12","0.1.13","0.1.14","0.1.15","0.1.16","0.1.17","0.1.18","0.1.19","0.1.20","0.1.21","0.1.22","0.1.23","0.1.24","0.1.25","0.1.26","0.1.27","0.2.0","0.2.1","0.2.2","0.2.3","0.2.4","0.2.5","0.2.6","0.2.7","0.2.8","0.3.0","0.3.1","0.3.2","0.3.3","0.3.4","0.3.5","0.3.6","0.4.0","0.4.1","0.4.2","0.4.3","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.5.5","0.5.6","0.5.7","0.5.8","0.5.9","0.6.0","0.6.1","0.6.3","0.7.0","0.7.1","0.7.2","0.7.3","0.7.4","0.7.5","0.7.6","0.7.7","0.7.8","0.7.9","0.7.10","0.7.11","0.7.12","0.7.13","0.8.0","0.8.1","0.8.2","0.8.3","0.8.4","0.8.5","0.9.0","0.9.1","0.9.2","0.9.3","0.9.4","0.10.0","0.10.1","0.10.2","0.10.3","0.10.4","0.10.5","0.11.0","0.12.0","0.12.1","0.12.2","0.12.3","0.12.4","0.12.5","0.12.6","0.12.7","0.12.8","0.12.9","0.12.10","0.13.0","0.13.1","0.14.0","0.14.1","0.14.2","0.15.0","0.15.1","0.15.2","0.16.0","0.17.0","0.17.1","0.18.0","0.18.1","0.19.0","0.19.1","0.20.0","0.20.1","0.20.2","0.20.3","0.21.0","0.21.1","0.22.0","0.22.1","0.23.0","0.23.1","0.23.2","0.23.4","0.24.0","0.24.1","0.24.2","0.24.3","0.24.4","0.24.5","0.25.0","0.25.1","0.25.2","0.25.3","0.25.4","0.25.5","0.25.6","0.25.7","0.25.8","0.26.0","0.26.1","0.26.2","0.26.3","0.27.0","0.27.1","0.27.2","0.27.3","0.28.0","0.28.1","0.28.2","0.28.3","0.28.4","0.28.5","0.29.0","0.29.1","0.29.2","0.29.3","0.29.4","0.29.5","0.29.6","0.29.7","0.29.8","0.30.0","0.30.1","0.31.0","0.31.1","0.31.2","0.31.3","0.31.4","0.32.0","0.32.1","0.32.2","0.32.3","0.32.4","0.33.0","0.34.0","0.34.1","0.34.2","0.34.3","0.34.4","0.34.5","0.34.6","0.34.7","1.0.0-beta.0","1.0.0-beta.1","1.0.0-beta.2","1.0.0-beta.3","1.0.0-beta.4","1.0.0-beta.5","1.0.0-beta.6","1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.1","1.2.2","1.3.0","1.3.1","1.4.0","1.5.0","1.5.1","1.5.2","1.5.3","1.6.0","1.6.1","2.0.0-beta.1","2.0.0-beta.2","2.0.0-beta.3","2.0.0-beta.5","2.0.0-beta.6","2.0.0-beta.7","2.0.0-beta.8","2.0.0-beta.9","2.0.0-beta.10","2.0.0-beta.11","2.0.0-beta.12","2.0.0-beta.13","2.0.0","2.0.1","2.0.2","2.0.3","2.0.4","2.0.5","2.1.0-beta.1","2.1.0-beta.2","2.1.0-beta.3","2.1.0-beta.4","2.1.0-beta.5","2.1.0-beta.6","2.1.0-beta.7","2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.1.5","2.1.6","2.1.7","2.1.8","2.1.9","2.2.0-beta.1","2.2.0-beta.2","3.0.0-beta.1","3.0.0-beta.2","3.0.0-beta.3","3.0.0-beta.4","3.0.0","3.0.1","3.0.2","3.0.3","3.0.4","3.0.5","3.0.6","3.0.7","3.0.8","3.0.9","3.1.0-beta.1","3.1.0-beta.2","3.1.0","3.1.1","3.1.2","3.1.3","3.1.4","3.2.0-beta.1","3.2.0-beta.2","3.2.0-beta.3","3.2.0","3.2.1","3.2.2","3.2.3","3.2.4","4.0.0-beta.1","4.0.0-beta.2","4.0.0-beta.3","4.0.0-beta.4","4.0.0-beta.5","4.0.0-beta.6","4.0.0-beta.7","4.0.0-beta.8","4.0.0-beta.9","4.0.0-beta.10","4.0.0-beta.11","4.0.0-beta.12","4.0.0-beta.13","4.0.0-beta.15","4.0.0-beta.16","4.0.0-beta.17","4.0.0-beta.18","4.0.0-beta.19","4.0.0","4.0.1","4.0.2","4.0.3","4.0.4","4.0.5","4.0.6","4.0.7","4.0.8","4.0.9","4.0.10","4.0.11","4.0.12","4.0.13","4.0.14","4.0.15"],"vulnerableVersions":["0.0.119","0.0.120","0.0.121","0.0.122","0.31.0","0.31.1","0.31.2","0.31.3","0.31.4","0.32.0","0.32.1","0.32.2","0.32.3","0.32.4","0.33.0","0.34.0","0.34.1","0.34.2","0.34.3","0.34.4","0.34.5","0.34.6","0.34.7","1.0.0-beta.0","1.0.0-beta.1","1.0.0-beta.2","1.0.0-beta.3","1.0.0-beta.4","1.0.0-beta.5","1.0.0-beta.6","1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.1","1.2.2","1.3.0","1.3.1","1.4.0","1.5.0","1.5.1","1.5.2","1.5.3","1.6.0","1.6.1","2.0.0-beta.1","2.0.0-beta.2","2.0.0-beta.3","2.0.0-beta.5","2.0.0-beta.6","2.0.0-beta.7","2.0.0-beta.8","2.0.0-beta.9","2.0.0-beta.10","2.0.0-beta.11","2.0.0-beta.12","2.0.0-beta.13","2.0.0","2.0.1","2.0.2","2.0.3","2.0.4","2.0.5","2.1.0-beta.1","2.1.0-beta.2","2.1.0-beta.3","2.1.0-beta.4","2.1.0-beta.5","2.1.0-beta.6","2.1.0-beta.7","2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.1.5","2.1.6","2.1.7","2.1.8","2.1.9","2.2.0-beta.1","2.2.0-beta.2"],"cwe":["CWE-346"],"cvss":{"score":5.3,"vectorString":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N"},"range":"<=0.0.122 || 0.31.0 - 2.2.0-beta.2","id":"Jf346EgaLUMIfps0Iiyt01/MkMDYEflXXoeXUYIe8k0MNuye+LW8u7aFPu9FPsI7LxiqUGdiHEW8m5Owev1tvg=="}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{"source":"XRC5FYn4BgxTqFRmBvXrbhEb/XwDQF7aS38Di6r7Pv9zY1oGG9mQ2VYohi/Jc8TchbgRdRy0c0xiUZ9w83+tUA==","name":"@vitest/coverage-v8","dependency":"vitest","title":"Depends on vulnerable versions of vitest","url":null,"severity":"moderate","versions":["0.32.0","0.32.1","0.32.2","0.32.3","0.32.4","0.33.0","0.34.0","0.34.1","0.34.2","0.34.3","0.34.4","0.34.5","0.34.6","1.0.0-beta.0","1.0.0-beta.1","1.0.0-beta.2","1.0.0-beta.3","1.0.0-beta.4","1.0.0-beta.5","1.0.0-beta.6","1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.1","1.2.2","1.3.0","1.3.1","1.4.0","1.5.0","1.5.1","1.5.2","1.5.3","1.6.0","1.6.1","2.0.0-beta.1","2.0.0-beta.2","2.0.0-beta.3","2.0.0-beta.5","2.0.0-beta.6","2.0.0-beta.7","2.0.0-beta.8","2.0.0-beta.9","2.0.0-beta.10","2.0.0-beta.11","2.0.0-beta.12","2.0.0-beta.13","2.0.0","2.0.1","2.0.2","2.0.3","2.0.4","2.0.5","2.1.0-beta.1","2.1.0-beta.2","2.1.0-beta.3","2.1.0-beta.4","2.1.0-beta.5","2.1.0-beta.6","2.1.0-beta.7","2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.1.5","2.1.6","2.1.7","2.1.8","2.1.9","2.2.0-beta.1","2.2.0-beta.2","3.0.0-beta.1","3.0.0-beta.2","3.0.0-beta.3","3.0.0-beta.4","3.0.0","3.0.1","3.0.2","3.0.3","3.0.4","3.0.5","3.0.6","3.0.7","3.0.8","3.0.9","3.1.0-beta.1","3.1.0-beta.2","3.1.0","3.1.1","3.1.2","3.1.3","3.1.4","3.2.0-beta.1","3.2.0-beta.2","3.2.0-beta.3","3.2.0","3.2.1","3.2.2","3.2.3","3.2.4","4.0.0-beta.1","4.0.0-beta.2","4.0.0-beta.3","4.0.0-beta.4","4.0.0-beta.5","4.0.0-beta.6","4.0.0-beta.7","4.0.0-beta.8","4.0.0-beta.9","4.0.0-beta.10","4.0.0-beta.11","4.0.0-beta.12","4.0.0-beta.13","4.0.0-beta.15","4.0.0-beta.16","4.0.0-beta.17","4.0.0-beta.18","4.0.0-beta.19","4.0.0","4.0.1","4.0.2","4.0.3","4.0.4","4.0.5","4.0.6","4.0.7","4.0.8","4.0.9","4.0.10","4.0.11","4.0.12","4.0.13","4.0.14","4.0.15"],"vulnerableVersions":["0.32.0","0.32.1","0.32.2","0.32.3","0.32.4","0.33.0","0.34.0","0.34.1","0.34.2","0.34.3","0.34.4","0.34.5","0.34.6","1.0.0-beta.0","1.0.0-beta.1","1.0.0-beta.2","1.0.0-beta.3","1.0.0-beta.4","1.0.0-beta.5","1.0.0-beta.6","1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.1","1.2.2","1.3.0","1.3.1","1.4.0","1.5.0","1.5.1","1.5.2","1.5.3","1.6.0","1.6.1","2.0.0-beta.1","2.0.0-beta.2","2.0.0-beta.3","2.0.0-beta.5","2.0.0-beta.6","2.0.0-beta.7","2.0.0-beta.8","2.0.0-beta.9","2.0.0-beta.10","2.0.0-beta.11","2.0.0-beta.12","2.0.0-beta.13","2.0.0","2.0.1","2.0.2","2.0.3","2.0.4","2.0.5","2.1.0-beta.1","2.1.0-beta.2","2.1.0-beta.3","2.1.0-beta.4","2.1.0-beta.5","2.1.0-beta.6","2.1.0-beta.7","2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.1.5","2.1.6","2.1.7","2.1.8","2.1.9","2.2.0-beta.1","2.2.0-beta.2"],"cwe":["CWE-346"],"cvss":{"score":5.3,"vectorString":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N"},"range":"<=2.2.0-beta.2","id":"8w+D6EgR9fC9fwYIQ5/ztU9fStSsiqzhMfsCGt9lhWi+PYQh74d1bO5hc5jsgsMwHJULRmw+J1H+qZOG8c5J0Q=="}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
2e12a9b844aef75f193f3ea8822eee13774ea567 {"key":"security-advisory:vite-node:qYQfE1mMxIUuwRggKZ3LbYT3bx3mXjMCa+BErBSpF5ui1NkOZf8s+ygWxS4DHMFgC2TLwtHm6g4avxKZe91a0g==","integrity":"sha512-nxdT8QydAqgMng/xbZpOTCRysrlmcx+v96My/WW4ahEYsoeB3FvZ7jdxeXRAnwUH/M8foahgJqmtb19znCjcDg==","time":1765766031210,"size":6009}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
1a72432cee955b10236d41af5ab95e104045b7fa {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/@vitest%2fmocker","integrity":"sha512-a5S7B//4P1CHJIxlBcby50eqmu9TpRI5wjBeFEeZDDvCGJjOLSiVjD/oMA3hal7XLRqTla5XBI6dXCouFNFwZg==","time":1765766030950,"size":87422,"metadata":{"time":1765766030905,"url":"https://registry.npmjs.org/@vitest%2fmocker","reqHeaders":{"accept":"application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*"},"resHeaders":{"cache-control":"public, max-age=300","content-encoding":"gzip","content-type":"application/vnd.npm.install-v1+json","date":"Mon, 15 Dec 2025 02:33:51 GMT","etag":"W/\"7df105404e25b46a75ea949538d59f9a\"","last-modified":"Tue, 02 Dec 2025 15:52:20 GMT","vary":"accept-encoding, accept"},"options":{"compress":true}}}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
3672bc1447385ab62995f47b4a0badb49679ccf6 {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/vitest","integrity":"sha512-f5YcdsQviENFPRNlF8LkdnO7ACI+Oq3eXwwQAb6v2OSNjCT+S6p0FhGAI7q3hZGrj49GJlRy33A+Jk01k2cjSw==","time":1765766031086,"size":1180529,"metadata":{"time":1765766030861,"url":"https://registry.npmjs.org/vitest","reqHeaders":{"accept":"application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*"},"resHeaders":{"cache-control":"public, max-age=300","content-encoding":"gzip","content-type":"application/vnd.npm.install-v1+json","date":"Mon, 15 Dec 2025 02:33:51 GMT","etag":"W/\"4dc2e5ea516804f198067da951ab43d8\"","last-modified":"Tue, 02 Dec 2025 15:52:43 GMT","vary":"accept-encoding, accept"},"options":{"compress":true}}}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
47f70fd675b2f69c0d6a85eb9369c7da878afd9b {"key":"security-advisory:esbuild:jKdCIzePj7J1488qgRXvF8Srh9wutSuR1exB8YooNX62hT+qhtrUXYbArLNoIhgwbaCqKpmduh18syZU7BR9SA==","integrity":"sha512-zdpBkCaGUhdHZVdnjMCKbBbbjWTLNzlSIEnXVtd0ELv9GCWQX5tkGUiZmAS/jF/JKKlamLpTxwDaQ3oOCj5ysw==","time":1765766030357,"size":8960}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
2332762012e041091533c9aed83b4f2d787a3215 {"key":"security-advisory:@vitest/ui:Jf346EgaLUMIfps0Iiyt01/MkMDYEflXXoeXUYIe8k0MNuye+LW8u7aFPu9FPsI7LxiqUGdiHEW8m5Owev1tvg==","integrity":"sha512-u6J/+HU60BfxuF/HlokFtjMjmSfbE83BEh+/a6xcrfgMokM/wNSMc7NLWdZQ+pdbVAjSsub1mSwq6QP72c4ohQ==","time":1765766032096,"size":4661}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
626281a27b99bfcdad4afc2c96b3f9248417eb55 {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/vite-node","integrity":"sha512-iZAhK2AcQq6fr04N+T66mYmujvab61DUgYu/85GG/CE2IkydDLkpndn23fHqGwb00AlB3z22D4GlyRbvAh4lcA==","time":1765766030946,"size":451021,"metadata":{"time":1765766030859,"url":"https://registry.npmjs.org/vite-node","reqHeaders":{"accept":"application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*"},"resHeaders":{"cache-control":"public, max-age=300","content-encoding":"gzip","content-type":"application/vnd.npm.install-v1+json","date":"Mon, 15 Dec 2025 02:33:51 GMT","etag":"W/\"d350de18ef91ca8751e353690ea27a62\"","last-modified":"Tue, 18 Nov 2025 04:12:58 GMT","vary":"accept-encoding, accept"},"options":{"compress":true}}}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
f35dbeb40f044e172b1ca4d897d2e500dcbd0432 {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz","integrity":"sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==","time":1765766030434,"size":948163,"metadata":{"time":1765766029992,"url":"https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz","reqHeaders":{},"resHeaders":{"cache-control":"public, must-revalidate, max-age=31557600","content-type":"application/octet-stream","date":"Mon, 15 Dec 2025 02:33:50 GMT","etag":"\"c66ffcc20a57dbe1a43de0a27ac067f2\"","last-modified":"Wed, 19 Nov 2025 06:33:17 GMT","vary":"Accept-Encoding"},"options":{"compress":true}}}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
432aec095fe104de014305fb7a5d87bf0917deed {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/@vitest%2fui","integrity":"sha512-zNKW5+TGaQxQ4Qm2G0FtndnJYVzke9uChFG6kqJxO2NCU63z5tD5Pi9Zfi2W6Dt6IHmbEsAugrYdFzWm+dte1A==","time":1765766032014,"size":652263,"metadata":{"time":1765766031824,"url":"https://registry.npmjs.org/@vitest%2fui","reqHeaders":{"accept":"application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*"},"resHeaders":{"cache-control":"public, max-age=300","content-encoding":"gzip","content-type":"application/vnd.npm.install-v1+json","date":"Mon, 15 Dec 2025 02:33:52 GMT","etag":"W/\"9a5d3c02c0b4b761bc124bb69eaacb12\"","last-modified":"Tue, 02 Dec 2025 15:53:02 GMT","vary":"accept-encoding, accept"},"options":{"compress":true}}}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
ede0d0eeb8dd9c78464015afe9acdfd52f031cab {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/esbuild","integrity":"sha512-zk9502gz9ZrR1BFDoLm0FyP7QNGYC/7VAGZEEjxPNbC1hVy2MhqCBFn/pkgBzWqOZKLcvZVRQ7aigxDiun0Z3w==","time":1765766030220,"size":876133,"metadata":{"time":1765766030005,"url":"https://registry.npmjs.org/esbuild","reqHeaders":{"accept":"application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*"},"resHeaders":{"cache-control":"public, max-age=300","content-encoding":"gzip","content-type":"application/vnd.npm.install-v1+json","date":"Mon, 15 Dec 2025 02:33:50 GMT","etag":"W/\"bf0daeeda89637bf815b29850db7c1fe\"","last-modified":"Wed, 03 Dec 2025 20:25:14 GMT","vary":"accept-encoding, accept"},"options":{"compress":true}}}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
5d3b61a36ec4e845838e09602bf39d1ee38fbe3c {"key":"security-advisory:vitest:XRC5FYn4BgxTqFRmBvXrbhEb/XwDQF7aS38Di6r7Pv9zY1oGG9mQ2VYohi/Jc8TchbgRdRy0c0xiUZ9w83+tUA==","integrity":"sha512-ld+a/MCAvt1L06nn35BcemBZyQE7JstqQ8uTYe4ITA4mv5vrV+L3SmPEfIGrB0AwQgKA33s2Fm9jgLY02cAlNA==","time":1765766031428,"size":7669}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
d189339d6a231a8b5234ac4089080d7dc7c21519 {"key":"security-advisory:vitest:BSMf7BHi5iZnvIquFfRkjWP6a8w6U34XKSRTgPQahAegm6GPZJH2KxXV9Lykl5yaU1n6yOYaeIOzMIn67rnZBA==","integrity":"sha512-ucm3IO1FNmtJ/kyjkwNIbelDZs+ReTPlKrAuXmB1f4CNxhLEGaJ5sT9Lbhj/5WZNAyQTV1AoqIcvozuN6FF/uQ==","time":1765766031642,"size":4966}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
d4301f14b31721928ac72fb22e62413069c937f3 {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/@vitest%2fcoverage-v8","integrity":"sha512-kU7xr5YxXmaA8+h6LFoIWXwh9SbSluL+3GecXjmh13xZ9B6g1oNiQ6STDyWwvRDf4FpOEKeGLnSyOiCo082VOA==","time":1765766031857,"size":201709,"metadata":{"time":1765766031802,"url":"https://registry.npmjs.org/@vitest%2fcoverage-v8","reqHeaders":{"accept":"application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*"},"resHeaders":{"cache-control":"public, max-age=300","content-encoding":"gzip","content-type":"application/vnd.npm.install-v1+json","date":"Mon, 15 Dec 2025 02:33:52 GMT","etag":"W/\"6793f4301477626363f1ef2bc31276ad\"","last-modified":"Tue, 02 Dec 2025 15:52:58 GMT","vary":"accept-encoding, accept"},"options":{"compress":true}}}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
427bbadc8c936fd9fbe914939e2513ef725ccfa3 {"key":"security-advisory:vitest:/pX+ULPoj9dEnRcNW69EXnv2mQCWcvTXV+PKVdUpqTO30rpIrWPLiQ08km9aOcIK0/KGaALKzFSV/S2lNDmaxg==","integrity":"sha512-Kh8fcVKrEx054bW7rniMm32181EtKAzAlj/2FWXCm4JmuUSDkozzLrtfxrZImXWPg4ITm87Kr1UMzRrB3/DE6w==","time":1765766031561,"size":5996}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
98b2d5afec7abf1a83609237552cd95cfeace6af {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/vite","integrity":"sha512-RlrpATiAfKMJTK7Geu4iv6GjqsgcfXiaO9jPkpYhjiIVenFSTmRW6shMb79KPJpuxJZ7uT6q5/MX9e3IgUJSpQ==","time":1765766030573,"size":2142322,"metadata":{"time":1765766030429,"url":"https://registry.npmjs.org/vite","reqHeaders":{"accept":"application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*"},"resHeaders":{"cache-control":"public, max-age=300","content-encoding":"gzip","content-type":"application/vnd.npm.install-v1+json","date":"Mon, 15 Dec 2025 02:33:50 GMT","etag":"W/\"69222b9fe8dd5a978b903508b4c87155\"","last-modified":"Fri, 12 Dec 2025 02:39:05 GMT","vary":"accept-encoding, accept"},"options":{"compress":true}}}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
93632c14fa7edbc4f90d697b47caed2669e4f415 {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz","integrity":"sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==","time":1765766031087,"size":4129742,"metadata":{"time":1765766029973,"url":"https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz","reqHeaders":{},"resHeaders":{"cache-control":"public, must-revalidate, max-age=31557600","content-type":"application/octet-stream","date":"Mon, 15 Dec 2025 02:33:50 GMT","etag":"\"a81560e260b8093916a4e5f0e719af65\"","last-modified":"Sun, 09 Jun 2024 21:17:16 GMT","vary":"Accept-Encoding"},"options":{"compress":true}}}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
4c93dcd01c1f55edf353b5a8c283f2fccd18d4d9 {"key":"security-advisory:@vitest/coverage-v8:8w+D6EgR9fC9fwYIQ5/ztU9fStSsiqzhMfsCGt9lhWi+PYQh74d1bO5hc5jsgsMwHJULRmw+J1H+qZOG8c5J0Q==","integrity":"sha512-00fh/GKzTm96OjkSfWpwyLY6TJBjqgzvPI3NSJdxCiAR+yNXx+rMR6zgy/kNe9FGdFi1hho30D2BN/zWPIWp6g==","time":1765766032024,"size":2876}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
42180b6796906671888f2daf75d6715255cbfcc0 {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz","integrity":"sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==","time":1765766030436,"size":954224,"metadata":{"time":1765766030024,"url":"https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz","reqHeaders":{},"resHeaders":{"cache-control":"public, must-revalidate, max-age=31557600","content-type":"application/octet-stream","date":"Mon, 15 Dec 2025 02:33:50 GMT","etag":"\"a2011fdf9e385023746daa23f40153a7\"","last-modified":"Wed, 19 Nov 2025 06:33:21 GMT","vary":"Accept-Encoding"},"options":{"compress":true}}}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
5841bbbc4112e649bb0be28e17edb937d9050434 {"key":"security-advisory:vite:tMBsdAS7JBTyRORp0YaJR984WAAsOxgmReSLBN0Nd41GhzEakjROICqAJ31iOdYG5Ijo/MlJ01p3ig1iN88+Tw==","integrity":"sha512-jFpi79Tu3C3tuIzBbesR1hKq25UaEE33lOPKarwVD/uynMIgovv2y2ku3lQzj4tWJRCqlMIthX/3uZA7imtN8A==","time":1765766030791,"size":15571}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
53fa5ae0a6ee63e208e75352f54bcea6b342d96a {"key":"security-advisory:@vitest/mocker:SJ6ALG5CByItLFxBhtpyrxAdDoKdsJCSnzbVFPNK6WdVHJq3/BQr5X33nTvglq430Jo7eFZBpLt727pFLHxHzA==","integrity":"sha512-qzxZ1rQ1tV5WsIR+MdhY/4Mgw4T8YEECHwEAXk4WVTOQsKt6Py+JJoQzRfoEyWvZZ2jkIGjl3CsJ0Wi4I9VSWg==","time":1765766031212,"size":1519}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
1d7006c87afb3418178d1e1eb7163a58fbc5e7c8 {"key":"security-advisory:vitest:B2iyJpQbKqq262urQixaYzRevOIazSKgo7gmc56QnnJ5+jtweKinFTx59GfPkNHv+WUcYBtgMVPbBDE5hghSXA==","integrity":"sha512-LH8mubJiYTVx3aZSuBf+3jNtZpQ2bsbKkbZgJn1diR4BbvIy2/vTrC3njCqJbbv5BkeqdTNhhVNuXNxRAqfN7g==","time":1765766032263,"size":5436}
|
||||||
83
Makefile
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# Makefile for Homelab Automation Dashboard - Test Commands
|
||||||
|
# ==========================================================
|
||||||
|
|
||||||
|
.PHONY: help test test-backend test-frontend test-all test-cov install-test-deps lint
|
||||||
|
|
||||||
|
# Default target
|
||||||
|
help:
|
||||||
|
@echo "Homelab Automation Dashboard - Test Commands"
|
||||||
|
@echo "============================================="
|
||||||
|
@echo ""
|
||||||
|
@echo "Usage: make <target>"
|
||||||
|
@echo ""
|
||||||
|
@echo "Targets:"
|
||||||
|
@echo " install-test-deps Install all test dependencies (Python + Node.js)"
|
||||||
|
@echo " test-backend Run backend Python tests"
|
||||||
|
@echo " test-frontend Run frontend JavaScript tests"
|
||||||
|
@echo " test-all Run all tests (backend + frontend)"
|
||||||
|
@echo " test-cov Run all tests with coverage reports"
|
||||||
|
@echo " test-watch Run tests in watch mode"
|
||||||
|
@echo " lint Run linters (if configured)"
|
||||||
|
@echo ""
|
||||||
|
|
||||||
|
# Install test dependencies
|
||||||
|
install-test-deps:
|
||||||
|
@echo "Installing Python test dependencies..."
|
||||||
|
pip install pytest pytest-asyncio pytest-cov httpx respx freezegun pytest-mock
|
||||||
|
@echo ""
|
||||||
|
@echo "Installing Node.js test dependencies..."
|
||||||
|
npm install
|
||||||
|
@echo ""
|
||||||
|
@echo "✅ All test dependencies installed"
|
||||||
|
|
||||||
|
# Backend tests only
|
||||||
|
test-backend:
|
||||||
|
@echo "Running backend tests..."
|
||||||
|
pytest tests/backend -v --tb=short -m "unit"
|
||||||
|
|
||||||
|
# Backend tests with coverage
|
||||||
|
test-backend-cov:
|
||||||
|
@echo "Running backend tests with coverage..."
|
||||||
|
pytest tests/backend -v --tb=short --cov=app --cov-report=html --cov-report=term-missing
|
||||||
|
|
||||||
|
# Frontend tests only
|
||||||
|
test-frontend:
|
||||||
|
@echo "Running frontend tests..."
|
||||||
|
npm test
|
||||||
|
|
||||||
|
# Frontend tests with coverage
|
||||||
|
test-frontend-cov:
|
||||||
|
@echo "Running frontend tests with coverage..."
|
||||||
|
npm run test:coverage
|
||||||
|
|
||||||
|
# All tests
|
||||||
|
test-all: test-backend test-frontend
|
||||||
|
@echo ""
|
||||||
|
@echo "✅ All tests completed"
|
||||||
|
|
||||||
|
# All tests with coverage
|
||||||
|
test-cov: test-backend-cov test-frontend-cov
|
||||||
|
@echo ""
|
||||||
|
@echo "✅ All tests completed with coverage"
|
||||||
|
@echo "Backend coverage: htmlcov/index.html"
|
||||||
|
@echo "Frontend coverage: coverage/index.html"
|
||||||
|
|
||||||
|
# Watch mode (frontend only - uses Vitest watch)
|
||||||
|
test-watch:
|
||||||
|
npm run test:watch
|
||||||
|
|
||||||
|
# Quick test (fast subset)
|
||||||
|
test-quick:
|
||||||
|
pytest tests/backend -v --tb=short -m "unit" -x -q
|
||||||
|
npm test -- --run
|
||||||
|
|
||||||
|
# Integration tests
|
||||||
|
test-integration:
|
||||||
|
pytest tests/backend -v --tb=short -m "integration"
|
||||||
|
|
||||||
|
# Clean test artifacts
|
||||||
|
clean-test:
|
||||||
|
@echo "Cleaning test artifacts..."
|
||||||
|
rm -rf .pytest_cache __pycache__ htmlcov coverage .coverage
|
||||||
|
rm -rf tests/backend/__pycache__ tests/frontend/__pycache__
|
||||||
|
@echo "✅ Test artifacts cleaned"
|
||||||
287
app/dashboard_core.js
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
/**
|
||||||
|
* DashboardCore - Core logic extracted from main.js for testability.
|
||||||
|
*
|
||||||
|
* This module contains the testable business logic:
|
||||||
|
* - Authentication (login, logout, checkAuthStatus)
|
||||||
|
* - API calls with auth headers
|
||||||
|
* - WebSocket message handling
|
||||||
|
* - Data management (hosts, tasks, schedules)
|
||||||
|
*
|
||||||
|
* The main.js file imports this module and adds DOM-specific functionality.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core dashboard functionality that can be tested without DOM dependencies.
|
||||||
|
*/
|
||||||
|
export class DashboardCore {
|
||||||
|
constructor(options = {}) {
|
||||||
|
// Allow injection of dependencies for testing
|
||||||
|
this.apiBase = options.apiBase || (typeof window !== 'undefined' ? window.location.origin : 'http://localhost');
|
||||||
|
this.storage = options.storage || (typeof localStorage !== 'undefined' ? localStorage : null);
|
||||||
|
this.fetchFn = options.fetch || (typeof fetch !== 'undefined' ? fetch : null);
|
||||||
|
this.WebSocketClass = options.WebSocket || (typeof WebSocket !== 'undefined' ? WebSocket : null);
|
||||||
|
|
||||||
|
// Authentication state
|
||||||
|
this.accessToken = this.storage?.getItem('accessToken') || null;
|
||||||
|
this.currentUser = null;
|
||||||
|
this.setupRequired = false;
|
||||||
|
|
||||||
|
// Data state
|
||||||
|
this.hosts = [];
|
||||||
|
this.tasks = [];
|
||||||
|
this.schedules = [];
|
||||||
|
this.logs = [];
|
||||||
|
this.alerts = [];
|
||||||
|
this.alertsUnread = 0;
|
||||||
|
|
||||||
|
// WebSocket
|
||||||
|
this.ws = null;
|
||||||
|
|
||||||
|
// Callbacks for UI updates (set by main.js)
|
||||||
|
this.onHostsUpdated = null;
|
||||||
|
this.onTasksUpdated = null;
|
||||||
|
this.onSchedulesUpdated = null;
|
||||||
|
this.onAlertsUpdated = null;
|
||||||
|
this.onAuthStateChanged = null;
|
||||||
|
this.onNotification = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== AUTHENTICATION =====
|
||||||
|
|
||||||
|
getAuthHeaders() {
|
||||||
|
const headers = { 'Content-Type': 'application/json' };
|
||||||
|
if (this.accessToken) {
|
||||||
|
headers['Authorization'] = `Bearer ${this.accessToken}`;
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkAuthStatus() {
|
||||||
|
try {
|
||||||
|
const response = await this.fetchFn(`${this.apiBase}/api/auth/status`, {
|
||||||
|
headers: this.getAuthHeaders()
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
this.setupRequired = data.setup_required;
|
||||||
|
|
||||||
|
if (data.setup_required) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.authenticated && data.user) {
|
||||||
|
this.currentUser = data.user;
|
||||||
|
this.onAuthStateChanged?.({ authenticated: true, user: data.user });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Auth status check failed:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async login(username, password) {
|
||||||
|
try {
|
||||||
|
const response = await this.fetchFn(`${this.apiBase}/api/auth/login/json`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ username, password })
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const error = await response.json();
|
||||||
|
throw new Error(error.detail || 'Login failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
this.accessToken = data.access_token;
|
||||||
|
this.storage?.setItem('accessToken', data.access_token);
|
||||||
|
|
||||||
|
await this.checkAuthStatus();
|
||||||
|
this.onNotification?.('Connexion réussie', 'success');
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Login failed:', error);
|
||||||
|
this.onNotification?.(error.message, 'error');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
this.accessToken = null;
|
||||||
|
this.currentUser = null;
|
||||||
|
this.storage?.removeItem('accessToken');
|
||||||
|
|
||||||
|
if (this.ws) {
|
||||||
|
this.ws.close();
|
||||||
|
this.ws = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onAuthStateChanged?.({ authenticated: false, user: null });
|
||||||
|
this.onNotification?.('Déconnexion réussie', 'success');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== API CALLS =====
|
||||||
|
|
||||||
|
async apiCall(endpoint, options = {}) {
|
||||||
|
const url = `${this.apiBase}${endpoint}`;
|
||||||
|
const defaultOptions = {
|
||||||
|
headers: this.getAuthHeaders()
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await this.fetchFn(url, { ...defaultOptions, ...options });
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`API Error (${endpoint}):`, error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== WEBSOCKET =====
|
||||||
|
|
||||||
|
connectWebSocket(wsUrl = null) {
|
||||||
|
if (!this.WebSocketClass) {
|
||||||
|
console.warn('WebSocket not available');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = wsUrl || this._getDefaultWsUrl();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.ws = new this.WebSocketClass(url);
|
||||||
|
|
||||||
|
this.ws.onopen = () => {
|
||||||
|
console.log('WebSocket connected');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ws.onmessage = (event) => {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(event.data);
|
||||||
|
this.handleWebSocketMessage(data);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('WebSocket message parse error:', e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ws.onclose = () => {
|
||||||
|
console.log('WebSocket closed');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ws.onerror = (error) => {
|
||||||
|
console.error('WebSocket error:', error);
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('WebSocket connection failed:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getDefaultWsUrl() {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return 'ws://localhost/ws';
|
||||||
|
}
|
||||||
|
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||||
|
return `${protocol}//${window.location.host}/ws`;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleWebSocketMessage(message) {
|
||||||
|
const { type, data } = message;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'host_updated':
|
||||||
|
this.updateHostInList(data);
|
||||||
|
break;
|
||||||
|
case 'task_started':
|
||||||
|
case 'task_updated':
|
||||||
|
case 'task_completed':
|
||||||
|
this.handleTaskUpdate(data);
|
||||||
|
break;
|
||||||
|
case 'schedule_completed':
|
||||||
|
this.updateScheduleStatus(data);
|
||||||
|
break;
|
||||||
|
case 'alert_created':
|
||||||
|
this.handleAlertCreated(data);
|
||||||
|
break;
|
||||||
|
case 'hosts_synced':
|
||||||
|
this.onHostsUpdated?.();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unknown message type - ignore
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== DATA MANAGEMENT =====
|
||||||
|
|
||||||
|
updateHostInList(hostData) {
|
||||||
|
if (!hostData?.id) return;
|
||||||
|
|
||||||
|
const idx = this.hosts.findIndex(h => h.id === hostData.id);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.hosts[idx] = { ...this.hosts[idx], ...hostData };
|
||||||
|
} else {
|
||||||
|
this.hosts.push(hostData);
|
||||||
|
}
|
||||||
|
this.onHostsUpdated?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTaskUpdate(taskData) {
|
||||||
|
if (!taskData?.id) return;
|
||||||
|
|
||||||
|
const idx = this.tasks.findIndex(t => t.id === taskData.id);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.tasks[idx] = { ...this.tasks[idx], ...taskData };
|
||||||
|
} else {
|
||||||
|
this.tasks.unshift(taskData);
|
||||||
|
}
|
||||||
|
this.onTasksUpdated?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateScheduleStatus(scheduleData) {
|
||||||
|
if (!scheduleData?.schedule_id) return;
|
||||||
|
|
||||||
|
const idx = this.schedules.findIndex(s => s.id === scheduleData.schedule_id);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.schedules[idx].last_status = scheduleData.status;
|
||||||
|
this.schedules[idx].last_run_at = scheduleData.completed_at;
|
||||||
|
}
|
||||||
|
this.onSchedulesUpdated?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAlertCreated(alert) {
|
||||||
|
if (!alert) return;
|
||||||
|
this.alerts = [alert, ...this.alerts].slice(0, 200);
|
||||||
|
this.alertsUnread++;
|
||||||
|
this.onAlertsUpdated?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== UTILITY =====
|
||||||
|
|
||||||
|
escapeHtml(text) {
|
||||||
|
if (!text) return '';
|
||||||
|
const div = typeof document !== 'undefined' ? document.createElement('div') : null;
|
||||||
|
if (div) {
|
||||||
|
div.textContent = text;
|
||||||
|
return div.innerHTML;
|
||||||
|
}
|
||||||
|
// Fallback for non-DOM environments
|
||||||
|
return String(text)
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export for both ESM and CommonJS
|
||||||
|
export default DashboardCore;
|
||||||
@ -1,4 +1,5 @@
|
|||||||
// Homelab Dashboard JavaScript - Intégration API
|
// Homelab Dashboard JavaScript - Intégration API
|
||||||
|
|
||||||
class DashboardManager {
|
class DashboardManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
// Configuration API - JWT token stored in localStorage
|
// Configuration API - JWT token stored in localStorage
|
||||||
@ -9584,3 +9585,8 @@ window.showCreateScheduleModal = function(prefilledPlaybook = null) {
|
|||||||
console.error('showCreateScheduleModal fallback error:', e);
|
console.error('showCreateScheduleModal fallback error:', e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Export for testing (ESM/CommonJS compatible)
|
||||||
|
if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
module.exports = { DashboardManager };
|
||||||
|
}
|
||||||
224
coverage/base.css
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
body, html {
|
||||||
|
margin:0; padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: Helvetica Neue, Helvetica, Arial;
|
||||||
|
font-size: 14px;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
.small { font-size: 12px; }
|
||||||
|
*, *:after, *:before {
|
||||||
|
-webkit-box-sizing:border-box;
|
||||||
|
-moz-box-sizing:border-box;
|
||||||
|
box-sizing:border-box;
|
||||||
|
}
|
||||||
|
h1 { font-size: 20px; margin: 0;}
|
||||||
|
h2 { font-size: 14px; }
|
||||||
|
pre {
|
||||||
|
font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
-moz-tab-size: 2;
|
||||||
|
-o-tab-size: 2;
|
||||||
|
tab-size: 2;
|
||||||
|
}
|
||||||
|
a { color:#0074D9; text-decoration:none; }
|
||||||
|
a:hover { text-decoration:underline; }
|
||||||
|
.strong { font-weight: bold; }
|
||||||
|
.space-top1 { padding: 10px 0 0 0; }
|
||||||
|
.pad2y { padding: 20px 0; }
|
||||||
|
.pad1y { padding: 10px 0; }
|
||||||
|
.pad2x { padding: 0 20px; }
|
||||||
|
.pad2 { padding: 20px; }
|
||||||
|
.pad1 { padding: 10px; }
|
||||||
|
.space-left2 { padding-left:55px; }
|
||||||
|
.space-right2 { padding-right:20px; }
|
||||||
|
.center { text-align:center; }
|
||||||
|
.clearfix { display:block; }
|
||||||
|
.clearfix:after {
|
||||||
|
content:'';
|
||||||
|
display:block;
|
||||||
|
height:0;
|
||||||
|
clear:both;
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
.fl { float: left; }
|
||||||
|
@media only screen and (max-width:640px) {
|
||||||
|
.col3 { width:100%; max-width:100%; }
|
||||||
|
.hide-mobile { display:none!important; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.quiet {
|
||||||
|
color: #7f7f7f;
|
||||||
|
color: rgba(0,0,0,0.5);
|
||||||
|
}
|
||||||
|
.quiet a { opacity: 0.7; }
|
||||||
|
|
||||||
|
.fraction {
|
||||||
|
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #555;
|
||||||
|
background: #E8E8E8;
|
||||||
|
padding: 4px 5px;
|
||||||
|
border-radius: 3px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.path a:link, div.path a:visited { color: #333; }
|
||||||
|
table.coverage {
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.coverage td {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
table.coverage td.line-count {
|
||||||
|
text-align: right;
|
||||||
|
padding: 0 5px 0 20px;
|
||||||
|
}
|
||||||
|
table.coverage td.line-coverage {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 10px;
|
||||||
|
min-width:20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.coverage td span.cline-any {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 5px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.missing-if-branch {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 5px;
|
||||||
|
border-radius: 3px;
|
||||||
|
position: relative;
|
||||||
|
padding: 0 4px;
|
||||||
|
background: #333;
|
||||||
|
color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-if-branch {
|
||||||
|
display: none;
|
||||||
|
margin-right: 10px;
|
||||||
|
position: relative;
|
||||||
|
padding: 0 4px;
|
||||||
|
background: #ccc;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.missing-if-branch .typ, .skip-if-branch .typ {
|
||||||
|
color: inherit !important;
|
||||||
|
}
|
||||||
|
.coverage-summary {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.coverage-summary tr { border-bottom: 1px solid #bbb; }
|
||||||
|
.keyline-all { border: 1px solid #ddd; }
|
||||||
|
.coverage-summary td, .coverage-summary th { padding: 10px; }
|
||||||
|
.coverage-summary tbody { border: 1px solid #bbb; }
|
||||||
|
.coverage-summary td { border-right: 1px solid #bbb; }
|
||||||
|
.coverage-summary td:last-child { border-right: none; }
|
||||||
|
.coverage-summary th {
|
||||||
|
text-align: left;
|
||||||
|
font-weight: normal;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.coverage-summary th.file { border-right: none !important; }
|
||||||
|
.coverage-summary th.pct { }
|
||||||
|
.coverage-summary th.pic,
|
||||||
|
.coverage-summary th.abs,
|
||||||
|
.coverage-summary td.pct,
|
||||||
|
.coverage-summary td.abs { text-align: right; }
|
||||||
|
.coverage-summary td.file { white-space: nowrap; }
|
||||||
|
.coverage-summary td.pic { min-width: 120px !important; }
|
||||||
|
.coverage-summary tfoot td { }
|
||||||
|
|
||||||
|
.coverage-summary .sorter {
|
||||||
|
height: 10px;
|
||||||
|
width: 7px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 0.5em;
|
||||||
|
background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
|
||||||
|
}
|
||||||
|
.coverage-summary .sorted .sorter {
|
||||||
|
background-position: 0 -20px;
|
||||||
|
}
|
||||||
|
.coverage-summary .sorted-desc .sorter {
|
||||||
|
background-position: 0 -10px;
|
||||||
|
}
|
||||||
|
.status-line { height: 10px; }
|
||||||
|
/* yellow */
|
||||||
|
.cbranch-no { background: yellow !important; color: #111; }
|
||||||
|
/* dark red */
|
||||||
|
.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
|
||||||
|
.low .chart { border:1px solid #C21F39 }
|
||||||
|
.highlighted,
|
||||||
|
.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
|
||||||
|
background: #C21F39 !important;
|
||||||
|
}
|
||||||
|
/* medium red */
|
||||||
|
.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
|
||||||
|
/* light red */
|
||||||
|
.low, .cline-no { background:#FCE1E5 }
|
||||||
|
/* light green */
|
||||||
|
.high, .cline-yes { background:rgb(230,245,208) }
|
||||||
|
/* medium green */
|
||||||
|
.cstat-yes { background:rgb(161,215,106) }
|
||||||
|
/* dark green */
|
||||||
|
.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
|
||||||
|
.high .chart { border:1px solid rgb(77,146,33) }
|
||||||
|
/* dark yellow (gold) */
|
||||||
|
.status-line.medium, .medium .cover-fill { background: #f9cd0b; }
|
||||||
|
.medium .chart { border:1px solid #f9cd0b; }
|
||||||
|
/* light yellow */
|
||||||
|
.medium { background: #fff4c2; }
|
||||||
|
|
||||||
|
.cstat-skip { background: #ddd; color: #111; }
|
||||||
|
.fstat-skip { background: #ddd; color: #111 !important; }
|
||||||
|
.cbranch-skip { background: #ddd !important; color: #111; }
|
||||||
|
|
||||||
|
span.cline-neutral { background: #eaeaea; }
|
||||||
|
|
||||||
|
.coverage-summary td.empty {
|
||||||
|
opacity: .5;
|
||||||
|
padding-top: 4px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
line-height: 1;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover-fill, .cover-empty {
|
||||||
|
display:inline-block;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
.chart {
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
.cover-empty {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
.cover-full {
|
||||||
|
border-right: none !important;
|
||||||
|
}
|
||||||
|
pre.prettyprint {
|
||||||
|
border: none !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
.com { color: #999 !important; }
|
||||||
|
.ignore-none { color: #999; font-weight: normal; }
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
min-height: 100%;
|
||||||
|
height: auto !important;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0 auto -48px;
|
||||||
|
}
|
||||||
|
.footer, .push {
|
||||||
|
height: 48px;
|
||||||
|
}
|
||||||
87
coverage/block-navigation.js
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
var jumpToCode = (function init() {
|
||||||
|
// Classes of code we would like to highlight in the file view
|
||||||
|
var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
|
||||||
|
|
||||||
|
// Elements to highlight in the file listing view
|
||||||
|
var fileListingElements = ['td.pct.low'];
|
||||||
|
|
||||||
|
// We don't want to select elements that are direct descendants of another match
|
||||||
|
var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
|
||||||
|
|
||||||
|
// Selector that finds elements on the page to which we can jump
|
||||||
|
var selector =
|
||||||
|
fileListingElements.join(', ') +
|
||||||
|
', ' +
|
||||||
|
notSelector +
|
||||||
|
missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
|
||||||
|
|
||||||
|
// The NodeList of matching elements
|
||||||
|
var missingCoverageElements = document.querySelectorAll(selector);
|
||||||
|
|
||||||
|
var currentIndex;
|
||||||
|
|
||||||
|
function toggleClass(index) {
|
||||||
|
missingCoverageElements
|
||||||
|
.item(currentIndex)
|
||||||
|
.classList.remove('highlighted');
|
||||||
|
missingCoverageElements.item(index).classList.add('highlighted');
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeCurrent(index) {
|
||||||
|
toggleClass(index);
|
||||||
|
currentIndex = index;
|
||||||
|
missingCoverageElements.item(index).scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'center',
|
||||||
|
inline: 'center'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function goToPrevious() {
|
||||||
|
var nextIndex = 0;
|
||||||
|
if (typeof currentIndex !== 'number' || currentIndex === 0) {
|
||||||
|
nextIndex = missingCoverageElements.length - 1;
|
||||||
|
} else if (missingCoverageElements.length > 1) {
|
||||||
|
nextIndex = currentIndex - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeCurrent(nextIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
function goToNext() {
|
||||||
|
var nextIndex = 0;
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof currentIndex === 'number' &&
|
||||||
|
currentIndex < missingCoverageElements.length - 1
|
||||||
|
) {
|
||||||
|
nextIndex = currentIndex + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeCurrent(nextIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function jump(event) {
|
||||||
|
if (
|
||||||
|
document.getElementById('fileSearch') === document.activeElement &&
|
||||||
|
document.activeElement != null
|
||||||
|
) {
|
||||||
|
// if we're currently focused on the search input, we don't want to navigate
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event.which) {
|
||||||
|
case 78: // n
|
||||||
|
case 74: // j
|
||||||
|
goToNext();
|
||||||
|
break;
|
||||||
|
case 66: // b
|
||||||
|
case 75: // k
|
||||||
|
case 80: // p
|
||||||
|
goToPrevious();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
window.addEventListener('keydown', jumpToCode);
|
||||||
946
coverage/dashboard_core.js.html
Normal file
@ -0,0 +1,946 @@
|
|||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Code coverage report for dashboard_core.js</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="stylesheet" href="prettify.css" />
|
||||||
|
<link rel="stylesheet" href="base.css" />
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style type='text/css'>
|
||||||
|
.coverage-summary .sorter {
|
||||||
|
background-image: url(sort-arrow-sprite.png);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class='wrapper'>
|
||||||
|
<div class='pad1'>
|
||||||
|
<h1><a href="index.html">All files</a> dashboard_core.js</h1>
|
||||||
|
<div class='clearfix'>
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">95.47% </span>
|
||||||
|
<span class="quiet">Statements</span>
|
||||||
|
<span class='fraction'>274/287</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">82.14% </span>
|
||||||
|
<span class="quiet">Branches</span>
|
||||||
|
<span class='fraction'>69/84</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">100% </span>
|
||||||
|
<span class="quiet">Functions</span>
|
||||||
|
<span class='fraction'>18/18</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">95.47% </span>
|
||||||
|
<span class="quiet">Lines</span>
|
||||||
|
<span class='fraction'>274/287</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="quiet">
|
||||||
|
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
|
||||||
|
</p>
|
||||||
|
<template id="filterTemplate">
|
||||||
|
<div class="quiet">
|
||||||
|
Filter:
|
||||||
|
<input type="search" id="fileSearch">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class='status-line high'></div>
|
||||||
|
<pre><table class="coverage">
|
||||||
|
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
||||||
|
<a name='L2'></a><a href='#L2'>2</a>
|
||||||
|
<a name='L3'></a><a href='#L3'>3</a>
|
||||||
|
<a name='L4'></a><a href='#L4'>4</a>
|
||||||
|
<a name='L5'></a><a href='#L5'>5</a>
|
||||||
|
<a name='L6'></a><a href='#L6'>6</a>
|
||||||
|
<a name='L7'></a><a href='#L7'>7</a>
|
||||||
|
<a name='L8'></a><a href='#L8'>8</a>
|
||||||
|
<a name='L9'></a><a href='#L9'>9</a>
|
||||||
|
<a name='L10'></a><a href='#L10'>10</a>
|
||||||
|
<a name='L11'></a><a href='#L11'>11</a>
|
||||||
|
<a name='L12'></a><a href='#L12'>12</a>
|
||||||
|
<a name='L13'></a><a href='#L13'>13</a>
|
||||||
|
<a name='L14'></a><a href='#L14'>14</a>
|
||||||
|
<a name='L15'></a><a href='#L15'>15</a>
|
||||||
|
<a name='L16'></a><a href='#L16'>16</a>
|
||||||
|
<a name='L17'></a><a href='#L17'>17</a>
|
||||||
|
<a name='L18'></a><a href='#L18'>18</a>
|
||||||
|
<a name='L19'></a><a href='#L19'>19</a>
|
||||||
|
<a name='L20'></a><a href='#L20'>20</a>
|
||||||
|
<a name='L21'></a><a href='#L21'>21</a>
|
||||||
|
<a name='L22'></a><a href='#L22'>22</a>
|
||||||
|
<a name='L23'></a><a href='#L23'>23</a>
|
||||||
|
<a name='L24'></a><a href='#L24'>24</a>
|
||||||
|
<a name='L25'></a><a href='#L25'>25</a>
|
||||||
|
<a name='L26'></a><a href='#L26'>26</a>
|
||||||
|
<a name='L27'></a><a href='#L27'>27</a>
|
||||||
|
<a name='L28'></a><a href='#L28'>28</a>
|
||||||
|
<a name='L29'></a><a href='#L29'>29</a>
|
||||||
|
<a name='L30'></a><a href='#L30'>30</a>
|
||||||
|
<a name='L31'></a><a href='#L31'>31</a>
|
||||||
|
<a name='L32'></a><a href='#L32'>32</a>
|
||||||
|
<a name='L33'></a><a href='#L33'>33</a>
|
||||||
|
<a name='L34'></a><a href='#L34'>34</a>
|
||||||
|
<a name='L35'></a><a href='#L35'>35</a>
|
||||||
|
<a name='L36'></a><a href='#L36'>36</a>
|
||||||
|
<a name='L37'></a><a href='#L37'>37</a>
|
||||||
|
<a name='L38'></a><a href='#L38'>38</a>
|
||||||
|
<a name='L39'></a><a href='#L39'>39</a>
|
||||||
|
<a name='L40'></a><a href='#L40'>40</a>
|
||||||
|
<a name='L41'></a><a href='#L41'>41</a>
|
||||||
|
<a name='L42'></a><a href='#L42'>42</a>
|
||||||
|
<a name='L43'></a><a href='#L43'>43</a>
|
||||||
|
<a name='L44'></a><a href='#L44'>44</a>
|
||||||
|
<a name='L45'></a><a href='#L45'>45</a>
|
||||||
|
<a name='L46'></a><a href='#L46'>46</a>
|
||||||
|
<a name='L47'></a><a href='#L47'>47</a>
|
||||||
|
<a name='L48'></a><a href='#L48'>48</a>
|
||||||
|
<a name='L49'></a><a href='#L49'>49</a>
|
||||||
|
<a name='L50'></a><a href='#L50'>50</a>
|
||||||
|
<a name='L51'></a><a href='#L51'>51</a>
|
||||||
|
<a name='L52'></a><a href='#L52'>52</a>
|
||||||
|
<a name='L53'></a><a href='#L53'>53</a>
|
||||||
|
<a name='L54'></a><a href='#L54'>54</a>
|
||||||
|
<a name='L55'></a><a href='#L55'>55</a>
|
||||||
|
<a name='L56'></a><a href='#L56'>56</a>
|
||||||
|
<a name='L57'></a><a href='#L57'>57</a>
|
||||||
|
<a name='L58'></a><a href='#L58'>58</a>
|
||||||
|
<a name='L59'></a><a href='#L59'>59</a>
|
||||||
|
<a name='L60'></a><a href='#L60'>60</a>
|
||||||
|
<a name='L61'></a><a href='#L61'>61</a>
|
||||||
|
<a name='L62'></a><a href='#L62'>62</a>
|
||||||
|
<a name='L63'></a><a href='#L63'>63</a>
|
||||||
|
<a name='L64'></a><a href='#L64'>64</a>
|
||||||
|
<a name='L65'></a><a href='#L65'>65</a>
|
||||||
|
<a name='L66'></a><a href='#L66'>66</a>
|
||||||
|
<a name='L67'></a><a href='#L67'>67</a>
|
||||||
|
<a name='L68'></a><a href='#L68'>68</a>
|
||||||
|
<a name='L69'></a><a href='#L69'>69</a>
|
||||||
|
<a name='L70'></a><a href='#L70'>70</a>
|
||||||
|
<a name='L71'></a><a href='#L71'>71</a>
|
||||||
|
<a name='L72'></a><a href='#L72'>72</a>
|
||||||
|
<a name='L73'></a><a href='#L73'>73</a>
|
||||||
|
<a name='L74'></a><a href='#L74'>74</a>
|
||||||
|
<a name='L75'></a><a href='#L75'>75</a>
|
||||||
|
<a name='L76'></a><a href='#L76'>76</a>
|
||||||
|
<a name='L77'></a><a href='#L77'>77</a>
|
||||||
|
<a name='L78'></a><a href='#L78'>78</a>
|
||||||
|
<a name='L79'></a><a href='#L79'>79</a>
|
||||||
|
<a name='L80'></a><a href='#L80'>80</a>
|
||||||
|
<a name='L81'></a><a href='#L81'>81</a>
|
||||||
|
<a name='L82'></a><a href='#L82'>82</a>
|
||||||
|
<a name='L83'></a><a href='#L83'>83</a>
|
||||||
|
<a name='L84'></a><a href='#L84'>84</a>
|
||||||
|
<a name='L85'></a><a href='#L85'>85</a>
|
||||||
|
<a name='L86'></a><a href='#L86'>86</a>
|
||||||
|
<a name='L87'></a><a href='#L87'>87</a>
|
||||||
|
<a name='L88'></a><a href='#L88'>88</a>
|
||||||
|
<a name='L89'></a><a href='#L89'>89</a>
|
||||||
|
<a name='L90'></a><a href='#L90'>90</a>
|
||||||
|
<a name='L91'></a><a href='#L91'>91</a>
|
||||||
|
<a name='L92'></a><a href='#L92'>92</a>
|
||||||
|
<a name='L93'></a><a href='#L93'>93</a>
|
||||||
|
<a name='L94'></a><a href='#L94'>94</a>
|
||||||
|
<a name='L95'></a><a href='#L95'>95</a>
|
||||||
|
<a name='L96'></a><a href='#L96'>96</a>
|
||||||
|
<a name='L97'></a><a href='#L97'>97</a>
|
||||||
|
<a name='L98'></a><a href='#L98'>98</a>
|
||||||
|
<a name='L99'></a><a href='#L99'>99</a>
|
||||||
|
<a name='L100'></a><a href='#L100'>100</a>
|
||||||
|
<a name='L101'></a><a href='#L101'>101</a>
|
||||||
|
<a name='L102'></a><a href='#L102'>102</a>
|
||||||
|
<a name='L103'></a><a href='#L103'>103</a>
|
||||||
|
<a name='L104'></a><a href='#L104'>104</a>
|
||||||
|
<a name='L105'></a><a href='#L105'>105</a>
|
||||||
|
<a name='L106'></a><a href='#L106'>106</a>
|
||||||
|
<a name='L107'></a><a href='#L107'>107</a>
|
||||||
|
<a name='L108'></a><a href='#L108'>108</a>
|
||||||
|
<a name='L109'></a><a href='#L109'>109</a>
|
||||||
|
<a name='L110'></a><a href='#L110'>110</a>
|
||||||
|
<a name='L111'></a><a href='#L111'>111</a>
|
||||||
|
<a name='L112'></a><a href='#L112'>112</a>
|
||||||
|
<a name='L113'></a><a href='#L113'>113</a>
|
||||||
|
<a name='L114'></a><a href='#L114'>114</a>
|
||||||
|
<a name='L115'></a><a href='#L115'>115</a>
|
||||||
|
<a name='L116'></a><a href='#L116'>116</a>
|
||||||
|
<a name='L117'></a><a href='#L117'>117</a>
|
||||||
|
<a name='L118'></a><a href='#L118'>118</a>
|
||||||
|
<a name='L119'></a><a href='#L119'>119</a>
|
||||||
|
<a name='L120'></a><a href='#L120'>120</a>
|
||||||
|
<a name='L121'></a><a href='#L121'>121</a>
|
||||||
|
<a name='L122'></a><a href='#L122'>122</a>
|
||||||
|
<a name='L123'></a><a href='#L123'>123</a>
|
||||||
|
<a name='L124'></a><a href='#L124'>124</a>
|
||||||
|
<a name='L125'></a><a href='#L125'>125</a>
|
||||||
|
<a name='L126'></a><a href='#L126'>126</a>
|
||||||
|
<a name='L127'></a><a href='#L127'>127</a>
|
||||||
|
<a name='L128'></a><a href='#L128'>128</a>
|
||||||
|
<a name='L129'></a><a href='#L129'>129</a>
|
||||||
|
<a name='L130'></a><a href='#L130'>130</a>
|
||||||
|
<a name='L131'></a><a href='#L131'>131</a>
|
||||||
|
<a name='L132'></a><a href='#L132'>132</a>
|
||||||
|
<a name='L133'></a><a href='#L133'>133</a>
|
||||||
|
<a name='L134'></a><a href='#L134'>134</a>
|
||||||
|
<a name='L135'></a><a href='#L135'>135</a>
|
||||||
|
<a name='L136'></a><a href='#L136'>136</a>
|
||||||
|
<a name='L137'></a><a href='#L137'>137</a>
|
||||||
|
<a name='L138'></a><a href='#L138'>138</a>
|
||||||
|
<a name='L139'></a><a href='#L139'>139</a>
|
||||||
|
<a name='L140'></a><a href='#L140'>140</a>
|
||||||
|
<a name='L141'></a><a href='#L141'>141</a>
|
||||||
|
<a name='L142'></a><a href='#L142'>142</a>
|
||||||
|
<a name='L143'></a><a href='#L143'>143</a>
|
||||||
|
<a name='L144'></a><a href='#L144'>144</a>
|
||||||
|
<a name='L145'></a><a href='#L145'>145</a>
|
||||||
|
<a name='L146'></a><a href='#L146'>146</a>
|
||||||
|
<a name='L147'></a><a href='#L147'>147</a>
|
||||||
|
<a name='L148'></a><a href='#L148'>148</a>
|
||||||
|
<a name='L149'></a><a href='#L149'>149</a>
|
||||||
|
<a name='L150'></a><a href='#L150'>150</a>
|
||||||
|
<a name='L151'></a><a href='#L151'>151</a>
|
||||||
|
<a name='L152'></a><a href='#L152'>152</a>
|
||||||
|
<a name='L153'></a><a href='#L153'>153</a>
|
||||||
|
<a name='L154'></a><a href='#L154'>154</a>
|
||||||
|
<a name='L155'></a><a href='#L155'>155</a>
|
||||||
|
<a name='L156'></a><a href='#L156'>156</a>
|
||||||
|
<a name='L157'></a><a href='#L157'>157</a>
|
||||||
|
<a name='L158'></a><a href='#L158'>158</a>
|
||||||
|
<a name='L159'></a><a href='#L159'>159</a>
|
||||||
|
<a name='L160'></a><a href='#L160'>160</a>
|
||||||
|
<a name='L161'></a><a href='#L161'>161</a>
|
||||||
|
<a name='L162'></a><a href='#L162'>162</a>
|
||||||
|
<a name='L163'></a><a href='#L163'>163</a>
|
||||||
|
<a name='L164'></a><a href='#L164'>164</a>
|
||||||
|
<a name='L165'></a><a href='#L165'>165</a>
|
||||||
|
<a name='L166'></a><a href='#L166'>166</a>
|
||||||
|
<a name='L167'></a><a href='#L167'>167</a>
|
||||||
|
<a name='L168'></a><a href='#L168'>168</a>
|
||||||
|
<a name='L169'></a><a href='#L169'>169</a>
|
||||||
|
<a name='L170'></a><a href='#L170'>170</a>
|
||||||
|
<a name='L171'></a><a href='#L171'>171</a>
|
||||||
|
<a name='L172'></a><a href='#L172'>172</a>
|
||||||
|
<a name='L173'></a><a href='#L173'>173</a>
|
||||||
|
<a name='L174'></a><a href='#L174'>174</a>
|
||||||
|
<a name='L175'></a><a href='#L175'>175</a>
|
||||||
|
<a name='L176'></a><a href='#L176'>176</a>
|
||||||
|
<a name='L177'></a><a href='#L177'>177</a>
|
||||||
|
<a name='L178'></a><a href='#L178'>178</a>
|
||||||
|
<a name='L179'></a><a href='#L179'>179</a>
|
||||||
|
<a name='L180'></a><a href='#L180'>180</a>
|
||||||
|
<a name='L181'></a><a href='#L181'>181</a>
|
||||||
|
<a name='L182'></a><a href='#L182'>182</a>
|
||||||
|
<a name='L183'></a><a href='#L183'>183</a>
|
||||||
|
<a name='L184'></a><a href='#L184'>184</a>
|
||||||
|
<a name='L185'></a><a href='#L185'>185</a>
|
||||||
|
<a name='L186'></a><a href='#L186'>186</a>
|
||||||
|
<a name='L187'></a><a href='#L187'>187</a>
|
||||||
|
<a name='L188'></a><a href='#L188'>188</a>
|
||||||
|
<a name='L189'></a><a href='#L189'>189</a>
|
||||||
|
<a name='L190'></a><a href='#L190'>190</a>
|
||||||
|
<a name='L191'></a><a href='#L191'>191</a>
|
||||||
|
<a name='L192'></a><a href='#L192'>192</a>
|
||||||
|
<a name='L193'></a><a href='#L193'>193</a>
|
||||||
|
<a name='L194'></a><a href='#L194'>194</a>
|
||||||
|
<a name='L195'></a><a href='#L195'>195</a>
|
||||||
|
<a name='L196'></a><a href='#L196'>196</a>
|
||||||
|
<a name='L197'></a><a href='#L197'>197</a>
|
||||||
|
<a name='L198'></a><a href='#L198'>198</a>
|
||||||
|
<a name='L199'></a><a href='#L199'>199</a>
|
||||||
|
<a name='L200'></a><a href='#L200'>200</a>
|
||||||
|
<a name='L201'></a><a href='#L201'>201</a>
|
||||||
|
<a name='L202'></a><a href='#L202'>202</a>
|
||||||
|
<a name='L203'></a><a href='#L203'>203</a>
|
||||||
|
<a name='L204'></a><a href='#L204'>204</a>
|
||||||
|
<a name='L205'></a><a href='#L205'>205</a>
|
||||||
|
<a name='L206'></a><a href='#L206'>206</a>
|
||||||
|
<a name='L207'></a><a href='#L207'>207</a>
|
||||||
|
<a name='L208'></a><a href='#L208'>208</a>
|
||||||
|
<a name='L209'></a><a href='#L209'>209</a>
|
||||||
|
<a name='L210'></a><a href='#L210'>210</a>
|
||||||
|
<a name='L211'></a><a href='#L211'>211</a>
|
||||||
|
<a name='L212'></a><a href='#L212'>212</a>
|
||||||
|
<a name='L213'></a><a href='#L213'>213</a>
|
||||||
|
<a name='L214'></a><a href='#L214'>214</a>
|
||||||
|
<a name='L215'></a><a href='#L215'>215</a>
|
||||||
|
<a name='L216'></a><a href='#L216'>216</a>
|
||||||
|
<a name='L217'></a><a href='#L217'>217</a>
|
||||||
|
<a name='L218'></a><a href='#L218'>218</a>
|
||||||
|
<a name='L219'></a><a href='#L219'>219</a>
|
||||||
|
<a name='L220'></a><a href='#L220'>220</a>
|
||||||
|
<a name='L221'></a><a href='#L221'>221</a>
|
||||||
|
<a name='L222'></a><a href='#L222'>222</a>
|
||||||
|
<a name='L223'></a><a href='#L223'>223</a>
|
||||||
|
<a name='L224'></a><a href='#L224'>224</a>
|
||||||
|
<a name='L225'></a><a href='#L225'>225</a>
|
||||||
|
<a name='L226'></a><a href='#L226'>226</a>
|
||||||
|
<a name='L227'></a><a href='#L227'>227</a>
|
||||||
|
<a name='L228'></a><a href='#L228'>228</a>
|
||||||
|
<a name='L229'></a><a href='#L229'>229</a>
|
||||||
|
<a name='L230'></a><a href='#L230'>230</a>
|
||||||
|
<a name='L231'></a><a href='#L231'>231</a>
|
||||||
|
<a name='L232'></a><a href='#L232'>232</a>
|
||||||
|
<a name='L233'></a><a href='#L233'>233</a>
|
||||||
|
<a name='L234'></a><a href='#L234'>234</a>
|
||||||
|
<a name='L235'></a><a href='#L235'>235</a>
|
||||||
|
<a name='L236'></a><a href='#L236'>236</a>
|
||||||
|
<a name='L237'></a><a href='#L237'>237</a>
|
||||||
|
<a name='L238'></a><a href='#L238'>238</a>
|
||||||
|
<a name='L239'></a><a href='#L239'>239</a>
|
||||||
|
<a name='L240'></a><a href='#L240'>240</a>
|
||||||
|
<a name='L241'></a><a href='#L241'>241</a>
|
||||||
|
<a name='L242'></a><a href='#L242'>242</a>
|
||||||
|
<a name='L243'></a><a href='#L243'>243</a>
|
||||||
|
<a name='L244'></a><a href='#L244'>244</a>
|
||||||
|
<a name='L245'></a><a href='#L245'>245</a>
|
||||||
|
<a name='L246'></a><a href='#L246'>246</a>
|
||||||
|
<a name='L247'></a><a href='#L247'>247</a>
|
||||||
|
<a name='L248'></a><a href='#L248'>248</a>
|
||||||
|
<a name='L249'></a><a href='#L249'>249</a>
|
||||||
|
<a name='L250'></a><a href='#L250'>250</a>
|
||||||
|
<a name='L251'></a><a href='#L251'>251</a>
|
||||||
|
<a name='L252'></a><a href='#L252'>252</a>
|
||||||
|
<a name='L253'></a><a href='#L253'>253</a>
|
||||||
|
<a name='L254'></a><a href='#L254'>254</a>
|
||||||
|
<a name='L255'></a><a href='#L255'>255</a>
|
||||||
|
<a name='L256'></a><a href='#L256'>256</a>
|
||||||
|
<a name='L257'></a><a href='#L257'>257</a>
|
||||||
|
<a name='L258'></a><a href='#L258'>258</a>
|
||||||
|
<a name='L259'></a><a href='#L259'>259</a>
|
||||||
|
<a name='L260'></a><a href='#L260'>260</a>
|
||||||
|
<a name='L261'></a><a href='#L261'>261</a>
|
||||||
|
<a name='L262'></a><a href='#L262'>262</a>
|
||||||
|
<a name='L263'></a><a href='#L263'>263</a>
|
||||||
|
<a name='L264'></a><a href='#L264'>264</a>
|
||||||
|
<a name='L265'></a><a href='#L265'>265</a>
|
||||||
|
<a name='L266'></a><a href='#L266'>266</a>
|
||||||
|
<a name='L267'></a><a href='#L267'>267</a>
|
||||||
|
<a name='L268'></a><a href='#L268'>268</a>
|
||||||
|
<a name='L269'></a><a href='#L269'>269</a>
|
||||||
|
<a name='L270'></a><a href='#L270'>270</a>
|
||||||
|
<a name='L271'></a><a href='#L271'>271</a>
|
||||||
|
<a name='L272'></a><a href='#L272'>272</a>
|
||||||
|
<a name='L273'></a><a href='#L273'>273</a>
|
||||||
|
<a name='L274'></a><a href='#L274'>274</a>
|
||||||
|
<a name='L275'></a><a href='#L275'>275</a>
|
||||||
|
<a name='L276'></a><a href='#L276'>276</a>
|
||||||
|
<a name='L277'></a><a href='#L277'>277</a>
|
||||||
|
<a name='L278'></a><a href='#L278'>278</a>
|
||||||
|
<a name='L279'></a><a href='#L279'>279</a>
|
||||||
|
<a name='L280'></a><a href='#L280'>280</a>
|
||||||
|
<a name='L281'></a><a href='#L281'>281</a>
|
||||||
|
<a name='L282'></a><a href='#L282'>282</a>
|
||||||
|
<a name='L283'></a><a href='#L283'>283</a>
|
||||||
|
<a name='L284'></a><a href='#L284'>284</a>
|
||||||
|
<a name='L285'></a><a href='#L285'>285</a>
|
||||||
|
<a name='L286'></a><a href='#L286'>286</a>
|
||||||
|
<a name='L287'></a><a href='#L287'>287</a>
|
||||||
|
<a name='L288'></a><a href='#L288'>288</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">12x</span>
|
||||||
|
<span class="cline-any cline-yes">12x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">12x</span>
|
||||||
|
<span class="cline-any cline-yes">12x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">5x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">5x</span>
|
||||||
|
<span class="cline-any cline-yes">5x</span>
|
||||||
|
<span class="cline-any cline-yes">5x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-yes">5x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">/**
|
||||||
|
* DashboardCore - Core logic extracted from main.js for testability.
|
||||||
|
*
|
||||||
|
* This module contains the testable business logic:
|
||||||
|
* - Authentication (login, logout, checkAuthStatus)
|
||||||
|
* - API calls with auth headers
|
||||||
|
* - WebSocket message handling
|
||||||
|
* - Data management (hosts, tasks, schedules)
|
||||||
|
*
|
||||||
|
* The main.js file imports this module and adds DOM-specific functionality.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core dashboard functionality that can be tested without DOM dependencies.
|
||||||
|
*/
|
||||||
|
export class DashboardCore {
|
||||||
|
constructor(options = {}) {
|
||||||
|
// Allow injection of dependencies for testing
|
||||||
|
this.apiBase = options.apiBase || (typeof window !== 'undefined' ? window.location.origin <span class="branch-0 cbranch-no" title="branch not covered" >: 'http://localhost')</span>;
|
||||||
|
this.storage = options.storage || (typeof localStorage !== 'undefined' ? localStorage <span class="branch-0 cbranch-no" title="branch not covered" >: null)</span>;
|
||||||
|
this.fetchFn = options.fetch || (typeof fetch !== 'undefined' ? fetch <span class="branch-0 cbranch-no" title="branch not covered" >: null)</span>;
|
||||||
|
this.WebSocketClass = options.WebSocket || (typeof WebSocket !== 'undefined' ? WebSocket <span class="branch-0 cbranch-no" title="branch not covered" >: null)</span>;
|
||||||
|
|
||||||
|
// Authentication state
|
||||||
|
this.accessToken = this.storage?.getItem('accessToken') || null;
|
||||||
|
this.currentUser = null;
|
||||||
|
this.setupRequired = false;
|
||||||
|
|
||||||
|
// Data state
|
||||||
|
this.hosts = [];
|
||||||
|
this.tasks = [];
|
||||||
|
this.schedules = [];
|
||||||
|
this.logs = [];
|
||||||
|
this.alerts = [];
|
||||||
|
this.alertsUnread = 0;
|
||||||
|
|
||||||
|
// WebSocket
|
||||||
|
this.ws = null;
|
||||||
|
|
||||||
|
// Callbacks for UI updates (set by main.js)
|
||||||
|
this.onHostsUpdated = null;
|
||||||
|
this.onTasksUpdated = null;
|
||||||
|
this.onSchedulesUpdated = null;
|
||||||
|
this.onAlertsUpdated = null;
|
||||||
|
this.onAuthStateChanged = null;
|
||||||
|
this.onNotification = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== AUTHENTICATION =====
|
||||||
|
|
||||||
|
getAuthHeaders() {
|
||||||
|
const headers = { 'Content-Type': 'application/json' };
|
||||||
|
if (this.accessToken) {
|
||||||
|
headers['Authorization'] = `Bearer ${this.accessToken}`;
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkAuthStatus() {
|
||||||
|
try {
|
||||||
|
const response = await this.fetchFn(`${this.apiBase}/api/auth/status`, {
|
||||||
|
headers: this.getAuthHeaders()
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > return false;</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > }</span>
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
this.setupRequired = data.setup_required;
|
||||||
|
|
||||||
|
if (data.setup_required) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.authenticated && data.user) {
|
||||||
|
this.currentUser = data.user;
|
||||||
|
this.onAuthStateChanged?.({ authenticated: true, user: data.user });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Auth status check failed:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async login(username, password) {
|
||||||
|
try {
|
||||||
|
const response = await this.fetchFn(`${this.apiBase}/api/auth/login/json`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ username, password })
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const error = await response.json();
|
||||||
|
throw new Error(error.detail <span class="branch-0 cbranch-no" title="branch not covered" >|| 'Login failed')</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
this.accessToken = data.access_token;
|
||||||
|
this.storage?.setItem('accessToken', data.access_token);
|
||||||
|
|
||||||
|
await this.checkAuthStatus();
|
||||||
|
this.onNotification?.('Connexion réussie', 'success');
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Login failed:', error);
|
||||||
|
this.onNotification?.(error.message, 'error');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
this.accessToken = null;
|
||||||
|
this.currentUser = null;
|
||||||
|
this.storage?.removeItem('accessToken');
|
||||||
|
|
||||||
|
if (this.ws) {
|
||||||
|
this.ws.close();
|
||||||
|
this.ws = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onAuthStateChanged?.({ authenticated: false, user: null });
|
||||||
|
this.onNotification<span class="branch-0 cbranch-no" title="branch not covered" >?.('Déconnexion réussie', 'success');</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== API CALLS =====
|
||||||
|
|
||||||
|
async apiCall(endpoint, options = {}) {
|
||||||
|
const url = `${this.apiBase}${endpoint}`;
|
||||||
|
const defaultOptions = {
|
||||||
|
headers: this.getAuthHeaders()
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await this.fetchFn(url, { ...defaultOptions, ...options });
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`API Error (${endpoint}):`, error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== WEBSOCKET =====
|
||||||
|
|
||||||
|
connectWebSocket(wsUrl = null) {
|
||||||
|
if (!this.WebSocketClass) {
|
||||||
|
console.warn('WebSocket not available');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = wsUrl || this._getDefaultWsUrl();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.ws = new this.WebSocketClass(url);
|
||||||
|
|
||||||
|
this.ws.onopen = () => {
|
||||||
|
console.log('WebSocket connected');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ws.onmessage = (event) => {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(event.data);
|
||||||
|
this.handleWebSocketMessage(data);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('WebSocket message parse error:', e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ws.onclose = () => {
|
||||||
|
console.log('WebSocket closed');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ws.onerror = (error) => {
|
||||||
|
console.error('WebSocket error:', error);
|
||||||
|
};
|
||||||
|
} <span class="branch-0 cbranch-no" title="branch not covered" >catch (error) {</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > console.error('WebSocket connection failed:', error);</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > }</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
_getDefaultWsUrl() {
|
||||||
|
if (typeof window === 'undefined') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > return 'ws://localhost/ws';</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > }</span>
|
||||||
|
const protocol = window.location.protocol === 'https:' <span class="branch-0 cbranch-no" title="branch not covered" >? 'wss:' </span>: 'ws:';
|
||||||
|
return `${protocol}//${window.location.host}/ws`;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleWebSocketMessage(message) {
|
||||||
|
const { type, data } = message;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'host_updated':
|
||||||
|
this.updateHostInList(data);
|
||||||
|
break;
|
||||||
|
case 'task_started':
|
||||||
|
case 'task_updated':
|
||||||
|
case 'task_completed':
|
||||||
|
this.handleTaskUpdate(data);
|
||||||
|
break;
|
||||||
|
case 'schedule_completed':
|
||||||
|
this.updateScheduleStatus(data);
|
||||||
|
break;
|
||||||
|
case 'alert_created':
|
||||||
|
this.handleAlertCreated(data);
|
||||||
|
break;
|
||||||
|
case 'hosts_synced':
|
||||||
|
this.onHostsUpdated?.();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unknown message type - ignore
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== DATA MANAGEMENT =====
|
||||||
|
|
||||||
|
updateHostInList(hostData) {
|
||||||
|
if (!hostData?.id) return;
|
||||||
|
|
||||||
|
const idx = this.hosts.findIndex(h => h.id === hostData.id);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.hosts[idx] = { ...this.hosts[idx], ...hostData };
|
||||||
|
} else {
|
||||||
|
this.hosts.push(hostData);
|
||||||
|
}
|
||||||
|
this.onHostsUpdated?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTaskUpdate(taskData) {
|
||||||
|
if (!taskData?.id) <span class="branch-0 cbranch-no" title="branch not covered" >return;</span>
|
||||||
|
|
||||||
|
const idx = this.tasks.findIndex(t => t.id === taskData.id);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.tasks[idx] = { ...this.tasks[idx], ...taskData };
|
||||||
|
} else {
|
||||||
|
this.tasks.unshift(taskData);
|
||||||
|
}
|
||||||
|
this.onTasksUpdated?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateScheduleStatus(scheduleData) {
|
||||||
|
if (!scheduleData?.schedule_id) <span class="branch-0 cbranch-no" title="branch not covered" >return;</span>
|
||||||
|
|
||||||
|
const idx = this.schedules.findIndex(s => s.id === scheduleData.schedule_id);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.schedules[idx].last_status = scheduleData.status;
|
||||||
|
this.schedules[idx].last_run_at = scheduleData.completed_at;
|
||||||
|
}
|
||||||
|
this.onSchedulesUpdated?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAlertCreated(alert) {
|
||||||
|
if (!alert) <span class="branch-0 cbranch-no" title="branch not covered" >return;</span>
|
||||||
|
this.alerts = [alert, ...this.alerts].slice(0, 200);
|
||||||
|
this.alertsUnread++;
|
||||||
|
this.onAlertsUpdated?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== UTILITY =====
|
||||||
|
|
||||||
|
escapeHtml(text) {
|
||||||
|
if (!text) return '';
|
||||||
|
const div = typeof document !== 'undefined' ? document.createElement('div') <span class="branch-0 cbranch-no" title="branch not covered" >: null;</span>
|
||||||
|
if (div) {
|
||||||
|
div.textContent = text;
|
||||||
|
return div.innerHTML;
|
||||||
|
}
|
||||||
|
<span class="cstat-no" title="statement not covered" ><span class="branch-0 cbranch-no" title="branch not covered" > // Fallback for non-DOM environments</span></span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > return String(text)</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > .replace(/&/g, '&amp;')</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > .replace(/</g, '&lt;')</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > .replace(/>/g, '&gt;')</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > .replace(/"/g, '&quot;')</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > .replace(/'/g, '&#039;');</span>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export for both ESM and CommonJS
|
||||||
|
export default DashboardCore;
|
||||||
|
</pre></td></tr></table></pre>
|
||||||
|
|
||||||
|
<div class='push'></div><!-- for sticky footer -->
|
||||||
|
</div><!-- /wrapper -->
|
||||||
|
<div class='footer quiet pad2 space-top1 center small'>
|
||||||
|
Code coverage generated by
|
||||||
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
||||||
|
at 2025-12-15T04:43:42.469Z
|
||||||
|
</div>
|
||||||
|
<script src="prettify.js"></script>
|
||||||
|
<script>
|
||||||
|
window.onload = function () {
|
||||||
|
prettyPrint();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script src="sorter.js"></script>
|
||||||
|
<script src="block-navigation.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
BIN
coverage/favicon.png
Normal file
|
After Width: | Height: | Size: 445 B |
116
coverage/index.html
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Code coverage report for All files</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="stylesheet" href="prettify.css" />
|
||||||
|
<link rel="stylesheet" href="base.css" />
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style type='text/css'>
|
||||||
|
.coverage-summary .sorter {
|
||||||
|
background-image: url(sort-arrow-sprite.png);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class='wrapper'>
|
||||||
|
<div class='pad1'>
|
||||||
|
<h1>All files</h1>
|
||||||
|
<div class='clearfix'>
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">95.47% </span>
|
||||||
|
<span class="quiet">Statements</span>
|
||||||
|
<span class='fraction'>274/287</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">82.14% </span>
|
||||||
|
<span class="quiet">Branches</span>
|
||||||
|
<span class='fraction'>69/84</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">100% </span>
|
||||||
|
<span class="quiet">Functions</span>
|
||||||
|
<span class='fraction'>18/18</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">95.47% </span>
|
||||||
|
<span class="quiet">Lines</span>
|
||||||
|
<span class='fraction'>274/287</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="quiet">
|
||||||
|
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
|
||||||
|
</p>
|
||||||
|
<template id="filterTemplate">
|
||||||
|
<div class="quiet">
|
||||||
|
Filter:
|
||||||
|
<input type="search" id="fileSearch">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class='status-line high'></div>
|
||||||
|
<div class="pad1">
|
||||||
|
<table class="coverage-summary">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
|
||||||
|
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
|
||||||
|
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
|
||||||
|
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
|
||||||
|
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
|
||||||
|
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
|
||||||
|
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
|
||||||
|
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
|
||||||
|
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
|
||||||
|
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody><tr>
|
||||||
|
<td class="file high" data-value="dashboard_core.js"><a href="dashboard_core.js.html">dashboard_core.js</a></td>
|
||||||
|
<td data-value="95.47" class="pic high">
|
||||||
|
<div class="chart"><div class="cover-fill" style="width: 95%"></div><div class="cover-empty" style="width: 5%"></div></div>
|
||||||
|
</td>
|
||||||
|
<td data-value="95.47" class="pct high">95.47%</td>
|
||||||
|
<td data-value="287" class="abs high">274/287</td>
|
||||||
|
<td data-value="82.14" class="pct high">82.14%</td>
|
||||||
|
<td data-value="84" class="abs high">69/84</td>
|
||||||
|
<td data-value="100" class="pct high">100%</td>
|
||||||
|
<td data-value="18" class="abs high">18/18</td>
|
||||||
|
<td data-value="95.47" class="pct high">95.47%</td>
|
||||||
|
<td data-value="287" class="abs high">274/287</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class='push'></div><!-- for sticky footer -->
|
||||||
|
</div><!-- /wrapper -->
|
||||||
|
<div class='footer quiet pad2 space-top1 center small'>
|
||||||
|
Code coverage generated by
|
||||||
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
||||||
|
at 2025-12-15T04:43:42.469Z
|
||||||
|
</div>
|
||||||
|
<script src="prettify.js"></script>
|
||||||
|
<script>
|
||||||
|
window.onload = function () {
|
||||||
|
prettyPrint();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script src="sorter.js"></script>
|
||||||
|
<script src="block-navigation.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
224
coverage/lcov-report/base.css
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
body, html {
|
||||||
|
margin:0; padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: Helvetica Neue, Helvetica, Arial;
|
||||||
|
font-size: 14px;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
.small { font-size: 12px; }
|
||||||
|
*, *:after, *:before {
|
||||||
|
-webkit-box-sizing:border-box;
|
||||||
|
-moz-box-sizing:border-box;
|
||||||
|
box-sizing:border-box;
|
||||||
|
}
|
||||||
|
h1 { font-size: 20px; margin: 0;}
|
||||||
|
h2 { font-size: 14px; }
|
||||||
|
pre {
|
||||||
|
font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
-moz-tab-size: 2;
|
||||||
|
-o-tab-size: 2;
|
||||||
|
tab-size: 2;
|
||||||
|
}
|
||||||
|
a { color:#0074D9; text-decoration:none; }
|
||||||
|
a:hover { text-decoration:underline; }
|
||||||
|
.strong { font-weight: bold; }
|
||||||
|
.space-top1 { padding: 10px 0 0 0; }
|
||||||
|
.pad2y { padding: 20px 0; }
|
||||||
|
.pad1y { padding: 10px 0; }
|
||||||
|
.pad2x { padding: 0 20px; }
|
||||||
|
.pad2 { padding: 20px; }
|
||||||
|
.pad1 { padding: 10px; }
|
||||||
|
.space-left2 { padding-left:55px; }
|
||||||
|
.space-right2 { padding-right:20px; }
|
||||||
|
.center { text-align:center; }
|
||||||
|
.clearfix { display:block; }
|
||||||
|
.clearfix:after {
|
||||||
|
content:'';
|
||||||
|
display:block;
|
||||||
|
height:0;
|
||||||
|
clear:both;
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
.fl { float: left; }
|
||||||
|
@media only screen and (max-width:640px) {
|
||||||
|
.col3 { width:100%; max-width:100%; }
|
||||||
|
.hide-mobile { display:none!important; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.quiet {
|
||||||
|
color: #7f7f7f;
|
||||||
|
color: rgba(0,0,0,0.5);
|
||||||
|
}
|
||||||
|
.quiet a { opacity: 0.7; }
|
||||||
|
|
||||||
|
.fraction {
|
||||||
|
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #555;
|
||||||
|
background: #E8E8E8;
|
||||||
|
padding: 4px 5px;
|
||||||
|
border-radius: 3px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.path a:link, div.path a:visited { color: #333; }
|
||||||
|
table.coverage {
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.coverage td {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
table.coverage td.line-count {
|
||||||
|
text-align: right;
|
||||||
|
padding: 0 5px 0 20px;
|
||||||
|
}
|
||||||
|
table.coverage td.line-coverage {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 10px;
|
||||||
|
min-width:20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.coverage td span.cline-any {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 5px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.missing-if-branch {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 5px;
|
||||||
|
border-radius: 3px;
|
||||||
|
position: relative;
|
||||||
|
padding: 0 4px;
|
||||||
|
background: #333;
|
||||||
|
color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-if-branch {
|
||||||
|
display: none;
|
||||||
|
margin-right: 10px;
|
||||||
|
position: relative;
|
||||||
|
padding: 0 4px;
|
||||||
|
background: #ccc;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.missing-if-branch .typ, .skip-if-branch .typ {
|
||||||
|
color: inherit !important;
|
||||||
|
}
|
||||||
|
.coverage-summary {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.coverage-summary tr { border-bottom: 1px solid #bbb; }
|
||||||
|
.keyline-all { border: 1px solid #ddd; }
|
||||||
|
.coverage-summary td, .coverage-summary th { padding: 10px; }
|
||||||
|
.coverage-summary tbody { border: 1px solid #bbb; }
|
||||||
|
.coverage-summary td { border-right: 1px solid #bbb; }
|
||||||
|
.coverage-summary td:last-child { border-right: none; }
|
||||||
|
.coverage-summary th {
|
||||||
|
text-align: left;
|
||||||
|
font-weight: normal;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.coverage-summary th.file { border-right: none !important; }
|
||||||
|
.coverage-summary th.pct { }
|
||||||
|
.coverage-summary th.pic,
|
||||||
|
.coverage-summary th.abs,
|
||||||
|
.coverage-summary td.pct,
|
||||||
|
.coverage-summary td.abs { text-align: right; }
|
||||||
|
.coverage-summary td.file { white-space: nowrap; }
|
||||||
|
.coverage-summary td.pic { min-width: 120px !important; }
|
||||||
|
.coverage-summary tfoot td { }
|
||||||
|
|
||||||
|
.coverage-summary .sorter {
|
||||||
|
height: 10px;
|
||||||
|
width: 7px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 0.5em;
|
||||||
|
background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
|
||||||
|
}
|
||||||
|
.coverage-summary .sorted .sorter {
|
||||||
|
background-position: 0 -20px;
|
||||||
|
}
|
||||||
|
.coverage-summary .sorted-desc .sorter {
|
||||||
|
background-position: 0 -10px;
|
||||||
|
}
|
||||||
|
.status-line { height: 10px; }
|
||||||
|
/* yellow */
|
||||||
|
.cbranch-no { background: yellow !important; color: #111; }
|
||||||
|
/* dark red */
|
||||||
|
.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
|
||||||
|
.low .chart { border:1px solid #C21F39 }
|
||||||
|
.highlighted,
|
||||||
|
.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
|
||||||
|
background: #C21F39 !important;
|
||||||
|
}
|
||||||
|
/* medium red */
|
||||||
|
.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
|
||||||
|
/* light red */
|
||||||
|
.low, .cline-no { background:#FCE1E5 }
|
||||||
|
/* light green */
|
||||||
|
.high, .cline-yes { background:rgb(230,245,208) }
|
||||||
|
/* medium green */
|
||||||
|
.cstat-yes { background:rgb(161,215,106) }
|
||||||
|
/* dark green */
|
||||||
|
.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
|
||||||
|
.high .chart { border:1px solid rgb(77,146,33) }
|
||||||
|
/* dark yellow (gold) */
|
||||||
|
.status-line.medium, .medium .cover-fill { background: #f9cd0b; }
|
||||||
|
.medium .chart { border:1px solid #f9cd0b; }
|
||||||
|
/* light yellow */
|
||||||
|
.medium { background: #fff4c2; }
|
||||||
|
|
||||||
|
.cstat-skip { background: #ddd; color: #111; }
|
||||||
|
.fstat-skip { background: #ddd; color: #111 !important; }
|
||||||
|
.cbranch-skip { background: #ddd !important; color: #111; }
|
||||||
|
|
||||||
|
span.cline-neutral { background: #eaeaea; }
|
||||||
|
|
||||||
|
.coverage-summary td.empty {
|
||||||
|
opacity: .5;
|
||||||
|
padding-top: 4px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
line-height: 1;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover-fill, .cover-empty {
|
||||||
|
display:inline-block;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
.chart {
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
.cover-empty {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
.cover-full {
|
||||||
|
border-right: none !important;
|
||||||
|
}
|
||||||
|
pre.prettyprint {
|
||||||
|
border: none !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
.com { color: #999 !important; }
|
||||||
|
.ignore-none { color: #999; font-weight: normal; }
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
min-height: 100%;
|
||||||
|
height: auto !important;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0 auto -48px;
|
||||||
|
}
|
||||||
|
.footer, .push {
|
||||||
|
height: 48px;
|
||||||
|
}
|
||||||
87
coverage/lcov-report/block-navigation.js
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
var jumpToCode = (function init() {
|
||||||
|
// Classes of code we would like to highlight in the file view
|
||||||
|
var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
|
||||||
|
|
||||||
|
// Elements to highlight in the file listing view
|
||||||
|
var fileListingElements = ['td.pct.low'];
|
||||||
|
|
||||||
|
// We don't want to select elements that are direct descendants of another match
|
||||||
|
var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
|
||||||
|
|
||||||
|
// Selector that finds elements on the page to which we can jump
|
||||||
|
var selector =
|
||||||
|
fileListingElements.join(', ') +
|
||||||
|
', ' +
|
||||||
|
notSelector +
|
||||||
|
missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
|
||||||
|
|
||||||
|
// The NodeList of matching elements
|
||||||
|
var missingCoverageElements = document.querySelectorAll(selector);
|
||||||
|
|
||||||
|
var currentIndex;
|
||||||
|
|
||||||
|
function toggleClass(index) {
|
||||||
|
missingCoverageElements
|
||||||
|
.item(currentIndex)
|
||||||
|
.classList.remove('highlighted');
|
||||||
|
missingCoverageElements.item(index).classList.add('highlighted');
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeCurrent(index) {
|
||||||
|
toggleClass(index);
|
||||||
|
currentIndex = index;
|
||||||
|
missingCoverageElements.item(index).scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'center',
|
||||||
|
inline: 'center'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function goToPrevious() {
|
||||||
|
var nextIndex = 0;
|
||||||
|
if (typeof currentIndex !== 'number' || currentIndex === 0) {
|
||||||
|
nextIndex = missingCoverageElements.length - 1;
|
||||||
|
} else if (missingCoverageElements.length > 1) {
|
||||||
|
nextIndex = currentIndex - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeCurrent(nextIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
function goToNext() {
|
||||||
|
var nextIndex = 0;
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof currentIndex === 'number' &&
|
||||||
|
currentIndex < missingCoverageElements.length - 1
|
||||||
|
) {
|
||||||
|
nextIndex = currentIndex + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeCurrent(nextIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function jump(event) {
|
||||||
|
if (
|
||||||
|
document.getElementById('fileSearch') === document.activeElement &&
|
||||||
|
document.activeElement != null
|
||||||
|
) {
|
||||||
|
// if we're currently focused on the search input, we don't want to navigate
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event.which) {
|
||||||
|
case 78: // n
|
||||||
|
case 74: // j
|
||||||
|
goToNext();
|
||||||
|
break;
|
||||||
|
case 66: // b
|
||||||
|
case 75: // k
|
||||||
|
case 80: // p
|
||||||
|
goToPrevious();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
window.addEventListener('keydown', jumpToCode);
|
||||||
946
coverage/lcov-report/dashboard_core.js.html
Normal file
@ -0,0 +1,946 @@
|
|||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Code coverage report for dashboard_core.js</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="stylesheet" href="prettify.css" />
|
||||||
|
<link rel="stylesheet" href="base.css" />
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style type='text/css'>
|
||||||
|
.coverage-summary .sorter {
|
||||||
|
background-image: url(sort-arrow-sprite.png);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class='wrapper'>
|
||||||
|
<div class='pad1'>
|
||||||
|
<h1><a href="index.html">All files</a> dashboard_core.js</h1>
|
||||||
|
<div class='clearfix'>
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">95.47% </span>
|
||||||
|
<span class="quiet">Statements</span>
|
||||||
|
<span class='fraction'>274/287</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">82.14% </span>
|
||||||
|
<span class="quiet">Branches</span>
|
||||||
|
<span class='fraction'>69/84</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">100% </span>
|
||||||
|
<span class="quiet">Functions</span>
|
||||||
|
<span class='fraction'>18/18</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">95.47% </span>
|
||||||
|
<span class="quiet">Lines</span>
|
||||||
|
<span class='fraction'>274/287</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="quiet">
|
||||||
|
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
|
||||||
|
</p>
|
||||||
|
<template id="filterTemplate">
|
||||||
|
<div class="quiet">
|
||||||
|
Filter:
|
||||||
|
<input type="search" id="fileSearch">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class='status-line high'></div>
|
||||||
|
<pre><table class="coverage">
|
||||||
|
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
||||||
|
<a name='L2'></a><a href='#L2'>2</a>
|
||||||
|
<a name='L3'></a><a href='#L3'>3</a>
|
||||||
|
<a name='L4'></a><a href='#L4'>4</a>
|
||||||
|
<a name='L5'></a><a href='#L5'>5</a>
|
||||||
|
<a name='L6'></a><a href='#L6'>6</a>
|
||||||
|
<a name='L7'></a><a href='#L7'>7</a>
|
||||||
|
<a name='L8'></a><a href='#L8'>8</a>
|
||||||
|
<a name='L9'></a><a href='#L9'>9</a>
|
||||||
|
<a name='L10'></a><a href='#L10'>10</a>
|
||||||
|
<a name='L11'></a><a href='#L11'>11</a>
|
||||||
|
<a name='L12'></a><a href='#L12'>12</a>
|
||||||
|
<a name='L13'></a><a href='#L13'>13</a>
|
||||||
|
<a name='L14'></a><a href='#L14'>14</a>
|
||||||
|
<a name='L15'></a><a href='#L15'>15</a>
|
||||||
|
<a name='L16'></a><a href='#L16'>16</a>
|
||||||
|
<a name='L17'></a><a href='#L17'>17</a>
|
||||||
|
<a name='L18'></a><a href='#L18'>18</a>
|
||||||
|
<a name='L19'></a><a href='#L19'>19</a>
|
||||||
|
<a name='L20'></a><a href='#L20'>20</a>
|
||||||
|
<a name='L21'></a><a href='#L21'>21</a>
|
||||||
|
<a name='L22'></a><a href='#L22'>22</a>
|
||||||
|
<a name='L23'></a><a href='#L23'>23</a>
|
||||||
|
<a name='L24'></a><a href='#L24'>24</a>
|
||||||
|
<a name='L25'></a><a href='#L25'>25</a>
|
||||||
|
<a name='L26'></a><a href='#L26'>26</a>
|
||||||
|
<a name='L27'></a><a href='#L27'>27</a>
|
||||||
|
<a name='L28'></a><a href='#L28'>28</a>
|
||||||
|
<a name='L29'></a><a href='#L29'>29</a>
|
||||||
|
<a name='L30'></a><a href='#L30'>30</a>
|
||||||
|
<a name='L31'></a><a href='#L31'>31</a>
|
||||||
|
<a name='L32'></a><a href='#L32'>32</a>
|
||||||
|
<a name='L33'></a><a href='#L33'>33</a>
|
||||||
|
<a name='L34'></a><a href='#L34'>34</a>
|
||||||
|
<a name='L35'></a><a href='#L35'>35</a>
|
||||||
|
<a name='L36'></a><a href='#L36'>36</a>
|
||||||
|
<a name='L37'></a><a href='#L37'>37</a>
|
||||||
|
<a name='L38'></a><a href='#L38'>38</a>
|
||||||
|
<a name='L39'></a><a href='#L39'>39</a>
|
||||||
|
<a name='L40'></a><a href='#L40'>40</a>
|
||||||
|
<a name='L41'></a><a href='#L41'>41</a>
|
||||||
|
<a name='L42'></a><a href='#L42'>42</a>
|
||||||
|
<a name='L43'></a><a href='#L43'>43</a>
|
||||||
|
<a name='L44'></a><a href='#L44'>44</a>
|
||||||
|
<a name='L45'></a><a href='#L45'>45</a>
|
||||||
|
<a name='L46'></a><a href='#L46'>46</a>
|
||||||
|
<a name='L47'></a><a href='#L47'>47</a>
|
||||||
|
<a name='L48'></a><a href='#L48'>48</a>
|
||||||
|
<a name='L49'></a><a href='#L49'>49</a>
|
||||||
|
<a name='L50'></a><a href='#L50'>50</a>
|
||||||
|
<a name='L51'></a><a href='#L51'>51</a>
|
||||||
|
<a name='L52'></a><a href='#L52'>52</a>
|
||||||
|
<a name='L53'></a><a href='#L53'>53</a>
|
||||||
|
<a name='L54'></a><a href='#L54'>54</a>
|
||||||
|
<a name='L55'></a><a href='#L55'>55</a>
|
||||||
|
<a name='L56'></a><a href='#L56'>56</a>
|
||||||
|
<a name='L57'></a><a href='#L57'>57</a>
|
||||||
|
<a name='L58'></a><a href='#L58'>58</a>
|
||||||
|
<a name='L59'></a><a href='#L59'>59</a>
|
||||||
|
<a name='L60'></a><a href='#L60'>60</a>
|
||||||
|
<a name='L61'></a><a href='#L61'>61</a>
|
||||||
|
<a name='L62'></a><a href='#L62'>62</a>
|
||||||
|
<a name='L63'></a><a href='#L63'>63</a>
|
||||||
|
<a name='L64'></a><a href='#L64'>64</a>
|
||||||
|
<a name='L65'></a><a href='#L65'>65</a>
|
||||||
|
<a name='L66'></a><a href='#L66'>66</a>
|
||||||
|
<a name='L67'></a><a href='#L67'>67</a>
|
||||||
|
<a name='L68'></a><a href='#L68'>68</a>
|
||||||
|
<a name='L69'></a><a href='#L69'>69</a>
|
||||||
|
<a name='L70'></a><a href='#L70'>70</a>
|
||||||
|
<a name='L71'></a><a href='#L71'>71</a>
|
||||||
|
<a name='L72'></a><a href='#L72'>72</a>
|
||||||
|
<a name='L73'></a><a href='#L73'>73</a>
|
||||||
|
<a name='L74'></a><a href='#L74'>74</a>
|
||||||
|
<a name='L75'></a><a href='#L75'>75</a>
|
||||||
|
<a name='L76'></a><a href='#L76'>76</a>
|
||||||
|
<a name='L77'></a><a href='#L77'>77</a>
|
||||||
|
<a name='L78'></a><a href='#L78'>78</a>
|
||||||
|
<a name='L79'></a><a href='#L79'>79</a>
|
||||||
|
<a name='L80'></a><a href='#L80'>80</a>
|
||||||
|
<a name='L81'></a><a href='#L81'>81</a>
|
||||||
|
<a name='L82'></a><a href='#L82'>82</a>
|
||||||
|
<a name='L83'></a><a href='#L83'>83</a>
|
||||||
|
<a name='L84'></a><a href='#L84'>84</a>
|
||||||
|
<a name='L85'></a><a href='#L85'>85</a>
|
||||||
|
<a name='L86'></a><a href='#L86'>86</a>
|
||||||
|
<a name='L87'></a><a href='#L87'>87</a>
|
||||||
|
<a name='L88'></a><a href='#L88'>88</a>
|
||||||
|
<a name='L89'></a><a href='#L89'>89</a>
|
||||||
|
<a name='L90'></a><a href='#L90'>90</a>
|
||||||
|
<a name='L91'></a><a href='#L91'>91</a>
|
||||||
|
<a name='L92'></a><a href='#L92'>92</a>
|
||||||
|
<a name='L93'></a><a href='#L93'>93</a>
|
||||||
|
<a name='L94'></a><a href='#L94'>94</a>
|
||||||
|
<a name='L95'></a><a href='#L95'>95</a>
|
||||||
|
<a name='L96'></a><a href='#L96'>96</a>
|
||||||
|
<a name='L97'></a><a href='#L97'>97</a>
|
||||||
|
<a name='L98'></a><a href='#L98'>98</a>
|
||||||
|
<a name='L99'></a><a href='#L99'>99</a>
|
||||||
|
<a name='L100'></a><a href='#L100'>100</a>
|
||||||
|
<a name='L101'></a><a href='#L101'>101</a>
|
||||||
|
<a name='L102'></a><a href='#L102'>102</a>
|
||||||
|
<a name='L103'></a><a href='#L103'>103</a>
|
||||||
|
<a name='L104'></a><a href='#L104'>104</a>
|
||||||
|
<a name='L105'></a><a href='#L105'>105</a>
|
||||||
|
<a name='L106'></a><a href='#L106'>106</a>
|
||||||
|
<a name='L107'></a><a href='#L107'>107</a>
|
||||||
|
<a name='L108'></a><a href='#L108'>108</a>
|
||||||
|
<a name='L109'></a><a href='#L109'>109</a>
|
||||||
|
<a name='L110'></a><a href='#L110'>110</a>
|
||||||
|
<a name='L111'></a><a href='#L111'>111</a>
|
||||||
|
<a name='L112'></a><a href='#L112'>112</a>
|
||||||
|
<a name='L113'></a><a href='#L113'>113</a>
|
||||||
|
<a name='L114'></a><a href='#L114'>114</a>
|
||||||
|
<a name='L115'></a><a href='#L115'>115</a>
|
||||||
|
<a name='L116'></a><a href='#L116'>116</a>
|
||||||
|
<a name='L117'></a><a href='#L117'>117</a>
|
||||||
|
<a name='L118'></a><a href='#L118'>118</a>
|
||||||
|
<a name='L119'></a><a href='#L119'>119</a>
|
||||||
|
<a name='L120'></a><a href='#L120'>120</a>
|
||||||
|
<a name='L121'></a><a href='#L121'>121</a>
|
||||||
|
<a name='L122'></a><a href='#L122'>122</a>
|
||||||
|
<a name='L123'></a><a href='#L123'>123</a>
|
||||||
|
<a name='L124'></a><a href='#L124'>124</a>
|
||||||
|
<a name='L125'></a><a href='#L125'>125</a>
|
||||||
|
<a name='L126'></a><a href='#L126'>126</a>
|
||||||
|
<a name='L127'></a><a href='#L127'>127</a>
|
||||||
|
<a name='L128'></a><a href='#L128'>128</a>
|
||||||
|
<a name='L129'></a><a href='#L129'>129</a>
|
||||||
|
<a name='L130'></a><a href='#L130'>130</a>
|
||||||
|
<a name='L131'></a><a href='#L131'>131</a>
|
||||||
|
<a name='L132'></a><a href='#L132'>132</a>
|
||||||
|
<a name='L133'></a><a href='#L133'>133</a>
|
||||||
|
<a name='L134'></a><a href='#L134'>134</a>
|
||||||
|
<a name='L135'></a><a href='#L135'>135</a>
|
||||||
|
<a name='L136'></a><a href='#L136'>136</a>
|
||||||
|
<a name='L137'></a><a href='#L137'>137</a>
|
||||||
|
<a name='L138'></a><a href='#L138'>138</a>
|
||||||
|
<a name='L139'></a><a href='#L139'>139</a>
|
||||||
|
<a name='L140'></a><a href='#L140'>140</a>
|
||||||
|
<a name='L141'></a><a href='#L141'>141</a>
|
||||||
|
<a name='L142'></a><a href='#L142'>142</a>
|
||||||
|
<a name='L143'></a><a href='#L143'>143</a>
|
||||||
|
<a name='L144'></a><a href='#L144'>144</a>
|
||||||
|
<a name='L145'></a><a href='#L145'>145</a>
|
||||||
|
<a name='L146'></a><a href='#L146'>146</a>
|
||||||
|
<a name='L147'></a><a href='#L147'>147</a>
|
||||||
|
<a name='L148'></a><a href='#L148'>148</a>
|
||||||
|
<a name='L149'></a><a href='#L149'>149</a>
|
||||||
|
<a name='L150'></a><a href='#L150'>150</a>
|
||||||
|
<a name='L151'></a><a href='#L151'>151</a>
|
||||||
|
<a name='L152'></a><a href='#L152'>152</a>
|
||||||
|
<a name='L153'></a><a href='#L153'>153</a>
|
||||||
|
<a name='L154'></a><a href='#L154'>154</a>
|
||||||
|
<a name='L155'></a><a href='#L155'>155</a>
|
||||||
|
<a name='L156'></a><a href='#L156'>156</a>
|
||||||
|
<a name='L157'></a><a href='#L157'>157</a>
|
||||||
|
<a name='L158'></a><a href='#L158'>158</a>
|
||||||
|
<a name='L159'></a><a href='#L159'>159</a>
|
||||||
|
<a name='L160'></a><a href='#L160'>160</a>
|
||||||
|
<a name='L161'></a><a href='#L161'>161</a>
|
||||||
|
<a name='L162'></a><a href='#L162'>162</a>
|
||||||
|
<a name='L163'></a><a href='#L163'>163</a>
|
||||||
|
<a name='L164'></a><a href='#L164'>164</a>
|
||||||
|
<a name='L165'></a><a href='#L165'>165</a>
|
||||||
|
<a name='L166'></a><a href='#L166'>166</a>
|
||||||
|
<a name='L167'></a><a href='#L167'>167</a>
|
||||||
|
<a name='L168'></a><a href='#L168'>168</a>
|
||||||
|
<a name='L169'></a><a href='#L169'>169</a>
|
||||||
|
<a name='L170'></a><a href='#L170'>170</a>
|
||||||
|
<a name='L171'></a><a href='#L171'>171</a>
|
||||||
|
<a name='L172'></a><a href='#L172'>172</a>
|
||||||
|
<a name='L173'></a><a href='#L173'>173</a>
|
||||||
|
<a name='L174'></a><a href='#L174'>174</a>
|
||||||
|
<a name='L175'></a><a href='#L175'>175</a>
|
||||||
|
<a name='L176'></a><a href='#L176'>176</a>
|
||||||
|
<a name='L177'></a><a href='#L177'>177</a>
|
||||||
|
<a name='L178'></a><a href='#L178'>178</a>
|
||||||
|
<a name='L179'></a><a href='#L179'>179</a>
|
||||||
|
<a name='L180'></a><a href='#L180'>180</a>
|
||||||
|
<a name='L181'></a><a href='#L181'>181</a>
|
||||||
|
<a name='L182'></a><a href='#L182'>182</a>
|
||||||
|
<a name='L183'></a><a href='#L183'>183</a>
|
||||||
|
<a name='L184'></a><a href='#L184'>184</a>
|
||||||
|
<a name='L185'></a><a href='#L185'>185</a>
|
||||||
|
<a name='L186'></a><a href='#L186'>186</a>
|
||||||
|
<a name='L187'></a><a href='#L187'>187</a>
|
||||||
|
<a name='L188'></a><a href='#L188'>188</a>
|
||||||
|
<a name='L189'></a><a href='#L189'>189</a>
|
||||||
|
<a name='L190'></a><a href='#L190'>190</a>
|
||||||
|
<a name='L191'></a><a href='#L191'>191</a>
|
||||||
|
<a name='L192'></a><a href='#L192'>192</a>
|
||||||
|
<a name='L193'></a><a href='#L193'>193</a>
|
||||||
|
<a name='L194'></a><a href='#L194'>194</a>
|
||||||
|
<a name='L195'></a><a href='#L195'>195</a>
|
||||||
|
<a name='L196'></a><a href='#L196'>196</a>
|
||||||
|
<a name='L197'></a><a href='#L197'>197</a>
|
||||||
|
<a name='L198'></a><a href='#L198'>198</a>
|
||||||
|
<a name='L199'></a><a href='#L199'>199</a>
|
||||||
|
<a name='L200'></a><a href='#L200'>200</a>
|
||||||
|
<a name='L201'></a><a href='#L201'>201</a>
|
||||||
|
<a name='L202'></a><a href='#L202'>202</a>
|
||||||
|
<a name='L203'></a><a href='#L203'>203</a>
|
||||||
|
<a name='L204'></a><a href='#L204'>204</a>
|
||||||
|
<a name='L205'></a><a href='#L205'>205</a>
|
||||||
|
<a name='L206'></a><a href='#L206'>206</a>
|
||||||
|
<a name='L207'></a><a href='#L207'>207</a>
|
||||||
|
<a name='L208'></a><a href='#L208'>208</a>
|
||||||
|
<a name='L209'></a><a href='#L209'>209</a>
|
||||||
|
<a name='L210'></a><a href='#L210'>210</a>
|
||||||
|
<a name='L211'></a><a href='#L211'>211</a>
|
||||||
|
<a name='L212'></a><a href='#L212'>212</a>
|
||||||
|
<a name='L213'></a><a href='#L213'>213</a>
|
||||||
|
<a name='L214'></a><a href='#L214'>214</a>
|
||||||
|
<a name='L215'></a><a href='#L215'>215</a>
|
||||||
|
<a name='L216'></a><a href='#L216'>216</a>
|
||||||
|
<a name='L217'></a><a href='#L217'>217</a>
|
||||||
|
<a name='L218'></a><a href='#L218'>218</a>
|
||||||
|
<a name='L219'></a><a href='#L219'>219</a>
|
||||||
|
<a name='L220'></a><a href='#L220'>220</a>
|
||||||
|
<a name='L221'></a><a href='#L221'>221</a>
|
||||||
|
<a name='L222'></a><a href='#L222'>222</a>
|
||||||
|
<a name='L223'></a><a href='#L223'>223</a>
|
||||||
|
<a name='L224'></a><a href='#L224'>224</a>
|
||||||
|
<a name='L225'></a><a href='#L225'>225</a>
|
||||||
|
<a name='L226'></a><a href='#L226'>226</a>
|
||||||
|
<a name='L227'></a><a href='#L227'>227</a>
|
||||||
|
<a name='L228'></a><a href='#L228'>228</a>
|
||||||
|
<a name='L229'></a><a href='#L229'>229</a>
|
||||||
|
<a name='L230'></a><a href='#L230'>230</a>
|
||||||
|
<a name='L231'></a><a href='#L231'>231</a>
|
||||||
|
<a name='L232'></a><a href='#L232'>232</a>
|
||||||
|
<a name='L233'></a><a href='#L233'>233</a>
|
||||||
|
<a name='L234'></a><a href='#L234'>234</a>
|
||||||
|
<a name='L235'></a><a href='#L235'>235</a>
|
||||||
|
<a name='L236'></a><a href='#L236'>236</a>
|
||||||
|
<a name='L237'></a><a href='#L237'>237</a>
|
||||||
|
<a name='L238'></a><a href='#L238'>238</a>
|
||||||
|
<a name='L239'></a><a href='#L239'>239</a>
|
||||||
|
<a name='L240'></a><a href='#L240'>240</a>
|
||||||
|
<a name='L241'></a><a href='#L241'>241</a>
|
||||||
|
<a name='L242'></a><a href='#L242'>242</a>
|
||||||
|
<a name='L243'></a><a href='#L243'>243</a>
|
||||||
|
<a name='L244'></a><a href='#L244'>244</a>
|
||||||
|
<a name='L245'></a><a href='#L245'>245</a>
|
||||||
|
<a name='L246'></a><a href='#L246'>246</a>
|
||||||
|
<a name='L247'></a><a href='#L247'>247</a>
|
||||||
|
<a name='L248'></a><a href='#L248'>248</a>
|
||||||
|
<a name='L249'></a><a href='#L249'>249</a>
|
||||||
|
<a name='L250'></a><a href='#L250'>250</a>
|
||||||
|
<a name='L251'></a><a href='#L251'>251</a>
|
||||||
|
<a name='L252'></a><a href='#L252'>252</a>
|
||||||
|
<a name='L253'></a><a href='#L253'>253</a>
|
||||||
|
<a name='L254'></a><a href='#L254'>254</a>
|
||||||
|
<a name='L255'></a><a href='#L255'>255</a>
|
||||||
|
<a name='L256'></a><a href='#L256'>256</a>
|
||||||
|
<a name='L257'></a><a href='#L257'>257</a>
|
||||||
|
<a name='L258'></a><a href='#L258'>258</a>
|
||||||
|
<a name='L259'></a><a href='#L259'>259</a>
|
||||||
|
<a name='L260'></a><a href='#L260'>260</a>
|
||||||
|
<a name='L261'></a><a href='#L261'>261</a>
|
||||||
|
<a name='L262'></a><a href='#L262'>262</a>
|
||||||
|
<a name='L263'></a><a href='#L263'>263</a>
|
||||||
|
<a name='L264'></a><a href='#L264'>264</a>
|
||||||
|
<a name='L265'></a><a href='#L265'>265</a>
|
||||||
|
<a name='L266'></a><a href='#L266'>266</a>
|
||||||
|
<a name='L267'></a><a href='#L267'>267</a>
|
||||||
|
<a name='L268'></a><a href='#L268'>268</a>
|
||||||
|
<a name='L269'></a><a href='#L269'>269</a>
|
||||||
|
<a name='L270'></a><a href='#L270'>270</a>
|
||||||
|
<a name='L271'></a><a href='#L271'>271</a>
|
||||||
|
<a name='L272'></a><a href='#L272'>272</a>
|
||||||
|
<a name='L273'></a><a href='#L273'>273</a>
|
||||||
|
<a name='L274'></a><a href='#L274'>274</a>
|
||||||
|
<a name='L275'></a><a href='#L275'>275</a>
|
||||||
|
<a name='L276'></a><a href='#L276'>276</a>
|
||||||
|
<a name='L277'></a><a href='#L277'>277</a>
|
||||||
|
<a name='L278'></a><a href='#L278'>278</a>
|
||||||
|
<a name='L279'></a><a href='#L279'>279</a>
|
||||||
|
<a name='L280'></a><a href='#L280'>280</a>
|
||||||
|
<a name='L281'></a><a href='#L281'>281</a>
|
||||||
|
<a name='L282'></a><a href='#L282'>282</a>
|
||||||
|
<a name='L283'></a><a href='#L283'>283</a>
|
||||||
|
<a name='L284'></a><a href='#L284'>284</a>
|
||||||
|
<a name='L285'></a><a href='#L285'>285</a>
|
||||||
|
<a name='L286'></a><a href='#L286'>286</a>
|
||||||
|
<a name='L287'></a><a href='#L287'>287</a>
|
||||||
|
<a name='L288'></a><a href='#L288'>288</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">49x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">12x</span>
|
||||||
|
<span class="cline-any cline-yes">12x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">12x</span>
|
||||||
|
<span class="cline-any cline-yes">12x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">5x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">7x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-yes">9x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">8x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">6x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">2x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">4x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">5x</span>
|
||||||
|
<span class="cline-any cline-yes">5x</span>
|
||||||
|
<span class="cline-any cline-yes">5x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-yes">3x</span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-no"> </span>
|
||||||
|
<span class="cline-any cline-yes">5x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-yes">1x</span>
|
||||||
|
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">/**
|
||||||
|
* DashboardCore - Core logic extracted from main.js for testability.
|
||||||
|
*
|
||||||
|
* This module contains the testable business logic:
|
||||||
|
* - Authentication (login, logout, checkAuthStatus)
|
||||||
|
* - API calls with auth headers
|
||||||
|
* - WebSocket message handling
|
||||||
|
* - Data management (hosts, tasks, schedules)
|
||||||
|
*
|
||||||
|
* The main.js file imports this module and adds DOM-specific functionality.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core dashboard functionality that can be tested without DOM dependencies.
|
||||||
|
*/
|
||||||
|
export class DashboardCore {
|
||||||
|
constructor(options = {}) {
|
||||||
|
// Allow injection of dependencies for testing
|
||||||
|
this.apiBase = options.apiBase || (typeof window !== 'undefined' ? window.location.origin <span class="branch-0 cbranch-no" title="branch not covered" >: 'http://localhost')</span>;
|
||||||
|
this.storage = options.storage || (typeof localStorage !== 'undefined' ? localStorage <span class="branch-0 cbranch-no" title="branch not covered" >: null)</span>;
|
||||||
|
this.fetchFn = options.fetch || (typeof fetch !== 'undefined' ? fetch <span class="branch-0 cbranch-no" title="branch not covered" >: null)</span>;
|
||||||
|
this.WebSocketClass = options.WebSocket || (typeof WebSocket !== 'undefined' ? WebSocket <span class="branch-0 cbranch-no" title="branch not covered" >: null)</span>;
|
||||||
|
|
||||||
|
// Authentication state
|
||||||
|
this.accessToken = this.storage?.getItem('accessToken') || null;
|
||||||
|
this.currentUser = null;
|
||||||
|
this.setupRequired = false;
|
||||||
|
|
||||||
|
// Data state
|
||||||
|
this.hosts = [];
|
||||||
|
this.tasks = [];
|
||||||
|
this.schedules = [];
|
||||||
|
this.logs = [];
|
||||||
|
this.alerts = [];
|
||||||
|
this.alertsUnread = 0;
|
||||||
|
|
||||||
|
// WebSocket
|
||||||
|
this.ws = null;
|
||||||
|
|
||||||
|
// Callbacks for UI updates (set by main.js)
|
||||||
|
this.onHostsUpdated = null;
|
||||||
|
this.onTasksUpdated = null;
|
||||||
|
this.onSchedulesUpdated = null;
|
||||||
|
this.onAlertsUpdated = null;
|
||||||
|
this.onAuthStateChanged = null;
|
||||||
|
this.onNotification = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== AUTHENTICATION =====
|
||||||
|
|
||||||
|
getAuthHeaders() {
|
||||||
|
const headers = { 'Content-Type': 'application/json' };
|
||||||
|
if (this.accessToken) {
|
||||||
|
headers['Authorization'] = `Bearer ${this.accessToken}`;
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkAuthStatus() {
|
||||||
|
try {
|
||||||
|
const response = await this.fetchFn(`${this.apiBase}/api/auth/status`, {
|
||||||
|
headers: this.getAuthHeaders()
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > return false;</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > }</span>
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
this.setupRequired = data.setup_required;
|
||||||
|
|
||||||
|
if (data.setup_required) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.authenticated && data.user) {
|
||||||
|
this.currentUser = data.user;
|
||||||
|
this.onAuthStateChanged?.({ authenticated: true, user: data.user });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Auth status check failed:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async login(username, password) {
|
||||||
|
try {
|
||||||
|
const response = await this.fetchFn(`${this.apiBase}/api/auth/login/json`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ username, password })
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const error = await response.json();
|
||||||
|
throw new Error(error.detail <span class="branch-0 cbranch-no" title="branch not covered" >|| 'Login failed')</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
this.accessToken = data.access_token;
|
||||||
|
this.storage?.setItem('accessToken', data.access_token);
|
||||||
|
|
||||||
|
await this.checkAuthStatus();
|
||||||
|
this.onNotification?.('Connexion réussie', 'success');
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Login failed:', error);
|
||||||
|
this.onNotification?.(error.message, 'error');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
this.accessToken = null;
|
||||||
|
this.currentUser = null;
|
||||||
|
this.storage?.removeItem('accessToken');
|
||||||
|
|
||||||
|
if (this.ws) {
|
||||||
|
this.ws.close();
|
||||||
|
this.ws = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onAuthStateChanged?.({ authenticated: false, user: null });
|
||||||
|
this.onNotification<span class="branch-0 cbranch-no" title="branch not covered" >?.('Déconnexion réussie', 'success');</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== API CALLS =====
|
||||||
|
|
||||||
|
async apiCall(endpoint, options = {}) {
|
||||||
|
const url = `${this.apiBase}${endpoint}`;
|
||||||
|
const defaultOptions = {
|
||||||
|
headers: this.getAuthHeaders()
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await this.fetchFn(url, { ...defaultOptions, ...options });
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`API Error (${endpoint}):`, error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== WEBSOCKET =====
|
||||||
|
|
||||||
|
connectWebSocket(wsUrl = null) {
|
||||||
|
if (!this.WebSocketClass) {
|
||||||
|
console.warn('WebSocket not available');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = wsUrl || this._getDefaultWsUrl();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.ws = new this.WebSocketClass(url);
|
||||||
|
|
||||||
|
this.ws.onopen = () => {
|
||||||
|
console.log('WebSocket connected');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ws.onmessage = (event) => {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(event.data);
|
||||||
|
this.handleWebSocketMessage(data);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('WebSocket message parse error:', e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ws.onclose = () => {
|
||||||
|
console.log('WebSocket closed');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ws.onerror = (error) => {
|
||||||
|
console.error('WebSocket error:', error);
|
||||||
|
};
|
||||||
|
} <span class="branch-0 cbranch-no" title="branch not covered" >catch (error) {</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > console.error('WebSocket connection failed:', error);</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > }</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
_getDefaultWsUrl() {
|
||||||
|
if (typeof window === 'undefined') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > return 'ws://localhost/ws';</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > }</span>
|
||||||
|
const protocol = window.location.protocol === 'https:' <span class="branch-0 cbranch-no" title="branch not covered" >? 'wss:' </span>: 'ws:';
|
||||||
|
return `${protocol}//${window.location.host}/ws`;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleWebSocketMessage(message) {
|
||||||
|
const { type, data } = message;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'host_updated':
|
||||||
|
this.updateHostInList(data);
|
||||||
|
break;
|
||||||
|
case 'task_started':
|
||||||
|
case 'task_updated':
|
||||||
|
case 'task_completed':
|
||||||
|
this.handleTaskUpdate(data);
|
||||||
|
break;
|
||||||
|
case 'schedule_completed':
|
||||||
|
this.updateScheduleStatus(data);
|
||||||
|
break;
|
||||||
|
case 'alert_created':
|
||||||
|
this.handleAlertCreated(data);
|
||||||
|
break;
|
||||||
|
case 'hosts_synced':
|
||||||
|
this.onHostsUpdated?.();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unknown message type - ignore
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== DATA MANAGEMENT =====
|
||||||
|
|
||||||
|
updateHostInList(hostData) {
|
||||||
|
if (!hostData?.id) return;
|
||||||
|
|
||||||
|
const idx = this.hosts.findIndex(h => h.id === hostData.id);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.hosts[idx] = { ...this.hosts[idx], ...hostData };
|
||||||
|
} else {
|
||||||
|
this.hosts.push(hostData);
|
||||||
|
}
|
||||||
|
this.onHostsUpdated?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTaskUpdate(taskData) {
|
||||||
|
if (!taskData?.id) <span class="branch-0 cbranch-no" title="branch not covered" >return;</span>
|
||||||
|
|
||||||
|
const idx = this.tasks.findIndex(t => t.id === taskData.id);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.tasks[idx] = { ...this.tasks[idx], ...taskData };
|
||||||
|
} else {
|
||||||
|
this.tasks.unshift(taskData);
|
||||||
|
}
|
||||||
|
this.onTasksUpdated?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateScheduleStatus(scheduleData) {
|
||||||
|
if (!scheduleData?.schedule_id) <span class="branch-0 cbranch-no" title="branch not covered" >return;</span>
|
||||||
|
|
||||||
|
const idx = this.schedules.findIndex(s => s.id === scheduleData.schedule_id);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.schedules[idx].last_status = scheduleData.status;
|
||||||
|
this.schedules[idx].last_run_at = scheduleData.completed_at;
|
||||||
|
}
|
||||||
|
this.onSchedulesUpdated?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAlertCreated(alert) {
|
||||||
|
if (!alert) <span class="branch-0 cbranch-no" title="branch not covered" >return;</span>
|
||||||
|
this.alerts = [alert, ...this.alerts].slice(0, 200);
|
||||||
|
this.alertsUnread++;
|
||||||
|
this.onAlertsUpdated?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== UTILITY =====
|
||||||
|
|
||||||
|
escapeHtml(text) {
|
||||||
|
if (!text) return '';
|
||||||
|
const div = typeof document !== 'undefined' ? document.createElement('div') <span class="branch-0 cbranch-no" title="branch not covered" >: null;</span>
|
||||||
|
if (div) {
|
||||||
|
div.textContent = text;
|
||||||
|
return div.innerHTML;
|
||||||
|
}
|
||||||
|
<span class="cstat-no" title="statement not covered" ><span class="branch-0 cbranch-no" title="branch not covered" > // Fallback for non-DOM environments</span></span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > return String(text)</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > .replace(/&/g, '&amp;')</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > .replace(/</g, '&lt;')</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > .replace(/>/g, '&gt;')</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > .replace(/"/g, '&quot;')</span>
|
||||||
|
<span class="cstat-no" title="statement not covered" > .replace(/'/g, '&#039;');</span>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export for both ESM and CommonJS
|
||||||
|
export default DashboardCore;
|
||||||
|
</pre></td></tr></table></pre>
|
||||||
|
|
||||||
|
<div class='push'></div><!-- for sticky footer -->
|
||||||
|
</div><!-- /wrapper -->
|
||||||
|
<div class='footer quiet pad2 space-top1 center small'>
|
||||||
|
Code coverage generated by
|
||||||
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
||||||
|
at 2025-12-15T04:43:42.682Z
|
||||||
|
</div>
|
||||||
|
<script src="prettify.js"></script>
|
||||||
|
<script>
|
||||||
|
window.onload = function () {
|
||||||
|
prettyPrint();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script src="sorter.js"></script>
|
||||||
|
<script src="block-navigation.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
BIN
coverage/lcov-report/favicon.png
Normal file
|
After Width: | Height: | Size: 445 B |
116
coverage/lcov-report/index.html
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Code coverage report for All files</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="stylesheet" href="prettify.css" />
|
||||||
|
<link rel="stylesheet" href="base.css" />
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style type='text/css'>
|
||||||
|
.coverage-summary .sorter {
|
||||||
|
background-image: url(sort-arrow-sprite.png);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class='wrapper'>
|
||||||
|
<div class='pad1'>
|
||||||
|
<h1>All files</h1>
|
||||||
|
<div class='clearfix'>
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">95.47% </span>
|
||||||
|
<span class="quiet">Statements</span>
|
||||||
|
<span class='fraction'>274/287</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">82.14% </span>
|
||||||
|
<span class="quiet">Branches</span>
|
||||||
|
<span class='fraction'>69/84</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">100% </span>
|
||||||
|
<span class="quiet">Functions</span>
|
||||||
|
<span class='fraction'>18/18</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='fl pad1y space-right2'>
|
||||||
|
<span class="strong">95.47% </span>
|
||||||
|
<span class="quiet">Lines</span>
|
||||||
|
<span class='fraction'>274/287</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="quiet">
|
||||||
|
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
|
||||||
|
</p>
|
||||||
|
<template id="filterTemplate">
|
||||||
|
<div class="quiet">
|
||||||
|
Filter:
|
||||||
|
<input type="search" id="fileSearch">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class='status-line high'></div>
|
||||||
|
<div class="pad1">
|
||||||
|
<table class="coverage-summary">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
|
||||||
|
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
|
||||||
|
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
|
||||||
|
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
|
||||||
|
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
|
||||||
|
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
|
||||||
|
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
|
||||||
|
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
|
||||||
|
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
|
||||||
|
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody><tr>
|
||||||
|
<td class="file high" data-value="dashboard_core.js"><a href="dashboard_core.js.html">dashboard_core.js</a></td>
|
||||||
|
<td data-value="95.47" class="pic high">
|
||||||
|
<div class="chart"><div class="cover-fill" style="width: 95%"></div><div class="cover-empty" style="width: 5%"></div></div>
|
||||||
|
</td>
|
||||||
|
<td data-value="95.47" class="pct high">95.47%</td>
|
||||||
|
<td data-value="287" class="abs high">274/287</td>
|
||||||
|
<td data-value="82.14" class="pct high">82.14%</td>
|
||||||
|
<td data-value="84" class="abs high">69/84</td>
|
||||||
|
<td data-value="100" class="pct high">100%</td>
|
||||||
|
<td data-value="18" class="abs high">18/18</td>
|
||||||
|
<td data-value="95.47" class="pct high">95.47%</td>
|
||||||
|
<td data-value="287" class="abs high">274/287</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class='push'></div><!-- for sticky footer -->
|
||||||
|
</div><!-- /wrapper -->
|
||||||
|
<div class='footer quiet pad2 space-top1 center small'>
|
||||||
|
Code coverage generated by
|
||||||
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
||||||
|
at 2025-12-15T04:43:42.682Z
|
||||||
|
</div>
|
||||||
|
<script src="prettify.js"></script>
|
||||||
|
<script>
|
||||||
|
window.onload = function () {
|
||||||
|
prettyPrint();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script src="sorter.js"></script>
|
||||||
|
<script src="block-navigation.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
1
coverage/lcov-report/prettify.css
Normal file
@ -0,0 +1 @@
|
|||||||
|
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
|
||||||
2
coverage/lcov-report/prettify.js
Normal file
BIN
coverage/lcov-report/sort-arrow-sprite.png
Normal file
|
After Width: | Height: | Size: 138 B |
210
coverage/lcov-report/sorter.js
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
var addSorting = (function() {
|
||||||
|
'use strict';
|
||||||
|
var cols,
|
||||||
|
currentSort = {
|
||||||
|
index: 0,
|
||||||
|
desc: false
|
||||||
|
};
|
||||||
|
|
||||||
|
// returns the summary table element
|
||||||
|
function getTable() {
|
||||||
|
return document.querySelector('.coverage-summary');
|
||||||
|
}
|
||||||
|
// returns the thead element of the summary table
|
||||||
|
function getTableHeader() {
|
||||||
|
return getTable().querySelector('thead tr');
|
||||||
|
}
|
||||||
|
// returns the tbody element of the summary table
|
||||||
|
function getTableBody() {
|
||||||
|
return getTable().querySelector('tbody');
|
||||||
|
}
|
||||||
|
// returns the th element for nth column
|
||||||
|
function getNthColumn(n) {
|
||||||
|
return getTableHeader().querySelectorAll('th')[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFilterInput() {
|
||||||
|
const searchValue = document.getElementById('fileSearch').value;
|
||||||
|
const rows = document.getElementsByTagName('tbody')[0].children;
|
||||||
|
|
||||||
|
// Try to create a RegExp from the searchValue. If it fails (invalid regex),
|
||||||
|
// it will be treated as a plain text search
|
||||||
|
let searchRegex;
|
||||||
|
try {
|
||||||
|
searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive
|
||||||
|
} catch (error) {
|
||||||
|
searchRegex = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < rows.length; i++) {
|
||||||
|
const row = rows[i];
|
||||||
|
let isMatch = false;
|
||||||
|
|
||||||
|
if (searchRegex) {
|
||||||
|
// If a valid regex was created, use it for matching
|
||||||
|
isMatch = searchRegex.test(row.textContent);
|
||||||
|
} else {
|
||||||
|
// Otherwise, fall back to the original plain text search
|
||||||
|
isMatch = row.textContent
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(searchValue.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
row.style.display = isMatch ? '' : 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// loads the search box
|
||||||
|
function addSearchBox() {
|
||||||
|
var template = document.getElementById('filterTemplate');
|
||||||
|
var templateClone = template.content.cloneNode(true);
|
||||||
|
templateClone.getElementById('fileSearch').oninput = onFilterInput;
|
||||||
|
template.parentElement.appendChild(templateClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
// loads all columns
|
||||||
|
function loadColumns() {
|
||||||
|
var colNodes = getTableHeader().querySelectorAll('th'),
|
||||||
|
colNode,
|
||||||
|
cols = [],
|
||||||
|
col,
|
||||||
|
i;
|
||||||
|
|
||||||
|
for (i = 0; i < colNodes.length; i += 1) {
|
||||||
|
colNode = colNodes[i];
|
||||||
|
col = {
|
||||||
|
key: colNode.getAttribute('data-col'),
|
||||||
|
sortable: !colNode.getAttribute('data-nosort'),
|
||||||
|
type: colNode.getAttribute('data-type') || 'string'
|
||||||
|
};
|
||||||
|
cols.push(col);
|
||||||
|
if (col.sortable) {
|
||||||
|
col.defaultDescSort = col.type === 'number';
|
||||||
|
colNode.innerHTML =
|
||||||
|
colNode.innerHTML + '<span class="sorter"></span>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cols;
|
||||||
|
}
|
||||||
|
// attaches a data attribute to every tr element with an object
|
||||||
|
// of data values keyed by column name
|
||||||
|
function loadRowData(tableRow) {
|
||||||
|
var tableCols = tableRow.querySelectorAll('td'),
|
||||||
|
colNode,
|
||||||
|
col,
|
||||||
|
data = {},
|
||||||
|
i,
|
||||||
|
val;
|
||||||
|
for (i = 0; i < tableCols.length; i += 1) {
|
||||||
|
colNode = tableCols[i];
|
||||||
|
col = cols[i];
|
||||||
|
val = colNode.getAttribute('data-value');
|
||||||
|
if (col.type === 'number') {
|
||||||
|
val = Number(val);
|
||||||
|
}
|
||||||
|
data[col.key] = val;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
// loads all row data
|
||||||
|
function loadData() {
|
||||||
|
var rows = getTableBody().querySelectorAll('tr'),
|
||||||
|
i;
|
||||||
|
|
||||||
|
for (i = 0; i < rows.length; i += 1) {
|
||||||
|
rows[i].data = loadRowData(rows[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sorts the table using the data for the ith column
|
||||||
|
function sortByIndex(index, desc) {
|
||||||
|
var key = cols[index].key,
|
||||||
|
sorter = function(a, b) {
|
||||||
|
a = a.data[key];
|
||||||
|
b = b.data[key];
|
||||||
|
return a < b ? -1 : a > b ? 1 : 0;
|
||||||
|
},
|
||||||
|
finalSorter = sorter,
|
||||||
|
tableBody = document.querySelector('.coverage-summary tbody'),
|
||||||
|
rowNodes = tableBody.querySelectorAll('tr'),
|
||||||
|
rows = [],
|
||||||
|
i;
|
||||||
|
|
||||||
|
if (desc) {
|
||||||
|
finalSorter = function(a, b) {
|
||||||
|
return -1 * sorter(a, b);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < rowNodes.length; i += 1) {
|
||||||
|
rows.push(rowNodes[i]);
|
||||||
|
tableBody.removeChild(rowNodes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
rows.sort(finalSorter);
|
||||||
|
|
||||||
|
for (i = 0; i < rows.length; i += 1) {
|
||||||
|
tableBody.appendChild(rows[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// removes sort indicators for current column being sorted
|
||||||
|
function removeSortIndicators() {
|
||||||
|
var col = getNthColumn(currentSort.index),
|
||||||
|
cls = col.className;
|
||||||
|
|
||||||
|
cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
|
||||||
|
col.className = cls;
|
||||||
|
}
|
||||||
|
// adds sort indicators for current column being sorted
|
||||||
|
function addSortIndicators() {
|
||||||
|
getNthColumn(currentSort.index).className += currentSort.desc
|
||||||
|
? ' sorted-desc'
|
||||||
|
: ' sorted';
|
||||||
|
}
|
||||||
|
// adds event listeners for all sorter widgets
|
||||||
|
function enableUI() {
|
||||||
|
var i,
|
||||||
|
el,
|
||||||
|
ithSorter = function ithSorter(i) {
|
||||||
|
var col = cols[i];
|
||||||
|
|
||||||
|
return function() {
|
||||||
|
var desc = col.defaultDescSort;
|
||||||
|
|
||||||
|
if (currentSort.index === i) {
|
||||||
|
desc = !currentSort.desc;
|
||||||
|
}
|
||||||
|
sortByIndex(i, desc);
|
||||||
|
removeSortIndicators();
|
||||||
|
currentSort.index = i;
|
||||||
|
currentSort.desc = desc;
|
||||||
|
addSortIndicators();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
for (i = 0; i < cols.length; i += 1) {
|
||||||
|
if (cols[i].sortable) {
|
||||||
|
// add the click event handler on the th so users
|
||||||
|
// dont have to click on those tiny arrows
|
||||||
|
el = getNthColumn(i).querySelector('.sorter').parentElement;
|
||||||
|
if (el.addEventListener) {
|
||||||
|
el.addEventListener('click', ithSorter(i));
|
||||||
|
} else {
|
||||||
|
el.attachEvent('onclick', ithSorter(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// adds sorting functionality to the UI
|
||||||
|
return function() {
|
||||||
|
if (!getTable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cols = loadColumns();
|
||||||
|
loadData();
|
||||||
|
addSearchBox();
|
||||||
|
addSortIndicators();
|
||||||
|
enableUI();
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
window.addEventListener('load', addSorting);
|
||||||
416
coverage/lcov.info
Normal file
@ -0,0 +1,416 @@
|
|||||||
|
TN:
|
||||||
|
SF:app/dashboard_core.js
|
||||||
|
FN:17,DashboardCore
|
||||||
|
FN:51,getAuthHeaders
|
||||||
|
FN:59,checkAuthStatus
|
||||||
|
FN:89,login
|
||||||
|
FN:116,logout
|
||||||
|
FN:132,apiCall
|
||||||
|
FN:152,connectWebSocket
|
||||||
|
FN:163,ws.onopen
|
||||||
|
FN:167,ws.onmessage
|
||||||
|
FN:176,ws.onclose
|
||||||
|
FN:180,ws.onerror
|
||||||
|
FN:188,_getDefaultWsUrl
|
||||||
|
FN:196,handleWebSocketMessage
|
||||||
|
FN:225,updateHostInList
|
||||||
|
FN:237,handleTaskUpdate
|
||||||
|
FN:249,updateScheduleStatus
|
||||||
|
FN:260,handleAlertCreated
|
||||||
|
FN:269,escapeHtml
|
||||||
|
FNF:18
|
||||||
|
FNH:18
|
||||||
|
FNDA:49,DashboardCore
|
||||||
|
FNDA:12,getAuthHeaders
|
||||||
|
FNDA:7,checkAuthStatus
|
||||||
|
FNDA:4,login
|
||||||
|
FNDA:3,logout
|
||||||
|
FNDA:3,apiCall
|
||||||
|
FNDA:9,connectWebSocket
|
||||||
|
FNDA:8,ws.onopen
|
||||||
|
FNDA:2,ws.onmessage
|
||||||
|
FNDA:1,ws.onclose
|
||||||
|
FNDA:1,ws.onerror
|
||||||
|
FNDA:2,_getDefaultWsUrl
|
||||||
|
FNDA:8,handleWebSocketMessage
|
||||||
|
FNDA:6,updateHostInList
|
||||||
|
FNDA:4,handleTaskUpdate
|
||||||
|
FNDA:1,updateScheduleStatus
|
||||||
|
FNDA:3,handleAlertCreated
|
||||||
|
FNDA:5,escapeHtml
|
||||||
|
DA:1,1
|
||||||
|
DA:2,1
|
||||||
|
DA:3,1
|
||||||
|
DA:4,1
|
||||||
|
DA:5,1
|
||||||
|
DA:6,1
|
||||||
|
DA:7,1
|
||||||
|
DA:8,1
|
||||||
|
DA:9,1
|
||||||
|
DA:10,1
|
||||||
|
DA:11,1
|
||||||
|
DA:12,1
|
||||||
|
DA:13,1
|
||||||
|
DA:14,1
|
||||||
|
DA:15,1
|
||||||
|
DA:16,1
|
||||||
|
DA:17,1
|
||||||
|
DA:18,49
|
||||||
|
DA:19,49
|
||||||
|
DA:20,49
|
||||||
|
DA:21,49
|
||||||
|
DA:22,49
|
||||||
|
DA:23,49
|
||||||
|
DA:24,49
|
||||||
|
DA:25,49
|
||||||
|
DA:26,49
|
||||||
|
DA:27,49
|
||||||
|
DA:28,49
|
||||||
|
DA:29,49
|
||||||
|
DA:30,49
|
||||||
|
DA:31,49
|
||||||
|
DA:32,49
|
||||||
|
DA:33,49
|
||||||
|
DA:34,49
|
||||||
|
DA:35,49
|
||||||
|
DA:36,49
|
||||||
|
DA:37,49
|
||||||
|
DA:38,49
|
||||||
|
DA:39,49
|
||||||
|
DA:40,49
|
||||||
|
DA:41,49
|
||||||
|
DA:42,49
|
||||||
|
DA:43,49
|
||||||
|
DA:44,49
|
||||||
|
DA:45,49
|
||||||
|
DA:46,49
|
||||||
|
DA:47,49
|
||||||
|
DA:48,1
|
||||||
|
DA:49,1
|
||||||
|
DA:50,1
|
||||||
|
DA:51,1
|
||||||
|
DA:52,12
|
||||||
|
DA:53,12
|
||||||
|
DA:54,6
|
||||||
|
DA:55,6
|
||||||
|
DA:56,12
|
||||||
|
DA:57,12
|
||||||
|
DA:58,1
|
||||||
|
DA:59,1
|
||||||
|
DA:60,7
|
||||||
|
DA:61,7
|
||||||
|
DA:62,7
|
||||||
|
DA:63,7
|
||||||
|
DA:64,6
|
||||||
|
DA:65,7
|
||||||
|
DA:66,0
|
||||||
|
DA:67,0
|
||||||
|
DA:68,6
|
||||||
|
DA:69,6
|
||||||
|
DA:70,6
|
||||||
|
DA:71,6
|
||||||
|
DA:72,7
|
||||||
|
DA:73,1
|
||||||
|
DA:74,1
|
||||||
|
DA:75,5
|
||||||
|
DA:76,7
|
||||||
|
DA:77,4
|
||||||
|
DA:78,4
|
||||||
|
DA:79,4
|
||||||
|
DA:80,4
|
||||||
|
DA:81,1
|
||||||
|
DA:82,1
|
||||||
|
DA:83,1
|
||||||
|
DA:84,1
|
||||||
|
DA:85,1
|
||||||
|
DA:86,1
|
||||||
|
DA:87,7
|
||||||
|
DA:88,1
|
||||||
|
DA:89,1
|
||||||
|
DA:90,4
|
||||||
|
DA:91,4
|
||||||
|
DA:92,4
|
||||||
|
DA:93,4
|
||||||
|
DA:94,4
|
||||||
|
DA:95,4
|
||||||
|
DA:96,4
|
||||||
|
DA:97,4
|
||||||
|
DA:98,2
|
||||||
|
DA:99,2
|
||||||
|
DA:100,2
|
||||||
|
DA:101,2
|
||||||
|
DA:102,2
|
||||||
|
DA:103,2
|
||||||
|
DA:104,4
|
||||||
|
DA:105,4
|
||||||
|
DA:106,4
|
||||||
|
DA:107,4
|
||||||
|
DA:108,4
|
||||||
|
DA:109,4
|
||||||
|
DA:110,2
|
||||||
|
DA:111,2
|
||||||
|
DA:112,2
|
||||||
|
DA:113,2
|
||||||
|
DA:114,4
|
||||||
|
DA:115,1
|
||||||
|
DA:116,1
|
||||||
|
DA:117,3
|
||||||
|
DA:118,3
|
||||||
|
DA:119,3
|
||||||
|
DA:120,3
|
||||||
|
DA:121,3
|
||||||
|
DA:122,1
|
||||||
|
DA:123,1
|
||||||
|
DA:124,1
|
||||||
|
DA:125,3
|
||||||
|
DA:126,3
|
||||||
|
DA:127,3
|
||||||
|
DA:128,3
|
||||||
|
DA:129,1
|
||||||
|
DA:130,1
|
||||||
|
DA:131,1
|
||||||
|
DA:132,1
|
||||||
|
DA:133,3
|
||||||
|
DA:134,3
|
||||||
|
DA:135,3
|
||||||
|
DA:136,3
|
||||||
|
DA:137,3
|
||||||
|
DA:138,3
|
||||||
|
DA:139,3
|
||||||
|
DA:140,3
|
||||||
|
DA:141,1
|
||||||
|
DA:142,1
|
||||||
|
DA:143,2
|
||||||
|
DA:144,3
|
||||||
|
DA:145,1
|
||||||
|
DA:146,1
|
||||||
|
DA:147,1
|
||||||
|
DA:148,3
|
||||||
|
DA:149,1
|
||||||
|
DA:150,1
|
||||||
|
DA:151,1
|
||||||
|
DA:152,1
|
||||||
|
DA:153,9
|
||||||
|
DA:154,1
|
||||||
|
DA:155,1
|
||||||
|
DA:156,1
|
||||||
|
DA:157,8
|
||||||
|
DA:158,9
|
||||||
|
DA:159,9
|
||||||
|
DA:160,9
|
||||||
|
DA:161,9
|
||||||
|
DA:162,9
|
||||||
|
DA:163,9
|
||||||
|
DA:164,8
|
||||||
|
DA:165,9
|
||||||
|
DA:166,9
|
||||||
|
DA:167,9
|
||||||
|
DA:168,2
|
||||||
|
DA:169,2
|
||||||
|
DA:170,2
|
||||||
|
DA:171,2
|
||||||
|
DA:172,1
|
||||||
|
DA:173,1
|
||||||
|
DA:174,9
|
||||||
|
DA:175,9
|
||||||
|
DA:176,9
|
||||||
|
DA:177,1
|
||||||
|
DA:178,9
|
||||||
|
DA:179,9
|
||||||
|
DA:180,9
|
||||||
|
DA:181,1
|
||||||
|
DA:182,9
|
||||||
|
DA:183,9
|
||||||
|
DA:184,0
|
||||||
|
DA:185,0
|
||||||
|
DA:186,9
|
||||||
|
DA:187,1
|
||||||
|
DA:188,1
|
||||||
|
DA:189,2
|
||||||
|
DA:190,0
|
||||||
|
DA:191,0
|
||||||
|
DA:192,2
|
||||||
|
DA:193,2
|
||||||
|
DA:194,2
|
||||||
|
DA:195,1
|
||||||
|
DA:196,1
|
||||||
|
DA:197,8
|
||||||
|
DA:198,8
|
||||||
|
DA:199,8
|
||||||
|
DA:200,8
|
||||||
|
DA:201,2
|
||||||
|
DA:202,2
|
||||||
|
DA:203,8
|
||||||
|
DA:204,8
|
||||||
|
DA:205,8
|
||||||
|
DA:206,2
|
||||||
|
DA:207,2
|
||||||
|
DA:208,8
|
||||||
|
DA:209,1
|
||||||
|
DA:210,1
|
||||||
|
DA:211,8
|
||||||
|
DA:212,1
|
||||||
|
DA:213,1
|
||||||
|
DA:214,8
|
||||||
|
DA:215,1
|
||||||
|
DA:216,1
|
||||||
|
DA:217,8
|
||||||
|
DA:218,1
|
||||||
|
DA:219,1
|
||||||
|
DA:220,8
|
||||||
|
DA:221,8
|
||||||
|
DA:222,1
|
||||||
|
DA:223,1
|
||||||
|
DA:224,1
|
||||||
|
DA:225,1
|
||||||
|
DA:226,6
|
||||||
|
DA:227,4
|
||||||
|
DA:228,4
|
||||||
|
DA:229,6
|
||||||
|
DA:230,2
|
||||||
|
DA:231,2
|
||||||
|
DA:232,2
|
||||||
|
DA:233,2
|
||||||
|
DA:234,6
|
||||||
|
DA:235,6
|
||||||
|
DA:236,1
|
||||||
|
DA:237,1
|
||||||
|
DA:238,4
|
||||||
|
DA:239,4
|
||||||
|
DA:240,4
|
||||||
|
DA:241,4
|
||||||
|
DA:242,2
|
||||||
|
DA:243,2
|
||||||
|
DA:244,2
|
||||||
|
DA:245,2
|
||||||
|
DA:246,4
|
||||||
|
DA:247,4
|
||||||
|
DA:248,1
|
||||||
|
DA:249,1
|
||||||
|
DA:250,1
|
||||||
|
DA:251,1
|
||||||
|
DA:252,1
|
||||||
|
DA:253,1
|
||||||
|
DA:254,1
|
||||||
|
DA:255,1
|
||||||
|
DA:256,1
|
||||||
|
DA:257,1
|
||||||
|
DA:258,1
|
||||||
|
DA:259,1
|
||||||
|
DA:260,1
|
||||||
|
DA:261,3
|
||||||
|
DA:262,3
|
||||||
|
DA:263,3
|
||||||
|
DA:264,3
|
||||||
|
DA:265,3
|
||||||
|
DA:266,1
|
||||||
|
DA:267,1
|
||||||
|
DA:268,1
|
||||||
|
DA:269,1
|
||||||
|
DA:270,5
|
||||||
|
DA:271,5
|
||||||
|
DA:272,5
|
||||||
|
DA:273,3
|
||||||
|
DA:274,3
|
||||||
|
DA:275,3
|
||||||
|
DA:276,0
|
||||||
|
DA:277,0
|
||||||
|
DA:278,0
|
||||||
|
DA:279,0
|
||||||
|
DA:280,0
|
||||||
|
DA:281,0
|
||||||
|
DA:282,0
|
||||||
|
DA:283,5
|
||||||
|
DA:284,1
|
||||||
|
DA:285,1
|
||||||
|
DA:286,1
|
||||||
|
DA:287,1
|
||||||
|
LF:287
|
||||||
|
LH:274
|
||||||
|
BRDA:17,0,0,49
|
||||||
|
BRDA:19,1,0,15
|
||||||
|
BRDA:19,2,0,0
|
||||||
|
BRDA:20,3,0,33
|
||||||
|
BRDA:20,4,0,0
|
||||||
|
BRDA:21,5,0,32
|
||||||
|
BRDA:21,6,0,0
|
||||||
|
BRDA:22,7,0,19
|
||||||
|
BRDA:22,8,0,0
|
||||||
|
BRDA:25,9,0,48
|
||||||
|
BRDA:51,10,0,12
|
||||||
|
BRDA:53,11,0,6
|
||||||
|
BRDA:59,12,0,7
|
||||||
|
BRDA:64,13,0,6
|
||||||
|
BRDA:65,14,0,0
|
||||||
|
BRDA:68,15,0,6
|
||||||
|
BRDA:72,16,0,1
|
||||||
|
BRDA:75,17,0,5
|
||||||
|
BRDA:76,18,0,4
|
||||||
|
BRDA:76,19,0,4
|
||||||
|
BRDA:78,20,0,1
|
||||||
|
BRDA:81,21,0,1
|
||||||
|
BRDA:89,22,0,4
|
||||||
|
BRDA:97,23,0,2
|
||||||
|
BRDA:99,24,0,0
|
||||||
|
BRDA:107,25,0,2
|
||||||
|
BRDA:107,26,0,1
|
||||||
|
BRDA:109,27,0,2
|
||||||
|
BRDA:111,28,0,1
|
||||||
|
BRDA:116,29,0,3
|
||||||
|
BRDA:121,30,0,1
|
||||||
|
BRDA:126,31,0,1
|
||||||
|
BRDA:127,32,0,0
|
||||||
|
BRDA:132,33,0,3
|
||||||
|
BRDA:140,34,0,1
|
||||||
|
BRDA:143,35,0,2
|
||||||
|
BRDA:144,36,0,1
|
||||||
|
BRDA:152,37,0,9
|
||||||
|
BRDA:153,38,0,1
|
||||||
|
BRDA:157,39,0,8
|
||||||
|
BRDA:158,40,0,1
|
||||||
|
BRDA:183,41,0,0
|
||||||
|
BRDA:163,42,0,8
|
||||||
|
BRDA:167,43,0,2
|
||||||
|
BRDA:171,44,0,1
|
||||||
|
BRDA:176,45,0,1
|
||||||
|
BRDA:180,46,0,1
|
||||||
|
BRDA:188,47,0,2
|
||||||
|
BRDA:189,48,0,0
|
||||||
|
BRDA:192,49,0,0
|
||||||
|
BRDA:196,50,0,8
|
||||||
|
BRDA:200,51,0,2
|
||||||
|
BRDA:203,52,0,1
|
||||||
|
BRDA:204,53,0,2
|
||||||
|
BRDA:205,54,0,2
|
||||||
|
BRDA:208,55,0,1
|
||||||
|
BRDA:211,56,0,1
|
||||||
|
BRDA:214,57,0,1
|
||||||
|
BRDA:217,58,0,1
|
||||||
|
BRDA:225,59,0,6
|
||||||
|
BRDA:226,60,0,5
|
||||||
|
BRDA:226,61,0,2
|
||||||
|
BRDA:227,62,0,4
|
||||||
|
BRDA:229,63,0,2
|
||||||
|
BRDA:234,64,0,4
|
||||||
|
BRDA:234,65,0,1
|
||||||
|
BRDA:228,66,0,2
|
||||||
|
BRDA:237,67,0,4
|
||||||
|
BRDA:238,68,0,0
|
||||||
|
BRDA:241,69,0,2
|
||||||
|
BRDA:246,70,0,1
|
||||||
|
BRDA:240,71,0,3
|
||||||
|
BRDA:249,72,0,1
|
||||||
|
BRDA:250,73,0,0
|
||||||
|
BRDA:252,74,0,1
|
||||||
|
BRDA:260,75,0,3
|
||||||
|
BRDA:261,76,0,0
|
||||||
|
BRDA:264,77,0,1
|
||||||
|
BRDA:269,78,0,5
|
||||||
|
BRDA:270,79,0,2
|
||||||
|
BRDA:271,80,0,3
|
||||||
|
BRDA:271,81,0,0
|
||||||
|
BRDA:272,82,0,3
|
||||||
|
BRDA:276,83,0,0
|
||||||
|
BRF:84
|
||||||
|
BRH:69
|
||||||
|
end_of_record
|
||||||
1
coverage/prettify.css
Normal file
@ -0,0 +1 @@
|
|||||||
|
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
|
||||||
2
coverage/prettify.js
Normal file
BIN
coverage/sort-arrow-sprite.png
Normal file
|
After Width: | Height: | Size: 138 B |
210
coverage/sorter.js
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
var addSorting = (function() {
|
||||||
|
'use strict';
|
||||||
|
var cols,
|
||||||
|
currentSort = {
|
||||||
|
index: 0,
|
||||||
|
desc: false
|
||||||
|
};
|
||||||
|
|
||||||
|
// returns the summary table element
|
||||||
|
function getTable() {
|
||||||
|
return document.querySelector('.coverage-summary');
|
||||||
|
}
|
||||||
|
// returns the thead element of the summary table
|
||||||
|
function getTableHeader() {
|
||||||
|
return getTable().querySelector('thead tr');
|
||||||
|
}
|
||||||
|
// returns the tbody element of the summary table
|
||||||
|
function getTableBody() {
|
||||||
|
return getTable().querySelector('tbody');
|
||||||
|
}
|
||||||
|
// returns the th element for nth column
|
||||||
|
function getNthColumn(n) {
|
||||||
|
return getTableHeader().querySelectorAll('th')[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFilterInput() {
|
||||||
|
const searchValue = document.getElementById('fileSearch').value;
|
||||||
|
const rows = document.getElementsByTagName('tbody')[0].children;
|
||||||
|
|
||||||
|
// Try to create a RegExp from the searchValue. If it fails (invalid regex),
|
||||||
|
// it will be treated as a plain text search
|
||||||
|
let searchRegex;
|
||||||
|
try {
|
||||||
|
searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive
|
||||||
|
} catch (error) {
|
||||||
|
searchRegex = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < rows.length; i++) {
|
||||||
|
const row = rows[i];
|
||||||
|
let isMatch = false;
|
||||||
|
|
||||||
|
if (searchRegex) {
|
||||||
|
// If a valid regex was created, use it for matching
|
||||||
|
isMatch = searchRegex.test(row.textContent);
|
||||||
|
} else {
|
||||||
|
// Otherwise, fall back to the original plain text search
|
||||||
|
isMatch = row.textContent
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(searchValue.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
row.style.display = isMatch ? '' : 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// loads the search box
|
||||||
|
function addSearchBox() {
|
||||||
|
var template = document.getElementById('filterTemplate');
|
||||||
|
var templateClone = template.content.cloneNode(true);
|
||||||
|
templateClone.getElementById('fileSearch').oninput = onFilterInput;
|
||||||
|
template.parentElement.appendChild(templateClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
// loads all columns
|
||||||
|
function loadColumns() {
|
||||||
|
var colNodes = getTableHeader().querySelectorAll('th'),
|
||||||
|
colNode,
|
||||||
|
cols = [],
|
||||||
|
col,
|
||||||
|
i;
|
||||||
|
|
||||||
|
for (i = 0; i < colNodes.length; i += 1) {
|
||||||
|
colNode = colNodes[i];
|
||||||
|
col = {
|
||||||
|
key: colNode.getAttribute('data-col'),
|
||||||
|
sortable: !colNode.getAttribute('data-nosort'),
|
||||||
|
type: colNode.getAttribute('data-type') || 'string'
|
||||||
|
};
|
||||||
|
cols.push(col);
|
||||||
|
if (col.sortable) {
|
||||||
|
col.defaultDescSort = col.type === 'number';
|
||||||
|
colNode.innerHTML =
|
||||||
|
colNode.innerHTML + '<span class="sorter"></span>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cols;
|
||||||
|
}
|
||||||
|
// attaches a data attribute to every tr element with an object
|
||||||
|
// of data values keyed by column name
|
||||||
|
function loadRowData(tableRow) {
|
||||||
|
var tableCols = tableRow.querySelectorAll('td'),
|
||||||
|
colNode,
|
||||||
|
col,
|
||||||
|
data = {},
|
||||||
|
i,
|
||||||
|
val;
|
||||||
|
for (i = 0; i < tableCols.length; i += 1) {
|
||||||
|
colNode = tableCols[i];
|
||||||
|
col = cols[i];
|
||||||
|
val = colNode.getAttribute('data-value');
|
||||||
|
if (col.type === 'number') {
|
||||||
|
val = Number(val);
|
||||||
|
}
|
||||||
|
data[col.key] = val;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
// loads all row data
|
||||||
|
function loadData() {
|
||||||
|
var rows = getTableBody().querySelectorAll('tr'),
|
||||||
|
i;
|
||||||
|
|
||||||
|
for (i = 0; i < rows.length; i += 1) {
|
||||||
|
rows[i].data = loadRowData(rows[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sorts the table using the data for the ith column
|
||||||
|
function sortByIndex(index, desc) {
|
||||||
|
var key = cols[index].key,
|
||||||
|
sorter = function(a, b) {
|
||||||
|
a = a.data[key];
|
||||||
|
b = b.data[key];
|
||||||
|
return a < b ? -1 : a > b ? 1 : 0;
|
||||||
|
},
|
||||||
|
finalSorter = sorter,
|
||||||
|
tableBody = document.querySelector('.coverage-summary tbody'),
|
||||||
|
rowNodes = tableBody.querySelectorAll('tr'),
|
||||||
|
rows = [],
|
||||||
|
i;
|
||||||
|
|
||||||
|
if (desc) {
|
||||||
|
finalSorter = function(a, b) {
|
||||||
|
return -1 * sorter(a, b);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < rowNodes.length; i += 1) {
|
||||||
|
rows.push(rowNodes[i]);
|
||||||
|
tableBody.removeChild(rowNodes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
rows.sort(finalSorter);
|
||||||
|
|
||||||
|
for (i = 0; i < rows.length; i += 1) {
|
||||||
|
tableBody.appendChild(rows[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// removes sort indicators for current column being sorted
|
||||||
|
function removeSortIndicators() {
|
||||||
|
var col = getNthColumn(currentSort.index),
|
||||||
|
cls = col.className;
|
||||||
|
|
||||||
|
cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
|
||||||
|
col.className = cls;
|
||||||
|
}
|
||||||
|
// adds sort indicators for current column being sorted
|
||||||
|
function addSortIndicators() {
|
||||||
|
getNthColumn(currentSort.index).className += currentSort.desc
|
||||||
|
? ' sorted-desc'
|
||||||
|
: ' sorted';
|
||||||
|
}
|
||||||
|
// adds event listeners for all sorter widgets
|
||||||
|
function enableUI() {
|
||||||
|
var i,
|
||||||
|
el,
|
||||||
|
ithSorter = function ithSorter(i) {
|
||||||
|
var col = cols[i];
|
||||||
|
|
||||||
|
return function() {
|
||||||
|
var desc = col.defaultDescSort;
|
||||||
|
|
||||||
|
if (currentSort.index === i) {
|
||||||
|
desc = !currentSort.desc;
|
||||||
|
}
|
||||||
|
sortByIndex(i, desc);
|
||||||
|
removeSortIndicators();
|
||||||
|
currentSort.index = i;
|
||||||
|
currentSort.desc = desc;
|
||||||
|
addSortIndicators();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
for (i = 0; i < cols.length; i += 1) {
|
||||||
|
if (cols[i].sortable) {
|
||||||
|
// add the click event handler on the th so users
|
||||||
|
// dont have to click on those tiny arrows
|
||||||
|
el = getNthColumn(i).querySelector('.sorter').parentElement;
|
||||||
|
if (el.addEventListener) {
|
||||||
|
el.addEventListener('click', ithSorter(i));
|
||||||
|
} else {
|
||||||
|
el.attachEvent('onclick', ithSorter(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// adds sorting functionality to the UI
|
||||||
|
return function() {
|
||||||
|
if (!getTable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cols = loadColumns();
|
||||||
|
loadData();
|
||||||
|
addSearchBox();
|
||||||
|
addSortIndicators();
|
||||||
|
enableUI();
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
window.addEventListener('load', addSorting);
|
||||||
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 422 B |
@ -1,728 +0,0 @@
|
|||||||
%PDF-1.4
|
|
||||||
%“Œ‹ž ReportLab Generated PDF document (opensource)
|
|
||||||
1 0 obj
|
|
||||||
<<
|
|
||||||
/F1 2 0 R /F2 5 0 R /F3 26 0 R /F4+0 59 0 R
|
|
||||||
>>
|
|
||||||
endobj
|
|
||||||
2 0 obj
|
|
||||||
<<
|
|
||||||
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
|
|
||||||
>>
|
|
||||||
endobj
|
|
||||||
3 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 96 /Length 2457 /SMask 4 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 96
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"/iHZ0Y=)8Q8BO;&V%2Jje_9[_-A9n9Tm3__D%-aY\"+.,R!d'O!E:%/9Qdbp?L0%?7"^]k_sa2$[>[Nib7$k,NN"J_&<#jWa/INq+d/3hFCA]^,'FHUL:m@;LfKliK=R:PSEmr,piXO2=#^\RT8h/=)r"9O->+:ne]!eETZ&-rC?JO%Fp]QXQcf3?9JX$,i5JO&/nrH%*.hB$.q_s4\lgMdH7%/hu3+-eA84D*#5=\B\ps7"?2/R^s+f>77fh/2S.o9eZqCLWZ>6bO'&[.h@]KDT8I@GO+)48^C?e-f='WlUE2"Qof'<L4jmP9$t&M2eC&ZVE;b0)TNd5M`A`6W)n.1`=kTZ%LRiS(rMQSD-4sr=AMi=VM_dZ_0i,+1Co]cW;ci1@t+u!H<m;\q4O+']mrl\+pd.q^j0KBcgWA9<a`&V1#oFd%'&kFK?gXT<SSX'Gm?!A*;%IVVXLVGBXf`LTD1#qMoSEC3a(LT9t:@+V4nf(Y%J08AHNRqb-03<BD9Y1Q(`e%J/'C:,*Fj',J2'i<*[s%k$uiOcaO*f^KmkLY6K%R7oN./ZPOMH)Mf_I1(o68p<f"e/Pn#CL*Mmg>!8uC4[QB$3^^/^:q=ZVh\L(@2USnD-8>&"V*u-B'EL]?+fupgL^s8YL.#70/!Q8kk06s79taD*YLtYU%#=O>Z<Ape-f<HEm@.7e7uBl<)`ht8h/o4?ekYM#'E1"+)WnO='o>M7:q[?(h%5F'L+ctLB;,PUT(f.3,tnn$>1\6PtFM@AaP&<hAcup$/AleF+p/uSBE'caq6%@#52'T&kqnlFk/4rS8p$8WiE'#!$"lLpW8h\""O-]-j'I&Q>=q9ej$p'WQ_lV/+Z#L-*rg3abGqTenB)o:+$&"A8,VN*&`]8%0-BlaV9,UW4@XUYc_'aL-gVtj@CuLU[)aR[RHCt<"bOUR9XB?UA67>]*86hS'Ac>g0`]n9/-8=DkURDf71[p.$gs>2JT2DOND%2c]mOi-TV,>=.KEn3#iG%bEaYnp9bt2qk5^;]D=?Wf;]Xg*r<6`<]Lj_WDk>I5b=]5;U-F3!<>qE'YuGHY'LnN?m?Cn5[e]Zm:fdjMG(21]k)TPY\Rj]>^dTU*k?"mQ#lH\d?:g#o($gQ+Jt@#i?knDHnIjt)m8&)!iC4^^JC"<:I"4*=Y?$C!)CTSNdfiRVeA;$HgT>I1DLW>7\_^5[>n>G`[.!Hed-td9;uP_e761Er8e'f8>T5+A28=&=B/@t<%>$$R=5$qlmf?<?*R+CPpbMa3u`=^/\.<?P&L^CD&p\2QcnK43l=.'O#hC/-8Vcqb<ft:d,!j`X>9b'Igb\A4'm9#qAq?XB@`K[PP.<d0O]$+8hP;b5!?2U20*!sS]_o$)=YV%pu4]FE<sj,*/`l?dVShiVRmQ\SZBL%j<:(sp>>8Q-.q.l:Z1$*s+AbPk6OK#2=<bRpX$rrkahNk;&pP%gk\\n^,"i)q!'qlHhZIR7R'lrUP8DuNF><fjH.>Zg#.:,htXM%_=51$9tJ3rL=%,YQ"gW&=h8eEc`H'Y-<_6B8uB"T3B`^/oZhjAMd&Nm"G?PCb=Bk!="VYlW<=0Bq\feB5OAiMDaq`[b:Q?@:$7c<?J3/o,o@]BNEPA%W]RUQq[52m$U03[JQ%\K;;Asj;LM,`@V]Di[j$Om-YCJjVH3(oJ&We%3TDA!)PN$LQ6b1Ug$!ck'-B#HctRd1j]F^]_02jUh`h3sM;LC4LsOR'MPGZhbhpY:jLWhT6Vd[%kLGLM"S"C2NScg8r):Ufb43007QS$iOko`9455h$SSDC%<@E6^/:)=%"8SYb!q'g)l#'_9SLJ,GDBt^`TdXSTl<aL5WciXpIm6oNZ(QHnd?=n+LZ3:[Ft4_O_W$)TiG:g9qN]h1/+U\kKU:\V:&845B%kaq,RkQ\(Y*q5Rf'IuG5]R#r"[UJF[7faV7,uV]@iP/Xgh&C0*+MZ>s0a`K\=eqs%)$O[=tM&h[>pP]?D.GjbgW"@:f\no&O0@rl44(pnf,#QNi)dP4!d9.j%3%o)?H\7I/+'YdL<QcY4dGDJMW$";PM;aJ,9(R@>.X+eGaFIQoAWO7^=>METANkE@c%2[mTuj#:mBd9saMjfh%i<+L8Hb*bB0a3R'!:mW9A:M`I*SCc[8`JJ<:"*=JSgCL(ChpR".-u)kH1AkBthbQ1M-BCulmC[C"AsG0S..=:U]0BmBjm>(]R?//k?R1`9(GGUo4T3&BVPK;+MBZc3W;@on(ZXt"`r:48h`D<:_d+993@Au9T-ru&:.;j1"].l0>A':$Qk&N$S59$1'=X2!LAGoIk_*E^g4,`P@rK6M[IBsPks)MNn3Sk*aVb%#<)L\SG<h9&nAA2n_*a]bll^,X%e!-/aU*3&.kKBX0:+EeGi53]ZkQjafO$X&AGc@U0`lnk+:ne]!eETZ&-rC?JNt=h#Qt20k:Q];K#[#R~>endstream
|
|
||||||
endobj
|
|
||||||
4 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 96 /Length 697
|
|
||||||
/Subtype /Image /Type /XObject /Width 96
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0Q9h:L7*67ShA_m#eZ4Q*V9uDSj"s/*<Mhn++6pu9]n/usQ,.%Ug;\VM06,\E6$UJ(2fHI\F4,OmZl:EpCM9o/#6^!=pmOqUaj]R#oGol,Jhi#_Qp<;JO&&U*m4@87R3h9$D91!o82+8t9_K3??!+;QF)0fcbHc19TY3/UJTBa43&[-ZLFi9pT(us+=Jr)I;Gs8q2brHehbGG(`O%jl%ol7D+R-?jf$\.Q=\W3;"#!Jg]YCsqE".qFudt&H[^A,=1&(13a>rdrnAA6T9=2t+"Vt-Ao3q/<TpK@'s:?6c(q%#m-h3uAi)Lq5";1,g6Mo6E6D9QZf,X*G`_hVqrcaXFFq]ro2NaF*6^8p84St05`XQT=rg>P:^&\m,taW:ZsXt&[YY7@,e^b[9c^_mV5VCMCK*V-gWX!8s]nWA,T?DO4n4u;Me,4BK&@:e<C"G6h`#]DCG44>n"JsCf38E>Ko=r]][2p&_B,Ni^Cd!7>oe+Xo(r%InWLW$eE#/+bKG,]DZ*BAt!aOblsJZk@1@/(=.%EnP^L=a1WnbR)2rj81[in4&kpoeaKrWMc7$mO0,nL)j+`E5]`s&AbKKdZT;rnGWS<u^t]QVPP0'9"a:U=-i4j#=Iq&:H+kn-c#>\*cIGjLO`$1ciGc#;9?*4+YC.c`d#(!opN^5u0CsYLD`X3h9"n/oL[i_Rbjo~>endstream
|
|
||||||
endobj
|
|
||||||
5 0 obj
|
|
||||||
<<
|
|
||||||
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
|
|
||||||
>>
|
|
||||||
endobj
|
|
||||||
6 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 439 /SMask 7 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0R5>+=?*6.MM,W:p);.Ha,)1p^20>^q=KDmD3Q!galNETKs(q&$@f>s7+C,2^dd-\gd7[WH)HAE\n5FrDK"e>&N^u58]6psF26tF-WUU1IfDTd!n=<2r&rY(HiLe"[)$luWK,=bI*[J6/bUZetCjWRVm>I.Zs$B!,P^ZA!>Wo"rHYG^S95^L")7s%UJc&a0Zkg"h0Vl.Uc7WQ_C,IAj\pLB6%U<DT$*/R+dcN>1ViAiBGS1&,Rcr:^?+>JDj$oV>8Ba1;i3_s/j4mNnElf35<616m,>NN@Lgg<F%EmC]+b<lW+U>.j6kutG;A3Q;JK'$QG<%1)&O<Rj!kus=?7,UF,OW/(`V[-ibWZ4:,cD%uULt5UkRZKQPA's;/i;"4Jc4?U6ZY86M%MqVWO1-S.o4\PZP]lOmqsSkC&J5Te&J>#\44VlTli~>endstream
|
|
||||||
endobj
|
|
||||||
7 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 269
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0J3t;9g(l%!&Odl`ck`&\qfRl^/DMat;JEZ>b6X7'.$V-n1X/S[f2!@X'.l=#lo1eto$[@OFcnnHi]?ZLg<25pEP.Slm?!.P$W=)#6#7P/g"JmaS`IAPcbYAGd6jQEH6Vt')+Xeia-oGE]!C[U/&sX>l]XHBp4*";L9c;+,9:u8%a,t!`)1l1"l%5QZ5u:;t5m``Mq,>ui-jpTNUEM%Z%t`426(*@u*"5,Y'L>Qa+=K$Y":a%r:'"`,"a<A`1_$GV"``6P%K~>endstream
|
|
||||||
endobj
|
|
||||||
8 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 343 /SMask 9 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0N^IlI!'ZY3a;F6u6G4Kp+JO9C`W?npP:F+4;c"&L=PMll6=p)kYH9j0d%OU`?flEs;iGaSQzi4#eq+b]/Q#f0\;C"i=[F?5EAGWd%$Te+B8h^M:CZ7s:oPaA;4OtjDJ/#@(:2TFB3cdO]c7A5s?oI6VS%sd5h&Gj,U3V7b"j%q#AHf)96&E<+#K]p"mHV\AHhUcnp3B+t5+,hqEo;647NH3<E<Md)MU.Z(1Bs"G9Em@PA^5K:JUA1E1IOL'qMW0Dcpn9*b.#K+(iqIq[hH\.'kiF%uU8P?DXQVCNU?D:+[dNfE\"[u<."3S%+,]'E?dZdMYC?QQzP`mc`b>fD~>endstream
|
|
||||||
endobj
|
|
||||||
9 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 206
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0J3t?j=&;B'F$"3oOL;f8$iG0=NS^;,-<l@MF#4?f9F:EnJ.koR,S8$@A(Gjm6aT+r4\X,`n7N$oUYB*g4B1am_?N[^n:^F;ra4%XG&YL+6*f6>"C;)>JMJmppp",Qu*^f@#527S6BaZnUU.qRrJ=m`)7>_d.o2$2Lb1]8:Rj\LTAS7_g9b]3/s.WJXKqagKDtX3W:.sj~>endstream
|
|
||||||
endobj
|
|
||||||
10 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 1081 /SMask 11 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0SlUt/b*!bt_jd]$QDqe$%0/RT]2^f">.]MX+(eCVVks[8"7c5[#(!:ANQeBUjDk!4ILo)gn'Q5+sWMNY,<aj_;REsR^`GoZf-\i"[cc5S8qr6u30[:KCk<.'N!!GS!"@3S%5nLu7+k7?=\eX_^.bgEiFoWktUlK^RGS^>nl`P*@%Z?srj&KCYk0&?B2bM[15g+\=FcABLL80![$Y_KlX-Ij>"k%/\q0BcA-!uHW9>$CZeS6t2c%%g]%#tPUb`85`SN5'*$O1Oe7t$=Q)S?7ADo0=,F!Q`+3]_MWLStbMU[IPfSPIebdc0qW%GPL^Bn<WG,)tAq2p8KhcT@]C`l?$trdMZ6kI3.m"RhA.cO:SI`FcIPO1W!7XB$iZb@+MD*)b`_O[u6uJH:D>:gRJ2<%@QerUB;1@&kjoL@;qK]_ML4+fkZ)B*g?8&.[[-sLrC%[McH[aa-S(J)ZEc6>68:DX#M9sH#1@_?hoI`6KlgLoeHEe@5<PO&Q-CujFgXGLCGOuA;n4n=RekAc8>l,T:&kbT#D@c3)7\65[NLXeSJ'0FUn(D@l=CV,+)Ql<R\CiKm0F`M(?BJ=RfNc8%JE<Xeoc@A1R(N1)*1((d8Wg@*BXG#;KX%o6UHbI8V1UM2?R@(PU5+D7]O;P(uE>^;3I8:(Fgi9jT!1dWH=t=E^WCc9;:'J$$M:tWkn:Th96FHF?Pg_Nh`JtXJt7+jCq2;Pe*8WA(N+WXHDV30NZ"L]]Sr(R\iHhJG4aS?B)gFI-=]HbK+>W.12NX'Hb@NEfllQO&(s1^<0>U7ZO(u;/4)V;_LL>6+k[gR>`%qAHp'MC4=,>4%/(UnN:)(CT+8m9Ldlqa2W:-$cYkKEj2)D]u)%IQBmg\q1?T)7?6C.+2UFD#*19th*cAS\,lmidqGg8OPYj3Bb[u_JnVXa#OK#-T5I(&diN0uLXCIc:,Y!KNSXibO-l@RGV5(\PL'TG+khXbB^!YD=!'i6%H!cLPX*ahR8/Kl2dc+JoP?-IK=o5,(_C%XD_;:hq](W`C;e3,(X?lA+[GnE>FD@dgKfUX#_F0)Jfk>N!5H:3=lW'~>endstream
|
|
||||||
endobj
|
|
||||||
11 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 504
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gar8O(^6[B'T<+IJEb]P!bnP0`rWQH@EMLldS8+fLO]gVc;"q/M[U]46TGc:f5B-]0TZbc5CS5=Kn3\*AhqS<@,NM[70QUrrgZhT\LB>r(rDD03P\%K0aoJ-9`KU2T*usYJ,fKUDMkqHUY2+`1/(9b]7pUI9sY]S2QS7CPiA#oNl+Sjqm^.jf4$L/q(Y;V&M>'$rr54"8qncMaJ#[(ETrq$dU\_C?!Y/75J'C-9he>Vm=VlB/ar.YQo3DtUmQ3&4t,eF5"!ZGcdPH?Kr5!BO-7mbaX>2#YJ3j]Uth2kP2O]`ckL.'T[4BD.@#rsAsSNf8otgs#=q9:H'9!G#FY#s7$EjOWo&4d!_RSd]Z?gpbbUWB_!nI5!kDha'1ed^04][sk2pfNRf^\4Pa]HnM,KP!$/U-uaeRXU??'_5/i,;)e:2@.9n=Sa(CnqKjo95@9K<O_lTEOE'djl:_$#g@W+!jK6R8$sJJ/`Zih]L+$:_i[@%[r/!(Lgl_#~>endstream
|
|
||||||
endobj
|
|
||||||
12 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 1344 /SMask 13 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"/hgJd*&'ZU1QLNQ+qFG,2K"9K`3a:/E<"B6!:dD=#aapbG*3k0to(JugYQ5(3F+>?SY>MHnR%oiBfS?Fu%EkV_X"9O->+:ne]!qE>%]!tN+1)CSQi2L6n3I'mSJbR:Bm6)CZ9SS_SKD3L0dFY@T(h097e-#0$rTqp27;O*o]PhL?+$/4IrGF;+!4^_8gbVi-]<81p_r:)us$V8PB2U\gg]I9GIWh^if\G+6;KQ'@!W[OB]hE0Bq`GK(+V_m"'#hc:TKhB!P`_]h0BIAX,Ot?c;M5bM27Q$lWR*MX)67a(eaGkIVR3an=9Psm/p"h58iYE.[j?hlBF9gHQ!D(<!,,2%,1]nta_P4':CEN4*!lFN1DFt8%fdM]S9M(0%CEdqL"kjkE^&ZH!DM.3oipH]-+qg5a$SKR52?i`-$=7:Ke.$^VGXae%iC4_;C'-l''\@(D^$7Z&m5CE;Hcr-A%Y_HDX4S)#TuL:e$2N$C^.ArBdn7+WAa3Loie+i4JVfn*$K?UW."W]hNp%;&0(A'-@cWuP1sU>M/7pb\5oq!R8?!s&Pe?2UlhVK[=GhYV.08@`HAlFBJnPX?6?t6H-)VMe$tU4i>Q$W=BtLOk`I8#k9n#IRFEht0;6EQEeJ[D^6kJ2";;E7)4r7.^6b)m@*rqHjL<Uacd/rHc:ZuhU"#]ai2Ruf,ren%1b=2H,Hu3Q9[6AE^MArQhJ3S8G*7o>dFT-b)M+.WDJO,n\,."EO,T*^A&St\U,]PTiV_K<g3&t+"kQpKfBsb\'QV4q%^+9P1RR:bK#fG(hd8HtkEC@>:d^%VK109U`WT=69=Yp#&"TlLc:!8`;6L@R,#_4Va?M;=Qh"BYd_hE/jf&R"?D#*p,--YL^eZ%+eM6Sn1;tb917ul4*#JU+`6YGP^<CV8?;BoPFLp2Vb=\%=1'/]4eq1K\%ba"=nVcIc$&jg)(^?$o0f`",r(`Qt"d)gO)S9EbnVo*eET%VILN]i/R_5FDQCuY-.uS3j)GGEno\+5dEPaK.Rt'Q1)o!GdS^Q(O,HN4Cm#C9L68/G^nJT.I&j\Hh1UQ5HiA(XOK+!Go]*Xbe)`:s:PBO+omC@Amla?r<afTh-[l8L2)YDo$s$kY]LYNISMbR@ZUM)SJ!#j>p\)K\f7_tS2c<g4kBQZOd"CORU'm0YJH=a+23XP`_XYRGO97IumLB&[ts1.C$o]AnQ)qD!XRT$9<UL@m'n)0D)-)VH9'K,19KAUB-'R%6%[dr<Ncfb/C`H&Ii1f?/S15D(bo#4QgZ*4B,?5PC6%&X#X"Q>mBo*gDlb=_HnadF(/drRM;(_I#V!eETZ&-rC?!WJG`$O?=^$3~>endstream
|
|
||||||
endobj
|
|
||||||
13 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 544
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gar8O(^6[B'FZo3FS5P*n*a;6;.PL1TDr<'LE]Zc+bopp-V0(C$_XBpf*:bUbrEg#AK/i-7g90`M1>Oi[jTjb"9sV00N5h*"EoF]Y7@@so"Ua](!MnGQ"prN(L'd3q>VCGaT$b:aSPr:3B*q7?j0S10h$p;VT`VEJgn`#W*maME<\0lq;-$;Y8qls*``%FA=.C7(;`b"`HbI6[5oCdVE>TDYnN4Hokuc<hYR90'>`@_*'3CV1$',pJeNZNb"#?'fo!^F6oO-c.AeXbiWtZ`ar)Ib+k`aj6&LR)A5hoX@`n_"3*Y_OE`=EJABMY8.$GU9HJ`#`Z_H'3`3fEF:DCaQ^B\f`4;j;kb5_LVO3Ci$&E0#unk;=Sa]("VQNK*=q>Z,3)Q*GAUl$V$,b":u"'uA+>R4gk+O(IPbOQ(g$M"/r,_gD3EOVO)6rS=J(_4DVnR5gE!G-kBU`':9X'qlmJVoiJgC'Fk0SEjabS3JM$:$)jOS<:r!<tM,%@FmZPSh9Q^_TsW?Cjr=>rE$Z_'g-($pt-t!)C=BNW~>endstream
|
|
||||||
endobj
|
|
||||||
14 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 760 /SMask 15 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0ScV"s\(r5[Va9oKmN#='27<HULJVUm+QU$X-*@a)aF\%WI5n[/T+h!W:nBfHu]:'MsJq^g8Y&8$W7^21Gqp,)QcP*VlgI>^7ZgYOOc^3fU0HXohSR70e78Xaf;%uIdQ3o9alj+qacn4;Gk]nPqp3>U[^uu#reEB1UZ<'3F#I=LLf`7g!NUogc9=/cpWm=)"aPDTn!_+ZIqMA!l2aA::fr`+/"N<&%ai-co54f@\h)0<nWaF0?A7>7_/AIg1^e/9TCAAU&DhkYR;eO<:rBRISeF@BsC*Pq"61^98HTU84(K@+Lgn/7X!5KsXm9%;D9,<90UsrSn%u8o*44B*7-&XLM,*qQu!&Q#WGMT0QgQk\I')ZU-Iuu:AUDX(<Q8n5<ABl*r<jVcc[Dh)+RZUhn%7J-5a3]c5p/WjkgOe]L1a)PK\Y)?*3Gu\a.SD\6e+m,dk3n$66<KijMW7F.05M3Bmk9;-V,)gT6K&=U.C(P`5Je/Gn';4h;Cfj#3T-3kh%m(_A8d2NOph#:j_R,6Mf:kn6D_J\*J'-]_t<J6#b:/mTBp:sB+sA8C?:7,T4fE]@q:$ZRn2W:S'@p\GAVtI;3-O2:M:;bLM9W+^C62t&');Nk&0AoM6]=-Q:2;uA+<So,$fCs=a\(B^$a)[_k2)@fR^e5WdDq6`U"nL)#!,:5E4:gj->opBBUmu_MI?MZ2\LnEk)>q?UVVgO\WKTH];qbieJ+Nq%EDX:_Z>q'Lbk578XoXIK:4sa!C~>endstream
|
|
||||||
endobj
|
|
||||||
15 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 447
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0L5:FHY*67U4I]0jmVj'K<J!!1BDNdddkt2_D%!$tU-jD!^&qa(U#1K]MbA`*Fm8?QE*!R+RIW<bTpQ>BccL^utchI/B#1%XDL=aoKH+lVtCpniDn9(b^>e(!7N"O)6(<qYmk["`!Z>8k,Oe-'1obnA;7&F>*&HJ^\^5uHrnNL!K%qMV@VVm+l<6]8?!\CUAq;2Huoh6WM+]/e\.U=e48Z"6d<SRRMfodgmY&Hk56s3(BZWpXF.G]"I#:sGF;!qH.3h[\5;::[aa?Z7c8m,OMSJ6Z]L,)(F<t&Yo<7%;A*7Du[2H#m>PmqSAQ:Bee23G<P%gC^68CP*c!lT5CE7Ps/jtr<&'nUh>>.IK[Qr,%N21eQqZY1cPD[I90MT4e<mjEUr077qBEgUMT]R$26DGN:0UqSVb`LU`g7#7lBajCSc_e-7.`#n^X6+0Tk~>endstream
|
|
||||||
endobj
|
|
||||||
16 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 826 /SMask 17 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0S]l+O'*67SV9bZR)kb$5Pak;?`5JUD,':6_W_8JgD/t/5n37UHm0kk+?Q%q.pH;Z__UJOBO$V(P'SpCRCiScbp;W*)b@:Ds+$f5g3M_X+5^*B92pBh3o3ugQu"@3S%5nF/bd!qX]-uu49GN9@fQ$\C_r4X'X#,<Pd8+--JqK#7q`U-d&8ER,=>4s7Ol$iY'&f[IqbnZ^<bppBO%?:Y(EVdBJLNhSaIk73@'saSeT..`()401BFag,W`_VAqahm75+^<)8Mlu0LmDt<*U=Nc-@AU`ig4tZjR]?c#:-0CuMggjN.OXaW-G7Xg-9>tO**-8)gJ2(BjDsNMs!>)mn:Ynf.#N%\UNPC]=L!.U7)`s[=0uLL00)FM<SLl;AYF>%,hd)DXshIdJOff77$5]h3B#hUcr;igP0]Pr'T"Eqk=+1pLa&6Kk/]M*JI"Xd!YL5R"<nD.#Xfd:&VtNE28kf(U@$3ic6A-VesXe42P6#uNOVY+?d+e)Fno,b<LUIhioirp^6aXfST\$mdC?1LhQ#kELaO!L\+Y)%']<#A^/Ou)>%1Zn*ck%De8JQc=:_/t-5'#3:.UjuJgd37C7:$_d1o(!&Q-<QPW+scWpX`@@!#b$7N7;(_t/E$e`EX_"eps3qUhONU)U/MYmBCH#\]+pF\b3]cH#'?RYkDS"n[tu7N%ubXrC*Ak]HoE\55=E];;K?YMM;>O?rUXFIuQ[:W$kNL)*0fP0g62HJl]n:=2!P#u*k+i@n>KcNWmG?=)`!S`e?E5;I7m-@C!*RITXD*#_u:b`rFjs7l=%"@3S%5nF/b&-P;:J%-S+J=qP~>endstream
|
|
||||||
endobj
|
|
||||||
17 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 231
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gar8O(^6[B'T@VU$(*$8iBW>.,f5BLO;8taOO2VZOhgi#I!/$Z+cC1!,/Oo-T?(48s8RTK&":9B,"tl5:C(b`_A$"%VOSrG#33)Z"AS]9gQ$e5rr7fU[gAFb:R!<C7njjYA^lrA;asKTOt$&lRIZ\p.8,LQjW=M%(/Vu79VP5V7_f^lcbu2+Q[gLnb4uc#@/^-*s1d-X#aL0$'/F,5N.On\$:Y$u%KHKh]:V@~>endstream
|
|
||||||
endobj
|
|
||||||
18 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 1180 /SMask 19 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"/h=`:<*'S-5`?a),a96UiU8Vp(S//X:ATg>ed6u,^U<a30aauVJl,\@*Mk^=kHbkK7?jF#r@k6q>5&-rC?JNt=h#fLnZlaif=NCJP3=dl3*L1+5neS;e3^06g+[L1J?]A;o:jX%Hg8u49[$uFZ&gV@:'i&H`*J0[^`BnC"SS';e)+ToXRI$CHckqENEYLe&kVeOk3[FoAJmErJY^7J)tWu0U"a5\ntZECG%GRV#HkPkI0mFjK-6PMsKZ<"#WaQkrN4SY`9\mDL>iV9U[0+\TToD)1)**urXi07QO#9n]mV[fZcj@8Y;+A(#]kr?J^^3[I&_IbQkcnp/uI([5/^\a(UP7rhJA6BDpjHRjLQ'!0p+?W?H'LhQMi*^1"WDonRDYl@QMo>aH\?/d>KZ%[b_f:&O!!GT$R^VHE]j;4-H@C;I@IWgWEHl`<':;H?U[,Mc5,tWoqH-`t6d\K%;Vn]6%/]XWGWbE-Ra:/&pX+,s<ia%tU+$#Tc?),?l6MS8Cc4qLjP/FYe)^/urH(*f$A8'k:"*?.,Y<H6IRZWdm-LfQ.QJdaLVm,r@2R[6(62(ddlogu/4W"(;Q7H3h;7#*.@R+S*?DudUX<bW:8?53jgf<sg>P$:Z7L5ZTdXZ\=MTd\FrO38H/>SH8^]8QkKDuXo^pY6Z`;\kG#MC`Q*Rm.kFKtL?O$R--knT(3#e'^8<2_BZe6hDfn'lo7%mG5K$J<pFQn%JQqjR>.^`5*$%a;CEkgMH\@<Xe_A*WJ%KIW<bJ?69;TTkf=dC09jA-%Sa"Ro1_cAh?AC</j[?7>#hV?lhe@E3'$gXT`;&''1)iSXg:JXb#7JXGI%&53X#`m$H8(]62J@So;]A;o*e^\Eh,tYCE/EUu`C:+uV&QYs_JrS]S^`QQV1RUp!*`"$o:7E&X`M.>$,KhiYeEM(,A>uToD<cA;#8(?#)SoEN'_Qr:`F:PGLYJ,+_4q$c@Gfu"5Lh1s$Bb/h;(e3ono,T+oE*nW*N)E`h;*dC9W-A.n*dD578^_"Cd+JPRZ7KnZE@)8Yo#b<4O5sU9oe8b*]QPga&u+>61"N&Hp/YKf&MggBs*$:#F_M7qfH4^gD0nmDY(Ld&dd/,)h$l?3QH.&kNB!ZL#]ZkME^3Dd773enT[/5$mq1[Ek)Uj*!?=o5TgUD"9O,SLqaPJq9o~>endstream
|
|
||||||
endobj
|
|
||||||
19 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 739
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"/d:InG^'ZRn--=p/27Va3j()[l?6sSqB10V&B!eUU^WeD<BCaWnMKR\$X?(2U`;A;N]VGnsYO;f]-*6As&D5pH!qi;T9*'*c-pL`7j_7eIfq\D!NI(]>dhOX,,$[D7'aci.0k9&$R0$j6_at[N3gO><^cPLt`OM*H7UAd8"aJ!i.K]mR*"L9Ela!W38AG+:do'.n/s+q8\3GAc0l'H8d0R%SMO<2Hpre^Mm/P&Go"LuCi<?4WH63[Prlo`Xg4NW6VX$eeI!NCpX'@B]bh6p;W2\D#t1NHZhfIo-.@pd0o>uet;l.!?ULMZtt\!IgQ-"#H4J!VherSP.9<ePk.<kk'tAfX4s(X@"`WWkIs*P`+F#2aF*P%k$aLl&E8$^)Vn$R#1(2_bQcXqU\Zr6`PS8Ar6bJirU<`4e>&MhorBfP4qA.c7>bQ(J")r)#e248_7`1FXN&V$7&)2?]lV\=+iMn:Ppg"&^]lNf#kIp\8<$o9)7YeK>^gL[WDI0]J+a1*jA!7*E,AQhS]-\J7qni(3Ee=T2?u9#]+*14V0(9Ps12r]\/foCmsY4X:4UchjM]MOYqAe0-fr/*\o6e>WI7V%\276nS,@r&e$3p8(+\'`VWH]je"o=)l.eJcd4j0oeCn,L=Y6>mSe%@mAPleGWDPAPaJ#^fXe,#IF(H5Y-hl8%/qV#qP>q+,@+A&]WOI@pWus<3('NR42$RZn/jIKI9Qe4CRR0"ElFjcN~>endstream
|
|
||||||
endobj
|
|
||||||
20 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 921 /SMask 21 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0S92?I''Ys5LAX?+MNH&Mg:&GoH[9`WDP;[<J4qb9lLlE$V>HA`.5b<iq#A++?@S)R0!k+($#4A#$P"_`s*fOC?S`K]))kB?:Im>W,"i)f#__;M:0WZ3bP/JZ#%G,2CR,elA7:H5[gG)g@<%R4>]9V"5#9P,-i$")7==tW^A9[iCTsS$A[>]jP+3dsZeuCt-L']$6<.<NZ;*O']E>;Tu4@^*T)kKdh)9A]G^fVpD!3d23Z-Q:)C6__MZ'4Vk95nFhb*'4_2U-._nP,#^+G;#7*1%50f?&pZqmK_RQJS"d'ig,HEF*pW&@*$A3pghZEWCEVEh*E5op$*]Y06"BZu<?U,l3kf[(AOa4OEDmF[l:Kc*?2QN1+RX`.f*<`9#m$=2WDNW($R7,*F3K1Qj"P2A0bee*d4BkYhDIhTeEj;m'bAHHnVPL)Q.!.21l%3U4e4s6i]TcK*okdJc?0r2Y<-Jk6HE/cYuNSG"8(1't:WGViq.f3m3.F(>ttNoOCQQV3+L9U_L!rk=eW8NjriDHUe3Q'5CZEdE18#KG3Qb`5K_F1q_1h&j:%^H24]]cub^!%;hY-#.aB>aJAK!/i+tAk'i53:?O!@&Zb'E`RZ?GVX[4@e[4B"RF"($[S>@_meb%UsJ`9X:V#OkD\2ip'p^m#-Z=Y]>NonSUH_TkMD"ALOGC6-ftf95GtT7;KE3C?@2EnE2+(]DALktn%6#N;+f,7-q2t","a9kH"6+?bFtkQ3gqj::k=>0^n)t6dln$=J:h[<'C*`f?4e"f$(TD+3hea?T*&StZesrc_oAX9NunB)C$saULC-+Z^d)a3HCItX4C/BfnE0E8?bJ\*"+Z;nS:aJ,jHKgcC1olp9FVGq"o>tKQE*ldF+.20nK$e:2<rDV#[nR)@2O`-(kuH90]*tI`cZY~>endstream
|
|
||||||
endobj
|
|
||||||
21 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 494
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0P0h;C$'F*LI;HbK)S?nEcA#WiD%aL*j6t[5H`1a;2&Oe)O"gMf>S4$GdL^o=%-4]$5#</??LgiX^XA>#F>oN0tpMQ2m_iYa[+%bl[!aoJHnt-P$]00EF%0]^S;<0%_:3;IJ'uscO73\oAVi7d+MMV@gU6*Y>WNH;.;$\05&4$.g]#>d*!Q;GWrM]JO0Y1U<.<lSOME@M2,Z;T/R\H0>\YB3klicj2W8L+F\<[lT>Gm;P5ZR6iEZ@-H(&SZ)*NHDY,8G#jJuW3Z+Ia9I!jX#;%1P=R0GM`sgPsnm`DDG]E@]Sk9f'H)"E;f9O\$;iBoSP?+Z`Q`+opj\`T5ZDWI7Eb-;r?S2]mDnCrZ(sZ'\SX<[//c2pO_S>qrZJV#V'c&PYc9'SI&]QOoAn/N*#Q1M#V&.Jae.m%l2Ti57)WQ"CR%0P-t&hQrOlrFunQ6f>jE>83nlr-'Jj8&W!MN\D-m9P<-rKSbPBM$^Q[$aTFDNr~>endstream
|
|
||||||
endobj
|
|
||||||
22 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 1065 /SMask 23 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"/gmn6SV(ruZ]q'-TK`-tNr+:(;2d#16UKbPduDi?+.Kb-fk6>qag![/c?h:;=2F#mOZ1tsSEeE&UOgc=Pho:4Ho[^FrIboc<oj*Z+.N-u4!?_6kZqjbR76m@aa,SGr%,*>DA7_nG,V+T)WmK\KV^p*;b<\,dW>?2&6*'63c@_qceO9fl(_/hQ?@Nh=IAX.@K0PMmLR^\Uk$,le`R`l<l238(\.=pH7o3"T)ec96M$O0Fl/l4TbV]-I*-"\;HX%WcsnWF7^d"LP.MX;u!8`I!ReGi4OnVR-hTm3:HJ8m;OZ*27":mb[;4/n3UB=ZOS/-m"h\M+#?;ZCg6k'S>[Off+E(+U/9M[sps'6b6/$lTu.ogNgf<s)VGWD33m[9=^@k99p8B=_gT%"P4UTrYA=m:;7IV2&;0W38EgTTp=i"DFgk^_'J6JB#,j!!t%!D%bCtQ\AB@3s$J``W->*n_@3RA=5oJ6eo_9LIGh%A6W1uIm.Bjfu>Bl,QPVH2WD;OWL*OMC8Yk9%0hkC!u0.u&=U89+#!FuDk[/];N4g:=OaH/'HJ<XXatA;1slo'g"/,4=0*m`?stFEE5n$PlgPohS?&Z\SYbCT2W'_t$#q&1Frme,(7q\+,L(R"Fj[5p]Toh62*p$L%dM$\8_61kR]68uWSt0<SH/<n'`?-`MqZ$RUt"f!.'QnEg^P$BE&4/fYOhVb/-%9Q_!Y"X\l/&>CLto>AlqX$8eVB7%:+=YY@OT+k-DGrg8qlHlo^qQ?E!ERN)HQ*pAt7n]S&^cb;uA5Dp<6b\lg!0$Z*k^YJ5<*T"\n!BWTmgZ)<b3!HDBt?:]\n#"u>l:Uk\SR$Z%k+Ji*d\&gNH(t*g99&=X0Re=k(e,ih:B#C?aaB&=BBti@'B(YoGQM^;ilFG0YJ1Nk+DkHAI<!klVUsp)?@M'CmKDbI&D;eeI98KLXBK#)4,*@9uA_ZgAkZQP@G\@>:\O`r!CGIX-V95._]YbhNScG5;+osqdDss:;@iBTU41)ack!pM$,]ercF9%0erro(-Au?c680eh)6m@aa,SGRep^P$$%>+~>endstream
|
|
||||||
endobj
|
|
||||||
23 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 656
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0O>tC/V(^KPCe(dG&a[Ukm7"H:F@1Yj&_<dnsOU-Nb`?6WHe6Ob)#n\AmkT]:9]FohTL!CVP7bo>G:nZ`K6%p&I2&8SILH9#HGgABs4W@>FR6h&Fs6=kN3'U`pcIjAH@`=4is"PmZ\n[kD&gVuCWUhZKq03(c"NI5i!anP@C!'rOK\>%n!luG679l#V@ZEe0#p]3;%/4.e/c5''D!>`d0&!^tF'5pY=?4WP?_4_m]oT/Y>;_@1/T76h1p3_fo`,8Sg63+@^.D7CUp*fMl?`R5T':^J!.#%7#?/_adT!m>FeT53M"Zl]EF1!QO2!HGm?<2'^TQf7[]@k*:%F$aUm9pHImgjFln<1C68%eD:bLF=A`_0s#`qps3kRlN?'K7Wa;IC&r:;up!>X]"2NAEtPuhOV\a+s]Z"lHP5X2<p^<DiRq5MOe";0Gnn@a_2Ve1gJ`=%P-\_3Cc.6=B>4fJWS_\PqM"hD\HI*a>l[hKG3HZR<_!$Am1-Y_,K0E2R,nkmIJ4B+_)R\Q@"alfmQ!?>g)C`ZMULb>hL91BDYK1A6GeNeq^)OoaBmMiXFd]TD`n'A4#LbU0KKs8&U]\I]bjgM&7Kt#$R,_4ci9r2U'jO2lcn:^M(RQ)(ClrbJm\.=</.orau^WKnl#T+$~>endstream
|
|
||||||
endobj
|
|
||||||
24 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 537 /SMask 25 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0Q4\J+M(rl)AFG:.&Tcr\/'\+21edt,O6^jtXeJ:3!9a0'F=kY9gc'^jcmiX6:8gMDBY7M&i:APs!]^P1,o*)9]hJ`URLkpkCLkpkCL^_o^CenMU$>RQXn64@D[\;&R&fs\aJRT\$"(1YB(>,1Wbu\$*ih12'[K<uJK"ZI<<6C#U2pPK)i,$;>^7GDZC\Ts_(9gG6+**sVUd0=lchSIdgn31^rtH4s(9f^LCqfZGHa><db:\m6[[o.^5X+N'q5:,UV1QquU\Rdq,U92XV&&QCC+isYheSqX#3?"tIXs]c<s?5P(;$g+=8,blEI/$U"WZDo!q#=Ro+1$3erl0LgR34J5;ZXD6S1b[j)0==)_V_`Ul]_#+;KSaXpRQ[ON5"!BLLAG].FTXO`p_A$X=`?.['oXcelBceFPUM:d+hKaO\!h3X5,C'TdbB/IR5%@=LOZJRC-;T:gjIJTMlXr%;rq!*'pEKZCHi^LMi[q*.69T*;AmT[8&Rqttk=.hTYtS@\;>+sJ3T+sJ3T,,k2AbbOcj~>endstream
|
|
||||||
endobj
|
|
||||||
25 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 326
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0J4%_k;(e*C($05-=g.#!8BH;b^Ks_F*B5t0!(doP;;:pb[NV;?;e3IW=?t5<e&8e_*O=%H]=[h7U"8Ia"78Xafd;2iG4ojl9?-SCI%0:VA_gm&G5Wq#u2L9m7pM<)X0q`F^!G^">TUm&u2huppn8:M)24u!.:mZNZ>'Vlr-55YtU/%GS8(@,[U&*s<^X);[lF7j$]q,^68h&S_d8$D"CR!37oaIea-1t)bH6kh).fa^RASP@2&>3>::if@%:^:b;e9qA_K`LeR#,qK#!U?6V[4OXlW<$a`7=_t=)qC,-b)T*=S(pr;.#O`iZdT2=lI1+~>endstream
|
|
||||||
endobj
|
|
||||||
26 0 obj
|
|
||||||
<<
|
|
||||||
/BaseFont /Helvetica-BoldOblique /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font
|
|
||||||
>>
|
|
||||||
endobj
|
|
||||||
27 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 476 /SMask 28 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0P0hTAL'ZT\31?)#+Udu*MKg>K"fGuM%ac^[?i7b5Fkn/%+Yoo@8p6&+hGsVS<-toU(qgRY-B)W2p,=4dd6psF26pq&jgU=,^n+5(Ee[DT5c<;/U&V.HqO69MC!JmI`(^::Pf6)'Q")+-8RacHh+HGKblU6NBmuo!tY[4N&V?)c(8`09:M7#69;iK-][FU4!`gE`U0h1e<//C4N>V8GSmsS?)!:i6:)<H,RTI`b)]nF[X?PEZo/BaQ)V^(A0Q=U&RU'Ns"[+Y8&m[OrQWPC?_c"9li$(Z/*o@rk>5X^?8d'3I%NXP'h!l#N?LP+eCi#_;TGCe`<;Nr!MSr<.@(L'aCi:]X)hh8V4"HBT.Imbj'!\D+g/AM<<^]H(&!^@KG[9e-0]9d`h?"!9"]ti=X.5,*&g<W%]W4g">Zh=It2smfB"t[Ok/AM<<^]H(&!\CPnrUhXrLkpkCLkpjXrj*+qErb\~>endstream
|
|
||||||
endobj
|
|
||||||
28 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 267
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0LYmJ9D'SYKb?4oa>*5Pq!&R7S;XAT6[G!_F$qS32e'IcpjP=Lp!&maIf,'a.MFC0/Y/Bb?#^FLsdHd*;QAADd1!^j'1/pa$V0'F+/W(>Y$F@MUsU*</:[#$Of;?E[Uq>c&XXr15Q`j%fEBqdJt$c.,<MQHD&-R":mH`*d!Me,d4ejR8IWd]&478^N.oghqU'K)ee#E$*\dBaNCePoK#lB7n0.-cedHA_QrW)&;^Vl4BgWgTi`R[RdreZpaLP'Qa%-o?+/~>endstream
|
|
||||||
endobj
|
|
||||||
29 0 obj
|
|
||||||
<<
|
|
||||||
/Contents 63 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 62 0 R /Resources <<
|
|
||||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
|
|
||||||
/FormXob.128c36d3fa36a80545c056de95684def 8 0 R /FormXob.12c34d4602fee5f44ef4112cfa5cbbda 6 0 R /FormXob.179ab001f5a5c46d7c41f69a294382b9 12 0 R /FormXob.4293c61331d589320a5ec7d5cc7e9e0a 22 0 R /FormXob.5834ce0a44022e11525f663f637f8d25 20 0 R /FormXob.728edfabc1b37c829917ecd0a0e6d29f 3 0 R
|
|
||||||
/FormXob.7bb41ecfe9239d7c319306e392f9f10e 27 0 R /FormXob.7cdd8edef734f0b41d87d533caf185f7 24 0 R /FormXob.8ce7803ede7f67b5431570c87f171b63 18 0 R /FormXob.a5ec36c65f5503cb5db822b6b212dbde 16 0 R /FormXob.c02fc6aababb61c3c457da7f381ebf6d 14 0 R /FormXob.dbe1c8e74a55b013a58677e049510784 10 0 R
|
|
||||||
>>
|
|
||||||
>> /Rotate 0 /Trans <<
|
|
||||||
|
|
||||||
>>
|
|
||||||
/Type /Page
|
|
||||||
>>
|
|
||||||
endobj
|
|
||||||
30 0 obj
|
|
||||||
<<
|
|
||||||
/Contents 64 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 62 0 R /Resources <<
|
|
||||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
|
||||||
>> /Rotate 0 /Trans <<
|
|
||||||
|
|
||||||
>>
|
|
||||||
/Type /Page
|
|
||||||
>>
|
|
||||||
endobj
|
|
||||||
31 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 1352 /SMask 32 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0TmnXmF*!bt_jZ[lbW_tkn'4d&5@lR$/+>2-fQp*22%u/2r0k?21KX_kd&:Hn3nKUMU0e#uTb"[u*9\<%kE!p21enPSi>D0,adW03nmUL.d>RRr6d1Q9;^9>0k[$Q-TkM>14^$?h>'Lbk578Xaf;%uGr'P2NU%R9de=GsXQ7oF_AZ;Z&073_*Fp_TO>BFp#^rl;WX`s$ge..4P=4!e)TIsZ4bDMrqQ[YU_MDrB3W/A!EpM"oDV@]<AR7RalS-00T+&e1cc7&.'>j6H)WFEYfu]1OK)6lUOt&YU\p"uK)QF'rAUGDCD[(]2T_C![(VfgcP3>dk:act:&i,t]*n\SoCj[+R=kCnS8HfAlBLMLn6SLQ`&CSpLQ<;cEU(PEV2$[-b&OU*sb0_Vt"Rn1`2[X/i9lY3T^5)6_A_JX)K8]A;oLqmEmsT9&12KnT[Ug0aIHb:3?AVdghd%.ZOLEk,doB&%:uo^judo?5>#81o>aX%aFMjmlb$#XV$OLY6M+33KZse_tJgZAdkmAe3bDI4^7C,1Y5o!5NSZ=]lWq-NWnEIQY4h[g'FU])eS$V5:)f#6:3^RuqCY-Bdm0lO>7XCXUO1Uksp[RI9D$33K9oI!of^k&S.9;Zd"d=',6id_peO#U$CQ@I/WQWL(D(<iqZ[Q7W6,Yrnduq5pI&"CMbUP1>`0^KCLkk!.ab)XegJZtVBs!Wd$)/*W=ne@`D["b<2%K%,cE*%Cr=2_5ND2l1DQGCCsdcXZs<7.bkt\2:q(0D.H#4STR/3BbYKFo:9rN824GDT>67F?'F'I5R+t;&L6>,&";u(IoWUV?R)[elojk$^cH]lhK,RL#->jT43[[B)Vppf78<YR'mdo%4D\PM7r2PI'N)]`n,80<L*`aVAR7\=Mc!'0+9WqnAPt>JG8bS3loe!<Mf-Wd/bAkJ_<h_q6`q85b=I)Ir[/JCVFr<<!^_I63obnMV"<'AE-3XSJ`9!\\,[2?>GS8h]uJK7rh\Kp,92*qT*EN@Tf"*XqiCN^[/L0;Z&AeZN0a-`UVS8b^\qOCAo(+\f/_sZF"`B`XS-RoN?OQiqMW'+hO:Vfbm(PhaXA3eqN&t>Pbg<rGFmg2E"IY/br23rRshj34l<)A@omi-@@e>G\tY/;AleAfC<CkNuG8(iD:^7/%5,?dB4Z^dJF@[LCMsfG;(cKa8tsLT`H+ZAman+Ik`\?R8BAYA'>.QBJSmHC'-ELe^qg'ku"BP2>H)V)F9\P_8_P1&S-54Xpbb)3cE3+fQg]fm$W?qO4tsh,laJhaQ:.VInB#!.5Z2M@]<?G)oXod2S?`PObOkUpQQ@\;%uGr'Lbk578Xaf;4,>[e5XQ1~>endstream
|
|
||||||
endobj
|
|
||||||
32 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 631
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0PcRXWf*5M(TV.]*COb9HQ0]Z;D./X0X,N6G[@6)E_@5J3*LE4lc;!,gZ`131l3,q8_4(**6U0-/HKTuCZ5'j<8c,8iDrB:JZI@p5hiROOg50rtK!-gUIO2q,^?2i6>Mc@Y[/([+9aJ2Z-a5VAR?`YcM8#q/4FapO4;e:AQHKi2C+B7\j<G'^R&.Ac\8LhO<,GhAEZL`galFass"EP<Q%XfLAeY*4=;7BkX1FQ7#'ZJL2eVuNtN$g+\TO8_>ku=k<H^q%caVKDM[*kpMj-(/,10eR1F^YXulB?4q,B3rHnF[e4ZKP7m2'pR6mM3m*7<BrF+D%juEFon$-rmV,D!jePjL/2T)h,E_C(Hsf[^$b6->QKWgccl[X]AXk;%7\+e5K#;lKhrl;t`(U9cYKH+cK8g$$.uhd)TaKWN)"T(/n4r,ft[VBUD[r=$#RmCL2Fp%`q\FZ0-2616'Q)PJp+Q]QY/"j@@d=m#KVqm5\<)XuE.=@2Q@Ps5UZ/./'[un+RnY=!NjKD9BHuMhIc8HdrnKCPfTZf1qJ,^Z?0;QiTJa"=)2(hO2+n5=WqfZr$9`':$CLqff[BG*Z-sm3?tA`AIBI;6bmEh+H9!d?!DZGW[#Xr_FV_9lpd~>endstream
|
|
||||||
endobj
|
|
||||||
33 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 1741 /SMask 34 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"/igJcg0'Sl_gLYC5#;+-:,J.P$[8-jbl+IAbVV,B]X/0%ih[FU3O]HB5`aY^pA&c6MWS*k4G6Y<VZPP*,5XL34^)$5@S+:ne]!eETZ&-rE5kJq;OZ$TU+hG\:+p@5eF+o`FeR[p*IHu(>Gm<3gHU2rK-Ar5_>"bJq#ULM-QTtJ`o42#@e.sCjP6saPqNOH(nST\(@BPNf\@g*>]D6<igje0,k_tc693`4S5h;-o/!-38:=0KgCWj)W5b(8jUrS%jS:2'*n`6@U#GTq*+XOfU9Y&dLo=FkL$=7Q4\cOifF=>Nlb%QG&b2fI:%_r3;hV2Z4OU:L0uqg,Yaj:f_n!OZJUL\uM-;ln+!nG)r"02K)ER#UfArTJP-ZdGR)`-@!h(#]!/UX;U:"RV]U&D"S^?!VJG1rfqu38']f+@P-%+PiQ))4MDRencirjUN4[Ya$c]i"5O;R#R[`G1Ff0:>F,39EDB?.+]@p1!FjF;#<"c>K59$To\Z2?6JGns$R%)p:eX6Tb%(/-]#_e^)6&(66IiadYVp,`><3KBR/^jM;WLZFl@g4kfBEj%16<P-,)o035eM/\9(IqB;Ld4-64G'E^h=JKNe$>7Csmof\Vem7#co:U=%nrH];bug:EPSaat'[&J&INDF(`cWX=9A#cT5'p`-A#Dj"f/o&=DQBE.<<G6BkW/8BSe'%AKg*QqNmpZg:@l_)_ooM3,k%YsfLh"1,!^@eAu!c%69Y-*bTcheM21F_i_Me77ARrF".@K&>]X%U_lRDc3!VtSLhrlobIE,\*]9KNY"00`/6QAG7\cK.(+]];`o73BClkW]uF>\fQLPTESQO?nItY;YK&`kLFGk]A`UN%?U'B4>\sqIZ6b@Q)q*JbQoolM1Rjcn$6=mHi0u83(%::e>2_<#(dd*J'o7Pn)e.D=cp^hA<2#1?gQTP=[^S$6U[IpSS@fmq7+q]oe4.S$ofd.M>qrJ?+4rV,J"a!=qEl,<c?r(5et*aQ&LmU=Ca>Qt$(YX%Q22OER(lPN2,<pj_`(Y]Y[Fin=Hb`hr0Y$ne%iT?;6!lB2f8q;PYN6pa\H[5Z\rW$RO_'\<:*:BB3*AhX2pp--XjN=nY['go^F^a'=V\@K.]M'sI-#_^YR")>#)#UV?a67H.7:p09=%Qgeq6&n)mW$>FN81_J@,,'jGp<1jga6J_I.?7)8_md?#%fkPaj9cEpZU]gm3L?.CE1rMum+2^d]8+A-SU`*I[eQ'F!p'dTWafm(GYi>#!2>AW0bGV#:.5L%.`l'BK8C0i.1&EdOKu(bFO$gb^BsTtJ!E=;DSdcC!rm;QbS7M2?rdJ7-.cJ7*r@'l@R;e?`O*[)5eu<0CMfU!c=-uP6=i;"%%aE'k6g=YEBBq2"&?1HDbqPH`2Q$W>EQa1S@WqKO#:<j4eX\0X,2^C2O^5o$;`<B7Y*WUd2I^n0cTMg:l(NYRRrj"o%IeBqSXi)K<>It]tXfF5Gg,]>dIWurJWf'In+eISPnkQm",`pNC/VZ2p_AfV<eEhT4gd,#&PYcs,G-r[Z)"MkGsJQA+u)$-_)MR6P9ruYSQm:&m:O0F%.8GB:Z);-%177)i;Y5J.#`)mS:Z%!F=Q/HL`<+D^i.NM8Ig)5R*a2HHTEA:.tUGh.SV`>[?7Bgr^!jVqj42i9Lt_kJGR,o&@eoJ_NWhf"\[.!*]="#2N%XR&sm3"k?5Ub*PO=rt#G=!eETZ&-rC?JNt=h#Qu@O_>F[>f#+l~>endstream
|
|
||||||
endobj
|
|
||||||
34 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 671
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0P9h85\'F4.-B]P8O@LI<5=IU!RF<sfmd=o$U<=W+>$.;.G=Xefn0#A;]V@Q95TaqMFg^&N$#QdF@0Mkq%'f#rM6k'6e9lFpn9YNU_jXe%d$h=3tkFBMPpFb7m*h]:'USDnY;Uf7pL=)S?'lE_5UA<o9Lh7[G:dTcsjJh!'P`RYGl@#]/jJi)WD3"7[l+kTcGnI:m^][[7!0lh<WqY`ZC9S&4V<Sn:HTtQ6V"(M(HJmYUlLNV7]3\+k<s]11P\m"KW!O,.;PF(b<h[f+JbkR[fd'$S'i:P]6!4*Znkn;6h0=#YU?_G(=/8U*qh(oJU?Z4=@@+T<X,BGCA'OZ\DUj6![[usSi<F%Aea`h^4IUm(54o$,]=&\q&"hS%%RqK(31kMX*ONsdle0*A3GL3/GToY+`t$Z@l=3"8HnE&cFeI\4Hn&9Adl..<McsuQ2g3>U0?i1Bhg@T:=a*GF]<#=u28pO,.7J[jrbY!fD9!Z(pHnei[tq(T`2Zk3P$jsjQ2%[cW+8e_]&utbm[m@McL@PNjD"Tp$@TSXb-!t`+3A$5C'Nh!3WX>XA*'%^DA6(NSl9b35]-.+H])qKfGSede)GL:9TL<R(95qS#HjRj;%rFr[1^o.fg\=Hnl0q>6L4*TGUH571gf%&MX'Ehkih6g2!6MRFKip~>endstream
|
|
||||||
endobj
|
|
||||||
35 0 obj
|
|
||||||
<<
|
|
||||||
/Contents 65 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 62 0 R /Resources <<
|
|
||||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
|
|
||||||
/FormXob.6c8c267d4ab253c7494566dad915cdc5 31 0 R /FormXob.856c7b8991de92c52463f16bd28d19de 33 0 R
|
|
||||||
>>
|
|
||||||
>> /Rotate 0 /Trans <<
|
|
||||||
|
|
||||||
>>
|
|
||||||
/Type /Page
|
|
||||||
>>
|
|
||||||
endobj
|
|
||||||
36 0 obj
|
|
||||||
<<
|
|
||||||
/Contents 66 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 62 0 R /Resources <<
|
|
||||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
|
||||||
>> /Rotate 0 /Trans <<
|
|
||||||
|
|
||||||
>>
|
|
||||||
/Type /Page
|
|
||||||
>>
|
|
||||||
endobj
|
|
||||||
37 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 909 /SMask 38 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0Tb=bf3*!buJW3Q&2=eT52$_mbH-n6F!C(Y<?^dZnMQ&ES<KWp+X*sENn1c%2O9_h46c$VC;O3(J`39U6unV.cMppau)3A\D\ht=eZbAcmn]b^YlKFgHU+bUCn#^M1X_E\P=h$9O%/>Num3<Y>U<8(,8(0ZatWo*#m"s<=La>.LE6oFdNF,k(nWL@jXrIF7-fV42QZ^u1Mgd_IWCE[PKXQPcAet=em9Mg,)%p+nOhEQqu)q&%<`pP9A+LB/.0)G"os1A;rn.?N[J4q,`?][P0-L*["L1#T1h?NZeZ`f48F5;>,&BL40@Bc/Y&!:89f'9FZ$S".CG#F4HpW'^@h[/U$#<RdAk3^cE,%H)+&.'G$CB<"/$>^rRHJPUi6m]jh.X^Tc]*jFOa']Y5F5G^V=T;C*$>D/6G6&UG%/*LJ'/%lIj:ZsFic22UQu-toJ^cPsTbAun7rIWp5XaqS'("W^*=M@4'jq=d.b:j)M3NQ#<,u/4rRJZ?GtK?uGV\F5Zp<n1>j;FOn^0Gp((c[*^j*6\ZG$M;^^Vt=%@--]J:9HfAlEeHA,Xnc\49*p#*X*OXUCp7_tY>k9T7Tg?9h1I","ubNQ7\*rqRn.8kDe3$?\!e4%d=g@cjN\qT_ql*s(s]a[i3Y4U\L^ZUuZ#$m2WE:OOT7=pHD5UG_;;DqZjTnb#3ElT=jc`7/k3gOic163?tS/?o!-`I:6f]Np$u<dId'#p6;>Fog;olKnY[o;&i'OMGap(C6:N]7@rp;[X:d]>0`i%rlN=!u^f[E3nO%f=YBSM56*D("4`R:$Y5F^$C.S?/PFTadCuT)^amD$)fJ1MB2#\p&mnr))&5pF_B:)s7?Z&CjN^</-7Dgn>I<JSqC+R@+'W3!=0j%&4-XGKFgHU+Tr\J-`Q5S?N~>endstream
|
|
||||||
endobj
|
|
||||||
38 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 524
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0Q5:FHY*67U,e[a[+\\TJ4.40l[/1=Y3\-reA`#pg?;2UN$K1)-4LkY@I\`(W(%(bO)1#1amPe4lQ?,)GBFnqSTrqsLFB=a]/qUB<YI_UqPk]AkVXote.SF\4#>u;`G>kJ1Q.o`QD!)Te^oE?m4Iaure<2D(NC?lQ/P0;rZd&n`uH>$6-Nb,=@O</A"%\&/#OQghB[\Wqu5go*,F[q@`^m--eZ8`0oS>c05ou7$da[1PJ]"5aZBBa/aXWGsA2n&QR7N9u.9_/*"ii)(7WZ+&X86*PiooQ2fnC/9eXllD!&sl^NX.k6DY4C+WRX2tTpM"AoYMPDg>!@fs%n5k%W+`$+9-SM1U4u)$/cdOsM:=LN*>+u1YAMc&'<B_;]BZgA"m0ZrCGI:l@gcS(6Xc#05asQm.c0LPeNI%L=I3+Lo'3?iqCSltjAgI>YOZFjqjQ'AP5D8`'7$upE7E=.nTA5f$'7W#/oU`NO15XAq9F'FOlE!LpWdJdZX']4e*1s8SPd9&!!pXN/-~>endstream
|
|
||||||
endobj
|
|
||||||
39 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 865 /SMask 40 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0Q:MA3R*5M(c":'g^Go:iA4EqGP4Etk'J#52q1B/MTCp<-gP\uFc'F$U/@+FO'l^p3U(:=5T$8NL9&3W"k[,'<1BcGIF[7ujtpY8#Hj(Th*[b@#/V('/4mhB(OT-WkO<E0<V+:*QA#caD$/&$GEULq0FMRAanXS&u<R_3BnH[ksZkZBU.9_8!E$d7`sWWVX`KVK[TSpj%XP==_aVj+`[285!u6l))n`P&j??7B5qE\&cJEUo!i,"Lo]APj1XeQ$-UN_gLn@aBZ46oplaNPDf[F&`%k.mp[*A=l=8+XAE7g^r[)]4`jA>=9*lmm?B/WC7'/%LFXg%O#@QW7S\VqJ`(>OOG!:R!0PkjmO]:BfW<4K'1B`U1:hdLXQl?qKq'5U/R208Ai7\2amt;RnR1rH(oX2'c7V[#2WJgk=igR1"LBj7br@PdhdEDK@t<-(O_I=dhEhLEY(^<,EMEqKYGM\$/,dD*.>ER\[B?[[0m4JFFo#3hg7t&eA+/RMh2MW/@EL"Jk%mm_5K*J.c`$9A7mmI]27@4pp0BOLNA.;05qjbC9ME3jR1%@G@cR!;L;Zg8q"4Q5`W+]pL2pHo)W54??CT7dN4OTE\MmME/roGUI4!e3?MthdR`6@h,t?1E05icl8V9Pabr/'P4ik(<luirdGfW\KTHn2C-sq<i09)>_D8_ip=)2SM:+Jr,!"a0ZEVRHi/MqPs)?Dq/_EuYVlW:_)B])Yjb_dWO-E*!"7<[W`b#@rU=uhW=-9M_>Ij&V7:,eJhP,k[WHJ25F>tY%a"!@oB;`0@YN]e)c*hf6LZU@A<Jl5$($QN)HP16i4*hRX*pIb*&#*ch+:*QA#_F0)JfrU"rW*n$0Hg~>endstream
|
|
||||||
endobj
|
|
||||||
40 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 201
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gar8O(^6[B'F\%#[I*4&gu.e3DCNG70[BSl#e[ShBM&_"6iR+89uo2>?\gDtIl@C,r.m)gs%NQlA.rOsG64Z&'4o>T;,]qY))Z!TPYk@K9c5gB,ZE]Z1?B5O;iHMfAIef?(etZQ8e<.E1d2O1A-jDH(`5*U&hr?9-So10(`:KGb&N'nE)C)g(^6[B'T<*Ji<K?#9r*1~>endstream
|
|
||||||
endobj
|
|
||||||
41 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 749 /SMask 42 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0S6#.-"'Ys7"PZgLJ&Hra\nQI33a<j>Z'WFWr(G/4PXl)K.kXA:ALZVKJ4g`p2O@6%UJcWiCV2&C2*[4VtB6WP+86BsIS*\@0BA2&8rp2L\nk08TgG"@j(kuH9L1(pB5XBDG):"G^1&GG2I8KDO7+pYdL,4"6S@W=)*Hrm'H94!]5PjB)SZphN<8RLLO$4F^f#[BD[`R]Ml:-'2hoU`K6iAO'MhluE3pFuWTBtE[_K86`.igU3;;F4Vlc]g81Kl2L(&=fA\k5`7+p4Td.">"lZ5G!P7tl$NK]Q`VR-*2j,?6-EL\.EOmAk,ef-&A[>n/?LkG"Wfj]HVuXIGslAJ?LWAS-6U)9?MXc,ud=bssQMi[?03obZ0>r,YqI&k<]P$Vl4EF+.'KdR7>"ii!]6!gGQjA2o$ErKf(XA57Zd14<[m;Q.*Er94&_rc`H-X(:fbJDg)*E\-R[5iLj@(+0S?=HV[3NTuX9.]W;P.eJ`^?77F]oVH8q`*X/%5`%TRTJ,2ZDSCmc''K$-NY5Nu><!8]r*c7OQKuL^a4D5c'&#geE"#-#V&GI@n_b^];tsEhkI9uf@@t7TSKj/8n'>\__=DqQ*)Y5]>>/[OY,IF,Jg)SG17c8HB-$;B(i&9C;Sg)B!UO>l/LMOgg\3=EoQJKn4;i)B7d8@$R`Q"JO$@IVT[N8gGpS[M7fu#e8tR]_KsFe7;`bs_IA>,TBqaU)mAQS7@2O`-(kuH9`r<;n",u"2H2~>endstream
|
|
||||||
endobj
|
|
||||||
42 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 476
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0P0h]DL*!Ph%a.ufB(No<o3/EcNMb^Z[FK$iO<>WVmi$NmZh4<?V>-3E8,0gZ*"VCkL5m46RPM!nP?]t$L*?"=*H/Su7a\)UM(DdlGV=U&.>u0'I*BudTO0Qd'#h'hiDp-t@^#td1pE)g,WD)QOh]=ID[=;@@'-Z@t;<j8fJq=aMYDb4c[#@C@P>Q:t@gLMPi=rI=R5SIh,k=sq&058:!+%J'(aFQT&nd*aLrrs:J7@+3!ITU+6id6d1,lXtb#fm=hoYp"nuW<3+Ff[X&n>_i@#ZRYRe:0soLZ57IJjQd94fo5=><CcJgnmPfUa6WDnTT$d#G.UlY"#3#j`BhO-RY>rfa&I\2lT]bg9pZ&7]<)'iDG"d/KC@1@uiSWmX^UO&;3cLr+6NAODC&0>ea(bl0Il^W\R1j=^+]AE[l+c1k<6Qa<E#rM/k-hVf"g2nrW;dFZiOoa)[ZEH,ta7em7c@,iC~>endstream
|
|
||||||
endobj
|
|
||||||
43 0 obj
|
|
||||||
<<
|
|
||||||
/Contents 67 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 62 0 R /Resources <<
|
|
||||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
|
|
||||||
/FormXob.0a472e3796a81670e3e4a126e9328826 41 0 R /FormXob.7281d02338005424254805513186bdb9 39 0 R /FormXob.8633d8d4488c46974d2b2e9e506361b8 37 0 R
|
|
||||||
>>
|
|
||||||
>> /Rotate 0 /Trans <<
|
|
||||||
|
|
||||||
>>
|
|
||||||
/Type /Page
|
|
||||||
>>
|
|
||||||
endobj
|
|
||||||
44 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 702 /SMask 45 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0Qb=e's*6.Lb?&<eD./a6)2&_L:-&Pm!Xu*u9]V(&lm/f3jW#2lQN/1[$_G.0W<5bP+.Oh+N,rELN]*ON8n:i9$1Qr;)O4_P.*+hY\&NoO@pYkiO4C?s5QPk;b63n`f&420pl_>:Ga+mhXXAFFa%6_hkm,4c,TRa$,_]6tK`UIpaL:/s\:n\\FL645.Qck*A&g>;D9,8Ao,575;)>^\tYeb8u<qKu"0&d;3Rp\3sci*!FL7W1bY/!=%/>G9uh`po^[Q$FE[NN`LDZ1_8=TnnqW770ggWcVB@-sT__C4A7D,.t[2Vrf+rmi(XcI"I#ms:?t1isNd-fd42gN3(TVDu7;2b>R[$k&VfT=F]aU>DBlgOVscS72+?'J&I_MOapL<5]Zo+$d(TcEKJ:`JOlkiH.>],0o]V,nql8Ug\Hd.MZrX:CU.%LaV364Cf[sr7W.RpNN1S)ncd8L^S':k/bmlG>VXsptOQ\XUIKF?4/,%`tY@?eD.TJC\.=NFMtl;JTD@m36C;mDuKq$iAGQ9fqj&KVM<O_h2[[^,L5d>"nkY]6JV:D_gEWon3?97P3;lee&R6*KK*eUos4S"/%lN4aCd.<gN/I-f=$Q1PGW'Q+[P.J0nFbBhN^G4^:*uR8bi8Lb%Y/obIreGlgu.;<NYIZ`d.:YQII_&JQl4s549OZ#U+j463n`f&=f#6;"kr.~>endstream
|
|
||||||
endobj
|
|
||||||
45 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 70 /Length 284
|
|
||||||
/Subtype /Image /Type /XObject /Width 70
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0F4UZgL(^A?RA<8>HK/+jE9a66h^nRpQ@^'&7!/n[.<Dj$bZJ$RV_4V3I;bBZF7,a;V%gL@$1#;!t*5`=SLgQ%IX*3mK]`BV:9+AZcW0r<6!797h9YF(#UpQH[28Re>Ok=<U"aQ*(E)3_2-n!m-@mOCGBfm%OXI)C^'D0OabM[5'7W!EH0R#2d'Ih5^a&p]a/;R2iTnT`o93IQU`e"h73VXI">*K0satg4W(??meg;R/jVC]af@mPmU+A#_UP\'C(ZMJ)Gs'cR,#\!Y])7%ga$i~>endstream
|
|
||||||
endobj
|
|
||||||
46 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 993 /SMask 47 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"/i]5Q.p'Sl.mcjB4I0J\2](g$e^0nWF3-A2L0.t+&t2Uhmr&I>15!i[BGo;E7L\96e9Vg17]o4V#\jO#kSKa>(\j#!m%5*@lp<Y,PA,W88R31kYPQZIQ#kA)a&M?3bXzzz!!%M(C:.**b"\aR>kt]njg``LH!*2,eS9tMW)d\,i<2U/Q87o2fZ7Uhosu]tlRNo*c*^M7qgn\[9?XWB(]Y_RNpgEO.%c;QP@-0,($nk:MT!.Tb-<+I`:bWUa="oXa_!S%q1OZ4TLbT1B+tH`dXD]?g_UKt_GTnRk/q+M\a_q[I%n,lcr0[GrW(8a50PM]J=Y_dK#s>0hoNNVkeggFmFP/b'op/dZI]uXo^kaMY#CO%+dCD5`Ri>2gE+^B)tCs]B=r8uhPo0YEr@UD?*J^ER;cn!+Dsbs$qsFSZdrqgZs<'QLS<3@,/gr(*f@ni%HP\#kbr(q'T&Gd(D%aY4s.2i5dtYR&Rsd!VV/b&Y,#\@:a@A7>_is[#>=GCE8>"H"8@$H%"J@4!!^4=(]XYG!"=AY0E;<m!#P\<?iUUc!AMl'"#3Lt-9;ThI"H>HYdD04/%<tm@9[2Q]Z)ZkOk;DUiReG!C+?kXRZ(g846;3Jh-;DC\/K<VRk3aTLgs=GGVt'RZd%%c\bXSHE4E,X@d![\p429P__tl"$s]Mq7#6%<5L+bd,qZ4a.Ao^a_idE@Ggfr7^O\2,DhntPGlF.WV:QV'Y_?<)R"&Ls)1:lo(h(o*JQ=ipYV'6?YGl:[`/>]rgMc#W.GMAE`]Ou40Cp\I&ph-[1M>H\i;@7XQ[q)2^DRmAd*q@hd=Io]DO]\M<>q9G]!ans'D5ilUgjLoEbHlK1VM4c"*A9JI<Ia`FUAS'R9%p(Q:Kt\p#9+ZA"R)JM*<8Lh.sb+78]oq\aIkte`!`eFS.G'0S3W7WNX4'i5nKj[Q_/oJp4o$r.EXf[^mM@)]sW0O'0,an+;J;zzz!!!!aq/?'=7R_,A~>endstream
|
|
||||||
endobj
|
|
||||||
47 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 274
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0IYmNd*(rl*,do!Di$XA;:A?ctgDSR[P?os:cifm-d)9b^Y$(GJ@-8PiHU0bt6SWA*S:.]d2j"pVu;$nJ"&458*OjQe8es&(ij$L)#-bWO!MUf.dn_12nW_6rVad]Of;:ia&-;fCs5;j=Nerd$$UKl8k03jb*lpQ)5Psgm_W[C`74LHh@>>V"[KaJPEeGiIf1:>/$2_oNu;g1!>a\s!2Fi73?1=b?_"VH((nl/W]L.;/@315+PVa=ARM%9>8!^[/9K[c(V!;.K<)?~>endstream
|
|
||||||
endobj
|
|
||||||
48 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 1415 /SMask 49 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"/ikth.L&:jf\IfU.7E!aNTpcpN05`cqb:nW?o#j(OUj=8N%':TiFV%qA<?2E==o?=#VUtb<4$U>gG#Qt3[5TgUD"9O->+:tc0kP9SAheKQj5&%L\K>Cs/?A$rD"JOT;-Bh"nL.ir3EL\-WTLMDG;)B2fp)k-/]tV44\u=6H5+dlsKQas:W^%,KHp1=H7CcZXIop(=q=toXW#lEP9;N9AEUTN=*65@$0GrR_4IJl.?2B7A@HWQ0kP8@8-]P$<)H<M>YLf%\/!YuKlg='K<2&2_2"jM=Bc9QR=VguGI?E3!L?.4Khnt;dZKs7;7FLEW;IQh4!;:LqSNkL,J9&2Z'R>1X#J?JNkC12Gl[llpJ4Jf*5c`F%3\VBZ!,lngSBpB)==cM(:8?4,I:=t"]O#N]=Bqt/#?@hVlUV7MUClG,Cc2ZT6=8;*dHgIf87_b.>V$YQ%SWd!^_2rEom6SiIMe'a>-7L.9gK?-i@r[\%&X>^+@N!PZNJTg1mq$,\MD3FLjh+I"O%D[_=.,j*D8;[Q)hQ"/4-&WTfYiIoX.l)c";#XSQAlo$;K`+3mu0OeLD>m+o6aTi6V_ns.sWf(gJ[078^U#:(691Sn2&obpEn.fkd/&k!siWU8l`nS:\K2DZADm4?brXcW[O('LaIS"ZcNp1lBU8:dP-Dk!jV80*m0Mj$BuP<i\1oQ.*L[]:7&WJA"-@dtpHo\bP]>N)Wo]<^rhralPKW:-T9q@!*k-"9NW?!:]XQKNpaI&4BEq'U#%[V<%9R)Af=#Ba&nbQqjPWMe9;Pe/8aOhp]otcZ`.(E78_^)EW/UaRC[CaWMckT<D:rIK05Mh/:!Uom4<lj2#)PZe8H_efXPc?o"-@FXW,>,SD*;nN8IZBf$`\_/OgNmIbeqf*;;1@J8(bWE-&]RipPuiD8M9nC.[C]A8M2;\UMo/-s,<@IHD<WBVGb&UgG%W4Y@JDRW,`+pj%Bd^LS6jR[Ym"7^V`T>Y?Jq0cSF9KJ_N/sh)7nTZ&<5d/eo1Nu$T(CC?-5"$TWiG]&>,M`KOI!co5J`li8YK&>Uhs\=n^%HV4DR\B^E]G*LK>E*<2aQ\JAj2h/>%Bgh3ueap$cVLV"858U5lH03:\7@.'0\o-"gZf4EodfB&&6`Jl#`:GJ%9Fop[d`ioXip3S.6m0#uO6i;SUW"s65<#80e`SNCHjG<"r4WPDO&H!FWHC?<g`+Fe[:IcKSo8d?'AS:01dJQchs[`8b\g(b?@.c"=:[WMJ#-bKJ)"OXI7aiq7WDN^]kpm2V(W(@1YIl#[u?YLi)?TJ*V(Cue'>E`alYQ^8Lb(St$OCc;=WY178SU!QC/ol1,(c%]XD\OBpbS&=2=rr7?C$&ccsfkdrF9@G`80XY(YIJ5jT5TgUD"9O->+:ne]!eC>diBIM)ps9~>endstream
|
|
||||||
endobj
|
|
||||||
49 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 871
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"/f>t@p\'Z\P&iKB>R)Fbtu'_IP#p45R&71`&P6UGJiAOQ_ROqF*[+dF=,&L:B[Q=aqd&bP'U#gr>Y5sC)r=L'AD-%2k3V7SgoBC=QGh7XGBmQC+qs-L@\5KrTTmekD!$XdLUA7T6C?`7@Vh;sqfjW'9$S:dLp6V[7@nS!Ml+(UO@Dpe](9ZU&M@KH5IS9le[='S,]B1!OuU'^\`7WhjZ9uhHa9pTOFG$7CNh?.*Yl@:dh]W9gjmiL1*R@[`l3j_3SQ=D&S<,0#i']9k?MeUOJdm2k1g1;OCnaC#T*M?5ae4L@]CC&hTGjo[$`_$nB[h4u8DT;#c7BZO:f']3C;B8p[8IObF.V[-hJh9I&dsBb(F.\P'YSWjl1=W!jZ$NZYoF^CY3ct">^NdH^XaINqJA:D:1,L$TQrQ5dMmkkVat?Sc$-"#6SXJ<H4s<2sB@EO$<7j?pcl)Q2d.([(BZ!JjX@5)J$Pqh*3jCsW$?tn(\)Quc\!sX9&^ZMPd'GVE9),TRkca+rJd1%FNG*,VIJb`[Qb6;A8@F0g%@[0#K#0!qnuCCSOD5-&:^F;4e6K5=f]^Bu1)0MsValuCLDcd36'pTF:O0C2CE<G>`mt\K8uld!_CX>c\k!]RS^@!h?ekJ#Ae+0(B**26hP(G1^V;imM(>q@Ae4=Sl>RrE<m4O^#JdobTH=rtW:d[tZnlfUH3l.AmDE6XkYL;]C244Ybt_(OT)t@(5&4tEM1BK@6XfCa%V`8ha"H5M=`fQ0W45)I(:ek#@c-u?9FDOWR,(P?e/I"^jb:"55?pPVHt%%$]j'G:$31=J&p*>=JJKYa0CZjT&e;CONW"??I`8!:a/_gS,)qP?N/W_2L&M.Db'93~>endstream
|
|
||||||
endobj
|
|
||||||
50 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 1176 /SMask 51 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"/igJ\_^*.\&;Hg(%M9\/E;1\RQr2!T](?"UC/-KVA/Bl#7n)g.[J67la_70Psn03g=C-VRDF'biqZjWZ)\HQ&ZQQ*Zudkb6i*pW[sap<<#S/BdHa&-;h3zz!!&&LD[/DjhLIg-#tJ\jM,"p@Vd%V_?k8g^BJD+n%"h<OIX2jOX?m94A+B$Feu[=Y8nX_424:Cgc\<6-MB)JY_o!_i`)J5JYWIV?j&pH$`b1F0-qp81P@ii;5$+YZ6@3,d.14El#gH)ujIr2G5bPi(h('HCX9,YZ\<&/(eg+N#kU;##c!M'Ji?0'!h*)g9i&e_\0SFAd0[/OSY=$#"*T&I^0l2sYm7]Wc=MRu\*/\?F`\<?gDCPOa_sTo:-Hh+kRc8<b"P;oC?9k]^MFJ(2gFs'-H1m<5VU)J+^PkPhY!ZpJKErO":!Q[n9E^)Y(1ut#Q^/CgOGMlFYtj%oD''2QEDB(qn9THiQ7lCeYQ+)7&]<k=ZF$(PEI^0)*+8dkp`"+M]@Tqb*Xd$/hDa9Fq<H;fhOR&$[f65Pou0Am`C5$)Xo.i^qBsoc89)MGO%7jnq!uteW!pDB*@,qdDn,J95!)(3qKgCc^`PsBJ=rMUD]0[YA]KNPfafO6g$*H%&i>aW^N][g>l)c]D@D!D&bIZpKk)r1-g5Lt'&&Bl7"5r%6dTbQWT;I!4P!"8B<nQoa/=E8n,l8>Cn+;DAPEo#crb^Ro^N3H<>B'CBnJj?/*c@)NE,***\BZbq6KtlXiaa6P06/((j`d8qHZh_MNY==`C6o:jmn>fo*4]\Dt`C4l;3_8bC!H'(;\=phpm*@?Y0oJgO,WBF/Pc)4Qhd&$mN3ODBAaXSVki'\^$XS&:o5Shqc/E07sPKhu-\MaaM1M'qmsg&T[,3l)j3n*2Bf,h@[9ja"6SX4F'H4odBE5r)T/C,7%Z1Q"pN8!+C"CQ4`TfSorK=@"_$`^KZu!BdjhMFDmA@;"*-B7^2N/,7,.\);ODG,qq[?SXW1BAEf-b:oRDda@%0`Sm8mZUfP9KEsSD])rX5.)%o)KIGLRd0[B\_,2j,'>+QqcPL1IQN>Hc)-Wbsk="f;O-$.[3Vl'IT-C7<#Cq+kIXoGotP'blBUql0oA[a\jh>)&62V,6Pcegq!X]3fpoY-5R,=j!a4RrRSzzz!!!"^0>@K>[4G8~>endstream
|
|
||||||
endobj
|
|
||||||
51 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 614
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0P9.32*(^KO`U6n&4Ok4&!$;":(Z!g6J4&)Rh.p5Rq733reb%AfEL9OQVe*Mf[ZOha7O(:*sAJ/S5rTVV<GOEqsq+aPQs5r2,X7PYKcKUo&+<r*U,P.PU2<:fZM+0k2j<9g@*^r1GW`A*,oBY35IT8g49D)?Rr+imQ:K<CQCPVR\bs^*<6A1AN%1NY0(%n?UfXNc5-+rN4a&"_#:MjN?f()liVi"OjH9K@!#)99)cLIoZ=e;T_R@<atkSbWtEN=>H@>EABSFf/A](-Kr=#$`*D/'0:I2hG6#XP$.l63OQ6VnG6<X(`=BESU@b4]&ek?=%;B)Pd&XVYY#-J\TE$[UP;<#'=no^5Z2DGu6S=7sN&$6#D`ob43?jT.*"G'#g<ME7t'!`0gT(NbP(fqW"2.]f#i6SWBf4/g-(h(R@P'#8\D:]YCR!N!+t-Cr\X=VH-I@PoIjL1tY/[eH%OPW4s8a6_e1N+G86>)?_AGTV`Qg$g+DZ[4\H24um?9PfNZ[_`PkS=i'7->I(0$0n7qB40'\eb_,sM%+O,YF0fM@oJZ*C9#1F4ds*)h&0;a2gJT6:7nA3+gO+/`/-f5mm%a.)&X;0)>O)V"(j5If)~>endstream
|
|
||||||
endobj
|
|
||||||
52 0 obj
|
|
||||||
<<
|
|
||||||
/Contents 68 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 62 0 R /Resources <<
|
|
||||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
|
|
||||||
/FormXob.2083d3d28883d55481f443ad2db9baad 48 0 R /FormXob.4fa78ffa9ea10443375a93f6b5a9b1cc 50 0 R /FormXob.5834ce0a44022e11525f663f637f8d25 20 0 R /FormXob.c1db75061a61021e80aed3288e3e1226 44 0 R /FormXob.ed6baac4d37b7009c0f9bdf6fc50e1b8 46 0 R
|
|
||||||
>>
|
|
||||||
>> /Rotate 0 /Trans <<
|
|
||||||
|
|
||||||
>>
|
|
||||||
/Type /Page
|
|
||||||
>>
|
|
||||||
endobj
|
|
||||||
53 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 1325 /SMask 54 0 R
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"0T>AkHL'EI&Ujtoe"5t2Qe'GXH@]Mt.G,XdR/!tt*"Ucb;N#aI<J8u4_9Mmu:l!EJ+#CHJ[tbILShD5Y\(EFKSCG2h5IlP['P[&hO?H6!XNM9`#E9'05sNb<!JB<;k7#U+j463n`f&4-Yr!s-2gPkGaB/cj^(qW!Kt`#+6[WrEWlN6PY$7YhmK@c`p()2KVr^I4%mcX$5d,mn!X,@i[ba=1t_[I6.ZOOtt#?W.k.dc?e/!^&Q<oE6:Mns#Dq."(,(8lh\[oZcYiNre!9\cE@)J#+ZXGZZjZI081#]0-l_X1*CZklX=H'Y^F<]4UVO&L'U7iVTpHEfFq=O@X;SfofhF;JCaG^Ml`;]0X'm*;f@a[h)[sPU:ounbcB"%m/s;4sS4b3sUWiM7r+R!B,F6Ba$n_B.&!@1g,fbKS\WKI:c5q=_S$bV,OSs]r<T5l.qso3:1"&JSlq=6EJtrSH-Z,TN.&EZBjdfHB?d!i(^$_@!*)&28?lL-f.#>UC[3%^t]^W^/qo)$^[IBfk*DD5^S,#6[gLMVVfm:>O2@HPhQ_^qs_fu5O%W3K@4]'E"VD[r28FT%CCRbZ3/tA:HopLIB*W_r=4?Sg&ggm?bFs8E8Gq7SeB!a5dZbVA7L1'/eV[h?fc0t&+M>\\dl*A!`.CqD#X?]-/Mi2j!`5K5\j'tPpkI2Id#PD3lG>1m%#q,T/l--4,kmgWaGg)[NFk?fsh!N$Adf5.KG!"8aJF)I`'mDjOSt/mIA$$jB+[57-fCp<he.eTj?`ib6M%&qlbq.gVBG\J/jXt:3Hi]k25M'0AADNP;ogc\YmG9kq5N0!^fusCNq*;Jl^j&I6^]8nOqaA!Un%j0$(//'g/&=4]^V=.rIKNUfdYR6q7GV5B0TPdOL>h,M09jPB[pHh(,:e,0#ar/pSS/.Zi_t4ILZABtD"\e8*9UERK=?A2U'48+&LuO$>C,#Ik236q@$h-"o:\OosGcd:9nnrL'uAGXUL0T3iZpL1GGLnO%PulX8DJ\Xg,-^\H6"s)ZgE"kgum=9)-IA1Dg(5]0'DbZV,f58#a/Qdt7]5)7CQo<&(#\tO^MDC'#V22B#G`arYRDn%4qiHYSI$1&F8-gNS%,EIi\r"TZ3DL]RP]*:Iu:hbNX]-]>[Id0.`0Agm-"REBd';BlXCZI\A^BNhuo)W$0>\WoCnE&K*Rm&cE3.(;&_[a!BZdO_RO!i*E#*"o@g"qu>*X:"m>(LkESBU-h:%o2o;r^'6Xb'774;m?AKQa*^X)/LiG.X))_uS`kC!m9XH=[W=d@m8i4(<jS63n`f&4-XGKFh&Xq[3_q($5~>endstream
|
|
||||||
endobj
|
|
||||||
54 0 obj
|
|
||||||
<<
|
|
||||||
/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 86 /Length 805
|
|
||||||
/Subtype /Image /Type /XObject /Width 86
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
Gb"/f8SD$g(rsB<[K4jgUe%U<EPmF].(ome-)cVdlVT65&Jkun`9iY=$WQDG+JF&,Jj$(<0>/21*lQJo0C;&%Ta$BX7>r/>L8J\a12i`X65!p;DU.]-o7ueT]Ql=)jq0$V$ACg?.)DG8"jr3]SujrWCRmac!kF[gC$e^7S]M$8Lj67t"XY#SJM5-HO$$#4UAuq;8Lp!6.ca$EQRPh%\`fl%`?f52nD$N>1#!L%ZZUOV9)<)#[p]q.ZMS7\->Qn/.qL,`%N/.2Dq!DnCF'>]BWl$?'qDR"^Kt4cp]BBBh1'3E?-??+(bjcRoqL58VsEEGoojW:pRZG,SFJ;cDJZW4.s&Ar^%C;.WnV!lH[.&ZQn#plV\Ej+B+/;L4dQjRTC@2K0"q(]5RLokFAUiIe=/l=IWR3.F7/6^.AhGm91V.'A#_M<,^/WQ3@W<$,[A?Lr7C&4=%&hnkmr6;SWi028YHq9"'UO0*&$RTFEsI6e3=/Mcs!-qGVSB#8%"/:W!u"@NSY-bjc3B2`%Ebj&LCQ8*OFojR;k=/[L5/GU92mD]bNqJ>SF\:>e8mb?MgbMMRo>/4i5M,B<u2iVL+R?L8K4[TWn($@o0_L7f8?Dc*-rXe*282K16j>ZEH.&euJ\$<dDDtX-LH)Xk-.!h4OB*Oc<Uj^llu6/-*[JXa7j(K<Jmr%ZRB,;PF1mrP4h,26AI9eok*MjNJO%:X+]sPQK`n!I+<,[iUaAZG"cUc<<&=C9G3,S/i+SKYrg+7ttX-^D>i8J?6;:.n3N$o;uD,.Y*;dTL,>K-ku;<nJ?`s/0k~>endstream
|
|
||||||
endobj
|
|
||||||
55 0 obj
|
|
||||||
<<
|
|
||||||
/Contents 69 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 62 0 R /Resources <<
|
|
||||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject <<
|
|
||||||
/FormXob.5c650c022c0d8f354ce49f5ee1420e0c 53 0 R
|
|
||||||
>>
|
|
||||||
>> /Rotate 0 /Trans <<
|
|
||||||
|
|
||||||
>>
|
|
||||||
/Type /Page
|
|
||||||
>>
|
|
||||||
endobj
|
|
||||||
56 0 obj
|
|
||||||
<<
|
|
||||||
/Filter [ /FlateDecode ] /Length 686
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
xœmÕÝjâ@Æñó\EwÙ<03>y¿Z¡Õ<ض{6Ž®P£D{л_ž<Òe…È?™Løïd±Z®úý¥<C3BD>üŽÝS¹´Û}¿Êùø:t¥}.»}ߤÜnöÝåz6þw‡õ©™,V˧·ó¥VýöØÌfíäwÙíÏ—áýr7þ¾-Žýùø²>m&?‡MöýîkO¯§ÓK9”þÒN›ù¼Ý”m3Y|_Ÿ~¬¥<>|Úð±üçíTÚ<ž'úºã¦œOë®ë~WšÙt:ogñ8oJ¿ù´–ò
÷<o»¿ëázït:<3A>ΛÙ4ÍÛY¶´@ç±y]ؼGÑ6î}¯{õœ¨ú¦ê۪諭¯zQõ²ê‡ª?:Uþ”ªÎUKÕZµU]ùSåO•?UþTùSåO•?UþTùSåÏôç±éÏ MÆ»ÍôgAÓŸñþ3ýÙÐôgGÓŸM¾AÓŸoÑôç;4ýùMÆ7<C386>éÏK4ýùM~œ73¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~£ßà7ú
~£ßà7ú
~£ßà7ú
~£ßà7ú
~£ßà7ú
~£ßà7ú
~£ßà7ú
~£ßà7ú
~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwúþ ?àúþ ?àúþ ?àúþ ?àúþ ?àúþ ?àúþ ?àúþ ?àú¯â: 0+0áÞ'P÷:¥¿Œcp<9û¾¼OÊÓñ„]8þ$<>7endstream
|
|
||||||
endobj
|
|
||||||
57 0 obj
|
|
||||||
<<
|
|
||||||
/Filter [ /FlateDecode ] /Length 20423 /Length1 33512
|
|
||||||
>>
|
|
||||||
stream
|
|
||||||
xœ¼} xTE¶ð©»õžÞÓ<C39E>î,·ÓéY;éÎB³ugƒ°'!`d'щ„E@ÔˆEddde q#>g†qÜðÍÿÆÑŒÃ o€Ÿ2ÉÍÿUÝîÐyßÿÿßûþ&Ý]·î©ªSçœ:çÔ9u@ | |||||||