diff --git a/.github/workflows/lint_pr.yml b/.github/workflows/lint_pr.yml new file mode 100644 index 00000000000..40c3dead003 --- /dev/null +++ b/.github/workflows/lint_pr.yml @@ -0,0 +1,24 @@ +name: lint-pr + +on: + pull_request_target: + types: + - opened + - edited + - synchronize + +jobs: + validate-title: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v4 + with: + # Must use uppercase + subjectPattern: ^(?=[A-Z]).+$ + subjectPatternError: | + The subject "{subject}" found in the pull request title "{title}" + didn't match the configured pattern. Please ensure that the subject + starts with an uppercase character. + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/master_only.yml b/.github/workflows/master_only.yml index 3cdddba8479..e7a89815fe4 100644 --- a/.github/workflows/master_only.yml +++ b/.github/workflows/master_only.yml @@ -65,16 +65,6 @@ jobs: env: OS: ${{ matrix.os }} PYTHON: ${{ matrix.python-version }} - services: - redis: - image: redis - ports: - - 6379:6379 - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 steps: - uses: actions/checkout@v2 - name: Setup Python @@ -120,6 +110,15 @@ jobs: run: pip install pip-tools - name: Install dependencies run: make install-python-ci-dependencies + - name: Start Redis + uses: supercharge/redis-github-action@1.4.0 + with: + redis-version: ${{ matrix.redis-version }} + redis-port: 12345 + - name: Setup Redis Cluster + run: | + docker pull vishnunair/docker-redis-cluster:latest + docker run -d -p 6001:6379 -p 6002:6380 -p 6003:6381 -p 6004:6382 -p 6005:6383 -p 6006:6384 --name redis-cluster vishnunair/docker-redis-cluster - name: Test python env: FEAST_SERVER_DOCKER_IMAGE_TAG: ${{ needs.build-lambda-docker-image.outputs.DOCKER_IMAGE_TAG }} diff --git a/.github/workflows/pr_integration_tests.yml b/.github/workflows/pr_integration_tests.yml index e04b78ec320..4c758d7601a 100644 --- a/.github/workflows/pr_integration_tests.yml +++ b/.github/workflows/pr_integration_tests.yml @@ -84,16 +84,6 @@ jobs: env: OS: ${{ matrix.os }} PYTHON: ${{ matrix.python-version }} - services: - redis: - image: redis - ports: - - 6379:6379 - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 steps: - uses: actions/checkout@v2 with: @@ -102,6 +92,11 @@ jobs: # code from the PR. ref: refs/pull/${{ github.event.pull_request.number }}/merge submodules: recursive + - name: Start Redis + uses: supercharge/redis-github-action@1.4.0 + with: + redis-version: ${{ matrix.redis-version }} + redis-port: 12345 - name: Setup Python uses: actions/setup-python@v2 id: setup-python @@ -145,6 +140,10 @@ jobs: run: pip install pip-tools - name: Install dependencies run: make install-python-ci-dependencies + - name: Setup Redis Cluster + run: | + docker pull vishnunair/docker-redis-cluster:latest + docker run -d -p 6001:6379 -p 6002:6380 -p 6003:6381 -p 6004:6382 -p 6005:6383 -p 6006:6384 --name redis-cluster vishnunair/docker-redis-cluster - name: Test python if: ${{ always() }} # this will guarantee that step won't be canceled and resources won't leak env: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000000..0d7476a82ba --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,206 @@ +name: publish + +on: + push: + tags: + - 'v*.*.*' + +jobs: + get-version: + runs-on: ubuntu-latest + outputs: + release_version: ${{ steps.get_release_version.outputs.release_version }} + version_without_prefix: ${{ steps.get_release_version_without_prefix.outputs.version_without_prefix }} + highest_semver_tag: ${{ steps.get_highest_semver.outputs.highest_semver_tag }} + steps: + - uses: actions/checkout@v2 + - name: Get release version + id: get_release_version + run: echo ::set-output name=release_version::${GITHUB_REF#refs/*/} + - name: Get release version without prefix + id: get_release_version_without_prefix + env: + RELEASE_VERSION: ${{ steps.get_release_version.outputs.release_version }} + run: | + echo ::set-output name=version_without_prefix::${RELEASE_VERSION:1} + - name: Get highest semver + id: get_highest_semver + env: + RELEASE_VERSION: ${{ steps.get_release_version.outputs.release_version }} + run: | + source infra/scripts/setup-common-functions.sh + SEMVER_REGEX='^v[0-9]+\.[0-9]+\.[0-9]+(-([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?$' + if echo "${RELEASE_VERSION}" | grep -P "$SEMVER_REGEX" &>/dev/null ; then + echo ::set-output name=highest_semver_tag::$(get_tag_release -m) + fi + - name: Check output + env: + RELEASE_VERSION: ${{ steps.get_release_version.outputs.release_version }} + VERSION_WITHOUT_PREFIX: ${{ steps.get_release_version_without_prefix.outputs.version_without_prefix }} + HIGHEST_SEMVER_TAG: ${{ steps.get_highest_semver.outputs.highest_semver_tag }} + run: | + echo $RELEASE_VERSION + echo $VERSION_WITHOUT_PREFIX + echo $HIGHEST_SEMVER_TAG + + build-publish-docker-images: + runs-on: ubuntu-latest + needs: get-version + strategy: + matrix: + component: [feature-server-python-aws, feature-server-java, feature-transformation-server] + env: + MAVEN_CACHE: gs://feast-templocation-kf-feast/.m2.2020-08-19.tar + REGISTRY: feastdev + steps: + - uses: actions/checkout@v2 + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Set up Cloud SDK + uses: google-github-actions/setup-gcloud@master + with: + project_id: ${{ secrets.GCP_PROJECT_ID }} + service_account_key: ${{ secrets.GCP_SA_KEY }} + export_default_credentials: true + - name: Use gcloud CLI + run: gcloud info + - run: gcloud auth configure-docker --quiet + - name: Get m2 cache + run: | + infra/scripts/download-maven-cache.sh \ + --archive-uri ${MAVEN_CACHE} \ + --output-dir . + - name: Build image + run: | + make build-${{ matrix.component }}-docker REGISTRY=${REGISTRY} VERSION=${VERSION_WITHOUT_PREFIX} + env: + RELEASE_VERSION: ${{ needs.get-version.outputs.release_version }} + VERSION_WITHOUT_PREFIX: ${{ needs.get-version.outputs.version_without_prefix }} + HIGHEST_SEMVER_TAG: ${{ needs.get-version.outputs.highest_semver_tag }} + - name: Push versioned images + env: + RELEASE_VERSION: ${{ needs.get-version.outputs.release_version }} + VERSION_WITHOUT_PREFIX: ${{ needs.get-version.outputs.version_without_prefix }} + HIGHEST_SEMVER_TAG: ${{ needs.get-version.outputs.highest_semver_tag }} + run: | + make push-${{ matrix.component }}-docker REGISTRY=${REGISTRY} VERSION=${VERSION_WITHOUT_PREFIX} + + echo "Only push to latest tag if tag is the highest semver version $HIGHEST_SEMVER_TAG" + if [ "${VERSION_WITHOUT_PREFIX}" = "${HIGHEST_SEMVER_TAG:1}" ] + then + docker tag feastdev/${{ matrix.component }}:${VERSION_WITHOUT_PREFIX} feastdev/${{ matrix.component }}:latest + docker push feastdev/${{ matrix.component }}:latest + fi + + publish-helm-charts: + runs-on: ubuntu-latest + needs: get-version + env: + HELM_VERSION: v3.8.0 + VERSION_WITHOUT_PREFIX: ${{ needs.get-version.outputs.version_without_prefix }} + steps: + - uses: actions/checkout@v2 + - uses: google-github-actions/setup-gcloud@master + with: + version: '290.0.1' + export_default_credentials: true + project_id: ${{ secrets.GCP_PROJECT_ID }} + service_account_key: ${{ secrets.GCP_SA_KEY }} + - run: gcloud auth configure-docker --quiet + - name: Remove previous Helm + run: sudo rm -rf $(which helm) + - name: Install Helm + run: ./infra/scripts/helm/install-helm.sh + - name: Validate Helm chart prior to publishing + run: ./infra/scripts/helm/validate-helm-chart-publish.sh + - name: Validate all version consistency + run: ./infra/scripts/helm/validate-helm-chart-versions.sh $VERSION_WITHOUT_PREFIX + - name: Publish Helm charts + run: ./infra/scripts/helm/push-helm-charts.sh $VERSION_WITHOUT_PREFIX + + publish-python-sdk: + runs-on: ubuntu-latest + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + container: python:3.7 + steps: + - uses: actions/checkout@v2 + - name: Install pip-tools + run: pip install pip-tools + - name: Install dependencies + run: make install-python-ci-dependencies PYTHON=3.7 + - name: Publish Python Package + run: | + cd sdk/python + python3 -m pip install --user --upgrade setuptools wheel twine + python3 setup.py sdist bdist_wheel + python3 -m twine upload --verbose dist/* + + publish-python-sdk-no-telemetry: + runs-on: ubuntu-latest + needs: get-version + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + container: python:3.7 + steps: + - uses: actions/checkout@v2 + - name: Install pip-tools + run: pip install pip-tools + - name: Install dependencies + run: make install-python-ci-dependencies PYTHON=3.7 + - name: Publish Python Package + env: + SETUPTOOLS_SCM_PRETEND_VERSION: ${{ needs.get-version.outputs.version_without_prefix }} + run: | + cd sdk/python + sed -i 's/DEFAULT_FEAST_USAGE_VALUE = "True"/DEFAULT_FEAST_USAGE_VALUE = "False"/g' feast/constants.py + sed -i 's/NAME = "feast"/NAME = "feast-no-telemetry"/g' setup.py + python3 -m pip install --user --upgrade setuptools wheel twine + python3 setup.py sdist bdist_wheel + python3 -m twine upload --verbose dist/* + + publish-java-sdk: + container: maven:3.6-jdk-11 + runs-on: ubuntu-latest + needs: get-version + steps: + - uses: actions/checkout@v2 + with: + submodules: 'true' + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: '11' + java-package: jdk + architecture: x64 + - uses: actions/setup-python@v2 + with: + python-version: '3.7' + architecture: 'x64' + - uses: actions/cache@v2 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-it-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-it-maven- + - name: Publish java sdk + env: + VERSION_WITHOUT_PREFIX: ${{ needs.get-version.outputs.version_without_prefix }} + GPG_PUBLIC_KEY: ${{ secrets.GPG_PUBLIC_KEY }} + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + MAVEN_SETTINGS: ${{ secrets.MAVEN_SETTINGS }} + run: | + echo -n "$GPG_PUBLIC_KEY" > /root/public-key + echo -n "$GPG_PRIVATE_KEY" > /root/private-key + mkdir -p /root/.m2/ + echo -n "$MAVEN_SETTINGS" > /root/.m2/settings.xml + infra/scripts/publish-java-sdk.sh --revision ${VERSION_WITHOUT_PREFIX} --gpg-key-import-dir /root diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8dd29aeb588..d66f895bf54 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,203 +1,43 @@ name: release on: - push: - tags: - - 'v*.*.*' + workflow_dispatch: + inputs: + dry_run: + description: 'Dry Run' + required: true + default: true + type: boolean + token: + description: 'Personal Access Token' + required: true + default: "" + type: string jobs: - get-version: - runs-on: ubuntu-latest - outputs: - release_version: ${{ steps.get_release_version.outputs.release_version }} - version_without_prefix: ${{ steps.get_release_version_without_prefix.outputs.version_without_prefix }} - highest_semver_tag: ${{ steps.get_highest_semver.outputs.highest_semver_tag }} - steps: - - uses: actions/checkout@v2 - - name: Get release version - id: get_release_version - run: echo ::set-output name=release_version::${GITHUB_REF#refs/*/} - - name: Get release version without prefix - id: get_release_version_without_prefix - env: - RELEASE_VERSION: ${{ steps.get_release_version.outputs.release_version }} - run: | - echo ::set-output name=version_without_prefix::${RELEASE_VERSION:1} - - name: Get highest semver - id: get_highest_semver - env: - RELEASE_VERSION: ${{ steps.get_release_version.outputs.release_version }} - run: | - source infra/scripts/setup-common-functions.sh - SEMVER_REGEX='^v[0-9]+\.[0-9]+\.[0-9]+(-([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?$' - if echo "${RELEASE_VERSION}" | grep -P "$SEMVER_REGEX" &>/dev/null ; then - echo ::set-output name=highest_semver_tag::$(get_tag_release -m) - fi - - name: Check output - env: - RELEASE_VERSION: ${{ steps.get_release_version.outputs.release_version }} - VERSION_WITHOUT_PREFIX: ${{ steps.get_release_version_without_prefix.outputs.version_without_prefix }} - HIGHEST_SEMVER_TAG: ${{ steps.get_highest_semver.outputs.highest_semver_tag }} - run: | - echo $RELEASE_VERSION - echo $VERSION_WITHOUT_PREFIX - echo $HIGHEST_SEMVER_TAG - - build-publish-docker-images: + release: + name: release runs-on: ubuntu-latest - needs: get-version - strategy: - matrix: - component: [feature-server-python-aws, feature-server-java, feature-transformation-server] env: - MAVEN_CACHE: gs://feast-templocation-kf-feast/.m2.2020-08-19.tar - REGISTRY: feastdev - steps: - - uses: actions/checkout@v2 - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@master - with: - project_id: ${{ secrets.GCP_PROJECT_ID }} - service_account_key: ${{ secrets.GCP_SA_KEY }} - export_default_credentials: true - - name: Use gcloud CLI - run: gcloud info - - run: gcloud auth configure-docker --quiet - - name: Get m2 cache - run: | - infra/scripts/download-maven-cache.sh \ - --archive-uri ${MAVEN_CACHE} \ - --output-dir . - - name: Build image - run: | - make build-${{ matrix.component }}-docker REGISTRY=${REGISTRY} VERSION=${VERSION_WITHOUT_PREFIX} - env: - RELEASE_VERSION: ${{ needs.get-version.outputs.release_version }} - VERSION_WITHOUT_PREFIX: ${{ needs.get-version.outputs.version_without_prefix }} - HIGHEST_SEMVER_TAG: ${{ needs.get-version.outputs.highest_semver_tag }} - - name: Push versioned images - env: - RELEASE_VERSION: ${{ needs.get-version.outputs.release_version }} - VERSION_WITHOUT_PREFIX: ${{ needs.get-version.outputs.version_without_prefix }} - HIGHEST_SEMVER_TAG: ${{ needs.get-version.outputs.highest_semver_tag }} - run: | - make push-${{ matrix.component }}-docker REGISTRY=${REGISTRY} VERSION=${VERSION_WITHOUT_PREFIX} - - echo "Only push to latest tag if tag is the highest semver version $HIGHEST_SEMVER_TAG" - if [ "${VERSION_WITHOUT_PREFIX}" = "${HIGHEST_SEMVER_TAG:1}" ] - then - docker tag feastdev/${{ matrix.component }}:${VERSION_WITHOUT_PREFIX} feastdev/${{ matrix.component }}:latest - docker push feastdev/${{ matrix.component }}:latest - fi - - publish-helm-charts: - runs-on: ubuntu-latest - needs: get-version - env: - HELM_VERSION: v2.17.0 - VERSION_WITHOUT_PREFIX: ${{ needs.get-version.outputs.version_without_prefix }} - steps: - - uses: actions/checkout@v2 - - uses: google-github-actions/setup-gcloud@master - with: - version: '290.0.1' - export_default_credentials: true - project_id: ${{ secrets.GCP_PROJECT_ID }} - service_account_key: ${{ secrets.GCP_SA_KEY }} - - run: gcloud auth configure-docker --quiet - - name: Remove previous Helm - run: sudo rm -rf $(which helm) - - name: Install Helm - run: ./infra/scripts/helm/install-helm.sh - - name: Validate Helm chart prior to publishing - run: ./infra/scripts/helm/validate-helm-chart-publish.sh - - name: Validate all version consistency - run: ./infra/scripts/helm/validate-helm-chart-versions.sh $VERSION_WITHOUT_PREFIX - - name: Publish Helm charts - run: ./infra/scripts/helm/push-helm-charts.sh $VERSION_WITHOUT_PREFIX - - publish-python-sdk: - runs-on: ubuntu-latest - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - container: python:3.7 - steps: - - uses: actions/checkout@v2 - - name: Install pip-tools - run: pip install pip-tools - - name: Install dependencies - run: make install-python-ci-dependencies PYTHON=3.7 - - name: Publish Python Package - run: | - cd sdk/python - python3 -m pip install --user --upgrade setuptools wheel twine - python3 setup.py sdist bdist_wheel - python3 -m twine upload --verbose dist/* - - publish-python-sdk-no-telemetry: - runs-on: ubuntu-latest - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - container: python:3.7 - steps: - - uses: actions/checkout@v2 - - name: Install pip-tools - run: pip install pip-tools - - name: Install dependencies - run: make install-python-ci-dependencies PYTHON=3.7 - - name: Publish Python Package - run: | - cd sdk/python - sed -i 's/DEFAULT_FEAST_USAGE_VALUE = "True"/DEFAULT_FEAST_USAGE_VALUE = "False"/g' feast/constants.py - sed -i 's/NAME = "feast"/NAME = "feast-no-telemetry"/g' setup.py - python3 -m pip install --user --upgrade setuptools wheel twine - python3 setup.py sdist bdist_wheel - python3 -m twine upload --verbose dist/* - - publish-java-sdk: - container: maven:3.6-jdk-11 - runs-on: ubuntu-latest - needs: get-version + GITHUB_TOKEN: ${{ github.event.inputs.token }} + GIT_AUTHOR_NAME: feast-ci-bot + GIT_AUTHOR_EMAIL: feast-ci-bot@willem.co + GIT_COMMITTER_NAME: feast-ci-bot + GIT_COMMITTER_EMAIL: feast-ci-bot@willem.co steps: - - uses: actions/checkout@v2 - with: - submodules: 'true' - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: '11' - java-package: jdk - architecture: x64 - - uses: actions/setup-python@v2 - with: - python-version: '3.7' - architecture: 'x64' - - uses: actions/cache@v2 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-it-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-it-maven- - - name: Publish java sdk - env: - VERSION_WITHOUT_PREFIX: ${{ needs.get-version.outputs.version_without_prefix }} - GPG_PUBLIC_KEY: ${{ secrets.GPG_PUBLIC_KEY }} - GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} - MAVEN_SETTINGS: ${{ secrets.MAVEN_SETTINGS }} - run: | - echo -n "$GPG_PUBLIC_KEY" > /root/public-key - echo -n "$GPG_PRIVATE_KEY" > /root/private-key - mkdir -p /root/.m2/ - echo -n "$MAVEN_SETTINGS" > /root/.m2/settings.xml - infra/scripts/publish-java-sdk.sh --revision ${VERSION_WITHOUT_PREFIX} --gpg-key-import-dir /root + - name: Checkout + uses: actions/checkout@v2 + with: + persist-credentials: false + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '16' + - name: Release (Dry Run) + if: github.event.inputs.dry_run == 'true' + run: | + npx -p @semantic-release/changelog -p @semantic-release/git -p @semantic-release/exec -p semantic-release semantic-release --dry-run + - name: Release + if: github.event.inputs.dry_run == 'false' + run: | + npx -p @semantic-release/changelog -p @semantic-release/git -p @semantic-release/exec -p semantic-release semantic-release \ No newline at end of file diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 5de5971703e..d9552e175e7 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -42,6 +42,12 @@ jobs: - name: Install dependencies run: make install-python-ci-dependencies - name: Test Python + env: + SNOWFLAKE_CI_DEPLOYMENT: ${{ secrets.SNOWFLAKE_CI_DEPLOYMENT }} + SNOWFLAKE_CI_USER: ${{ secrets.SNOWFLAKE_CI_USER }} + SNOWFLAKE_CI_PASSWORD: ${{ secrets.SNOWFLAKE_CI_PASSWORD }} + SNOWFLAKE_CI_ROLE: ${{ secrets.SNOWFLAKE_CI_ROLE }} + SNOWFLAKE_CI_WAREHOUSE: ${{ secrets.SNOWFLAKE_CI_WAREHOUSE }} run: FEAST_USAGE=False pytest -n 8 --cov=./ --cov-report=xml --verbose --color=yes sdk/python/tests - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 diff --git a/.gitignore b/.gitignore index 90b1a66a8c4..05c73a42951 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ ### Scratch files ### scratch* -### Feast UI deprecated folder #### -ui/ - ### Local Environment ### *local*.env @@ -54,7 +51,7 @@ vendor .terraform/ *.tfvars -# python +# python # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -107,6 +104,7 @@ coverage.xml *.cover .hypothesis/ .pytest_cache/ +infra/scripts/*.conf # Translations *.mo @@ -191,3 +189,32 @@ sdk/go/protos/ #benchmarks .benchmarks + +# Examples registry +**/registry.db +**/*.aof +**/*.rdb +**/nodes.conf + + +# Feast UI dependencies +ui/node_modules +ui/.pnp +ui/.pnp.js +ui/coverage +ui/build +ui/feature_repo/data/online.db +ui/feature_repo/registry.db +ui/.vercel + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +**/npm-debug.log* +**/yarn-debug.log* +**/yarn-error.log* + diff --git a/.prow/config.yaml b/.prow/config.yaml index 3bc2d760a3d..8b3905e43bb 100644 --- a/.prow/config.yaml +++ b/.prow/config.yaml @@ -64,6 +64,9 @@ tide: merge_method: feast-dev/feast: squash feast-dev/feast-spark: squash + merge_commit_template: + feast-dev/feast: + title: '{{.Title}} (#{{.Number}})' blocker_label: merge-blocker squash_label: tide/squash diff --git a/.prow/plugins.yaml b/.prow/plugins.yaml index 0f89e07be57..0dbf0f4c72b 100644 --- a/.prow/plugins.yaml +++ b/.prow/plugins.yaml @@ -34,6 +34,8 @@ config_updater: maps: .prow/config.yaml: name: config + .prow.yaml: + name: job-config external_plugins: feast-dev/feast: diff --git a/.releaserc.js b/.releaserc.js new file mode 100644 index 00000000000..60a8616e073 --- /dev/null +++ b/.releaserc.js @@ -0,0 +1,52 @@ +// Release script for semantic-release.gitbook.io + +const execSync = require("child_process").execSync; + +// Get the current branch +const current_branch = execSync("git rev-parse --abbrev-ref HEAD").toString("utf8").trim(); + +// Validate the current branch +if (current_branch !== 'master') { + // Should be a release branch like v0.18-branch + is_valid = /v[0-9]\.[0-9][0-9]\-branch/gm.test(current_branch) + if (!is_valid) { + throw new Error(`Invalid branch name: ${current_branch}. Must be in release branch form like v0.18-branch or master`) + } +} + +// We have to dynamically generate all the supported branches for Feast because we use the `vA.B-branch` pattern for +// maintenance branches +possible_branches = [{name: "master"}, {name: current_branch}] + +// Below is the configuration for semantic release +module.exports = { + branches: possible_branches, + plugins: [ + "@semantic-release/commit-analyzer", + ["@semantic-release/exec", { + "verifyReleaseCmd": "./infra/scripts/validate-release.sh ${nextRelease.type} " + current_branch, + "prepareCmd": "python ./infra/scripts/version_bump/bump_file_versions.py ${lastRelease.version} ${nextRelease.version}" + }], + "@semantic-release/release-notes-generator", + [ + "@semantic-release/changelog", + { + changelogFile: "CHANGELOG.md", + changelogTitle: "# Changelog", + } + ], + [ + "@semantic-release/git", + { + assets: [ + "CHANGELOG.md", + "java/pom.xml", + "infra/charts/**/*.*" + ], + message: "chore(release): release ${nextRelease.version}\n\n${nextRelease.notes}" + } + ], + "@semantic-release/github" + ] +} + diff --git a/CHANGELOG.md b/CHANGELOG.md index bc0368cca25..73b8d2f0500 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,52 @@ # Changelog +# [0.19.0](https://github.com/feast-dev/feast/compare/v0.18.0...v0.19.0) (2022-03-05) + + +### Bug Fixes + +* Added additional value types to UI parser and removed references to registry-bq.json ([#2361](https://github.com/feast-dev/feast/issues/2361)) ([d202d51](https://github.com/feast-dev/feast/commit/d202d5170b7e6bf1e1b0f103aac247bfc04c2760)) +* Fix Redshift bug that stops waiting on statements after 5 minutes ([#2363](https://github.com/feast-dev/feast/issues/2363)) ([74f887f](https://github.com/feast-dev/feast/commit/74f887f72e109147a2e6214c2e3baade63d55fbe)) +* Method _should_use_plan only returns true for local sqlite provider ([#2344](https://github.com/feast-dev/feast/issues/2344)) ([fdb5f21](https://github.com/feast-dev/feast/commit/fdb5f215fe7f4946a6c88cfb34dc0c24eb5ac733)) +* Remove redis service to prevent more conflicts and add redis node to master_only ([#2354](https://github.com/feast-dev/feast/issues/2354)) ([993616f](https://github.com/feast-dev/feast/commit/993616fe152d097e2d918e5f56fc13e2e409175c)) +* Rollback Redis-py to Redis-py-cluster ([#2347](https://github.com/feast-dev/feast/issues/2347)) ([1ba86fb](https://github.com/feast-dev/feast/commit/1ba86fb0cc7f2e86b8c70477462faa68075f99cd)) +* Update github workflow to prevent redis from overlapping ports. ([#2350](https://github.com/feast-dev/feast/issues/2350)) ([c2a6c6c](https://github.com/feast-dev/feast/commit/c2a6c6cc34d64fd3483f0b2cef394f833e9124e2)) + + +### Features + +* Add owner field to Entity and rename labels to tags ([412d625](https://github.com/feast-dev/feast/commit/412d62516da184350de473c87dd2ab369ad4cf86)) +* Allow all snowflake python connector connection methods to be available to Feast ([#2356](https://github.com/feast-dev/feast/issues/2356)) ([ec7385c](https://github.com/feast-dev/feast/commit/ec7385c16f6899c5388b7a786fce6e0d543776f5)) +* Allowing password based authentication and SSL for Redis in Java feature server ([0af8adb](https://github.com/feast-dev/feast/commit/0af8adba1c56a2a29d02c2fc5aeccf51ee78fd5f)) +* Event timestamps response ([#2355](https://github.com/feast-dev/feast/issues/2355)) ([5481caf](https://github.com/feast-dev/feast/commit/5481caf37989c347bf4469f5f081f4f15f20fdb7)) +* Feast Spark Offline Store ([#2349](https://github.com/feast-dev/feast/issues/2349)) ([98b8d8d](https://github.com/feast-dev/feast/commit/98b8d8da7e8e717ec93197f253368551951ca675)) +* Initial merge of Web UI logic ([#2352](https://github.com/feast-dev/feast/issues/2352)) ([ce3bc59](https://github.com/feast-dev/feast/commit/ce3bc598501949f82197c7fa2409319282197276)) +* Key ttl setting for redis online store ([#2341](https://github.com/feast-dev/feast/issues/2341)) ([236a108](https://github.com/feast-dev/feast/commit/236a108c87aed106e0a46e48172d31dc94ed9c2b)) +* Metadata changes & making data sources top level objects to power Feast UI ([#2336](https://github.com/feast-dev/feast/issues/2336)) ([43da230](https://github.com/feast-dev/feast/commit/43da2302dfcbf3b5e56ed068021b5821d544c05f)) + +## [v0.18.1](https://github.com/feast-dev/feast/tree/v0.18.1) (2022-02-15) + +[Full Changelog](https://github.com/feast-dev/feast/compare/v0.18.0...v0.18.1) + +**Fixed bugs:** + +- ODFVs raise a PerformanceWarning for very large sets of features [\#2293](https://github.com/feast-dev/feast/issues/2293) +- Don't require `snowflake` to always be installed [\#2309](https://github.com/feast-dev/feast/pull/2309) ([judahrand](https://github.com/judahrand)) +- podAnnotations Values in the feature-server chart [\#2304](https://github.com/feast-dev/feast/pull/2304) ([tpvasconcelos](https://github.com/tpvasconcelos)) +- Fixing the Java helm charts and adding a demo tutorial on how to use them [\#2298](https://github.com/feast-dev/feast/pull/2298) ([adchia](https://github.com/adchia)) +- avoid using transactions on OSS Redis [\#2296](https://github.com/feast-dev/feast/pull/2296) ([DvirDukhan](https://github.com/DvirDukhan)) +- Include infra objects in registry dump and fix Infra's from\_proto [\#2295](https://github.com/feast-dev/feast/pull/2295) ([adchia](https://github.com/adchia)) +- Expose snowflake credentials for unit testing [\#2288](https://github.com/feast-dev/feast/pull/2288) ([sfc-gh-madkins](https://github.com/sfc-gh-madkins)) +- Fix flaky tests \(test\_online\_store\_cleanup & test\_feature\_get\_online\_features\_types\_match\) [\#2276](https://github.com/feast-dev/feast/pull/2276) ([pyalex](https://github.com/pyalex)) + +**Merged pull requests:** + +- Remove old flag warning with the python feature server [\#2300](https://github.com/feast-dev/feast/pull/2300) ([adchia](https://github.com/adchia)) +- Use an OFFLINE schema for Snowflake offline store tests [\#2291](https://github.com/feast-dev/feast/pull/2291) ([sfc-gh-madkins](https://github.com/sfc-gh-madkins)) +- fix typos in markdown files [\#2289](https://github.com/feast-dev/feast/pull/2289) ([charliec443](https://github.com/charliec443)) +- Add -SNAPSHOT suffix to pom.xml version [\#2286](https://github.com/feast-dev/feast/pull/2286) ([tsotnet](https://github.com/tsotnet)) +- Update CONTRIBUTING.md [\#2282](https://github.com/feast-dev/feast/pull/2282) ([adchia](https://github.com/adchia)) + ## [v0.18.0](https://github.com/feast-dev/feast/tree/v0.18.0) (2022-02-05) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.17.0...v0.18.0) @@ -1879,4 +1926,4 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Directory structure changes [\#7](https://github.com/feast-dev/feast/pull/7) ([zhilingc](https://github.com/zhilingc)) - Change register to apply [\#4](https://github.com/feast-dev/feast/pull/4) ([zhilingc](https://github.com/zhilingc)) - Empty response handling in serving api [\#3](https://github.com/feast-dev/feast/pull/3) ([pradithya](https://github.com/pradithya)) -- Proto file fixes [\#1](https://github.com/feast-dev/feast/pull/1) ([pradithya](https://github.com/pradithya)) \ No newline at end of file +- Proto file fixes [\#1](https://github.com/feast-dev/feast/pull/1) ([pradithya](https://github.com/pradithya)) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bef64577f91..62e42d4df09 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ # Development Guide: Main Feast Repository > Please see [Development Guide](https://docs.feast.dev/project/development-guide) for project level development instructions. -### Overview +## Overview This guide is targeted at developers looking to contribute to Feast components in the main Feast repository: - [Feast Python SDK / CLI](#feast-python-sdk-%2F-cli) @@ -10,6 +10,20 @@ the main Feast repository: ## Making a pull request +### Pull request checklist +A quick list of things to keep in mind as you're making changes: +- As you make changes + - Make your changes in a [forked repo](#forking-the-repo) (instead of making a branch on the main Feast repo) + - [Sign your commits](#signing-off-commits) as you go (to avoid DCO checks failing) + - [Rebase from master](#incorporating-upstream-changes-from-master) instead of using `git pull` on your PR branch + - Install [pre-commit hooks](#pre-commit-hooks) to ensure all the default linters / formatters are run when you push. +- When you make the PR + - Make a pull request from the forked repo you made + - Ensure you add a GitHub **label** (i.e. a kind tag to the PR (e.g. `kind/bug` or `kind/housekeeping`)) or else checks will fail. + - Ensure you leave a release note for any user facing changes in the PR. There is a field automatically generated in the PR request. You can write `NONE` in that field if there are no user facing changes. + - Please run tests locally before submitting a PR (e.g. for Python, the [local integration tests](#local-integration-tests)) + - Try to keep PRs smaller. This makes them easier to review. + ### Forking the repo Fork the Feast Github repo and clone your fork locally. Then make changes to a local branch to the fork. @@ -26,6 +40,9 @@ pre-commit install --hook-type pre-commit --hook-type pre-push 3. On push, the pre-commit hook will run. This runs `make format` and `make lint`. ### Signing off commits +> :warning: Warning: using the default integrations with IDEs like VSCode or IntelliJ will not sign commits. +> When you submit a PR, you'll have to re-sign commits to pass the DCO check. + Use git signoffs to sign your commits. See https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification for details @@ -96,13 +113,27 @@ make test-python > - Ensure Feast Python SDK / CLI is not configured with configuration overrides (ie `~/.feast/config` should be empty). ### Integration Tests -To get tests running, you'll need to have GCP / AWS / Redis setup: +There are two sets of tests you can run: +1. Local integration tests (for faster development) +2. Full integration tests (requires cloud environment setups) + +#### Local integration tests +To get local integration tests running, you'll need to have Redis setup: Redis 1. Install Redis: [Quickstart](https://redis.io/topics/quickstart) 2. Run `redis-server` -GCP +Now run `make test-python-universal-local` + +#### Full integration tests +To test across clouds, on top of setting up Redis, you also need GCP / AWS / Snowflake setup. + +> Note: you can manually control what tests are run today by inspecting +> [RepoConfiguration](https://github.com/feast-dev/feast/blob/master/sdk/python/tests/integration/feature_repos/repo_configuration.py) +> and commenting out tests that are added to `DEFAULT_FULL_REPO_CONFIGS` + +**GCP** 1. Install the [Cloud SDK](https://cloud.google.com/sdk/docs/install). 2. Then run login to gcloud: ``` @@ -111,18 +142,19 @@ GCP ``` 3. Export `GCLOUD_PROJECT=[your project]` to your .zshrc -AWS +**AWS** 1. TODO(adchia): flesh out setting up AWS login (or create helper script) 2. Modify `RedshiftDataSourceCreator` to use your credentials -Then run `make test-python-integration`. Note that for GCP / AWS, this will create new temporary tables / datasets. +**Snowflake** +- See https://signup.snowflake.com/ + +Then run `make test-python-integration`. Note that for Snowflake / GCP / AWS, this will create new temporary tables / datasets. ## Feast Java Serving See [Java contributing guide](java/CONTRIBUTING.md) ## Feast Go Client -:warning: Feast Go Client will move to its own standalone repository in the future. - ### Environment Setup Setting up your development environment for Feast Go SDK: diff --git a/README.md b/README.md index de972225dd2..9f15c1a1714 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,11 @@ cd my_feature_repo feast apply ``` -### 4. Build a training dataset +### 4. Explore your data in the web UI (experimental) + +![Web UI](ui/sample.png) + +### 5. Build a training dataset ```python from feast import FeatureStore import pandas as pd @@ -86,7 +90,7 @@ print(training_df.head()) ``` -### 5. Load feature values into your online store +### 6. Load feature values into your online store ```commandline CURRENT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%S") feast materialize-incremental $CURRENT_TIME @@ -96,7 +100,7 @@ feast materialize-incremental $CURRENT_TIME Materializing feature view driver_hourly_stats from 2021-04-14 to 2021-04-15 done! ``` -### 6. Read online features at low latency +### 7. Read online features at low latency ```python from pprint import pprint from feast import FeatureStore @@ -153,7 +157,7 @@ The list below contains the functionality that contributors are planning to deve * [x] [Synapse (community plugin)](https://github.com/Azure/feast-azure) * [x] [Hive (community plugin)](https://github.com/baineng/feast-hive) * [x] [Postgres (community plugin)](https://github.com/nossrannug/feast-postgres) - * [x] [Trino (communiuty plugin)](https://github.com/Shopify/feast-trino) + * [x] [Trino (community plugin)](https://github.com/Shopify/feast-trino) * [x] [Spark (community plugin)](https://github.com/Adyen/feast-spark-offline-store) * [x] [In-memory / Pandas](https://docs.feast.dev/reference/offline-stores/file) * [x] [Custom offline store support](https://docs.feast.dev/how-to-guides/adding-a-new-offline-store) @@ -165,7 +169,7 @@ The list below contains the functionality that contributors are planning to deve * [x] [Azure Cache for Redis (community plugin)](https://github.com/Azure/feast-azure) * [x] [Postgres (community plugin)](https://github.com/nossrannug/feast-postgres) * [x] [Custom online store support](https://docs.feast.dev/how-to-guides/adding-support-for-a-new-online-store) - * [ ] Bigtable + * [ ] Bigtable (in progress) * [ ] Cassandra * **Streaming** * [x] [Custom streaming ingestion job support](https://docs.feast.dev/how-to-guides/creating-a-custom-provider) @@ -192,16 +196,16 @@ The list below contains the functionality that contributors are planning to deve * [ ] Feature Logging (for training) * **Data Quality Management (See [RFC](https://docs.google.com/document/d/110F72d4NTv80p35wDSONxhhPBqWRwbZXG4f9mNEMd98/edit))** * [x] Data profiling and validation (Great Expectations) + * [ ] Training-serving skew detection (in progress) * [ ] Metric production - * [ ] Training-serving skew detection * [ ] Drift detection * **Feature Discovery and Governance** * [x] Python SDK for browsing feature registry * [x] CLI for browsing feature registry * [x] Model-centric feature tracking (feature services) * [x] Amundsen integration (see [Feast extractor](https://github.com/amundsen-io/amundsen/blob/main/databuilder/databuilder/extractor/feast_extractor.py)) + * [ ] Feast Web UI (in progress) * [ ] REST API for browsing feature registry - * [ ] Feast Web UI * [ ] Feature versioning diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 439742af9f5..deec3e9eed0 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -46,6 +46,7 @@ * [Load data into the online store](how-to-guides/feast-snowflake-gcp-aws/load-data-into-the-online-store.md) * [Read features from the online store](how-to-guides/feast-snowflake-gcp-aws/read-features-from-the-online-store.md) * [Running Feast in production](how-to-guides/running-feast-in-production.md) +* [Deploying a Java feature server on Kubernetes](how-to-guides/fetching-java-features-k8s.md) * [Upgrading from Feast 0.9](https://docs.google.com/document/u/1/d/1AOsr\_baczuARjCpmZgVd8mCqTF4AZ49OEyU4Cn-uTT0/edit) * [Adding a custom provider](how-to-guides/creating-a-custom-provider.md) * [Adding a new online store](how-to-guides/adding-support-for-a-new-online-store.md) diff --git a/docs/getting-started/third-party-integrations.md b/docs/getting-started/third-party-integrations.md index ba1b360fc05..0bf8733b3f5 100644 --- a/docs/getting-started/third-party-integrations.md +++ b/docs/getting-started/third-party-integrations.md @@ -32,7 +32,7 @@ Don't see your offline store or online store of choice here? Check out our guide * [x] [Synapse (community plugin)](https://github.com/Azure/feast-azure) * [x] [Hive (community plugin)](https://github.com/baineng/feast-hive) * [x] [Postgres (community plugin)](https://github.com/nossrannug/feast-postgres) -* [x] [Trino (communiuty plugin)](https://github.com/Shopify/feast-trino) +* [x] [Trino (community plugin)](https://github.com/Shopify/feast-trino) * [x] [Spark (community plugin)](https://github.com/Adyen/feast-spark-offline-store) * [x] [In-memory / Pandas](https://docs.feast.dev/reference/offline-stores/file) * [x] [Custom offline store support](https://docs.feast.dev/how-to-guides/adding-a-new-offline-store) @@ -46,7 +46,7 @@ Don't see your offline store or online store of choice here? Check out our guide * [x] [Azure Cache for Redis (community plugin)](https://github.com/Azure/feast-azure) * [x] [Postgres (community plugin)](https://github.com/nossrannug/feast-postgres) * [x] [Custom online store support](https://docs.feast.dev/how-to-guides/adding-support-for-a-new-online-store) -* [ ] Bigtable +* [ ] Bigtable (in progress) * [ ] Cassandra ### **Deployments** diff --git a/docs/how-to-guides/adding-or-reusing-tests.md b/docs/how-to-guides/adding-or-reusing-tests.md index 1730abe2096..5a29342d6e1 100644 --- a/docs/how-to-guides/adding-or-reusing-tests.md +++ b/docs/how-to-guides/adding-or-reusing-tests.md @@ -79,7 +79,6 @@ def test_historical_features(environment, universal_data_sources, full_feature_n datasets["global"], datasets["entity"], ) - # ... more test code customer_fv, driver_fv, driver_odfv, order_fv, global_fv = ( @@ -93,7 +92,7 @@ def test_historical_features(environment, universal_data_sources, full_feature_n feature_service = FeatureService( "convrate_plus100", features=[ - feature_views["driver"][["conv_rate"]], + feature_views["driver"][["conv_rate"]], feature_views["driver_odfv"] ], ) @@ -112,7 +111,6 @@ def test_historical_features(environment, universal_data_sources, full_feature_n ] ) store.apply(feast_objects) - # ... more test code job_from_df = store.get_historical_features( @@ -132,13 +130,11 @@ def test_historical_features(environment, universal_data_sources, full_feature_n full_feature_names=full_feature_names, ) actual_df_from_df_entities = job_from_df.to_df() - # ... more test code assert_frame_equal( expected_df, actual_df_from_df_entities, check_dtype=False, ) - # ... more test code ``` {% endtab %} @@ -186,6 +182,24 @@ def your_test(environment: Environment): your_fv = driver_feature_view(data_source) entity = driver(value_type=ValueType.UNKNOWN) fs.apply([fv, entity]) - + # ... run test ``` + +### Running your own redis cluster for testing + +* Install redis on your computer. If you are a mac user, you should be able to `brew install redis`. + * Running `redis-server --help` and `redis-cli --help` should show corresponding help menus. +* Run `cd scripts/create-cluster` and run `./create-cluster start` then `./create-cluster create` to start the server. You should see output that looks like this: +~~~~ +Starting 6001 +Starting 6002 +Starting 6003 +Starting 6004 +Starting 6005 +Starting 6006 +~~~~ +* You should be able to run the integration tests and have the redis cluster tests pass. +* If you would like to run your own redis cluster, you can run the above commands with your own specified ports and connect to the newly configured cluster. +* To stop the cluster, run `./create-cluster stop` and then `./create-cluster clean`. + diff --git a/docs/how-to-guides/fetching-java-features-k8s.md b/docs/how-to-guides/fetching-java-features-k8s.md new file mode 100644 index 00000000000..1aa6abd52b0 --- /dev/null +++ b/docs/how-to-guides/fetching-java-features-k8s.md @@ -0,0 +1,15 @@ +# How to set up a Java feature server + +This tutorial guides you on how to: + +* Define features and data sources in Feast using the Feast CLI +* Materialize features to a Redis cluster deployed on Kubernetes. +* Deploy a Feast Java feature server into a Kubernetes cluster using the Feast helm charts +* Retrieve features using the gRPC API exposed by the Feast Java server + +Try it and let us know what you think! + +| ![](../.gitbook/assets/github-mark-32px.png)[ View guide in Github](../../examples/java-demo/README.md) | +|:--------------------------------------------------------------------------------------------------------| + + diff --git a/docs/reference/data-sources/README.md b/docs/reference/data-sources/README.md index fc6e136a9c2..cba652a91ad 100644 --- a/docs/reference/data-sources/README.md +++ b/docs/reference/data-sources/README.md @@ -9,3 +9,5 @@ Please see [Data Source](../../getting-started/concepts/feature-view.md#data-sou {% page-ref page="bigquery.md" %} {% page-ref page="redshift.md" %} + +{% page-ref page="spark.md" %} diff --git a/docs/reference/data-sources/spark.md b/docs/reference/data-sources/spark.md new file mode 100644 index 00000000000..25b69c7355e --- /dev/null +++ b/docs/reference/data-sources/spark.md @@ -0,0 +1,45 @@ +# Spark + +## Description + +**NOTE**: Spark data source api is currently in alpha development and the API is not completely stable. The API may change or update in the future. + +The spark data source API allows for the retrieval of historical feature values from file/database sources for building training datasets as well as materializing features into an online store. + +* Either a table name, a SQL query, or a file path can be provided. + +## Examples + +Using a table reference from SparkSession(for example, either in memory or a Hive Metastore) + +```python +from feast import SparkSource + +my_spark_source = SparkSource( + table="FEATURE_TABLE", +) +``` + +Using a query + +```python +from feast import SparkSource + +my_spark_source = SparkSource( + query="SELECT timestamp as ts, created, f1, f2 " + "FROM spark_table", +) +``` + +Using a file reference + +```python +from feast import SparkSource + +my_spark_source = SparkSource( + path=f"{CURRENT_DIR}/data/driver_hourly_stats", + file_format="parquet", + event_timestamp_column="event_timestamp", + created_timestamp_column="created", +) +``` diff --git a/docs/reference/offline-stores/README.md b/docs/reference/offline-stores/README.md index 141a34d03b6..b3c85470b9d 100644 --- a/docs/reference/offline-stores/README.md +++ b/docs/reference/offline-stores/README.md @@ -9,3 +9,5 @@ Please see [Offline Store](../../getting-started/architecture-and-components/off {% page-ref page="bigquery.md" %} {% page-ref page="redshift.md" %} + +{% page-ref page="spark.md" %} diff --git a/docs/reference/offline-stores/spark.md b/docs/reference/offline-stores/spark.md new file mode 100644 index 00000000000..48ddf46d179 --- /dev/null +++ b/docs/reference/offline-stores/spark.md @@ -0,0 +1,38 @@ +# Spark + +## Description + +The Spark offline store is an offline store currently in alpha development that provides support for reading [SparkSources](../data-sources/spark.md). + +## Disclaimer + +This Spark offline store still does not achieve full test coverage and continues to fail some integration tests when integrating with the feast universal test suite. Please do NOT assume complete stability of the API. + +* Spark tables and views are allowed as sources that are loaded in from some Spark store(e.g in Hive or in memory). +* Entity dataframes can be provided as a SQL query or can be provided as a Pandas dataframe. Pandas dataframes will be converted to a Spark dataframe and processed as a temporary view. +* A `SparkRetrievalJob` is returned when calling `get_historical_features()`. + * This allows you to call + * `to_df` to retrieve the pandas dataframe. + * `to_arrow` to retrieve the dataframe as a pyarrow Table. + * `to_spark_df` to retrieve the dataframe the spark. + +## Example + +{% code title="feature_store.yaml" %} +```yaml +project: my_project +registry: data/registry.db +provider: local +offline_store: + type: spark + spark_conf: + spark.master: "local[*]" + spark.ui.enabled: "false" + spark.eventLog.enabled: "false" + spark.sql.catalogImplementation: "hive" + spark.sql.parser.quotedRegexColumnNames: "true" + spark.sql.session.timeZone: "UTC" +online_store: + path: data/online_store.db +``` +{% endcode %} diff --git a/docs/roadmap.md b/docs/roadmap.md index 83c43e313e9..daec463dbdf 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -25,7 +25,7 @@ The list below contains the functionality that contributors are planning to deve * [x] [Synapse (community plugin)](https://github.com/Azure/feast-azure) * [x] [Hive (community plugin)](https://github.com/baineng/feast-hive) * [x] [Postgres (community plugin)](https://github.com/nossrannug/feast-postgres) - * [x] [Trino (communiuty plugin)](https://github.com/Shopify/feast-trino) + * [x] [Trino (community plugin)](https://github.com/Shopify/feast-trino) * [x] [Spark (community plugin)](https://github.com/Adyen/feast-spark-offline-store) * [x] [In-memory / Pandas](https://docs.feast.dev/reference/offline-stores/file) * [x] [Custom offline store support](https://docs.feast.dev/how-to-guides/adding-a-new-offline-store) @@ -37,7 +37,7 @@ The list below contains the functionality that contributors are planning to deve * [x] [Azure Cache for Redis (community plugin)](https://github.com/Azure/feast-azure) * [x] [Postgres (community plugin)](https://github.com/nossrannug/feast-postgres) * [x] [Custom online store support](https://docs.feast.dev/how-to-guides/adding-support-for-a-new-online-store) - * [ ] Bigtable + * [ ] Bigtable (in progress) * [ ] Cassandra * **Streaming** * [x] [Custom streaming ingestion job support](https://docs.feast.dev/how-to-guides/creating-a-custom-provider) @@ -64,14 +64,14 @@ The list below contains the functionality that contributors are planning to deve * [ ] Feature Logging (for training) * **Data Quality Management (See [RFC](https://docs.google.com/document/d/110F72d4NTv80p35wDSONxhhPBqWRwbZXG4f9mNEMd98/edit))** * [x] Data profiling and validation (Great Expectations) + * [ ] Training-serving skew detection (in progress) * [ ] Metric production - * [ ] Training-serving skew detection * [ ] Drift detection * **Feature Discovery and Governance** * [x] Python SDK for browsing feature registry * [x] CLI for browsing feature registry * [x] Model-centric feature tracking (feature services) * [x] Amundsen integration (see [Feast extractor](https://github.com/amundsen-io/amundsen/blob/main/databuilder/databuilder/extractor/feast_extractor.py)) + * [ ] Feast Web UI (in progress) * [ ] REST API for browsing feature registry - * [ ] Feast Web UI * [ ] Feature versioning diff --git a/examples/java-demo/README.md b/examples/java-demo/README.md new file mode 100644 index 00000000000..b908bb76254 --- /dev/null +++ b/examples/java-demo/README.md @@ -0,0 +1,162 @@ + +# Running Feast Java Server with Redis & calling with python (with registry in GCP) + +For this tutorial, we setup Feast with Redis, using the Feast CLI to register and materialize features, and then retrieving via a Feast Java server deployed in Kubernetes via a gRPC call. +> :point_right: for tips on how to run and debug this locally without using Kubernetes, see [java/serving/README.md](https://github.com/feast-dev/feast/blob/master/java/serving/README.md) + +## First, let's setup a Redis cluster +1. Start minikube (`minikube start`) +2. Use helm to install a default Redis cluster + ```bash + helm repo add bitnami https://charts.bitnami.com/bitnami + helm repo update + helm install my-redis bitnami/redis + ``` + ![](redis-screenshot.png) +3. Port forward Redis so we can materialize features to it + + ```bash + kubectl port-forward --namespace default svc/my-redis-master 6379:6379 + ``` +4. Get your Redis password using the command (pasted below for convenience). We'll need this to tell Feast how to communicate with the cluster. + + ```bash + export REDIS_PASSWORD=$(kubectl get secret --namespace default my-redis -o jsonpath="{.data.redis-password}" | base64 --decode) + echo $REDIS_PASSWORD + ``` + +## Next, we setup a local Feast repo +1. Install Feast with Redis dependencies `pip install "feast[redis]"` +2. Make a bucket in GCS (or S3) +3. The feature repo is already setup here, so you just need to swap in your GCS bucket and Redis credentials. + We need to modify the `feature_store.yaml`, which has two fields for you to replace: + ```yaml + registry: gs://[YOUR BUCKET]/demo-repo/registry.db + project: feast_java_demo + provider: gcp + online_store: + type: redis + connection_string: localhost:6379,password=[YOUR PASSWORD] + offline_store: + type: file + flags: + alpha_features: true + on_demand_transforms: true + ``` +4. Run `feast apply` to apply your local features to the remote registry +5. Materialize features to the online store: + ```bash + CURRENT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%S") + feast materialize-incremental $CURRENT_TIME + ``` + +## Now let's setup the Feast Server +1. Add the gcp-auth addon to mount GCP credentials: + ```bash + minikube addons enable gcp-auth + ``` +3. Add Feast's Java feature server chart repo + ```bash + helm repo add feast-charts https://feast-helm-charts.storage.googleapis.com + helm repo update + ``` +4. Modify the application-override.yaml file to have your credentials + bucket location: + ```yaml + feature-server: + application-override.yaml: + enabled: true + feast: + activeStore: online + stores: + - name: online + type: REDIS + config: + host: my-redis-master + port: 6379 + password: [YOUR PASSWORD] + global: + registry: + path: gs://[YOUR BUCKET]/demo-repo/registry.db + cache_ttl_seconds: 60 + project: feast_java_demo + ``` +5. Install the Feast helm chart: `helm install feast-release feast-charts/feast --values application-override.yaml` +6. (Optional): check logs of the server to make sure it’s working + ```bash + kubectl logs svc/feast-release-feature-server + ``` +7. Port forward to expose the grpc endpoint: + ```bash + kubectl port-forward svc/feast-release-feature-server 6566:6566 + ``` +8. Make a gRPC call: + - Python example + ```bash + python test.py + ``` + - gRPC cli: + + ```bash + grpc_cli call localhost:6566 GetOnlineFeatures ' + features { + val: "driver_hourly_stats:conv_rate" + val: "driver_hourly_stats:acc_rate" + } + entities { + key: "driver_id" + value { + val { + int64_val: 1001 + } + val { + int64_val: 1002 + } + } + }' + ``` + + - Response: + + ```bash + connecting to localhost:6566 + metadata { + feature_names { + val: "driver_hourly_stats:conv_rate" + val: "driver_hourly_stats:acc_rate" + } + } + results { + values { + float_val: 0.812357187 + } + values { + float_val: 0.379484832 + } + statuses: PRESENT + statuses: PRESENT + event_timestamps { + seconds: 1631725200 + } + event_timestamps { + seconds: 1631725200 + } + } + results { + values { + float_val: 0.840873241 + } + values { + float_val: 0.151376978 + } + statuses: PRESENT + statuses: PRESENT + event_timestamps { + seconds: 1631725200 + } + event_timestamps { + seconds: 1631725200 + } + } + Rpc succeeded with OK status + + ``` \ No newline at end of file diff --git a/examples/java-demo/feature_repo/__init__.py b/examples/java-demo/feature_repo/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/java-demo/feature_repo/application-override.yaml b/examples/java-demo/feature_repo/application-override.yaml new file mode 100644 index 00000000000..dbdeda4c04f --- /dev/null +++ b/examples/java-demo/feature_repo/application-override.yaml @@ -0,0 +1,17 @@ +feature-server: + application-override.yaml: + enabled: true + feast: + activeStore: online + stores: + - name: online + type: REDIS + config: + host: my-redis-master + port: 6379 + password: [YOUR PASSWORD] +global: + registry: + path: gs://[YOUR BUCKET]/demo-repo/registry.db + cache_ttl_seconds: 60 + project: feast_java_demo diff --git a/examples/java-demo/feature_repo/data/driver_stats_with_string.parquet b/examples/java-demo/feature_repo/data/driver_stats_with_string.parquet new file mode 100644 index 00000000000..83b8c31aa51 Binary files /dev/null and b/examples/java-demo/feature_repo/data/driver_stats_with_string.parquet differ diff --git a/examples/java-demo/feature_repo/driver_repo.py b/examples/java-demo/feature_repo/driver_repo.py new file mode 100644 index 00000000000..233593ff02a --- /dev/null +++ b/examples/java-demo/feature_repo/driver_repo.py @@ -0,0 +1,61 @@ +import pandas as pd +from feast import Entity, Feature, FeatureView, FileSource, ValueType +from feast.data_source import RequestDataSource +from feast.on_demand_feature_view import on_demand_feature_view +from feast.request_feature_view import RequestFeatureView +from google.protobuf.duration_pb2 import Duration + +driver_hourly_stats = FileSource( + path="data/driver_stats_with_string.parquet", + event_timestamp_column="event_timestamp", + created_timestamp_column="created", +) +driver = Entity(name="driver_id", value_type=ValueType.INT64, description="driver id",) +driver_hourly_stats_view = FeatureView( + name="driver_hourly_stats", + entities=["driver_id"], + ttl=Duration(seconds=86400000), + features=[ + Feature(name="conv_rate", dtype=ValueType.FLOAT), + Feature(name="acc_rate", dtype=ValueType.FLOAT), + Feature(name="avg_daily_trips", dtype=ValueType.INT64), + Feature(name="string_feature", dtype=ValueType.STRING), + ], + online=True, + batch_source=driver_hourly_stats, + tags={}, +) + +# Define a request data source which encodes features / information only +# available at request time (e.g. part of the user initiated HTTP request) +input_request = RequestDataSource( + name="vals_to_add", + schema={"val_to_add": ValueType.INT64, "val_to_add_2": ValueType.INT64}, +) + +# Define an on demand feature view which can generate new features based on +# existing feature views and RequestDataSource features +@on_demand_feature_view( + inputs={ + "driver_hourly_stats": driver_hourly_stats_view, + "vals_to_add": input_request, + }, + features=[ + Feature(name="conv_rate_plus_val1", dtype=ValueType.DOUBLE), + Feature(name="conv_rate_plus_val2", dtype=ValueType.DOUBLE), + ], +) +def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: + df = pd.DataFrame() + df["conv_rate_plus_val1"] = inputs["conv_rate"] + inputs["val_to_add"] + df["conv_rate_plus_val2"] = inputs["conv_rate"] + inputs["val_to_add_2"] + return df + + +# Define request feature view +driver_age_request_fv = RequestFeatureView( + name="driver_age", + request_data_source=RequestDataSource( + name="driver_age", schema={"driver_age": ValueType.INT64,} + ), +) diff --git a/examples/java-demo/feature_repo/feature_store.yaml b/examples/java-demo/feature_repo/feature_store.yaml new file mode 100644 index 00000000000..91c65b512ad --- /dev/null +++ b/examples/java-demo/feature_repo/feature_store.yaml @@ -0,0 +1,11 @@ +registry: gs://[YOUR BUCKET]/demo-repo/registry.db +project: feast_java_demo +provider: gcp +online_store: + type: redis + connection_string: localhost:6379,password=[YOUR PASSWORD] +offline_store: + type: file +flags: + alpha_features: true + on_demand_transforms: true diff --git a/examples/java-demo/feature_repo/test.py b/examples/java-demo/feature_repo/test.py new file mode 100644 index 00000000000..f73883019d6 --- /dev/null +++ b/examples/java-demo/feature_repo/test.py @@ -0,0 +1,28 @@ +import grpc +from feast.protos.feast.serving.ServingService_pb2 import ( + FeatureList, + GetOnlineFeaturesRequest, +) +from feast.protos.feast.serving.ServingService_pb2_grpc import ServingServiceStub +from feast.protos.feast.types.Value_pb2 import RepeatedValue, Value + + +# Sample logic to fetch from a local gRPC java server deployed at 6566 +def fetch_java(): + channel = grpc.insecure_channel("localhost:6566") + stub = ServingServiceStub(channel) + feature_refs = FeatureList(val=["driver_hourly_stats:conv_rate"]) + entity_rows = { + "driver_id": RepeatedValue( + val=[Value(int64_val=driver_id) for driver_id in range(1001, 1003)] + ) + } + + print( + stub.GetOnlineFeatures( + GetOnlineFeaturesRequest(features=feature_refs, entities=entity_rows,) + ) + ) + +if __name__ == "__main__": + fetch_java() diff --git a/examples/java-demo/redis-screenshot.png b/examples/java-demo/redis-screenshot.png new file mode 100644 index 00000000000..489deb699dd Binary files /dev/null and b/examples/java-demo/redis-screenshot.png differ diff --git a/infra/charts/feast-python-server/Chart.yaml b/infra/charts/feast-python-server/Chart.yaml index d7e9d7a1471..6e3773af725 100644 --- a/infra/charts/feast-python-server/Chart.yaml +++ b/infra/charts/feast-python-server/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: feast-python-server description: Feast Feature Server in Python type: application -version: 0.18.0 +version: 0.19.0 keywords: - machine learning - big data diff --git a/infra/charts/feast-python-server/README.md b/infra/charts/feast-python-server/README.md index 45b5f73b3cb..5182d4c451d 100644 --- a/infra/charts/feast-python-server/README.md +++ b/infra/charts/feast-python-server/README.md @@ -1,6 +1,6 @@ # feast-python-server -![Version: 0.18.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) +![Version: 0.19.0](https://img.shields.io/badge/Version-0.19.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) Feast Feature Server in Python diff --git a/infra/charts/feast/Chart.yaml b/infra/charts/feast/Chart.yaml index c0a3849e59e..ef47acb778a 100644 --- a/infra/charts/feast/Chart.yaml +++ b/infra/charts/feast/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v1 description: Feature store for machine learning name: feast -version: 0.18.0 +version: 0.19.0 keywords: - machine learning - big data diff --git a/infra/charts/feast/README.md b/infra/charts/feast/README.md index 40e67b0857c..7a62bd2a56c 100644 --- a/infra/charts/feast/README.md +++ b/infra/charts/feast/README.md @@ -1,7 +1,5 @@ # Feast Helm Charts -> :warning: **Disclaimer**: Since Feast 0.10 our vision is to manage all infrastructure for feature store from one place - Feast SDK. But while this new paradigm is still in development, we are planning to support the installation of some Feast components (like Java feature server) through Helm chart presented in this repository. However, we do not expect helm chart to become a long-term solution for deploying Feast components to production, and some frictions still might exist. For example, you will need to manually sync some configurations from [feature_store.yaml](https://docs.feast.dev/reference/feature-repository/feature-store-yaml) into the chart context (like path to the registry file or project name). - This repo contains Helm charts for Feast components that are being installed on Kubernetes: * Feast (root chart): The complete Helm chart containing all Feast components and dependencies. Most users will use this chart, but can selectively enable/disable subcharts using the values.yaml file. * [Feature Server](charts/feature-server): High performant JVM-based implementation of feature server. @@ -10,7 +8,7 @@ This repo contains Helm charts for Feast components that are being installed on ## Chart: Feast -Feature store for machine learning Current chart version is `0.18.0` +Feature store for machine learning Current chart version is `0.19.0` ## Installation @@ -56,9 +54,9 @@ For more details, please see: https://docs.feast.dev/how-to-guides/running-feast | Repository | Name | Version | |------------|------|---------| -| https://charts.helm.sh/stable | redis | 10.5.6 | -| https://feast-helm-charts.storage.googleapis.com | feature-server(feature-server) | 0.18.0 | -| https://feast-helm-charts.storage.googleapis.com | transformation-service(transformation-service) | 0.18.0 | +| https://charts.helm.sh/stable | redis | 10.5.6 | +| https://feast-helm-charts.storage.googleapis.com | feature-server(feature-server) | 0.19.0 | +| https://feast-helm-charts.storage.googleapis.com | transformation-service(transformation-service) | 0.19.0 | ## Values diff --git a/infra/charts/feast/charts/feature-server/Chart.yaml b/infra/charts/feast/charts/feature-server/Chart.yaml index 006acfc4b45..7e58368ab01 100644 --- a/infra/charts/feast/charts/feature-server/Chart.yaml +++ b/infra/charts/feast/charts/feature-server/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v1 description: "Feast Feature Server: Online feature serving service for Feast" name: feature-server -version: 0.18.0 -appVersion: v0.18.0 +version: 0.19.0 +appVersion: v0.19.0 keywords: - machine learning - big data diff --git a/infra/charts/feast/charts/feature-server/README.md b/infra/charts/feast/charts/feature-server/README.md index 23ed4102b85..74596103572 100644 --- a/infra/charts/feast/charts/feature-server/README.md +++ b/infra/charts/feast/charts/feature-server/README.md @@ -1,6 +1,6 @@ # feature-server -![Version: 0.18.0](https://img.shields.io/badge/Version-0.18.0-informational?style=flat-square) ![AppVersion: v0.18.0](https://img.shields.io/badge/AppVersion-v0.18.0-informational?style=flat-square) +![Version: 0.19.0](https://img.shields.io/badge/Version-0.19.0-informational?style=flat-square) ![AppVersion: v0.19.0](https://img.shields.io/badge/AppVersion-v0.19.0-informational?style=flat-square) Feast Feature Server: Online feature serving service for Feast @@ -8,62 +8,63 @@ Feast Feature Server: Online feature serving service for Feast ## Values -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| "application-generated.yaml".enabled | bool | `true` | Flag to include Helm generated configuration. Please set `application-override.yaml` to override this configuration. | -| "application-override.yaml" | object | `{"enabled":true}` | Configuration to override the default [application.yaml](https://github.com/feast-dev/feast/blob/master/java/serving/src/main/resources/application.yml). Will be created as a ConfigMap. `application-override.yaml` has a higher precedence than `application-secret.yaml` | -| "application-secret.yaml" | object | `{"enabled":true}` | Configuration to override the default [application.yaml](https://github.com/feast-dev/feast/blob/master/java/serving/src/main/resources/application.yml). Will be created as a Secret. `application-override.yaml` has a higher precedence than `application-secret.yaml`. It is recommended to either set `application-override.yaml` or `application-secret.yaml` only to simplify config management. | -| "application.yaml".enabled | bool | `true` | Flag to include the default [configuration](https://github.com/feast-dev/feast/blob/master/java/serving/src/main/resources/application.yml). Please set `application-override.yaml` to override this configuration. | -| envOverrides | object | `{}` | Extra environment variables to set | -| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | -| image.repository | string | `"feastdev/feature-server-java"` | Docker image for Feature Server repository | -| image.tag | string | `"0.18.0"` | Image tag | -| ingress.grpc.annotations | object | `{}` | Extra annotations for the ingress | -| ingress.grpc.auth.enabled | bool | `false` | Flag to enable auth | -| ingress.grpc.class | string | `"nginx"` | Which ingress controller to use | -| ingress.grpc.enabled | bool | `false` | Flag to create an ingress resource for the service | -| ingress.grpc.hosts | list | `[]` | List of hostnames to match when routing requests | -| ingress.grpc.https.enabled | bool | `true` | Flag to enable HTTPS | -| ingress.grpc.https.secretNames | object | `{}` | Map of hostname to TLS secret name | -| ingress.grpc.whitelist | string | `""` | Allowed client IP source ranges | -| ingress.http.annotations | object | `{}` | Extra annotations for the ingress | +| Key | Type | Default | Description | +|-----|------|-------------------------------------------------------|-------------| +| "application-generated.yaml".enabled | bool | `true` | Flag to include Helm generated configuration. Please set `application-override.yaml` to override this configuration. | +| "application-override.yaml" | object | `{"enabled":true}` | Configuration to override the default [application.yaml](https://github.com/feast-dev/feast/blob/master/java/serving/src/main/resources/application.yml). Will be created as a ConfigMap. `application-override.yaml` has a higher precedence than `application-secret.yaml` | +| "application-secret.yaml" | object | `{"enabled":true}` | Configuration to override the default [application.yaml](https://github.com/feast-dev/feast/blob/master/java/serving/src/main/resources/application.yml). Will be created as a Secret. `application-override.yaml` has a higher precedence than `application-secret.yaml`. It is recommended to either set `application-override.yaml` or `application-secret.yaml` only to simplify config management. | +| "application.yaml".enabled | bool | `true` | Flag to include the default [configuration](https://github.com/feast-dev/feast/blob/master/java/serving/src/main/resources/application.yml). Please set `application-override.yaml` to override this configuration. | +| envOverrides | object | `{}` | Extra environment variables to set | +| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | +| image.repository | string | `"feastdev/feature-server-java"` | Docker image for Feature Server repository | +| image.tag | string | `"0.19.0"` | Image tag | +| ingress.grpc.annotations | object | `{}` | Extra annotations for the ingress | +| ingress.grpc.auth.enabled | bool | `false` | Flag to enable auth | +| ingress.grpc.class | string | `"nginx"` | Which ingress controller to use | +| ingress.grpc.enabled | bool | `false` | Flag to create an ingress resource for the service | +| ingress.grpc.hosts | list | `[]` | List of hostnames to match when routing requests | +| ingress.grpc.https.enabled | bool | `true` | Flag to enable HTTPS | +| ingress.grpc.https.secretNames | object | `{}` | Map of hostname to TLS secret name | +| ingress.grpc.whitelist | string | `""` | Allowed client IP source ranges | +| ingress.http.annotations | object | `{}` | Extra annotations for the ingress | | ingress.http.auth.authUrl | string | `"http://auth-server.auth-ns.svc.cluster.local/auth"` | URL to an existing authentication service | -| ingress.http.auth.enabled | bool | `false` | Flag to enable auth | -| ingress.http.class | string | `"nginx"` | Which ingress controller to use | -| ingress.http.enabled | bool | `false` | Flag to create an ingress resource for the service | -| ingress.http.hosts | list | `[]` | List of hostnames to match when routing requests | -| ingress.http.https.enabled | bool | `true` | Flag to enable HTTPS | -| ingress.http.https.secretNames | object | `{}` | Map of hostname to TLS secret name | -| ingress.http.whitelist | string | `""` | Allowed client IP source ranges | -| javaOpts | string | `nil` | [JVM options](https://docs.oracle.com/cd/E22289_01/html/821-1274/configuring-the-default-jvm-and-java-arguments.html). For better performance, it is advised to set the min and max heap:
`-Xms2048m -Xmx2048m` | -| livenessProbe.enabled | bool | `true` | Flag to enabled the probe | -| livenessProbe.failureThreshold | int | `5` | Min consecutive failures for the probe to be considered failed | -| livenessProbe.initialDelaySeconds | int | `60` | Delay before the probe is initiated | -| livenessProbe.periodSeconds | int | `10` | How often to perform the probe | -| livenessProbe.successThreshold | int | `1` | Min consecutive success for the probe to be considered successful | -| livenessProbe.timeoutSeconds | int | `5` | When the probe times out | -| logLevel | string | `"WARN"` | Default log level, use either one of `DEBUG`, `INFO`, `WARN` or `ERROR` | -| logType | string | `"Console"` | Log format, either `JSON` or `Console` | -| nodeSelector | object | `{}` | Node labels for pod assignment | -| podLabels | object | `{}` | Labels to be added to Feast Serving pods | -| readinessProbe.enabled | bool | `true` | Flag to enabled the probe | -| readinessProbe.failureThreshold | int | `5` | Min consecutive failures for the probe to be considered failed | -| readinessProbe.initialDelaySeconds | int | `15` | Delay before the probe is initiated | -| readinessProbe.periodSeconds | int | `10` | How often to perform the probe | -| readinessProbe.successThreshold | int | `1` | Min consecutive success for the probe to be considered successful | -| readinessProbe.timeoutSeconds | int | `10` | When the probe times out | -| replicaCount | int | `1` | Number of pods that will be created | -| resources | object | `{}` | CPU/memory [resource requests/limit](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container) | -| secrets | list | `[]` | List of Kubernetes secrets to be mounted. These secrets will be mounted on /etc/secrets/. | -| service.grpc.nodePort | string | `nil` | Port number that each cluster node will listen to | -| service.grpc.port | int | `6566` | Service port for GRPC requests | -| service.grpc.targetPort | int | `6566` | Container port serving GRPC requests | -| service.http.nodePort | string | `nil` | Port number that each cluster node will listen to | -| service.http.port | int | `80` | Service port for HTTP requests | -| service.http.targetPort | int | `8080` | Container port serving HTTP requests and Prometheus metrics | -| service.type | string | `"ClusterIP"` | Kubernetes service type | -| transformationService.host | string | `""` | | -| transformationService.port | int | `6566` | | +| ingress.http.auth.enabled | bool | `false` | Flag to enable auth | +| ingress.http.class | string | `"nginx"` | Which ingress controller to use | +| ingress.http.enabled | bool | `false` | Flag to create an ingress resource for the service | +| ingress.http.hosts | list | `[]` | List of hostnames to match when routing requests | +| ingress.http.https.enabled | bool | `true` | Flag to enable HTTPS | +| ingress.http.https.secretNames | object | `{}` | Map of hostname to TLS secret name | +| ingress.http.whitelist | string | `""` | Allowed client IP source ranges | +| javaOpts | string | `nil` | [JVM options](https://docs.oracle.com/cd/E22289_01/html/821-1274/configuring-the-default-jvm-and-java-arguments.html). For better performance, it is advised to set the min and max heap:
`-Xms2048m -Xmx2048m` | +| livenessProbe.enabled | bool | `true` | Flag to enabled the probe | +| livenessProbe.failureThreshold | int | `5` | Min consecutive failures for the probe to be considered failed | +| livenessProbe.initialDelaySeconds | int | `60` | Delay before the probe is initiated | +| livenessProbe.periodSeconds | int | `10` | How often to perform the probe | +| livenessProbe.successThreshold | int | `1` | Min consecutive success for the probe to be considered successful | +| livenessProbe.timeoutSeconds | int | `5` | When the probe times out | +| logLevel | string | `"WARN"` | Default log level, use either one of `DEBUG`, `INFO`, `WARN` or `ERROR` | +| logType | string | `"Console"` | Log format, either `JSON` or `Console` | +| nodeSelector | object | `{}` | Node labels for pod assignment | +| podAnnotations | object | `{}` | Annotations to be added to Feast Serving pods | +| podLabels | object | `{}` | Labels to be added to Feast Serving pods | +| readinessProbe.enabled | bool | `true` | Flag to enabled the probe | +| readinessProbe.failureThreshold | int | `5` | Min consecutive failures for the probe to be considered failed | +| readinessProbe.initialDelaySeconds | int | `15` | Delay before the probe is initiated | +| readinessProbe.periodSeconds | int | `10` | How often to perform the probe | +| readinessProbe.successThreshold | int | `1` | Min consecutive success for the probe to be considered successful | +| readinessProbe.timeoutSeconds | int | `10` | When the probe times out | +| replicaCount | int | `1` | Number of pods that will be created | +| resources | object | `{}` | CPU/memory [resource requests/limit](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container) | +| secrets | list | `[]` | List of Kubernetes secrets to be mounted. These secrets will be mounted on /etc/secrets/. | +| service.grpc.nodePort | string | `nil` | Port number that each cluster node will listen to | +| service.grpc.port | int | `6566` | Service port for GRPC requests | +| service.grpc.targetPort | int | `6566` | Container port serving GRPC requests | +| service.http.nodePort | string | `nil` | Port number that each cluster node will listen to | +| service.http.port | int | `80` | Service port for HTTP requests | +| service.http.targetPort | int | `8080` | Container port serving HTTP requests and Prometheus metrics | +| service.type | string | `"ClusterIP"` | Kubernetes service type | +| transformationService.host | string | `""` | | +| transformationService.port | int | `6566` | | ---------------------------------------------- Autogenerated from chart metadata using [helm-docs v1.5.0](https://github.com/norwoodj/helm-docs/releases/v1.5.0) diff --git a/infra/charts/feast/charts/feature-server/templates/configmap.yaml b/infra/charts/feast/charts/feature-server/templates/configmap.yaml index c4bdd5a6646..fbf2633e8ed 100644 --- a/infra/charts/feast/charts/feature-server/templates/configmap.yaml +++ b/infra/charts/feast/charts/feature-server/templates/configmap.yaml @@ -14,26 +14,40 @@ data: {{- if index .Values "application-generated.yaml" "enabled" }} feast: registry: {{ .Values.global.registry.path }} - registry-refresh-interval: {{ .Values.global.registry.cache_ttl_seconds }} + registryRefreshInterval: {{ .Values.global.registry.cache_ttl_seconds }} {{- if .Values.transformationService.host }} - transformation-service-endpoint: {{ .Values.transformationService.host}}:{{ .Values.transformationService.port }} + transformationServiceEndpoint: {{ .Values.transformationService.host}}:{{ .Values.transformationService.port }} {{- else }} - transformation-service-endpoint: {{ .Release.Name }}-transformation-service:{{ .Values.transformationService.port }} + transformationServiceEndpoint: {{ .Release.Name }}-transformation-service:{{ .Values.transformationService.port }} {{- end }} - active_store: online + activeStore: online stores: - name: online type: REDIS config: host: {{ .Release.Name }}-redis-master port: 6379 - - server: - port: {{ .Values.service.http.targetPort }} + rest: + server: + port: {{ .Values.service.http.targetPort }} + grpc: + server: + port: {{ .Values.service.grpc.targetPort }} {{- end }} application-override.yaml: | {{- if index .Values "application-override.yaml" "enabled" }} -{{- toYaml (index .Values "application-override.yaml") | nindent 4 }} + {{- if index .Values "application-override.yaml" "feast" }} + feast: {{- toYaml (index .Values "application-override.yaml" "feast") | nindent 6 }} + registry: {{ .Values.global.registry.path }} + registryRefreshInterval: {{ .Values.global.registry.cache_ttl_seconds }} + project: {{ .Values.global.project }} + {{- end }} + {{- if index .Values "application-override.yaml" "rest" }} + rest: {{- toYaml (index .Values "application-override.yaml" "rest") | nindent 6 }} + {{- end }} + {{- if index .Values "application-override.yaml" "grpc" }} + grpc: {{- toYaml (index .Values "application-override.yaml" "grpc") | nindent 6 }} + {{- end }} {{- end }} diff --git a/infra/charts/feast/charts/feature-server/templates/deployment.yaml b/infra/charts/feast/charts/feature-server/templates/deployment.yaml index 02323cbffc6..1d1bc400292 100644 --- a/infra/charts/feast/charts/feature-server/templates/deployment.yaml +++ b/infra/charts/feast/charts/feature-server/templates/deployment.yaml @@ -21,6 +21,9 @@ spec: annotations: checksum/configmap: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- if .Values.podAnnotations }} + {{ toYaml .Values.podAnnotations | nindent 8 }} + {{- end }} labels: app: {{ template "feature-server.name" . }} component: serving diff --git a/infra/charts/feast/charts/feature-server/templates/secret.yaml b/infra/charts/feast/charts/feature-server/templates/secret.yaml index d821f8e6f18..b6aa88c258e 100644 --- a/infra/charts/feast/charts/feature-server/templates/secret.yaml +++ b/infra/charts/feast/charts/feature-server/templates/secret.yaml @@ -12,4 +12,12 @@ metadata: type: Opaque stringData: application-secret.yaml: | -{{- toYaml (index .Values "application-secret.yaml") | nindent 4 }} + {{- if index .Values "application-secret.yaml" "feast" }} + feast: {{- toYaml (index .Values "application-secret.yaml" "feast") | nindent 6 }} + {{- end }} + {{- if index .Values "application-secret.yaml" "rest" }} + rest: {{- toYaml (index .Values "application-secret.yaml" "rest") | nindent 6 }} + {{- end }} + {{- if index .Values "application-secret.yaml" "grpc" }} + grpc: {{- toYaml (index .Values "application-secret.yaml" "grpc") | nindent 6 }} + {{- end }} diff --git a/infra/charts/feast/charts/feature-server/values.yaml b/infra/charts/feast/charts/feature-server/values.yaml index a6cf0f41b7c..99a9bf460d9 100644 --- a/infra/charts/feast/charts/feature-server/values.yaml +++ b/infra/charts/feast/charts/feature-server/values.yaml @@ -5,7 +5,7 @@ image: # image.repository -- Docker image for Feature Server repository repository: feastdev/feature-server-java # image.tag -- Image tag - tag: 0.18.0 + tag: 0.19.0 # image.pullPolicy -- Image pull policy pullPolicy: IfNotPresent @@ -25,7 +25,7 @@ application-generated.yaml: # "application-secret.yaml" -- Configuration to override the default [application.yaml](https://github.com/feast-dev/feast/blob/master/java/serving/src/main/resources/application.yml). Will be created as a Secret. `application-override.yaml` has a higher precedence than `application-secret.yaml`. It is recommended to either set `application-override.yaml` or `application-secret.yaml` only to simplify config management. application-secret.yaml: - enabled: true + enabled: false # "application-override.yaml" -- Configuration to override the default [application.yaml](https://github.com/feast-dev/feast/blob/master/java/serving/src/main/resources/application.yml). Will be created as a ConfigMap. `application-override.yaml` has a higher precedence than `application-secret.yaml` application-override.yaml: @@ -140,5 +140,8 @@ envOverrides: {} # secrets -- List of Kubernetes secrets to be mounted. These secrets will be mounted on /etc/secrets/. secrets: [] +# podAnnotations -- Annotations to be added to Feast Serving pods +podAnnotations: {} + # podLabels -- Labels to be added to Feast Serving pods podLabels: {} diff --git a/infra/charts/feast/charts/transformation-service/Chart.yaml b/infra/charts/feast/charts/transformation-service/Chart.yaml index ea4f9ccfe5f..0e1d26e6678 100644 --- a/infra/charts/feast/charts/transformation-service/Chart.yaml +++ b/infra/charts/feast/charts/transformation-service/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v1 description: "Transformation service: to compute on-demand features" name: transformation-service -version: 0.18.0 -appVersion: v0.18.0 +version: 0.19.0 +appVersion: v0.19.0 keywords: - machine learning - big data diff --git a/infra/charts/feast/charts/transformation-service/README.md b/infra/charts/feast/charts/transformation-service/README.md index f101f911b45..7747fabc610 100644 --- a/infra/charts/feast/charts/transformation-service/README.md +++ b/infra/charts/feast/charts/transformation-service/README.md @@ -1,6 +1,6 @@ # transformation-service -![Version: 0.18.0](https://img.shields.io/badge/Version-0.18.0-informational?style=flat-square) ![AppVersion: v0.18.0](https://img.shields.io/badge/AppVersion-v0.18.0-informational?style=flat-square) +![Version: 0.19.0](https://img.shields.io/badge/Version-0.19.0-informational?style=flat-square) ![AppVersion: v0.19.0](https://img.shields.io/badge/AppVersion-v0.19.0-informational?style=flat-square) Transformation service: to compute on-demand features @@ -8,20 +8,20 @@ Transformation service: to compute on-demand features ## Values -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| envOverrides | object | `{}` | Extra environment variables to set | -| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | +| Key | Type | Default | Description | +|-----|------|--------------------------------------------|-------------| +| envOverrides | object | `{}` | Extra environment variables to set | +| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | | image.repository | string | `"feastdev/feature-transformation-server"` | Docker image for Transformation Server repository | -| image.tag | string | `"0.18.0"` | Image tag | -| nodeSelector | object | `{}` | Node labels for pod assignment | -| podLabels | object | `{}` | Labels to be added to Feast Serving pods | -| replicaCount | int | `1` | Number of pods that will be created | -| resources | object | `{}` | CPU/memory [resource requests/limit](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container) | -| service.grpc.nodePort | string | `nil` | Port number that each cluster node will listen to | -| service.grpc.port | int | `6566` | Service port for GRPC requests | -| service.grpc.targetPort | int | `6566` | Container port serving GRPC requests | -| service.type | string | `"ClusterIP"` | Kubernetes service type | +| image.tag | string | `"0.19.0"` | Image tag | +| nodeSelector | object | `{}` | Node labels for pod assignment | +| podLabels | object | `{}` | Labels to be added to Feast Serving pods | +| replicaCount | int | `1` | Number of pods that will be created | +| resources | object | `{}` | CPU/memory [resource requests/limit](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container) | +| service.grpc.nodePort | string | `nil` | Port number that each cluster node will listen to | +| service.grpc.port | int | `6566` | Service port for GRPC requests | +| service.grpc.targetPort | int | `6566` | Container port serving GRPC requests | +| service.type | string | `"ClusterIP"` | Kubernetes service type | ---------------------------------------------- Autogenerated from chart metadata using [helm-docs v1.5.0](https://github.com/norwoodj/helm-docs/releases/v1.5.0) diff --git a/infra/charts/feast/charts/transformation-service/values.yaml b/infra/charts/feast/charts/transformation-service/values.yaml index e758a535963..f76fa979799 100644 --- a/infra/charts/feast/charts/transformation-service/values.yaml +++ b/infra/charts/feast/charts/transformation-service/values.yaml @@ -5,7 +5,7 @@ image: # image.repository -- Docker image for Transformation Server repository repository: feastdev/feature-transformation-server # image.tag -- Image tag - tag: 0.18.0 + tag: 0.19.0 # image.pullPolicy -- Image pull policy pullPolicy: IfNotPresent diff --git a/infra/charts/feast/requirements.yaml b/infra/charts/feast/requirements.yaml index 60eaf7f67de..2839b039ca4 100644 --- a/infra/charts/feast/requirements.yaml +++ b/infra/charts/feast/requirements.yaml @@ -1,12 +1,12 @@ dependencies: - name: feature-server alias: feature-server - version: 0.18.0 + version: 0.19.0 condition: feature-server.enabled repository: https://feast-helm-charts.storage.googleapis.com - name: transformation-service alias: transformation-service - version: 0.18.0 + version: 0.19.0 condition: transformation-service.enabled repository: https://feast-helm-charts.storage.googleapis.com - name: redis diff --git a/infra/scripts/create-cluster.sh b/infra/scripts/create-cluster.sh new file mode 100755 index 00000000000..24b961b9770 --- /dev/null +++ b/infra/scripts/create-cluster.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +# Settings +# Make sure you run "brew install redis" + +# BIN_PATH="/opt/homebrew/bin" +REDIS_CLI=`which redis-cli` +REDIS_SERVER=`which redis-server` +CLUSTER_HOST=127.0.0.1 +# Creates a cluster at ports 6001-6006 with 3 masters 6001-6003 and 3 slaves 6004-6006 +PORT=${2:-6000} +TIMEOUT=2000 +NODES=6 +REPLICAS=1 +PROTECTED_MODE=yes +ADDITIONAL_OPTIONS="" + +if [ -a config.sh ] +then + source "config.sh" +fi + +# Computed vars +ENDPORT=$((PORT+NODES)) + +if [ "$1" == "start" ] +then + while [ $((PORT < ENDPORT)) != "0" ]; do + PORT=$((PORT+1)) + echo "Starting $PORT" + $REDIS_SERVER --port $PORT --protected-mode $PROTECTED_MODE --cluster-enabled yes --cluster-config-file nodes-${PORT}.conf --cluster-node-timeout $TIMEOUT --appendonly yes --appendfilename appendonly-${PORT}.aof --dbfilename dump-${PORT}.rdb --logfile ${PORT}.log --daemonize yes ${ADDITIONAL_OPTIONS} + done + exit 0 +fi + +if [ "$1" == "create" ] +then + HOSTS="" + while [ $((PORT < ENDPORT)) != "0" ]; do + PORT=$((PORT+1)) + HOSTS="$HOSTS $CLUSTER_HOST:$PORT" + done + OPT_ARG="" + if [ "$2" == "-f" ]; then + OPT_ARG="--cluster-yes" + fi + $REDIS_CLI --cluster create $HOSTS --cluster-replicas $REPLICAS $OPT_ARG + exit 0 +fi + +if [ "$1" == "stop" ] +then + while [ $((PORT < ENDPORT)) != "0" ]; do + PORT=$((PORT+1)) + echo "Stopping $PORT" + $REDIS_CLI -p $PORT shutdown nosave + done + exit 0 +fi + +if [ "$1" == "watch" ] +then + PORT=$((PORT+1)) + while [ 1 ]; do + clear + date + $REDIS_CLI -p $PORT cluster nodes | head -30 + sleep 1 + done + exit 0 +fi + +if [ "$1" == "clean" ] +then + echo "Cleaning *.log" + rm -rf *.log + echo "Cleaning appendonly-*" + rm -rf appendonly-* + echo "Cleaning dump-*.rdb" + rm -rf dump-*.rdb + echo "Cleaning nodes-*.conf" + rm -rf nodes-*.conf + exit 0 +fi + +if [ "$1" == "clean-logs" ] +then + echo "Cleaning *.log" + rm -rf *.log + exit 0 +fi + +echo "Usage: $0 [start|create|stop|watch|clean|clean-logs|call]" +echo "start [PORT] -- Launch Redis Cluster instances." +echo "create [PORT] [-f] -- Create a cluster using redis-cli --cluster create." +echo "stop [PORT] -- Stop Redis Cluster instances." +echo "watch [PORT] -- Show CLUSTER NODES output (first 30 lines) of first node." +echo "clean -- Remove all instances data, logs, configs." +echo "clean-logs -- Remove just instances logs." diff --git a/infra/scripts/helm/install-helm.sh b/infra/scripts/helm/install-helm.sh index 3686f9dfdb1..a5073289dfe 100755 --- a/infra/scripts/helm/install-helm.sh +++ b/infra/scripts/helm/install-helm.sh @@ -6,5 +6,4 @@ readonly STABLE_REPO_URL=https://charts.helm.sh/stable readonly INCUBATOR_REPO_URL=https://charts.helm.sh/incubator curl -s "https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz" | tar -C /tmp -xz sudo mv /tmp/linux-amd64/helm /usr/bin/helm -helm init --client-only -helm repo add incubator "$INCUBATOR_REPO_URL" \ No newline at end of file +helm repo add incubator "$INCUBATOR_REPO_URL" diff --git a/infra/scripts/helm/push-helm-charts.sh b/infra/scripts/helm/push-helm-charts.sh index f9750ccecc4..08753adb3c9 100755 --- a/infra/scripts/helm/push-helm-charts.sh +++ b/infra/scripts/helm/push-helm-charts.sh @@ -19,4 +19,5 @@ helm package feast helm package feast-python-server helm gcs push --public feast-${1}.tgz feast-helm-chart-repo --force -helm gcs push --public feast-python-server-${1}.tgz feast-helm-chart-repo --force \ No newline at end of file +helm gcs push --public feast-python-server-${1}.tgz feast-helm-chart-repo --force +rm -f ./*.tgz \ No newline at end of file diff --git a/infra/scripts/helm/validate-helm-chart-versions.sh b/infra/scripts/helm/validate-helm-chart-versions.sh index 8a6b464cbb2..0ba75bd7440 100755 --- a/infra/scripts/helm/validate-helm-chart-versions.sh +++ b/infra/scripts/helm/validate-helm-chart-versions.sh @@ -21,7 +21,7 @@ echo "Found ${CHANGED_VERSIONS_COUNT} versions that have been changed" echo "This repository should contain ${UNIQUE_VERSIONS_COUNT} changed versions" if [ $UNIQUE_VERSIONS_COUNT -ne "${CHANGED_VERSIONS_COUNT}" ]; then - echo "We expected $UNIQUE_VERSIONS_COUNT to have been updated to the latest version, but online ${CHANGED_VERSIONS_COUNT} have. This number is statically defined based on a simple grep" + echo "We expected $UNIQUE_VERSIONS_COUNT to have been updated to the latest version, but only ${CHANGED_VERSIONS_COUNT} have. This number is statically defined based on a simple grep" echo "Please confirm that all versions in all charts and requirements files have been bumped to the tagged release version. If you have successfully bumped all versions and there is still a mismatch in the expected and actual counts, then rerun the following command" echo "grep -R 'insert_your_semver_version_here' . | wc -l" echo "and update the script scripts/validate-helm-chart-versions.sh" diff --git a/infra/scripts/publish-java-sdk.sh b/infra/scripts/publish-java-sdk.sh index ce1f79d2f1d..68174db17a3 100755 --- a/infra/scripts/publish-java-sdk.sh +++ b/infra/scripts/publish-java-sdk.sh @@ -69,4 +69,4 @@ gpg --import --batch --yes $GPG_KEY_IMPORT_DIR/private-key echo "============================================================" echo "Deploying Java SDK with revision: $REVISION" echo "============================================================" -mvn -f java/pom.xml --projects .,datatypes/java,sdk/java -Drevision=$REVISION --batch-mode clean deploy +mvn -f java/pom.xml --projects .,datatypes,sdk -Drevision=$REVISION --batch-mode clean deploy diff --git a/infra/scripts/validate-release.sh b/infra/scripts/validate-release.sh new file mode 100755 index 00000000000..3ccc4f4f15d --- /dev/null +++ b/infra/scripts/validate-release.sh @@ -0,0 +1,30 @@ +# This script ensures that we don't accidentally cut the wrong kind of release on master or release branches + +if [ "$#" -ne 2 ] +then + echo "Usage: validate-release.sh [major, minor, patch] branch" + echo "Example: validate-release.sh patch master" + exit 1 +fi + +if [ "$1" = "minor" ]; then + if [ "$2" = "master" ]; then + echo "Releasing a minor version on master, looks good!" + exit 0 + else + echo "Can't release a minor version from a non-master branch! Please confirm the version you are releasing!!" + exit 1 + fi +elif [ "$1" = "patch" ]; then + if [ "$2" = "master" ]; then + echo "Can't release a patch version from master branch! Please confirm the version you are releasing!!" + exit 1 + else + echo "Releasing a patch version from a non-master branch, looks good!" + exit 0 + fi +else + echo "Not sure what kind of release is happening. Please confirm that you are creating a minor release from master + or a patch from a release branch" + exit 1 +fi \ No newline at end of file diff --git a/infra/scripts/version_bump/bump_file_versions.py b/infra/scripts/version_bump/bump_file_versions.py new file mode 100644 index 00000000000..b87c3392fbe --- /dev/null +++ b/infra/scripts/version_bump/bump_file_versions.py @@ -0,0 +1,100 @@ +# This script will bump the versions found in files (charts, pom.xml) during the Feast release process. + +import pathlib +import sys + +USAGE = f"Usage: python {sys.argv[0]} [--help] | current_semver_version new_semver_version]" +VERSIONS_TO_BUMP = 26 + + +def main() -> None: + args = sys.argv[1:] + if not args or len(args) != 2: + raise SystemExit(USAGE) + + current_version = args[0].strip() + new_version = args[1].strip() + + if current_version == new_version: + raise SystemExit(f"Current and new versions are the same: {current_version} == {new_version}") + + # Validate that the input arguments are semver versions + if not is_semantic_version(current_version): + raise SystemExit(f"Current version is not a valid semantic version: {current_version}") + + if not is_semantic_version(new_version): + raise SystemExit(f"New version is not a valid semantic version: {new_version}") + + # Get git repo root directory + repo_root = pathlib.Path(__file__).resolve().parent.parent.parent.parent + path_to_file_list = repo_root.joinpath("infra", "scripts", "version_bump", "files_to_bump.txt") + + # Get files to bump versions within + with open(path_to_file_list, "r") as f: + files_to_bump = f.read().splitlines() + + # The current version should be 0.18.0 or 0.19.0 or 0.20.0 etc, but we should also make sure to support the + # occasional patch release on the master branch like 0.18.1 or 0.18.2 + versions_in_files = 0 + if current_version[-2:] != ".0": + print(current_version[-2:]) + versions_in_files = count_version(current_version, files_to_bump, repo_root) + if versions_in_files != VERSIONS_TO_BUMP: + raise SystemExit(f"Found {versions_in_files} occurrences of {current_version} in files to bump, but " + f"expected {VERSIONS_TO_BUMP}") + else: + found = False + + # Lets make sure the files don't contain a patch version (e.g, 0.x.0 -> 0.x.20) + for patch_version in range(0, 20): + current_version_patch = current_version[:-1] + str(patch_version) + versions_in_files = count_version(current_version_patch, files_to_bump, repo_root) + + # We are using a patch version, let's change our version number + if versions_in_files == VERSIONS_TO_BUMP: + print(f"Found {versions_in_files} occurrences of {current_version_patch}, changing current version to " + f"{current_version_patch}") + current_version = current_version_patch + found = True + break + if not found: + raise SystemExit(f"Could not find {VERSIONS_TO_BUMP} versions of {current_version} in {path_to_file_list}") + + print(f"Found {versions_in_files} occurrences of {current_version} in files to bump {path_to_file_list}") + + # Bump the version in the files + updated_count = 0 + for file in files_to_bump: + with open(repo_root.joinpath(file), "r") as f: + file_contents = f.read() + file_contents = file_contents.replace(current_version, new_version) + + with open(repo_root.joinpath(file), "w") as f: + f.write(file_contents) + updated_count += 1 + + print(f"Updated {updated_count} files with new version {new_version}") + + +def is_semantic_version(version: str) -> bool: + components = version.split(".") + if len(components) != 3: + return False + for component in components: + if not component.isdigit(): + return False + return True + + +def count_version(current_version, files_to_bump, repo_root): + # Count how many of the existing versions we find + total = 0 + for file in files_to_bump: + with open(repo_root.joinpath(file), "r") as f: + file_contents = f.read() + total += file_contents.count(current_version) + return total + + +if __name__ == "__main__": + main() diff --git a/infra/scripts/version_bump/files_to_bump.txt b/infra/scripts/version_bump/files_to_bump.txt new file mode 100644 index 00000000000..7b086081d9c --- /dev/null +++ b/infra/scripts/version_bump/files_to_bump.txt @@ -0,0 +1,12 @@ +infra/charts/feast/requirements.yaml +infra/charts/feast/Chart.yaml +infra/charts/feast/charts/transformation-service/Chart.yaml +infra/charts/feast/charts/transformation-service/README.md +infra/charts/feast/charts/transformation-service/values.yaml +infra/charts/feast/charts/feature-server/Chart.yaml +infra/charts/feast/charts/feature-server/README.md +infra/charts/feast/charts/feature-server/values.yaml +infra/charts/feast/README.md +infra/charts/feast-python-server/Chart.yaml +infra/charts/feast-python-server/README.md +java/pom.xml \ No newline at end of file diff --git a/infra/templates/README.md.jinja2 b/infra/templates/README.md.jinja2 index 7d08c0d36f1..9d3b5649ce9 100644 --- a/infra/templates/README.md.jinja2 +++ b/infra/templates/README.md.jinja2 @@ -43,7 +43,11 @@ cd my_feature_repo feast apply ``` -### 4. Build a training dataset +### 4. Explore your data in the web UI (experimental) + +![Web UI](ui/sample.png) + +### 5. Build a training dataset ```python from feast import FeatureStore import pandas as pd @@ -84,7 +88,7 @@ print(training_df.head()) ``` -### 5. Load feature values into your online store +### 6. Load feature values into your online store ```commandline CURRENT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%S") feast materialize-incremental $CURRENT_TIME @@ -94,7 +98,7 @@ feast materialize-incremental $CURRENT_TIME Materializing feature view driver_hourly_stats from 2021-04-14 to 2021-04-15 done! ``` -### 6. Read online features at low latency +### 7. Read online features at low latency ```python from pprint import pprint from feast import FeatureStore diff --git a/java/pom.xml b/java/pom.xml index afbd6298055..c11e7f7df28 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -38,7 +38,7 @@ - 0.18.0 + 0.19.0 https://github.com/feast-dev/feast UTF-8 @@ -222,7 +222,7 @@ - feast.proto.*:io.grpc.*:org.tensorflow.* + io.grpc.*:org.tensorflow.* diff --git a/java/serving/README.md b/java/serving/README.md index 0ce2edc091d..5ac7194924f 100644 --- a/java/serving/README.md +++ b/java/serving/README.md @@ -3,7 +3,6 @@ ### Overview This guide is targeted at developers looking to contribute to Feast Serving: - [Building and running Feast Serving locally](#building-and-running-feast-serving-locally) -- [Feast Java Client](#feast-java-client) ### Pre-requisites: @@ -20,9 +19,23 @@ From the Feast GitHub root, run: 1. Note if you have a remote registry, you can specify that too (e.g. `gs://...`) ```yaml feast: - project: "feast_demo" - registry: "/Users/[your username]/GitHub/feast-demo/feature_repo/data/registry.db" + project: feast_demo + registry: /Users/[your username]/GitHub/feast-demo/feature_repo/data/registry.db ``` + 2. An example of if you're using Redis with a remote registry: + ```yaml + feast: + project: feast_java_demo + registry: gs://[YOUR BUCKET]/demo-repo/registry.db + activeStore: online + stores: + - name: online + type: REDIS + config: + host: localhost + port: 6379 + password: [YOUR PASSWORD] + ``` 4. Run the jar with dependencies that was built from Maven (note the version might vary): ``` java \ diff --git a/java/serving/src/main/java/feast/serving/config/ApplicationProperties.java b/java/serving/src/main/java/feast/serving/config/ApplicationProperties.java index 791c871e59b..268592d20ac 100644 --- a/java/serving/src/main/java/feast/serving/config/ApplicationProperties.java +++ b/java/serving/src/main/java/feast/serving/config/ApplicationProperties.java @@ -33,9 +33,12 @@ import javax.validation.*; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; +import org.slf4j.Logger; /** Feast Serving properties. */ public class ApplicationProperties { + private static final Logger log = org.slf4j.LoggerFactory.getLogger(ApplicationProperties.class); + public static class FeastProperties { /* Feast Serving build version */ @NotBlank private String version = "unknown"; @@ -246,10 +249,33 @@ public void setType(String type) { * @return Returns the store specific configuration */ public RedisClusterStoreConfig getRedisClusterConfig() { + String read_from; + if (!this.config.containsKey("read_from") || this.config.get("read_from") == null) { + log.info("'read_from' not defined in Redis cluster config, so setting to UPSTREAM"); + read_from = ReadFrom.UPSTREAM.toString(); + } else { + read_from = this.config.get("read_from"); + } + + if (!this.config.containsKey("timeout") || this.config.get("timeout") == null) { + throw new IllegalArgumentException( + "Redis cluster config does not have 'timeout' specified"); + } + + Boolean ssl = null; + if (!this.config.containsKey("ssl") || this.config.get("ssl") == null) { + log.info("'ssl' not defined in Redis cluster config, so setting to false"); + ssl = false; + } else { + ssl = Boolean.parseBoolean(this.config.get("ssl")); + } + Duration timeout = Duration.parse(this.config.get("timeout")); return new RedisClusterStoreConfig( this.config.get("connection_string"), - ReadFrom.valueOf(this.config.get("read_from")), - Duration.parse(this.config.get("timeout"))); + ReadFrom.valueOf(read_from), + timeout, + ssl, + this.config.getOrDefault("password", "")); } public RedisStoreConfig getRedisConfig() { diff --git a/java/serving/src/test/java/feast/serving/it/TestUtils.java b/java/serving/src/test/java/feast/serving/it/TestUtils.java index 867fa4afb06..9bca14db4e6 100644 --- a/java/serving/src/test/java/feast/serving/it/TestUtils.java +++ b/java/serving/src/test/java/feast/serving/it/TestUtils.java @@ -83,7 +83,8 @@ public static ApplicationProperties.FeastProperties createBasicFeastProperties( new ApplicationProperties.Store( "online", "REDIS", - ImmutableMap.of("host", redisHost, "port", redisPort.toString())))); + ImmutableMap.of( + "host", redisHost, "port", redisPort.toString(), "password", "testpw")))); return feastProperties; } diff --git a/java/serving/src/test/java/feast/serving/util/DataGenerator.java b/java/serving/src/test/java/feast/serving/util/DataGenerator.java index d53632d0d64..c6c11a9bf78 100644 --- a/java/serving/src/test/java/feast/serving/util/DataGenerator.java +++ b/java/serving/src/test/java/feast/serving/util/DataGenerator.java @@ -116,12 +116,12 @@ public static EntityProto.EntitySpecV2 createEntitySpecV2( String name, String description, ValueProto.ValueType.Enum valueType, - Map labels) { + Map tags) { return EntityProto.EntitySpecV2.newBuilder() .setName(name) .setDescription(description) .setValueType(valueType) - .putAllLabels(labels) + .putAllTags(tags) .build(); } diff --git a/java/serving/src/test/resources/docker-compose/docker-compose-redis-it.yml b/java/serving/src/test/resources/docker-compose/docker-compose-redis-it.yml index 13835e07d41..1dee243cb80 100644 --- a/java/serving/src/test/resources/docker-compose/docker-compose-redis-it.yml +++ b/java/serving/src/test/resources/docker-compose/docker-compose-redis-it.yml @@ -3,6 +3,7 @@ version: '3' services: redis: image: redis:6.2 + command: redis-server --requirepass testpw ports: - "6379:6379" feast: diff --git a/java/serving/src/test/resources/docker-compose/feast10/feature_store.yaml b/java/serving/src/test/resources/docker-compose/feast10/feature_store.yaml index 7554725004f..2e6625c025b 100644 --- a/java/serving/src/test/resources/docker-compose/feast10/feature_store.yaml +++ b/java/serving/src/test/resources/docker-compose/feast10/feature_store.yaml @@ -3,7 +3,7 @@ registry: registry.db provider: local online_store: type: redis - connection_string: "redis:6379" + connection_string: "redis:6379,password=testpw" offline_store: {} flags: alpha_features: true diff --git a/java/storage/connectors/redis/src/main/java/feast/storage/connectors/redis/retriever/RedisClusterClient.java b/java/storage/connectors/redis/src/main/java/feast/storage/connectors/redis/retriever/RedisClusterClient.java index 6574962bbb5..d527f245aef 100644 --- a/java/storage/connectors/redis/src/main/java/feast/storage/connectors/redis/retriever/RedisClusterClient.java +++ b/java/storage/connectors/redis/src/main/java/feast/storage/connectors/redis/retriever/RedisClusterClient.java @@ -71,7 +71,16 @@ public static RedisClientAdapter create(RedisClusterStoreConfig config) { .map( hostPort -> { String[] hostPortSplit = hostPort.trim().split(":"); - return RedisURI.create(hostPortSplit[0], Integer.parseInt(hostPortSplit[1])); + RedisURI redisURI = + RedisURI.create(hostPortSplit[0], Integer.parseInt(hostPortSplit[1])); + if (!config.getPassword().isEmpty()) { + redisURI.setPassword(config.getPassword()); + } + if (config.getSsl()) { + redisURI.setSsl(true); + } + redisURI.setTimeout(config.getTimeout()); + return redisURI; }) .collect(Collectors.toList()); diff --git a/java/storage/connectors/redis/src/main/java/feast/storage/connectors/redis/retriever/RedisClusterStoreConfig.java b/java/storage/connectors/redis/src/main/java/feast/storage/connectors/redis/retriever/RedisClusterStoreConfig.java index c179ffe9645..271b07759c0 100644 --- a/java/storage/connectors/redis/src/main/java/feast/storage/connectors/redis/retriever/RedisClusterStoreConfig.java +++ b/java/storage/connectors/redis/src/main/java/feast/storage/connectors/redis/retriever/RedisClusterStoreConfig.java @@ -23,11 +23,16 @@ public class RedisClusterStoreConfig { private final String connectionString; private final ReadFrom readFrom; private final Duration timeout; + private final Boolean ssl; + private final String password; - public RedisClusterStoreConfig(String connectionString, ReadFrom readFrom, Duration timeout) { + public RedisClusterStoreConfig( + String connectionString, ReadFrom readFrom, Duration timeout, Boolean ssl, String password) { this.connectionString = connectionString; this.readFrom = readFrom; this.timeout = timeout; + this.ssl = ssl; + this.password = password; } public String getConnectionString() { @@ -41,4 +46,12 @@ public ReadFrom getReadFrom() { public Duration getTimeout() { return this.timeout; } + + public Boolean getSsl() { + return ssl; + } + + public String getPassword() { + return password; + } } diff --git a/protos/feast/core/DataSource.proto b/protos/feast/core/DataSource.proto index 41bba6443fd..82f6c4ab4a6 100644 --- a/protos/feast/core/DataSource.proto +++ b/protos/feast/core/DataSource.proto @@ -26,6 +26,7 @@ import "feast/core/DataFormat.proto"; import "feast/types/Value.proto"; // Defines a Data Source that can be used source Feature data +// Next available id: 22 message DataSource { // Field indexes should *not* be reused. Not sure if fields 6-10 were used previously or not, // but they are going to be reserved for backwards compatibility. @@ -45,6 +46,13 @@ message DataSource { REQUEST_SOURCE = 7; } + + // Unique name of data source within the project + string name = 20; + + // Name of Feast project that this data source belongs to. + string project = 21; + SourceType type = 1; // Defines mapping between fields in the sourced data @@ -156,9 +164,7 @@ message DataSource { // Defines options for DataSource that sources features from request data message RequestDataOptions { - // Name of the request data source - string name = 1; - + reserved 1; // Mapping of feature name to type map schema = 2; } diff --git a/protos/feast/core/Entity.proto b/protos/feast/core/Entity.proto index 7846015c73d..cd54c649229 100644 --- a/protos/feast/core/Entity.proto +++ b/protos/feast/core/Entity.proto @@ -48,7 +48,10 @@ message EntitySpecV2 { string join_key = 4; // User defined metadata - map labels = 8; + map tags = 8; + + // Owner of the entity. + string owner = 10; } message EntityMeta { diff --git a/protos/feast/core/FeatureService.proto b/protos/feast/core/FeatureService.proto index 952b30eb0a7..4aaa0d5f06f 100644 --- a/protos/feast/core/FeatureService.proto +++ b/protos/feast/core/FeatureService.proto @@ -32,6 +32,9 @@ message FeatureServiceSpec { // Description of the feature service. string description = 5; + + // Owner of the feature service. + string owner = 6; } diff --git a/protos/feast/core/OnDemandFeatureView.proto b/protos/feast/core/OnDemandFeatureView.proto index 58feff5bfdb..bd9a289a1bb 100644 --- a/protos/feast/core/OnDemandFeatureView.proto +++ b/protos/feast/core/OnDemandFeatureView.proto @@ -48,8 +48,6 @@ message OnDemandFeatureViewSpec { map inputs = 4; UserDefinedFunction user_defined_function = 5; - - } message OnDemandFeatureViewMeta { diff --git a/protos/feast/core/Registry.proto b/protos/feast/core/Registry.proto index 3deeb972385..a19e4c0a094 100644 --- a/protos/feast/core/Registry.proto +++ b/protos/feast/core/Registry.proto @@ -28,13 +28,16 @@ import "feast/core/FeatureView.proto"; import "feast/core/InfraObject.proto"; import "feast/core/OnDemandFeatureView.proto"; import "feast/core/RequestFeatureView.proto"; +import "feast/core/DataSource.proto"; import "feast/core/SavedDataset.proto"; import "google/protobuf/timestamp.proto"; +// Next id: 13 message Registry { repeated Entity entities = 1; repeated FeatureTable feature_tables = 2; repeated FeatureView feature_views = 6; + repeated DataSource data_sources = 12; repeated OnDemandFeatureView on_demand_feature_views = 8; repeated RequestFeatureView request_feature_views = 9; repeated FeatureService feature_services = 7; diff --git a/protos/feast/core/RequestFeatureView.proto b/protos/feast/core/RequestFeatureView.proto index c9ee540e6f9..39711d8d3f2 100644 --- a/protos/feast/core/RequestFeatureView.proto +++ b/protos/feast/core/RequestFeatureView.proto @@ -22,8 +22,6 @@ option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; option java_outer_classname = "RequestFeatureViewProto"; option java_package = "feast.proto.core"; -import "feast/core/FeatureView.proto"; -import "feast/core/Feature.proto"; import "feast/core/DataSource.proto"; message RequestFeatureView { diff --git a/protos/feast/core/SavedDataset.proto b/protos/feast/core/SavedDataset.proto index ebd2e56d350..e6d103a691b 100644 --- a/protos/feast/core/SavedDataset.proto +++ b/protos/feast/core/SavedDataset.proto @@ -23,8 +23,8 @@ option java_outer_classname = "SavedDatasetProto"; option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; import "google/protobuf/timestamp.proto"; -import "feast/core/FeatureViewProjection.proto"; import "feast/core/DataSource.proto"; +import "feast/core/FeatureService.proto"; message SavedDatasetSpec { // Name of the dataset. Must be unique since it's possible to overwrite dataset by name @@ -44,6 +44,9 @@ message SavedDatasetSpec { SavedDatasetStorage storage = 6; + // Optional and only populated if generated from a feature service fetch + string feature_service_name = 8; + // User defined metadata map tags = 7; } diff --git a/protos/feast/core/ValidationProfile.proto b/protos/feast/core/ValidationProfile.proto index 31c4e150a07..502e79f72b4 100644 --- a/protos/feast/core/ValidationProfile.proto +++ b/protos/feast/core/ValidationProfile.proto @@ -22,7 +22,6 @@ option java_package = "feast.proto.core"; option java_outer_classname = "ValidationProfile"; option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; -import "google/protobuf/timestamp.proto"; import "feast/core/SavedDataset.proto"; message GEValidationProfiler { diff --git a/protos/feast/storage/Redis.proto b/protos/feast/storage/Redis.proto index a662e352f48..bc9d0c61d32 100644 --- a/protos/feast/storage/Redis.proto +++ b/protos/feast/storage/Redis.proto @@ -16,7 +16,6 @@ syntax = "proto3"; -import "feast/types/Field.proto"; import "feast/types/Value.proto"; package feast.storage; diff --git a/sdk/python/feast/__init__.py b/sdk/python/feast/__init__.py index 9f78f9d98bf..0af226aa056 100644 --- a/sdk/python/feast/__init__.py +++ b/sdk/python/feast/__init__.py @@ -3,6 +3,9 @@ from pkg_resources import DistributionNotFound, get_distribution from feast.infra.offline_stores.bigquery_source import BigQuerySource +from feast.infra.offline_stores.contrib.spark_offline_store.spark_source import ( + SparkSource, +) from feast.infra.offline_stores.file_source import FileSource from feast.infra.offline_stores.redshift_source import RedshiftSource from feast.infra.offline_stores.snowflake_source import SnowflakeSource @@ -15,6 +18,7 @@ from .feature_view import FeatureView from .on_demand_feature_view import OnDemandFeatureView from .repo_config import RepoConfig +from .request_feature_view import RequestFeatureView from .value_type import ValueType logging.basicConfig( @@ -44,5 +48,7 @@ "BigQuerySource", "FileSource", "RedshiftSource", + "RequestFeatureView", "SnowflakeSource", + "SparkSource", ] diff --git a/sdk/python/feast/base_feature_view.py b/sdk/python/feast/base_feature_view.py index b2178ec6312..b0cd70617fc 100644 --- a/sdk/python/feast/base_feature_view.py +++ b/sdk/python/feast/base_feature_view.py @@ -33,32 +33,12 @@ class BaseFeatureView(ABC): @abstractmethod def __init__(self, name: str, features: List[Feature]): - self._name = name - self._features = features - self._projection = FeatureViewProjection.from_definition(self) + self.name = name + self.features = features + self.projection = FeatureViewProjection.from_definition(self) self.created_timestamp: Optional[datetime] = None self.last_updated_timestamp: Optional[datetime] = None - @property - def name(self) -> str: - return self._name - - @property - def features(self) -> List[Feature]: - return self._features - - @features.setter - def features(self, value): - self._features = value - - @property - def projection(self) -> FeatureViewProjection: - return self._projection - - @projection.setter - def projection(self, value): - self._projection = value - @property @abstractmethod def proto_class(self) -> Type[Message]: diff --git a/sdk/python/feast/cli.py b/sdk/python/feast/cli.py index f6d326410a3..d2a71bc561b 100644 --- a/sdk/python/feast/cli.py +++ b/sdk/python/feast/cli.py @@ -126,6 +126,56 @@ def endpoint(ctx: click.Context): _logger.info("There is no active feature server.") +@cli.group(name="data-sources") +def data_sources_cmd(): + """ + Access data sources + """ + pass + + +@data_sources_cmd.command("describe") +@click.argument("name", type=click.STRING) +@click.pass_context +def data_source_describe(ctx: click.Context, name: str): + """ + Describe a data source + """ + repo = ctx.obj["CHDIR"] + cli_check_repo(repo) + store = FeatureStore(repo_path=str(repo)) + + try: + data_source = store.get_data_source(name) + except FeastObjectNotFoundException as e: + print(e) + exit(1) + + print( + yaml.dump( + yaml.safe_load(str(data_source)), default_flow_style=False, sort_keys=False + ) + ) + + +@data_sources_cmd.command(name="list") +@click.pass_context +def data_source_list(ctx: click.Context): + """ + List all data sources + """ + repo = ctx.obj["CHDIR"] + cli_check_repo(repo) + store = FeatureStore(repo_path=str(repo)) + table = [] + for datasource in store.list_data_sources(): + table.append([datasource.name, datasource.__class__]) + + from tabulate import tabulate + + print(tabulate(table, headers=["NAME", "CLASS"], tablefmt="plain")) + + @cli.group(name="entities") def entities_cmd(): """ @@ -477,7 +527,9 @@ def materialize_incremental_command(ctx: click.Context, end_ts: str, views: List @click.option( "--template", "-t", - type=click.Choice(["local", "gcp", "aws", "snowflake"], case_sensitive=False), + type=click.Choice( + ["local", "gcp", "aws", "snowflake", "spark"], case_sensitive=False + ), help="Specify a template for the created project", default="local", ) @@ -512,7 +564,7 @@ def init_command(project_directory, minimal: bool, template: str): ) @click.pass_context def serve_command(ctx: click.Context, host: str, port: int, no_access_log: bool): - """[Experimental] Start a the feature consumption server locally on a given port.""" + """Start a feature server locally on a given port.""" repo = ctx.obj["CHDIR"] cli_check_repo(repo) store = FeatureStore(repo_path=str(repo)) diff --git a/sdk/python/feast/data_source.py b/sdk/python/feast/data_source.py index 94910c6c083..15ce0c23773 100644 --- a/sdk/python/feast/data_source.py +++ b/sdk/python/feast/data_source.py @@ -44,51 +44,9 @@ class KafkaOptions: def __init__( self, bootstrap_servers: str, message_format: StreamFormat, topic: str, ): - self._bootstrap_servers = bootstrap_servers - self._message_format = message_format - self._topic = topic - - @property - def bootstrap_servers(self): - """ - Returns a comma-separated list of Kafka bootstrap servers - """ - return self._bootstrap_servers - - @bootstrap_servers.setter - def bootstrap_servers(self, bootstrap_servers): - """ - Sets a comma-separated list of Kafka bootstrap servers - """ - self._bootstrap_servers = bootstrap_servers - - @property - def message_format(self): - """ - Returns the data format that is used to encode the feature data in Kafka messages - """ - return self._message_format - - @message_format.setter - def message_format(self, message_format): - """ - Sets the data format that is used to encode the feature data in Kafka messages - """ - self._message_format = message_format - - @property - def topic(self): - """ - Returns the Kafka topic to collect feature data from - """ - return self._topic - - @topic.setter - def topic(self, topic): - """ - Sets the Kafka topic to collect feature data from - """ - self._topic = topic + self.bootstrap_servers = bootstrap_servers + self.message_format = message_format + self.topic = topic @classmethod def from_proto(cls, kafka_options_proto: DataSourceProto.KafkaOptions): @@ -135,51 +93,9 @@ class KinesisOptions: def __init__( self, record_format: StreamFormat, region: str, stream_name: str, ): - self._record_format = record_format - self._region = region - self._stream_name = stream_name - - @property - def record_format(self): - """ - Returns the data format used to encode the feature data in the Kinesis records. - """ - return self._record_format - - @record_format.setter - def record_format(self, record_format): - """ - Sets the data format used to encode the feature data in the Kinesis records. - """ - self._record_format = record_format - - @property - def region(self): - """ - Returns the AWS region of Kinesis stream - """ - return self._region - - @region.setter - def region(self, region): - """ - Sets the AWS region of Kinesis stream - """ - self._region = region - - @property - def stream_name(self): - """ - Returns the Kinesis stream name to obtain feature data from - """ - return self._stream_name - - @stream_name.setter - def stream_name(self, stream_name): - """ - Sets the Kinesis stream name to obtain feature data from - """ - self._stream_name = stream_name + self.record_format = record_format + self.region = region + self.stream_name = stream_name @classmethod def from_proto(cls, kinesis_options_proto: DataSourceProto.KinesisOptions): @@ -223,6 +139,7 @@ class DataSource(ABC): DataSource that can be used to source features. Args: + name: Name of data source, which should be unique within a project event_timestamp_column (optional): Event timestamp column used for point in time joins of feature values. created_timestamp_column (optional): Timestamp column indicating when the row @@ -233,36 +150,43 @@ class DataSource(ABC): date_partition_column (optional): Timestamp column used for partitioning. """ - _event_timestamp_column: str - _created_timestamp_column: str - _field_mapping: Dict[str, str] - _date_partition_column: str + name: str + event_timestamp_column: str + created_timestamp_column: str + field_mapping: Dict[str, str] + date_partition_column: str def __init__( self, + name: str, event_timestamp_column: Optional[str] = None, created_timestamp_column: Optional[str] = None, field_mapping: Optional[Dict[str, str]] = None, date_partition_column: Optional[str] = None, ): """Creates a DataSource object.""" - self._event_timestamp_column = ( + self.name = name + self.event_timestamp_column = ( event_timestamp_column if event_timestamp_column else "" ) - self._created_timestamp_column = ( + self.created_timestamp_column = ( created_timestamp_column if created_timestamp_column else "" ) - self._field_mapping = field_mapping if field_mapping else {} - self._date_partition_column = ( + self.field_mapping = field_mapping if field_mapping else {} + self.date_partition_column = ( date_partition_column if date_partition_column else "" ) + def __hash__(self): + return hash((id(self), self.name)) + def __eq__(self, other): if not isinstance(other, DataSource): raise TypeError("Comparisons should only involve DataSource class objects.") if ( - self.event_timestamp_column != other.event_timestamp_column + self.name != other.name + or self.event_timestamp_column != other.event_timestamp_column or self.created_timestamp_column != other.created_timestamp_column or self.field_mapping != other.field_mapping or self.date_partition_column != other.date_partition_column @@ -271,62 +195,6 @@ def __eq__(self, other): return True - @property - def field_mapping(self) -> Dict[str, str]: - """ - Returns the field mapping of this data source. - """ - return self._field_mapping - - @field_mapping.setter - def field_mapping(self, field_mapping): - """ - Sets the field mapping of this data source. - """ - self._field_mapping = field_mapping - - @property - def event_timestamp_column(self) -> str: - """ - Returns the event timestamp column of this data source. - """ - return self._event_timestamp_column - - @event_timestamp_column.setter - def event_timestamp_column(self, event_timestamp_column): - """ - Sets the event timestamp column of this data source. - """ - self._event_timestamp_column = event_timestamp_column - - @property - def created_timestamp_column(self) -> str: - """ - Returns the created timestamp column of this data source. - """ - return self._created_timestamp_column - - @created_timestamp_column.setter - def created_timestamp_column(self, created_timestamp_column): - """ - Sets the created timestamp column of this data source. - """ - self._created_timestamp_column = created_timestamp_column - - @property - def date_partition_column(self) -> str: - """ - Returns the date partition column of this data source. - """ - return self._date_partition_column - - @date_partition_column.setter - def date_partition_column(self, date_partition_column): - """ - Sets the date partition column of this data source. - """ - self._date_partition_column = date_partition_column - @staticmethod @abstractmethod def from_proto(data_source: DataSourceProto) -> Any: @@ -346,7 +214,9 @@ def from_proto(data_source: DataSourceProto) -> Any: cls = get_data_source_class_from_type(data_source.data_source_class_type) return cls.from_proto(data_source) - if data_source.file_options.file_format and data_source.file_options.file_url: + if data_source.request_data_options and data_source.request_data_options.schema: + data_source_obj = RequestDataSource.from_proto(data_source) + elif data_source.file_options.file_format and data_source.file_options.file_url: from feast.infra.offline_stores.file_source import FileSource data_source_obj = FileSource.from_proto(data_source) @@ -386,7 +256,7 @@ def from_proto(data_source: DataSourceProto) -> Any: @abstractmethod def to_proto(self) -> DataSourceProto: """ - Converts an DataSourceProto object to its protobuf representation. + Converts a DataSourceProto object to its protobuf representation. """ raise NotImplementedError @@ -436,6 +306,7 @@ def get_table_column_names_and_types( def __init__( self, + name: str, event_timestamp_column: str, bootstrap_servers: str, message_format: StreamFormat, @@ -445,12 +316,13 @@ def __init__( date_partition_column: Optional[str] = "", ): super().__init__( + name, event_timestamp_column, created_timestamp_column, field_mapping, date_partition_column, ) - self._kafka_options = KafkaOptions( + self.kafka_options = KafkaOptions( bootstrap_servers=bootstrap_servers, message_format=message_format, topic=topic, @@ -472,23 +344,10 @@ def __eq__(self, other): return True - @property - def kafka_options(self): - """ - Returns the kafka options of this data source - """ - return self._kafka_options - - @kafka_options.setter - def kafka_options(self, kafka_options): - """ - Sets the kafka options of this data source - """ - self._kafka_options = kafka_options - @staticmethod def from_proto(data_source: DataSourceProto): return KafkaSource( + name=data_source.name, field_mapping=dict(data_source.field_mapping), bootstrap_servers=data_source.kafka_options.bootstrap_servers, message_format=StreamFormat.from_proto( @@ -502,6 +361,7 @@ def from_proto(data_source: DataSourceProto): def to_proto(self) -> DataSourceProto: data_source_proto = DataSourceProto( + name=self.name, type=DataSourceProto.STREAM_KAFKA, field_mapping=self.field_mapping, kafka_options=self.kafka_options.to_proto(), @@ -517,6 +377,9 @@ def to_proto(self) -> DataSourceProto: def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]: return type_map.redshift_to_feast_value_type + def get_table_query_string(self) -> str: + raise NotImplementedError + class RequestDataSource(DataSource): """ @@ -527,34 +390,15 @@ class RequestDataSource(DataSource): schema: Schema mapping from the input feature name to a ValueType """ - @staticmethod - def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]: - raise NotImplementedError - - _name: str - _schema: Dict[str, ValueType] + name: str + schema: Dict[str, ValueType] def __init__( self, name: str, schema: Dict[str, ValueType], ): """Creates a RequestDataSource object.""" - super().__init__() - self._name = name - self._schema = schema - - @property - def name(self) -> str: - """ - Returns the name of this data source - """ - return self._name - - @property - def schema(self) -> Dict[str, ValueType]: - """ - Returns the schema for this request data source - """ - return self._schema + super().__init__(name) + self.schema = schema def validate(self, config: RepoConfig): pass @@ -570,21 +414,28 @@ def from_proto(data_source: DataSourceProto): schema = {} for key in schema_pb.keys(): schema[key] = ValueType(schema_pb.get(key)) - return RequestDataSource( - name=data_source.request_data_options.name, schema=schema - ) + return RequestDataSource(name=data_source.name, schema=schema) def to_proto(self) -> DataSourceProto: schema_pb = {} - for key, value in self._schema.items(): + for key, value in self.schema.items(): schema_pb[key] = value.value - options = DataSourceProto.RequestDataOptions(name=self._name, schema=schema_pb) + options = DataSourceProto.RequestDataOptions(schema=schema_pb) data_source_proto = DataSourceProto( - type=DataSourceProto.REQUEST_SOURCE, request_data_options=options + name=self.name, + type=DataSourceProto.REQUEST_SOURCE, + request_data_options=options, ) return data_source_proto + def get_table_query_string(self) -> str: + raise NotImplementedError + + @staticmethod + def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]: + raise NotImplementedError + class KinesisSource(DataSource): def validate(self, config: RepoConfig): @@ -598,6 +449,7 @@ def get_table_column_names_and_types( @staticmethod def from_proto(data_source: DataSourceProto): return KinesisSource( + name=data_source.name, field_mapping=dict(data_source.field_mapping), record_format=StreamFormat.from_proto( data_source.kinesis_options.record_format @@ -613,8 +465,12 @@ def from_proto(data_source: DataSourceProto): def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]: pass + def get_table_query_string(self) -> str: + raise NotImplementedError + def __init__( self, + name: str, event_timestamp_column: str, created_timestamp_column: str, record_format: StreamFormat, @@ -624,12 +480,13 @@ def __init__( date_partition_column: Optional[str] = "", ): super().__init__( + name, event_timestamp_column, created_timestamp_column, field_mapping, date_partition_column, ) - self._kinesis_options = KinesisOptions( + self.kinesis_options = KinesisOptions( record_format=record_format, region=region, stream_name=stream_name ) @@ -643,7 +500,8 @@ def __eq__(self, other): ) if ( - self.kinesis_options.record_format != other.kinesis_options.record_format + self.name != other.name + or self.kinesis_options.record_format != other.kinesis_options.record_format or self.kinesis_options.region != other.kinesis_options.region or self.kinesis_options.stream_name != other.kinesis_options.stream_name ): @@ -651,22 +509,9 @@ def __eq__(self, other): return True - @property - def kinesis_options(self): - """ - Returns the kinesis options of this data source - """ - return self._kinesis_options - - @kinesis_options.setter - def kinesis_options(self, kinesis_options): - """ - Sets the kinesis options of this data source - """ - self._kinesis_options = kinesis_options - def to_proto(self) -> DataSourceProto: data_source_proto = DataSourceProto( + name=self.name, type=DataSourceProto.STREAM_KINESIS, field_mapping=self.field_mapping, kinesis_options=self.kinesis_options.to_proto(), diff --git a/sdk/python/feast/diff/registry_diff.py b/sdk/python/feast/diff/registry_diff.py index 1f68d3ff65c..4558a149a5c 100644 --- a/sdk/python/feast/diff/registry_diff.py +++ b/sdk/python/feast/diff/registry_diff.py @@ -1,11 +1,14 @@ from dataclasses import dataclass -from typing import Any, Dict, Generic, Iterable, List, Set, Tuple, TypeVar +from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, TypeVar, cast from feast.base_feature_view import BaseFeatureView +from feast.data_source import DataSource from feast.diff.property_diff import PropertyDiff, TransitionType from feast.entity import Entity +from feast.feast_object import FeastObject, FeastObjectSpecProto from feast.feature_service import FeatureService from feast.feature_view import DUMMY_ENTITY_NAME +from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto from feast.protos.feast.core.Entity_pb2 import Entity as EntityProto from feast.protos.feast.core.FeatureService_pb2 import ( FeatureService as FeatureServiceProto, @@ -20,15 +23,13 @@ from feast.registry import FEAST_OBJECT_TYPES, FeastObjectType, Registry from feast.repo_contents import RepoContents -FeastObject = TypeVar("FeastObject", Entity, BaseFeatureView, FeatureService) - @dataclass -class FeastObjectDiff(Generic[FeastObject]): +class FeastObjectDiff: name: str feast_object_type: FeastObjectType - current_feast_object: FeastObject - new_feast_object: FeastObject + current_feast_object: Optional[FeastObject] + new_feast_object: Optional[FeastObject] feast_object_property_diffs: List[PropertyDiff] transition_type: TransitionType @@ -90,6 +91,7 @@ def tag_objects_for_keep_delete_update_add( FeastObjectProto = TypeVar( "FeastObjectProto", + DataSourceProto, EntityProto, FeatureViewProto, FeatureServiceProto, @@ -109,23 +111,33 @@ def diff_registry_objects( assert current_proto.DESCRIPTOR.full_name == new_proto.DESCRIPTOR.full_name property_diffs = [] transition: TransitionType = TransitionType.UNCHANGED - if current_proto.spec != new_proto.spec: - for _field in current_proto.spec.DESCRIPTOR.fields: + + current_spec: FeastObjectSpecProto + new_spec: FeastObjectSpecProto + if isinstance(current_proto, DataSourceProto) or isinstance( + new_proto, DataSourceProto + ): + assert type(current_proto) == type(new_proto) + current_spec = cast(DataSourceProto, current_proto) + new_spec = cast(DataSourceProto, new_proto) + else: + current_spec = current_proto.spec + new_spec = new_proto.spec + if current_spec != new_spec: + for _field in current_spec.DESCRIPTOR.fields: if _field.name in FIELDS_TO_IGNORE: continue - if getattr(current_proto.spec, _field.name) != getattr( - new_proto.spec, _field.name - ): + if getattr(current_spec, _field.name) != getattr(new_spec, _field.name): transition = TransitionType.UPDATE property_diffs.append( PropertyDiff( _field.name, - getattr(current_proto.spec, _field.name), - getattr(new_proto.spec, _field.name), + getattr(current_spec, _field.name), + getattr(new_spec, _field.name), ) ) return FeastObjectDiff( - name=new_proto.spec.name, + name=new_spec.name, feast_object_type=object_type, current_feast_object=current, new_feast_object=new, @@ -257,33 +269,48 @@ def apply_diff_to_registry( # will automatically delete the existing object. if feast_object_diff.transition_type == TransitionType.DELETE: if feast_object_diff.feast_object_type == FeastObjectType.ENTITY: - registry.delete_entity( - feast_object_diff.current_feast_object.name, project, commit=False - ) + entity_obj = cast(Entity, feast_object_diff.current_feast_object) + registry.delete_entity(entity_obj.name, project, commit=False) elif feast_object_diff.feast_object_type == FeastObjectType.FEATURE_SERVICE: + feature_service_obj = cast( + FeatureService, feast_object_diff.current_feast_object + ) registry.delete_feature_service( - feast_object_diff.current_feast_object.name, project, commit=False + feature_service_obj.name, project, commit=False ) elif feast_object_diff.feast_object_type in [ FeastObjectType.FEATURE_VIEW, FeastObjectType.ON_DEMAND_FEATURE_VIEW, FeastObjectType.REQUEST_FEATURE_VIEW, ]: + feature_view_obj = cast( + BaseFeatureView, feast_object_diff.current_feast_object + ) registry.delete_feature_view( - feast_object_diff.current_feast_object.name, project, commit=False, + feature_view_obj.name, project, commit=False, ) if feast_object_diff.transition_type in [ TransitionType.CREATE, TransitionType.UPDATE, ]: + if feast_object_diff.feast_object_type == FeastObjectType.DATA_SOURCE: + registry.apply_data_source( + cast(DataSource, feast_object_diff.new_feast_object), + project, + commit=False, + ) if feast_object_diff.feast_object_type == FeastObjectType.ENTITY: registry.apply_entity( - feast_object_diff.new_feast_object, project, commit=False + cast(Entity, feast_object_diff.new_feast_object), + project, + commit=False, ) elif feast_object_diff.feast_object_type == FeastObjectType.FEATURE_SERVICE: registry.apply_feature_service( - feast_object_diff.new_feast_object, project, commit=False + cast(FeatureService, feast_object_diff.new_feast_object), + project, + commit=False, ) elif feast_object_diff.feast_object_type in [ FeastObjectType.FEATURE_VIEW, @@ -291,7 +318,9 @@ def apply_diff_to_registry( FeastObjectType.REQUEST_FEATURE_VIEW, ]: registry.apply_feature_view( - feast_object_diff.new_feast_object, project, commit=False + cast(BaseFeatureView, feast_object_diff.new_feast_object), + project, + commit=False, ) if commit: diff --git a/sdk/python/feast/entity.py b/sdk/python/feast/entity.py index 8066eae60ab..efac8c17dab 100644 --- a/sdk/python/feast/entity.py +++ b/sdk/python/feast/entity.py @@ -11,42 +11,48 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import warnings from datetime import datetime from typing import Dict, Optional -import yaml -from google.protobuf import json_format -from google.protobuf.json_format import MessageToDict, MessageToJson +from google.protobuf.json_format import MessageToJson -from feast.loaders import yaml as feast_yaml -from feast.protos.feast.core.Entity_pb2 import Entity as EntityV2Proto +from feast.protos.feast.core.Entity_pb2 import Entity as EntityProto from feast.protos.feast.core.Entity_pb2 import EntityMeta as EntityMetaProto from feast.protos.feast.core.Entity_pb2 import EntitySpecV2 as EntitySpecProto from feast.usage import log_exceptions from feast.value_type import ValueType +warnings.simplefilter("once", DeprecationWarning) + class Entity: """ - Represents a collection of entities and associated metadata. - - Args: - name: Name of the entity. - value_type (optional): The type of the entity, such as string or float. - description (optional): Additional information to describe the entity. - join_key (optional): A property that uniquely identifies different entities - within the collection. Used as a key for joining entities with their - associated features. If not specified, defaults to the name of the entity. - labels (optional): User-defined metadata in dictionary form. + An entity defines a collection of entities for which features can be defined. An + entity can also contain associated metadata. + + Attributes: + name: The unique name of the entity. + value_type: The type of the entity, such as string or float. + join_key: A property that uniquely identifies different entities within the + collection. The join_key property is typically used for joining entities + with their associated features. If not specified, defaults to the name. + description: A human-readable description. + tags: A dictionary of key-value pairs to store arbitrary metadata. + owner: The owner of the feature service, typically the email of the primary + maintainer. + created_timestamp: The time when the entity was created. + last_updated_timestamp: The time when the entity was last updated. """ - _name: str - _value_type: ValueType - _description: str - _join_key: str - _labels: Dict[str, str] - _created_timestamp: Optional[datetime] - _last_updated_timestamp: Optional[datetime] + name: str + value_type: ValueType + join_key: str + description: str + tags: Dict[str, str] + owner: str + created_timestamp: Optional[datetime] + last_updated_timestamp: Optional[datetime] @log_exceptions def __init__( @@ -55,24 +61,31 @@ def __init__( value_type: ValueType = ValueType.UNKNOWN, description: str = "", join_key: Optional[str] = None, + tags: Dict[str, str] = None, labels: Optional[Dict[str, str]] = None, + owner: str = "", ): """Creates an Entity object.""" - self._name = name - self._description = description - self._value_type = value_type - if join_key: - self._join_key = join_key - else: - self._join_key = name - - if labels is None: - self._labels = dict() + self.name = name + self.value_type = value_type + self.join_key = join_key if join_key else name + self.description = description + + if labels is not None: + self.tags = labels + warnings.warn( + ( + "The parameter 'labels' is being deprecated. Please use 'tags' instead. " + "Feast 0.20 and onwards will not support the parameter 'labels'." + ), + DeprecationWarning, + ) else: - self._labels = labels + self.tags = labels or tags or {} - self._created_timestamp: Optional[datetime] = None - self._last_updated_timestamp: Optional[datetime] = None + self.owner = owner + self.created_timestamp = None + self.last_updated_timestamp = None def __hash__(self) -> int: return hash((id(self), self.name)) @@ -82,11 +95,12 @@ def __eq__(self, other): raise TypeError("Comparisons should only involve Entity class objects.") if ( - self.labels != other.labels - or self.name != other.name - or self.description != other.description + self.name != other.name or self.value_type != other.value_type or self.join_key != other.join_key + or self.description != other.description + or self.tags != other.tags + or self.owner != other.owner ): return False @@ -95,90 +109,6 @@ def __eq__(self, other): def __str__(self): return str(MessageToJson(self.to_proto())) - @property - def name(self) -> str: - """ - Gets the name of this entity. - """ - return self._name - - @name.setter - def name(self, name): - """ - Sets the name of this entity. - """ - self._name = name - - @property - def description(self) -> str: - """ - Gets the description of this entity. - """ - return self._description - - @description.setter - def description(self, description): - """ - Sets the description of this entity. - """ - self._description = description - - @property - def join_key(self) -> str: - """ - Gets the join key of this entity. - """ - return self._join_key - - @join_key.setter - def join_key(self, join_key): - """ - Sets the join key of this entity. - """ - self._join_key = join_key - - @property - def value_type(self) -> ValueType: - """ - Gets the type of this entity. - """ - return self._value_type - - @value_type.setter - def value_type(self, value_type: ValueType): - """ - Sets the type of this entity. - """ - self._value_type = value_type - - @property - def labels(self) -> Dict[str, str]: - """ - Gets the labels of this entity. - """ - return self._labels - - @labels.setter - def labels(self, labels: Dict[str, str]): - """ - Sets the labels of this entity. - """ - self._labels = labels - - @property - def created_timestamp(self) -> Optional[datetime]: - """ - Gets the created_timestamp of this entity. - """ - return self._created_timestamp - - @property - def last_updated_timestamp(self) -> Optional[datetime]: - """ - Gets the last_updated_timestamp of this entity. - """ - return self._last_updated_timestamp - def is_valid(self): """ Validates the state of this entity locally. @@ -187,42 +117,13 @@ def is_valid(self): ValueError: The entity does not have a name or does not have a type. """ if not self.name: - raise ValueError("No name found in entity.") + raise ValueError("The entity does not have a name.") if not self.value_type: - raise ValueError("No type found in entity {self.value_type}") + raise ValueError(f"The entity {self.name} does not have a type.") @classmethod - def from_yaml(cls, yml: str): - """ - Creates an entity from a YAML string body or a file path. - - Args: - yml: Either a file path containing a yaml file or a YAML string. - - Returns: - An EntityV2 object based on the YAML file. - """ - return cls.from_dict(feast_yaml.yaml_loader(yml, load_single=True)) - - @classmethod - def from_dict(cls, entity_dict): - """ - Creates an entity from a dict. - - Args: - entity_dict: A dict representation of an entity. - - Returns: - An EntityV2 object based on the entity dict. - """ - entity_proto = json_format.ParseDict( - entity_dict, EntityV2Proto(), ignore_unknown_fields=True - ) - return cls.from_proto(entity_proto) - - @classmethod - def from_proto(cls, entity_proto: EntityV2Proto): + def from_proto(cls, entity_proto: EntityProto): """ Creates an entity from a protobuf representation of an entity. @@ -230,102 +131,46 @@ def from_proto(cls, entity_proto: EntityV2Proto): entity_proto: A protobuf representation of an entity. Returns: - An EntityV2 object based on the entity protobuf. + An Entity object based on the entity protobuf. """ entity = cls( name=entity_proto.spec.name, - description=entity_proto.spec.description, value_type=ValueType(entity_proto.spec.value_type), - labels=entity_proto.spec.labels, join_key=entity_proto.spec.join_key, + description=entity_proto.spec.description, + tags=entity_proto.spec.tags, + owner=entity_proto.spec.owner, ) if entity_proto.meta.HasField("created_timestamp"): - entity._created_timestamp = entity_proto.meta.created_timestamp.ToDatetime() + entity.created_timestamp = entity_proto.meta.created_timestamp.ToDatetime() if entity_proto.meta.HasField("last_updated_timestamp"): - entity._last_updated_timestamp = ( + entity.last_updated_timestamp = ( entity_proto.meta.last_updated_timestamp.ToDatetime() ) return entity - def to_proto(self) -> EntityV2Proto: + def to_proto(self) -> EntityProto: """ Converts an entity object to its protobuf representation. Returns: - An EntityV2Proto protobuf. + An EntityProto protobuf. """ meta = EntityMetaProto() - if self._created_timestamp: - meta.created_timestamp.FromDatetime(self._created_timestamp) - if self._last_updated_timestamp: - meta.last_updated_timestamp.FromDatetime(self._last_updated_timestamp) + if self.created_timestamp: + meta.created_timestamp.FromDatetime(self.created_timestamp) + if self.last_updated_timestamp: + meta.last_updated_timestamp.FromDatetime(self.last_updated_timestamp) spec = EntitySpecProto( name=self.name, - description=self.description, value_type=self.value_type.value, - labels=self.labels, join_key=self.join_key, - ) - - return EntityV2Proto(spec=spec, meta=meta) - - def to_dict(self) -> Dict: - """ - Converts entity to dict. - - Returns: - Dictionary object representation of entity. - """ - entity_dict = MessageToDict(self.to_proto()) - - # Remove meta when empty for more readable exports - if entity_dict["meta"] == {}: - del entity_dict["meta"] - - return entity_dict - - def to_yaml(self): - """ - Converts a entity to a YAML string. - - Returns: - An entity string returned in YAML format. - """ - entity_dict = self.to_dict() - return yaml.dump(entity_dict, allow_unicode=True, sort_keys=False) - - def to_spec_proto(self) -> EntitySpecProto: - """ - Converts an EntityV2 object to its protobuf representation. - Used when passing EntitySpecV2 object to Feast request. - - Returns: - An EntitySpecV2 protobuf. - """ - spec = EntitySpecProto( - name=self.name, description=self.description, - value_type=self.value_type.value, - labels=self.labels, - join_key=self.join_key, + tags=self.tags, + owner=self.owner, ) - return spec - - def _update_from_entity(self, entity): - """ - Deep replaces one entity with another. - - Args: - entity: Entity to use as a source of configuration. - """ - self.name = entity.name - self.description = entity.description - self.value_type = entity.value_type - self.labels = entity.labels - self.join_key = entity.join_key - self._created_timestamp = entity.created_timestamp - self._last_updated_timestamp = entity.last_updated_timestamp + return EntityProto(spec=spec, meta=meta) diff --git a/sdk/python/feast/errors.py b/sdk/python/feast/errors.py index 17147f8a603..942d3e9c166 100644 --- a/sdk/python/feast/errors.py +++ b/sdk/python/feast/errors.py @@ -10,6 +10,13 @@ def __init__(self, path): ) +class DataSourceNoNameException(Exception): + def __init__(self): + super().__init__( + "Unable to infer a name for this data source. Either table or name must be specified." + ) + + class FeastObjectNotFoundException(Exception): pass @@ -64,6 +71,14 @@ def __init__(self, feature_names): ) +class DataSourceObjectNotFoundException(FeastObjectNotFoundException): + def __init__(self, name, project=None): + if project: + super().__init__(f"Data source {name} does not exist in project {project}") + else: + super().__init__(f"Data source {name} does not exist") + + class S3RegistryBucketNotExist(FeastObjectNotFoundException): def __init__(self, bucket): super().__init__(f"S3 bucket {bucket} for the Feast registry does not exist") diff --git a/sdk/python/feast/feast_object.py b/sdk/python/feast/feast_object.py new file mode 100644 index 00000000000..4ffd693c44f --- /dev/null +++ b/sdk/python/feast/feast_object.py @@ -0,0 +1,33 @@ +from typing import Union + +from .data_source import DataSource +from .entity import Entity +from .feature_service import FeatureService +from .feature_view import FeatureView +from .on_demand_feature_view import OnDemandFeatureView +from .protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto +from .protos.feast.core.Entity_pb2 import EntitySpecV2 +from .protos.feast.core.FeatureService_pb2 import FeatureServiceSpec +from .protos.feast.core.FeatureView_pb2 import FeatureViewSpec +from .protos.feast.core.OnDemandFeatureView_pb2 import OnDemandFeatureViewSpec +from .protos.feast.core.RequestFeatureView_pb2 import RequestFeatureViewSpec +from .request_feature_view import RequestFeatureView + +# Convenience type representing all Feast objects +FeastObject = Union[ + FeatureView, + OnDemandFeatureView, + RequestFeatureView, + Entity, + FeatureService, + DataSource, +] + +FeastObjectSpecProto = Union[ + FeatureViewSpec, + OnDemandFeatureViewSpec, + RequestFeatureViewSpec, + EntitySpecV2, + FeatureServiceSpec, + DataSourceProto, +] diff --git a/sdk/python/feast/feature_server.py b/sdk/python/feast/feature_server.py index 1f4513fa371..585075843a6 100644 --- a/sdk/python/feast/feature_server.py +++ b/sdk/python/feast/feature_server.py @@ -1,6 +1,5 @@ import traceback -import click import uvicorn from fastapi import FastAPI, HTTPException, Request from fastapi.logger import logger @@ -66,9 +65,4 @@ def start_server( store: "feast.FeatureStore", host: str, port: int, no_access_log: bool ): app = get_app(store) - click.echo( - "This is an " - + click.style("experimental", fg="yellow", bold=True, underline=True) - + " feature. It's intended for early testing and feedback, and could change without warnings in future releases." - ) uvicorn.run(app, host=host, port=port, access_log=(not no_access_log)) diff --git a/sdk/python/feast/feature_service.py b/sdk/python/feast/feature_service.py index 16815531a3b..40030b34ceb 100644 --- a/sdk/python/feast/feature_service.py +++ b/sdk/python/feast/feature_service.py @@ -11,39 +11,47 @@ FeatureService as FeatureServiceProto, ) from feast.protos.feast.core.FeatureService_pb2 import ( - FeatureServiceMeta, - FeatureServiceSpec, + FeatureServiceMeta as FeatureServiceMetaProto, +) +from feast.protos.feast.core.FeatureService_pb2 import ( + FeatureServiceSpec as FeatureServiceSpecProto, ) from feast.usage import log_exceptions class FeatureService: """ - A feature service is a logical grouping of features for retrieval (training or serving). - The features grouped by a feature service may come from any number of feature views. - - Args: - name: Unique name of the feature service. - features: A list of Features that are grouped as part of this FeatureService. - The list may contain Feature Views, Feature Tables, or a subset of either. - tags (optional): A dictionary of key-value pairs used for organizing Feature - Services. + A feature service defines a logical group of features from one or more feature views. + This group of features can be retrieved together during training or serving. + + Attributes: + name: The unique name of the feature service. + feature_view_projections: A list containing feature views and feature view + projections, representing the features in the feature service. + description: A human-readable description. + tags: A dictionary of key-value pairs to store arbitrary metadata. + owner: The owner of the feature service, typically the email of the primary + maintainer. + created_timestamp: The time when the feature service was created. + last_updated_timestamp: The time when the feature service was last updated. """ - _name: str - _feature_view_projections: List[FeatureViewProjection] - _tags: Dict[str, str] - _description: Optional[str] = None - _created_timestamp: Optional[datetime] = None - _last_updated_timestamp: Optional[datetime] = None + name: str + feature_view_projections: List[FeatureViewProjection] + description: str + tags: Dict[str, str] + owner: str + created_timestamp: Optional[datetime] = None + last_updated_timestamp: Optional[datetime] = None @log_exceptions def __init__( self, name: str, features: List[Union[FeatureView, OnDemandFeatureView]], - tags: Optional[Dict[str, str]] = None, - description: Optional[str] = None, + tags: Dict[str, str] = None, + description: str = "", + owner: str = "", ): """ Creates a FeatureService object. @@ -51,22 +59,23 @@ def __init__( Raises: ValueError: If one of the specified features is not a valid type. """ - self._name = name - self._feature_view_projections = [] + self.name = name + self.feature_view_projections = [] for feature_grouping in features: if isinstance(feature_grouping, BaseFeatureView): - self._feature_view_projections.append(feature_grouping.projection) + self.feature_view_projections.append(feature_grouping.projection) else: raise ValueError( - "The FeatureService {fs_name} has been provided with an invalid type" + f"The feature service {name} has been provided with an invalid type " f'{type(feature_grouping)} as part of the "features" argument.)' ) - self._tags = tags or {} - self._description = description - self._created_timestamp = None - self._last_updated_timestamp = None + self.description = description + self.tags = tags or {} + self.owner = owner + self.created_timestamp = None + self.last_updated_timestamp = None def __repr__(self): items = (f"{k} = {v}" for k, v in self.__dict__.items()) @@ -83,7 +92,13 @@ def __eq__(self, other): raise TypeError( "Comparisons should only involve FeatureService class objects." ) - if self.tags != other.tags or self.name != other.name: + + if ( + self.name != other.name + or self.description != other.description + or self.tags != other.tags + or self.owner != other.owner + ): return False if sorted(self.feature_view_projections) != sorted( @@ -93,73 +108,20 @@ def __eq__(self, other): return True - @property - def name(self) -> str: - return self._name - - @name.setter - def name(self, name: str): - self._name = name - - @property - def feature_view_projections(self) -> List[FeatureViewProjection]: - return self._feature_view_projections - - @feature_view_projections.setter - def feature_view_projections( - self, feature_view_projections: List[FeatureViewProjection] - ): - self._feature_view_projections = feature_view_projections - - @property - def tags(self) -> Dict[str, str]: - return self._tags - - @tags.setter - def tags(self, tags: Dict[str, str]): - self._tags = tags - - @property - def description(self) -> Optional[str]: - return self._description - - @description.setter - def description(self, description: str): - self._description = description - - @property - def created_timestamp(self) -> Optional[datetime]: - return self._created_timestamp - - @created_timestamp.setter - def created_timestamp(self, created_timestamp: datetime): - self._created_timestamp = created_timestamp - - @property - def last_updated_timestamp(self) -> Optional[datetime]: - return self._last_updated_timestamp - - @last_updated_timestamp.setter - def last_updated_timestamp(self, last_updated_timestamp: datetime): - self._last_updated_timestamp = last_updated_timestamp - - @staticmethod - def from_proto(feature_service_proto: FeatureServiceProto): + @classmethod + def from_proto(cls, feature_service_proto: FeatureServiceProto): """ Converts a FeatureServiceProto to a FeatureService object. Args: feature_service_proto: A protobuf representation of a FeatureService. """ - fs = FeatureService( + fs = cls( name=feature_service_proto.spec.name, features=[], tags=dict(feature_service_proto.spec.tags), - description=( - feature_service_proto.spec.description - if feature_service_proto.spec.description != "" - else None - ), + description=feature_service_proto.spec.description, + owner=feature_service_proto.spec.owner, ) fs.feature_view_projections.extend( [ @@ -181,29 +143,28 @@ def from_proto(feature_service_proto: FeatureServiceProto): def to_proto(self) -> FeatureServiceProto: """ - Converts a FeatureService to its protobuf representation. + Converts a feature service to its protobuf representation. Returns: A FeatureServiceProto protobuf. """ - meta = FeatureServiceMeta() + meta = FeatureServiceMetaProto() if self.created_timestamp: meta.created_timestamp.FromDatetime(self.created_timestamp) + if self.last_updated_timestamp: + meta.last_updated_timestamp.FromDatetime(self.last_updated_timestamp) - spec = FeatureServiceSpec( + spec = FeatureServiceSpecProto( name=self.name, features=[ projection.to_proto() for projection in self.feature_view_projections ], + tags=self.tags, + description=self.description, + owner=self.owner, ) - if self.tags: - spec.tags.update(self.tags) - if self.description: - spec.description = self.description - - feature_service_proto = FeatureServiceProto(spec=spec, meta=meta) - return feature_service_proto + return FeatureServiceProto(spec=spec, meta=meta) def validate(self): pass diff --git a/sdk/python/feast/feature_store.py b/sdk/python/feast/feature_store.py index fcd94f9bea8..89e4df1d5fc 100644 --- a/sdk/python/feast/feature_store.py +++ b/sdk/python/feast/feature_store.py @@ -39,8 +39,10 @@ from feast import feature_server, flags, flags_helper, utils from feast.base_feature_view import BaseFeatureView +from feast.data_source import DataSource from feast.diff.infra_diff import InfraDiff, diff_infra_protos from feast.diff.registry_diff import RegistryDiff, apply_diff_to_registry, diff_between +from feast.dqm.profilers.ge_profiler import GEProfiler from feast.entity import Entity from feast.errors import ( EntityNotFoundException, @@ -50,6 +52,7 @@ RequestDataNotFoundInEntityDfException, RequestDataNotFoundInEntityRowsException, ) +from feast.feast_object import FeastObject from feast.feature_service import FeatureService from feast.feature_view import ( DUMMY_ENTITY, @@ -259,6 +262,19 @@ def list_on_demand_feature_views( self.project, allow_cache=allow_cache ) + @log_exceptions_and_usage + def list_data_sources(self, allow_cache: bool = False) -> List[DataSource]: + """ + Retrieves the list of data sources from the registry. + + Args: + allow_cache: Whether to allow returning data sources from a cached registry. + + Returns: + A list of data sources. + """ + return self._registry.list_data_sources(self.project, allow_cache=allow_cache) + @log_exceptions_and_usage def get_entity(self, name: str) -> Entity: """ @@ -284,6 +300,7 @@ def get_feature_service( Args: name: Name of feature service. + allow_cache: Whether to allow returning feature services from a cached registry. Returns: The specified feature service. @@ -333,6 +350,22 @@ def get_on_demand_feature_view(self, name: str) -> OnDemandFeatureView: """ return self._registry.get_on_demand_feature_view(name, self.project) + @log_exceptions_and_usage + def get_data_source(self, name: str) -> DataSource: + """ + Retrieves the list of data sources from the registry. + + Args: + name: Name of the data source. + + Returns: + The specified data source. + + Raises: + DataSourceObjectNotFoundException: The data source could not be found. + """ + return self._registry.get_data_source(name, self.project) + @log_exceptions_and_usage def delete_feature_view(self, name: str): """ @@ -392,8 +425,10 @@ def _get_features( def _should_use_plan(self): """Returns True if _plan and _apply_diffs should be used, False otherwise.""" - # Currently only the local provider supports _plan and _apply_diffs. - return self.config.provider == "local" + # Currently only the local provider with sqlite online store supports _plan and _apply_diffs. + return self.config.provider == "local" and ( + self.config.online_store and self.config.online_store.type == "sqlite" + ) def _validate_all_feature_views( self, @@ -416,6 +451,7 @@ def _validate_all_feature_views( def _make_inferences( self, + data_sources_to_update: List[DataSource], entities_to_update: List[Entity], views_to_update: List[FeatureView], odfvs_to_update: List[OnDemandFeatureView], @@ -425,6 +461,10 @@ def _make_inferences( entities_to_update, views_to_update, self.config ) + update_data_sources_with_inferred_event_timestamp_col( + data_sources_to_update, self.config + ) + update_data_sources_with_inferred_event_timestamp_col( [view.batch_source for view in views_to_update], self.config ) @@ -476,7 +516,13 @@ def _plan( ... ttl=timedelta(seconds=86400 * 1), ... batch_source=driver_hourly_stats, ... ) - >>> registry_diff, infra_diff, new_infra = fs._plan(RepoContents({driver_hourly_stats_view}, set(), set(), {driver}, set())) # register entity and feature view + >>> registry_diff, infra_diff, new_infra = fs._plan(RepoContents( + ... data_sources={driver_hourly_stats}, + ... feature_views={driver_hourly_stats_view}, + ... on_demand_feature_views=set(), + ... request_feature_views=set(), + ... entities={driver}, + ... feature_services=set())) # register entity and feature view """ # Validate and run inference on all the objects to be registered. self._validate_all_feature_views( @@ -484,7 +530,9 @@ def _plan( list(desired_repo_contents.on_demand_feature_views), list(desired_repo_contents.request_feature_views), ) + _validate_data_sources(list(desired_repo_contents.data_sources)) self._make_inferences( + list(desired_repo_contents.data_sources), list(desired_repo_contents.entities), list(desired_repo_contents.feature_views), list(desired_repo_contents.on_demand_feature_views), @@ -526,38 +574,22 @@ def _apply_diffs( apply_diff_to_registry( self._registry, registry_diff, self.project, commit=False ) + self._registry.update_infra(new_infra, self.project, commit=True) @log_exceptions_and_usage def apply( self, objects: Union[ + DataSource, Entity, FeatureView, OnDemandFeatureView, RequestFeatureView, FeatureService, - List[ - Union[ - FeatureView, - OnDemandFeatureView, - RequestFeatureView, - Entity, - FeatureService, - ] - ], + List[FeastObject], ], - objects_to_delete: Optional[ - List[ - Union[ - FeatureView, - OnDemandFeatureView, - RequestFeatureView, - Entity, - FeatureService, - ] - ] - ] = None, + objects_to_delete: Optional[List[FeastObject]] = None, partial: bool = True, ): """Register objects to metadata store and update related infrastructure. @@ -613,22 +645,31 @@ def apply( ] odfvs_to_update = [ob for ob in objects if isinstance(ob, OnDemandFeatureView)] services_to_update = [ob for ob in objects if isinstance(ob, FeatureService)] + data_sources_to_update = [ob for ob in objects if isinstance(ob, DataSource)] if len(entities_to_update) + len(views_to_update) + len( request_views_to_update - ) + len(odfvs_to_update) + len(services_to_update) != len(objects): + ) + len(odfvs_to_update) + len(services_to_update) + len( + data_sources_to_update + ) != len( + objects + ): raise ValueError("Unknown object type provided as part of apply() call") # Validate all feature views and make inferences. self._validate_all_feature_views( views_to_update, odfvs_to_update, request_views_to_update ) - self._make_inferences(entities_to_update, views_to_update, odfvs_to_update) + self._make_inferences( + data_sources_to_update, entities_to_update, views_to_update, odfvs_to_update + ) # Handle all entityless feature views by using DUMMY_ENTITY as a placeholder entity. entities_to_update.append(DUMMY_ENTITY) # Add all objects to the registry and update the provider's infrastructure. + for ds in data_sources_to_update: + self._registry.apply_data_source(ds, project=self.project, commit=False) for view in itertools.chain( views_to_update, odfvs_to_update, request_views_to_update ): @@ -657,7 +698,14 @@ def apply( services_to_delete = [ ob for ob in objects_to_delete if isinstance(ob, FeatureService) ] + data_sources_to_delete = [ + ob for ob in objects_to_delete if isinstance(ob, DataSource) + ] + for data_source in data_sources_to_delete: + self._registry.delete_data_source( + data_source.name, project=self.project, commit=False + ) for entity in entities_to_delete: self._registry.delete_entity( entity.name, project=self.project, commit=False @@ -832,6 +880,8 @@ def create_saved_dataset( name: str, storage: SavedDatasetStorage, tags: Optional[Dict[str, str]] = None, + feature_service: Optional[FeatureService] = None, + profiler: Optional[GEProfiler] = None, ) -> SavedDataset: """ Execute provided retrieval job and persist its outcome in given storage. @@ -866,6 +916,7 @@ def create_saved_dataset( full_feature_names=from_.full_feature_names, storage=storage, tags=tags, + feature_service_name=feature_service.name if feature_service else None, ) dataset.min_event_timestamp = from_.metadata.min_event_timestamp @@ -873,14 +924,15 @@ def create_saved_dataset( from_.persist(storage) - self._registry.apply_saved_dataset(dataset, self.project, commit=True) - - return dataset.with_retrieval_job( + dataset = dataset.with_retrieval_job( self._get_provider().retrieve_saved_dataset( config=self.config, dataset=dataset ) ) + self._registry.apply_saved_dataset(dataset, self.project, commit=True) + return dataset + @log_exceptions_and_usage def get_saved_dataset(self, name: str) -> SavedDataset: """ @@ -1001,7 +1053,7 @@ def tqdm_builder(length): ) self._registry.apply_materialization( - feature_view, self.project, start_date, end_date + feature_view, self.project, start_date, end_date, ) @log_exceptions_and_usage @@ -1088,7 +1140,7 @@ def tqdm_builder(length): ) self._registry.apply_materialization( - feature_view, self.project, start_date, end_date + feature_view, self.project, start_date, end_date, ) @log_exceptions_and_usage @@ -1523,10 +1575,10 @@ def _read_from_online_store( # Each row is a set of features for a given entity key. We only need to convert # the data to Protobuf once. - row_ts_proto = Timestamp() null_value = Value() read_row_protos = [] for read_row in read_rows: + row_ts_proto = Timestamp() row_ts, feature_data = read_row if row_ts is not None: row_ts_proto.FromDatetime(row_ts) @@ -1916,3 +1968,18 @@ def _validate_feature_views(feature_views: List[BaseFeatureView]): ) else: fv_names.add(case_insensitive_fv_name) + + +def _validate_data_sources(data_sources: List[DataSource]): + """ Verify data sources have case-insensitively unique names""" + ds_names = set() + for fv in data_sources: + case_insensitive_ds_name = fv.name.lower() + if case_insensitive_ds_name in ds_names: + raise ValueError( + f"More than one data source with name {case_insensitive_ds_name} found. " + f"Please ensure that all data source names are case-insensitively unique. " + f"It may be necessary to ignore certain files in your feature repository by using a .feastignore file." + ) + else: + ds_names.add(case_insensitive_ds_name) diff --git a/sdk/python/feast/feature_view_projection.py b/sdk/python/feast/feature_view_projection.py index 97b3b0ab577..04d923122c5 100644 --- a/sdk/python/feast/feature_view_projection.py +++ b/sdk/python/feast/feature_view_projection.py @@ -10,6 +10,18 @@ @dataclass class FeatureViewProjection: + """ + A feature view projection represents a selection of one or more features from a + single feature view. + + Attributes: + name: The unique name of the feature view from which this projection is created. + name_alias: An optional alias for the name. + features: The list of features represented by the feature view projection. + join_key_map: A map to modify join key columns during retrieval of this feature + view projection. + """ + name: str name_alias: Optional[str] features: List[Feature] @@ -18,10 +30,10 @@ class FeatureViewProjection: def name_to_use(self): return self.name_alias or self.name - def to_proto(self): + def to_proto(self) -> FeatureViewProjectionProto: feature_reference_proto = FeatureViewProjectionProto( feature_view_name=self.name, - feature_view_name_alias=self.name_alias, + feature_view_name_alias=self.name_alias or "", join_key_map=self.join_key_map, ) for feature in self.features: @@ -31,16 +43,16 @@ def to_proto(self): @staticmethod def from_proto(proto: FeatureViewProjectionProto): - ref = FeatureViewProjection( + feature_view_projection = FeatureViewProjection( name=proto.feature_view_name, name_alias=proto.feature_view_name_alias, features=[], join_key_map=dict(proto.join_key_map), ) for feature_column in proto.feature_columns: - ref.features.append(Feature.from_proto(feature_column)) + feature_view_projection.features.append(Feature.from_proto(feature_column)) - return ref + return feature_view_projection @staticmethod def from_definition(feature_grouping): diff --git a/sdk/python/feast/inference.py b/sdk/python/feast/inference.py index ce8fa919f13..d233631d3da 100644 --- a/sdk/python/feast/inference.py +++ b/sdk/python/feast/inference.py @@ -8,8 +8,9 @@ FileSource, RedshiftSource, SnowflakeSource, + SparkSource, ) -from feast.data_source import DataSource +from feast.data_source import DataSource, RequestDataSource from feast.errors import RegistryInferenceFailure from feast.feature_view import FeatureView from feast.repo_config import RepoConfig @@ -78,13 +79,17 @@ def update_data_sources_with_inferred_event_timestamp_col( ERROR_MSG_PREFIX = "Unable to infer DataSource event_timestamp_column" for data_source in data_sources: + if isinstance(data_source, RequestDataSource): + continue if ( data_source.event_timestamp_column is None or data_source.event_timestamp_column == "" ): # prepare right match pattern for data source ts_column_type_regex_pattern = "" - if isinstance(data_source, FileSource): + if isinstance(data_source, FileSource) or isinstance( + data_source, SparkSource + ): ts_column_type_regex_pattern = r"^timestamp" elif isinstance(data_source, BigQuerySource): ts_column_type_regex_pattern = "TIMESTAMP|DATETIME" @@ -95,9 +100,10 @@ def update_data_sources_with_inferred_event_timestamp_col( else: raise RegistryInferenceFailure( "DataSource", - """ + f""" DataSource inferencing of event_timestamp_column is currently only supported - for FileSource and BigQuerySource. + for FileSource, SparkSource, BigQuerySource, RedshiftSource, and SnowflakeSource. + Attempting to infer from {data_source}. """, ) # for informing the type checker diff --git a/sdk/python/feast/infra/infra_object.py b/sdk/python/feast/infra/infra_object.py index f21016dea54..91770e64e5d 100644 --- a/sdk/python/feast/infra/infra_object.py +++ b/sdk/python/feast/infra/infra_object.py @@ -37,6 +37,14 @@ class InfraObject(ABC): Represents a single infrastructure object (e.g. online store table) managed by Feast. """ + @abstractmethod + def __init__(self, name: str): + self._name = name + + @property + def name(self) -> str: + return self._name + @abstractmethod def to_infra_object_proto(self) -> InfraObjectProto: """Converts an InfraObject to its protobuf representation, wrapped in an InfraObjectProto.""" @@ -47,6 +55,9 @@ def to_proto(self) -> Any: """Converts an InfraObject to its protobuf representation.""" pass + def __lt__(self, other) -> bool: + return self.name < other.name + @staticmethod @abstractmethod def from_infra_object_proto(infra_object_proto: InfraObjectProto) -> Any: @@ -136,7 +147,7 @@ def from_proto(cls, infra_proto: InfraProto): Returns an Infra object created from a protobuf representation. """ infra = cls() - cls.infra_objects += [ + infra.infra_objects += [ InfraObject.from_infra_object_proto(infra_object_proto) for infra_object_proto in infra_proto.infra_objects ] diff --git a/sdk/python/feast/infra/offline_stores/bigquery_source.py b/sdk/python/feast/infra/offline_stores/bigquery_source.py index f97f687b0f6..6c5be2b5f4c 100644 --- a/sdk/python/feast/infra/offline_stores/bigquery_source.py +++ b/sdk/python/feast/infra/offline_stores/bigquery_source.py @@ -1,8 +1,9 @@ +import warnings from typing import Callable, Dict, Iterable, List, Optional, Tuple from feast import type_map from feast.data_source import DataSource -from feast.errors import DataSourceNotFoundException +from feast.errors import DataSourceNoNameException, DataSourceNotFoundException from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto from feast.protos.feast.core.SavedDataset_pb2 import ( SavedDatasetStorage as SavedDatasetStorageProto, @@ -15,22 +16,67 @@ class BigQuerySource(DataSource): def __init__( self, + name: Optional[str] = None, event_timestamp_column: Optional[str] = "", + table: Optional[str] = None, table_ref: Optional[str] = None, created_timestamp_column: Optional[str] = "", field_mapping: Optional[Dict[str, str]] = None, date_partition_column: Optional[str] = "", query: Optional[str] = None, ): - self._bigquery_options = BigQueryOptions(table_ref=table_ref, query=query) + """Create a BigQuerySource from an existing table or query. + + Args: + name (optional): Name for the source. Defaults to the table_ref if not specified. + table (optional): The BigQuery table where features can be found. + table_ref (optional): (Deprecated) The BigQuery table where features can be found. + event_timestamp_column: Event timestamp column used for point in time joins of feature values. + created_timestamp_column (optional): Timestamp column when row was created, used for deduplicating rows. + field_mapping: A dictionary mapping of column names in this data source to feature names in a feature table + or view. Only used for feature columns, not entities or timestamp columns. + date_partition_column (optional): Timestamp column used for partitioning. + query (optional): SQL query to execute to generate data for this data source. + + Example: + >>> from feast import BigQuerySource + >>> my_bigquery_source = BigQuerySource(table="gcp_project:bq_dataset.bq_table") + """ + if table is None and table_ref is None and query is None: + raise ValueError('No "table" argument provided.') + if not table and table_ref: + warnings.warn( + ( + "The argument 'table_ref' is being deprecated. Please use 'table' " + "instead. Feast 0.20 and onwards will not support the argument 'table_ref'." + ), + DeprecationWarning, + ) + table = table_ref + self.bigquery_options = BigQueryOptions(table_ref=table, query=query) + + # If no name, use the table_ref as the default name + _name = name + if not _name: + if table: + _name = table + elif table_ref: + _name = table_ref + else: + raise DataSourceNoNameException() super().__init__( + _name if _name else "", event_timestamp_column, created_timestamp_column, field_mapping, date_partition_column, ) + # Note: Python requires redefining hash in child classes that override __eq__ + def __hash__(self): + return super().__hash__() + def __eq__(self, other): if not isinstance(other, BigQuerySource): raise TypeError( @@ -38,7 +84,8 @@ def __eq__(self, other): ) return ( - self.bigquery_options.table_ref == other.bigquery_options.table_ref + self.name == other.name + and self.bigquery_options.table_ref == other.bigquery_options.table_ref and self.bigquery_options.query == other.bigquery_options.query and self.event_timestamp_column == other.event_timestamp_column and self.created_timestamp_column == other.created_timestamp_column @@ -47,25 +94,11 @@ def __eq__(self, other): @property def table_ref(self): - return self._bigquery_options.table_ref + return self.bigquery_options.table_ref @property def query(self): - return self._bigquery_options.query - - @property - def bigquery_options(self): - """ - Returns the bigquery options of this data source - """ - return self._bigquery_options - - @bigquery_options.setter - def bigquery_options(self, bigquery_options): - """ - Sets the bigquery options of this data source - """ - self._bigquery_options = bigquery_options + return self.bigquery_options.query @staticmethod def from_proto(data_source: DataSourceProto): @@ -73,6 +106,7 @@ def from_proto(data_source: DataSourceProto): assert data_source.HasField("bigquery_options") return BigQuerySource( + name=data_source.name, field_mapping=dict(data_source.field_mapping), table_ref=data_source.bigquery_options.table_ref, event_timestamp_column=data_source.event_timestamp_column, @@ -83,6 +117,7 @@ def from_proto(data_source: DataSourceProto): def to_proto(self) -> DataSourceProto: data_source_proto = DataSourceProto( + name=self.name, type=DataSourceProto.BATCH_BIGQUERY, field_mapping=self.field_mapping, bigquery_options=self.bigquery_options.to_proto(), @@ -146,7 +181,9 @@ class BigQueryOptions: DataSource BigQuery options used to source features from BigQuery query """ - def __init__(self, table_ref: Optional[str], query: Optional[str]): + def __init__( + self, table_ref: Optional[str], query: Optional[str], + ): self._table_ref = table_ref self._query = query diff --git a/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/__init__.py b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark.py b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark.py new file mode 100644 index 00000000000..95e306aa605 --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark.py @@ -0,0 +1,522 @@ +import warnings +from datetime import datetime +from typing import Dict, List, Optional, Tuple, Union + +import numpy as np +import pandas +import pandas as pd +import pyarrow +import pyspark +from pydantic import StrictStr +from pyspark import SparkConf +from pyspark.sql import SparkSession +from pytz import utc + +from feast import FeatureView, OnDemandFeatureView +from feast.data_source import DataSource +from feast.errors import InvalidEntityType +from feast.feature_view import DUMMY_ENTITY_ID, DUMMY_ENTITY_VAL +from feast.infra.offline_stores import offline_utils +from feast.infra.offline_stores.contrib.spark_offline_store.spark_source import ( + SparkSource, +) +from feast.infra.offline_stores.offline_store import ( + OfflineStore, + RetrievalJob, + RetrievalMetadata, +) +from feast.registry import Registry +from feast.repo_config import FeastConfigBaseModel, RepoConfig +from feast.saved_dataset import SavedDatasetStorage +from feast.type_map import spark_schema_to_np_dtypes + + +class SparkOfflineStoreConfig(FeastConfigBaseModel): + type: StrictStr = "spark" + """ Offline store type selector""" + + spark_conf: Optional[Dict[str, str]] = None + """ Configuration overlay for the spark session """ + # sparksession is not serializable and we dont want to pass it around as an argument + + +class SparkOfflineStore(OfflineStore): + @staticmethod + def pull_latest_from_table_or_query( + config: RepoConfig, + data_source: DataSource, + join_key_columns: List[str], + feature_name_columns: List[str], + event_timestamp_column: str, + created_timestamp_column: Optional[str], + start_date: datetime, + end_date: datetime, + ) -> RetrievalJob: + spark_session = get_spark_session_or_start_new_with_repoconfig( + config.offline_store + ) + assert isinstance(config.offline_store, SparkOfflineStoreConfig) + assert isinstance(data_source, SparkSource) + + warnings.warn( + "The spark offline store is an experimental feature in alpha development. " + "Some functionality may still be unstable so functionality can change in the future.", + RuntimeWarning, + ) + + print("Pulling latest features from spark offline store") + + from_expression = data_source.get_table_query_string() + + partition_by_join_key_string = ", ".join(join_key_columns) + if partition_by_join_key_string != "": + partition_by_join_key_string = ( + "PARTITION BY " + partition_by_join_key_string + ) + timestamps = [event_timestamp_column] + if created_timestamp_column: + timestamps.append(created_timestamp_column) + timestamp_desc_string = " DESC, ".join(timestamps) + " DESC" + field_string = ", ".join(join_key_columns + feature_name_columns + timestamps) + + start_date_str = _format_datetime(start_date) + end_date_str = _format_datetime(end_date) + query = f""" + SELECT + {field_string} + {f", {repr(DUMMY_ENTITY_VAL)} AS {DUMMY_ENTITY_ID}" if not join_key_columns else ""} + FROM ( + SELECT {field_string}, + ROW_NUMBER() OVER({partition_by_join_key_string} ORDER BY {timestamp_desc_string}) AS feast_row_ + FROM {from_expression} t1 + WHERE {event_timestamp_column} BETWEEN TIMESTAMP('{start_date_str}') AND TIMESTAMP('{end_date_str}') + ) t2 + WHERE feast_row_ = 1 + """ + + return SparkRetrievalJob( + spark_session=spark_session, + query=query, + full_feature_names=False, + on_demand_feature_views=None, + ) + + @staticmethod + def get_historical_features( + config: RepoConfig, + feature_views: List[FeatureView], + feature_refs: List[str], + entity_df: Union[pandas.DataFrame, str], + registry: Registry, + project: str, + full_feature_names: bool = False, + ) -> RetrievalJob: + assert isinstance(config.offline_store, SparkOfflineStoreConfig) + warnings.warn( + "The spark offline store is an experimental feature in alpha development. " + "Some functionality may still be unstable so functionality can change in the future.", + RuntimeWarning, + ) + spark_session = get_spark_session_or_start_new_with_repoconfig( + store_config=config.offline_store + ) + tmp_entity_df_table_name = offline_utils.get_temp_entity_table_name() + + entity_schema = _upload_entity_df_and_get_entity_schema( + spark_session=spark_session, + table_name=tmp_entity_df_table_name, + entity_df=entity_df, + ) + event_timestamp_col = offline_utils.infer_event_timestamp_from_entity_df( + entity_schema=entity_schema, + ) + entity_df_event_timestamp_range = _get_entity_df_event_timestamp_range( + entity_df, event_timestamp_col, spark_session, + ) + + expected_join_keys = offline_utils.get_expected_join_keys( + project=project, feature_views=feature_views, registry=registry + ) + offline_utils.assert_expected_columns_in_entity_df( + entity_schema=entity_schema, + join_keys=expected_join_keys, + entity_df_event_timestamp_col=event_timestamp_col, + ) + + query_context = offline_utils.get_feature_view_query_context( + feature_refs, + feature_views, + registry, + project, + entity_df_event_timestamp_range, + ) + + query = offline_utils.build_point_in_time_query( + feature_view_query_contexts=query_context, + left_table_query_string=tmp_entity_df_table_name, + entity_df_event_timestamp_col=event_timestamp_col, + entity_df_columns=entity_schema.keys(), + query_template=MULTIPLE_FEATURE_VIEW_POINT_IN_TIME_JOIN, + full_feature_names=full_feature_names, + ) + + return SparkRetrievalJob( + spark_session=spark_session, + query=query, + full_feature_names=full_feature_names, + on_demand_feature_views=OnDemandFeatureView.get_requested_odfvs( + feature_refs, project, registry + ), + metadata=RetrievalMetadata( + features=feature_refs, + keys=list(set(entity_schema.keys()) - {event_timestamp_col}), + min_event_timestamp=entity_df_event_timestamp_range[0], + max_event_timestamp=entity_df_event_timestamp_range[1], + ), + ) + + @staticmethod + def pull_all_from_table_or_query( + config: RepoConfig, + data_source: DataSource, + join_key_columns: List[str], + feature_name_columns: List[str], + event_timestamp_column: str, + start_date: datetime, + end_date: datetime, + ) -> RetrievalJob: + """ + Note that join_key_columns, feature_name_columns, event_timestamp_column, and created_timestamp_column + have all already been mapped to column names of the source table and those column names are the values passed + into this function. + """ + assert isinstance(data_source, SparkSource) + warnings.warn( + "The spark offline store is an experimental feature in alpha development. " + "This API is unstable and it could and most probably will be changed in the future.", + RuntimeWarning, + ) + from_expression = data_source.get_table_query_string() + + field_string = ( + '"' + + '", "'.join( + join_key_columns + feature_name_columns + [event_timestamp_column] + ) + + '"' + ) + start_date = start_date.astimezone(tz=utc) + end_date = end_date.astimezone(tz=utc) + + query = f""" + SELECT {field_string} + FROM {from_expression} + WHERE "{event_timestamp_column}" BETWEEN TIMESTAMP '{start_date}' AND TIMESTAMP '{end_date}' + """ + spark_session = get_spark_session_or_start_new_with_repoconfig( + store_config=config.offline_store + ) + return SparkRetrievalJob( + spark_session=spark_session, query=query, full_feature_names=False + ) + + +class SparkRetrievalJob(RetrievalJob): + def __init__( + self, + spark_session: SparkSession, + query: str, + full_feature_names: bool, + on_demand_feature_views: Optional[List[OnDemandFeatureView]] = None, + metadata: Optional[RetrievalMetadata] = None, + ): + super().__init__() + self.spark_session = spark_session + self.query = query + self._full_feature_names = full_feature_names + self._on_demand_feature_views = on_demand_feature_views + self._metadata = metadata + + @property + def full_feature_names(self) -> bool: + return self._full_feature_names + + @property + def on_demand_feature_views(self) -> Optional[List[OnDemandFeatureView]]: + return self._on_demand_feature_views + + def to_spark_df(self) -> pyspark.sql.DataFrame: + statements = self.query.split( + "---EOS---" + ) # TODO can do better than this dirty split + *_, last = map(self.spark_session.sql, statements) + return last + + def _to_df_internal(self) -> pd.DataFrame: + """Return dataset as Pandas DataFrame synchronously""" + return self.to_spark_df().toPandas() + + def _to_arrow_internal(self) -> pyarrow.Table: + """Return dataset as pyarrow Table synchronously""" + df = self.to_df() + return pyarrow.Table.from_pandas(df) # noqa + + def persist(self, storage: SavedDatasetStorage): + """ + Run the retrieval and persist the results in the same offline store used for read. + """ + pass + + @property + def metadata(self) -> Optional[RetrievalMetadata]: + """ + Return metadata information about retrieval. + Should be available even before materializing the dataset itself. + """ + return self._metadata + + +def get_spark_session_or_start_new_with_repoconfig( + store_config: SparkOfflineStoreConfig, +) -> SparkSession: + spark_session = SparkSession.getActiveSession() + if not spark_session: + spark_builder = SparkSession.builder + spark_conf = store_config.spark_conf + if spark_conf: + spark_builder = spark_builder.config( + conf=SparkConf().setAll([(k, v) for k, v in spark_conf.items()]) + ) + + spark_session = spark_builder.getOrCreate() + spark_session.conf.set("spark.sql.parser.quotedRegexColumnNames", "true") + return spark_session + + +def _get_entity_df_event_timestamp_range( + entity_df: Union[pd.DataFrame, str], + entity_df_event_timestamp_col: str, + spark_session: SparkSession, +) -> Tuple[datetime, datetime]: + if isinstance(entity_df, pd.DataFrame): + entity_df_event_timestamp = entity_df.loc[ + :, entity_df_event_timestamp_col + ].infer_objects() + if pd.api.types.is_string_dtype(entity_df_event_timestamp): + entity_df_event_timestamp = pd.to_datetime( + entity_df_event_timestamp, utc=True + ) + entity_df_event_timestamp_range = ( + entity_df_event_timestamp.min().to_pydatetime(), + entity_df_event_timestamp.max().to_pydatetime(), + ) + elif isinstance(entity_df, str): + # If the entity_df is a string (SQL query), determine range + # from table + df = spark_session.sql(entity_df).select(entity_df_event_timestamp_col) + # TODO(kzhang132): need utc conversion here. + entity_df_event_timestamp_range = ( + df.agg({entity_df_event_timestamp_col: "max"}).collect()[0][0], + df.agg({entity_df_event_timestamp_col: "min"}).collect()[0][0], + ) + else: + raise InvalidEntityType(type(entity_df)) + + return entity_df_event_timestamp_range + + +def _upload_entity_df_and_get_entity_schema( + spark_session: SparkSession, + table_name: str, + entity_df: Union[pandas.DataFrame, str], +) -> Dict[str, np.dtype]: + if isinstance(entity_df, pd.DataFrame): + spark_session.createDataFrame(entity_df).createOrReplaceTempView(table_name) + return dict(zip(entity_df.columns, entity_df.dtypes)) + elif isinstance(entity_df, str): + spark_session.sql(entity_df).createOrReplaceTempView(table_name) + limited_entity_df = spark_session.table(table_name) + return dict( + zip( + limited_entity_df.columns, + spark_schema_to_np_dtypes(limited_entity_df.dtypes), + ) + ) + else: + raise InvalidEntityType(type(entity_df)) + + +def _format_datetime(t: datetime) -> str: + # Since Hive does not support timezone, need to transform to utc. + if t.tzinfo: + t = t.astimezone(tz=utc) + dt = t.strftime("%Y-%m-%d %H:%M:%S.%f") + return dt + + +MULTIPLE_FEATURE_VIEW_POINT_IN_TIME_JOIN = """/* + Compute a deterministic hash for the `left_table_query_string` that will be used throughout + all the logic as the field to GROUP BY the data +*/ +CREATE OR REPLACE TEMPORARY VIEW entity_dataframe AS ( + SELECT *, + {{entity_df_event_timestamp_col}} AS entity_timestamp + {% for featureview in featureviews %} + ,CONCAT( + {% for entity in featureview.entities %} + CAST({{entity}} AS STRING), + {% endfor %} + CAST({{entity_df_event_timestamp_col}} AS STRING) + ) AS {{featureview.name}}__entity_row_unique_id + {% endfor %} + FROM {{ left_table_query_string }} +); +---EOS--- +-- Start create temporary table *__base +{% for featureview in featureviews %} +CREATE OR REPLACE TEMPORARY VIEW {{ featureview.name }}__base AS +WITH {{ featureview.name }}__entity_dataframe AS ( + SELECT + {{ featureview.entities | join(', ')}}, + entity_timestamp, + {{featureview.name}}__entity_row_unique_id + FROM entity_dataframe + GROUP BY {{ featureview.entities | join(', ')}}, entity_timestamp, {{featureview.name}}__entity_row_unique_id +), +/* + This query template performs the point-in-time correctness join for a single feature set table + to the provided entity table. + 1. We first join the current feature_view to the entity dataframe that has been passed. + This JOIN has the following logic: + - For each row of the entity dataframe, only keep the rows where the `event_timestamp_column` + is less than the one provided in the entity dataframe + - If there a TTL for the current feature_view, also keep the rows where the `event_timestamp_column` + is higher the the one provided minus the TTL + - For each row, Join on the entity key and retrieve the `entity_row_unique_id` that has been + computed previously + The output of this CTE will contain all the necessary information and already filtered out most + of the data that is not relevant. +*/ +{{ featureview.name }}__subquery AS ( + SELECT + {{ featureview.event_timestamp_column }} as event_timestamp, + {{ featureview.created_timestamp_column ~ ' as created_timestamp,' if featureview.created_timestamp_column else '' }} + {{ featureview.entity_selections | join(', ')}}, + {% for feature in featureview.features %} + {{ feature }} as {% if full_feature_names %}{{ featureview.name }}__{{feature}}{% else %}{{ feature }}{% endif %}{% if loop.last %}{% else %}, {% endif %} + {% endfor %} + FROM {{ featureview.table_subquery }} AS subquery + INNER JOIN ( + SELECT MAX(entity_timestamp) as max_entity_timestamp_ + {% if featureview.ttl == 0 %}{% else %} + ,(MIN(entity_timestamp) - interval '{{ featureview.ttl }}' second) as min_entity_timestamp_ + {% endif %} + FROM entity_dataframe + ) AS temp + ON ( + {{ featureview.event_timestamp_column }} <= max_entity_timestamp_ + {% if featureview.ttl == 0 %}{% else %} + AND {{ featureview.event_timestamp_column }} >= min_entity_timestamp_ + {% endif %} + ) +) +SELECT + subquery.*, + entity_dataframe.entity_timestamp, + entity_dataframe.{{featureview.name}}__entity_row_unique_id +FROM {{ featureview.name }}__subquery AS subquery +INNER JOIN ( + SELECT * + {% if featureview.ttl == 0 %}{% else %} + , (entity_timestamp - interval '{{ featureview.ttl }}' second) as ttl_entity_timestamp + {% endif %} + FROM {{ featureview.name }}__entity_dataframe +) AS entity_dataframe +ON ( + subquery.event_timestamp <= entity_dataframe.entity_timestamp + {% if featureview.ttl == 0 %}{% else %} + AND subquery.event_timestamp >= entity_dataframe.ttl_entity_timestamp + {% endif %} + {% for entity in featureview.entities %} + AND subquery.{{ entity }} = entity_dataframe.{{ entity }} + {% endfor %} +); +---EOS--- +{% endfor %} +-- End create temporary table *__base +{% for featureview in featureviews %} +{% if loop.first %}WITH{% endif %} +/* + 2. If the `created_timestamp_column` has been set, we need to + deduplicate the data first. This is done by calculating the + `MAX(created_at_timestamp)` for each event_timestamp. + We then join the data on the next CTE +*/ +{% if featureview.created_timestamp_column %} +{{ featureview.name }}__dedup AS ( + SELECT + {{featureview.name}}__entity_row_unique_id, + event_timestamp, + MAX(created_timestamp) as created_timestamp + FROM {{ featureview.name }}__base + GROUP BY {{featureview.name}}__entity_row_unique_id, event_timestamp +), +{% endif %} +/* + 3. The data has been filtered during the first CTE "*__base" + Thus we only need to compute the latest timestamp of each feature. +*/ +{{ featureview.name }}__latest AS ( + SELECT + base.{{featureview.name}}__entity_row_unique_id, + MAX(base.event_timestamp) AS event_timestamp + {% if featureview.created_timestamp_column %} + ,MAX(base.created_timestamp) AS created_timestamp + {% endif %} + FROM {{ featureview.name }}__base AS base + {% if featureview.created_timestamp_column %} + INNER JOIN {{ featureview.name }}__dedup AS dedup + ON ( + dedup.{{featureview.name}}__entity_row_unique_id=base.{{featureview.name}}__entity_row_unique_id + AND dedup.event_timestamp=base.event_timestamp + AND dedup.created_timestamp=base.created_timestamp + ) + {% endif %} + GROUP BY base.{{featureview.name}}__entity_row_unique_id +), +/* + 4. Once we know the latest value of each feature for a given timestamp, + we can join again the data back to the original "base" dataset +*/ +{{ featureview.name }}__cleaned AS ( + SELECT base.* + FROM {{ featureview.name }}__base AS base + INNER JOIN {{ featureview.name }}__latest AS latest + ON ( + base.{{featureview.name}}__entity_row_unique_id=latest.{{featureview.name}}__entity_row_unique_id + AND base.event_timestamp=latest.event_timestamp + {% if featureview.created_timestamp_column %} + AND base.created_timestamp=latest.created_timestamp + {% endif %} + ) +){% if loop.last %}{% else %}, {% endif %} +{% endfor %} +/* + Joins the outputs of multiple time travel joins to a single table. + The entity_dataframe dataset being our source of truth here. + */ +SELECT `(entity_timestamp|{% for featureview in featureviews %}{{featureview.name}}__entity_row_unique_id{% if loop.last %}{% else %}|{% endif %}{% endfor %})?+.+` +FROM entity_dataframe +{% for featureview in featureviews %} +LEFT JOIN ( + SELECT + {{featureview.name}}__entity_row_unique_id + {% for feature in featureview.features %} + ,{% if full_feature_names %}{{ featureview.name }}__{{feature}}{% else %}{{ feature }}{% endif %} + {% endfor %} + FROM {{ featureview.name }}__cleaned +) AS {{ featureview.name }}__joined +ON ( + {{ featureview.name }}__joined.{{featureview.name}}__entity_row_unique_id=entity_dataframe.{{featureview.name}}__entity_row_unique_id +) +{% endfor %}""" diff --git a/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark_source.py b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark_source.py new file mode 100644 index 00000000000..3ffdf6eda0c --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark_source.py @@ -0,0 +1,254 @@ +import logging +import pickle +import traceback +import warnings +from enum import Enum +from typing import Any, Callable, Dict, Iterable, Optional, Tuple + +from pyspark.sql import SparkSession + +from feast.data_source import DataSource +from feast.errors import DataSourceNoNameException +from feast.infra.offline_stores.offline_utils import get_temp_entity_table_name +from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto +from feast.protos.feast.core.SavedDataset_pb2 import ( + SavedDatasetStorage as SavedDatasetStorageProto, +) +from feast.repo_config import RepoConfig +from feast.saved_dataset import SavedDatasetStorage +from feast.type_map import spark_to_feast_value_type +from feast.value_type import ValueType + +logger = logging.getLogger(__name__) + + +class SparkSourceFormat(Enum): + csv = "csv" + json = "json" + parquet = "parquet" + + +class SparkSource(DataSource): + def __init__( + self, + name: Optional[str] = None, + table: Optional[str] = None, + query: Optional[str] = None, + path: Optional[str] = None, + file_format: Optional[str] = None, + event_timestamp_column: Optional[str] = None, + created_timestamp_column: Optional[str] = None, + field_mapping: Optional[Dict[str, str]] = None, + date_partition_column: Optional[str] = None, + ): + # If no name, use the table_ref as the default name + _name = name + if not _name: + if table: + _name = table + else: + raise DataSourceNoNameException() + super().__init__( + _name, + event_timestamp_column, + created_timestamp_column, + field_mapping, + date_partition_column, + ) + warnings.warn( + "The spark data source API is an experimental feature in alpha development. " + "This API is unstable and it could and most probably will be changed in the future.", + RuntimeWarning, + ) + self.allowed_formats = [format.value for format in SparkSourceFormat] + + # Check that only one of the ways to load a spark dataframe can be used. + if sum([(arg is not None) for arg in [table, query, path]]) != 1: + raise ValueError( + "Exactly one of params(table, query, path) must be specified." + ) + + if path is not None: + if file_format is None: + raise ValueError( + "If 'path' is specified, then 'file_format' is required." + ) + if file_format not in self.allowed_formats: + raise ValueError( + f"'file_format' should be one of {self.allowed_formats}" + ) + + self.spark_options = SparkOptions( + table=table, query=query, path=path, file_format=file_format, + ) + + @property + def table(self): + """ + Returns the table of this feature data source + """ + return self.spark_options.table + + @property + def query(self): + """ + Returns the query of this feature data source + """ + return self.spark_options.query + + @property + def path(self): + """ + Returns the path of the spark data source file. + """ + return self.spark_options.path + + @property + def file_format(self): + """ + Returns the file format of this feature data source. + """ + return self.spark_options.file_format + + @staticmethod + def from_proto(data_source: DataSourceProto) -> Any: + assert data_source.HasField("custom_options") + + spark_options = SparkOptions.from_proto(data_source.custom_options) + return SparkSource( + name=data_source.name, + field_mapping=dict(data_source.field_mapping), + table=spark_options.table, + query=spark_options.query, + path=spark_options.path, + file_format=spark_options.file_format, + event_timestamp_column=data_source.event_timestamp_column, + created_timestamp_column=data_source.created_timestamp_column, + date_partition_column=data_source.date_partition_column, + ) + + def to_proto(self) -> DataSourceProto: + data_source_proto = DataSourceProto( + name=self.name, + type=DataSourceProto.CUSTOM_SOURCE, + field_mapping=self.field_mapping, + custom_options=self.spark_options.to_proto(), + ) + + data_source_proto.event_timestamp_column = self.event_timestamp_column + data_source_proto.created_timestamp_column = self.created_timestamp_column + data_source_proto.date_partition_column = self.date_partition_column + + return data_source_proto + + def validate(self, config: RepoConfig): + self.get_table_column_names_and_types(config) + + @staticmethod + def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]: + return spark_to_feast_value_type + + def get_table_column_names_and_types( + self, config: RepoConfig + ) -> Iterable[Tuple[str, str]]: + from feast.infra.offline_stores.contrib.spark_offline_store.spark import ( + get_spark_session_or_start_new_with_repoconfig, + ) + + spark_session = get_spark_session_or_start_new_with_repoconfig( + store_config=config.offline_store + ) + df = spark_session.sql(f"SELECT * FROM {self.get_table_query_string()}") + return ( + (fields["name"], fields["type"]) + for fields in df.schema.jsonValue()["fields"] + ) + + def get_table_query_string(self) -> str: + """Returns a string that can directly be used to reference this table in SQL""" + if self.table: + # Backticks make sure that spark sql knows this a table reference. + return f"`{self.table}`" + if self.query: + return f"({self.query})" + + # If both the table query string and the actual query are null, we can load from file. + spark_session = SparkSession.getActiveSession() + if spark_session is None: + raise AssertionError("Could not find an active spark session.") + try: + df = spark_session.read.format(self.file_format).load(self.path) + except Exception: + logger.exception( + "Spark read of file source failed.\n" + traceback.format_exc() + ) + tmp_table_name = get_temp_entity_table_name() + df.createOrReplaceTempView(tmp_table_name) + + return f"`{tmp_table_name}`" + + +class SparkOptions: + def __init__( + self, + table: Optional[str] = None, + query: Optional[str] = None, + path: Optional[str] = None, + file_format: Optional[str] = None, + ): + self.table = table + self.query = query + self.path = path + self.file_format = file_format + + @classmethod + def from_proto(cls, spark_options_proto: DataSourceProto.CustomSourceOptions): + """ + Creates a SparkOptions from a protobuf representation of a spark option + args: + spark_options_proto: a protobuf representation of a datasource + Returns: + Returns a SparkOptions object based on the spark_options protobuf + """ + spark_configuration = pickle.loads(spark_options_proto.configuration) + + spark_options = cls( + table=spark_configuration.table, + query=spark_configuration.query, + path=spark_configuration.path, + file_format=spark_configuration.file_format, + ) + return spark_options + + def to_proto(self) -> DataSourceProto.CustomSourceOptions: + """ + Converts an SparkOptionsProto object to its protobuf representation. + Returns: + SparkOptionsProto protobuf + """ + + spark_options_proto = DataSourceProto.CustomSourceOptions( + configuration=pickle.dumps(self), + ) + + return spark_options_proto + + +class SavedDatasetSparkStorage(SavedDatasetStorage): + _proto_attr_name = "spark_storage" + + spark_options: SparkOptions + + def __init__(self, table_ref: Optional[str] = None, query: Optional[str] = None): + self.spark_options = SparkOptions(table=table_ref, query=query) + + @staticmethod + def from_proto(storage_proto: SavedDatasetStorageProto) -> SavedDatasetStorage: + # TODO: implementation is not correct. Needs fix and update to protos. + return SavedDatasetSparkStorage(table_ref="", query=None) + + def to_proto(self) -> SavedDatasetStorageProto: + return SavedDatasetStorageProto() + + def to_data_source(self) -> DataSource: + return SparkSource(table=self.spark_options.table) diff --git a/sdk/python/feast/infra/offline_stores/file.py b/sdk/python/feast/infra/offline_stores/file.py index a49ce643d0b..c71f0c3ff74 100644 --- a/sdk/python/feast/infra/offline_stores/file.py +++ b/sdk/python/feast/infra/offline_stores/file.py @@ -1,6 +1,7 @@ from datetime import datetime from typing import Callable, List, Optional, Tuple, Union +import dask.dataframe as dd import pandas as pd import pyarrow import pytz @@ -21,7 +22,7 @@ ) from feast.infra.provider import ( _get_requested_feature_views_to_features_dict, - _run_field_mapping, + _run_dask_field_mapping, ) from feast.registry import Registry from feast.repo_config import FeastConfigBaseModel, RepoConfig @@ -65,13 +66,13 @@ def on_demand_feature_views(self) -> Optional[List[OnDemandFeatureView]]: @log_exceptions_and_usage def _to_df_internal(self) -> pd.DataFrame: # Only execute the evaluation function to build the final historical retrieval dataframe at the last moment. - df = self.evaluation_function() + df = self.evaluation_function().compute() return df @log_exceptions_and_usage def _to_arrow_internal(self): # Only execute the evaluation function to build the final historical retrieval dataframe at the last moment. - df = self.evaluation_function() + df = self.evaluation_function().compute() return pyarrow.Table.from_pandas(df) def persist(self, storage: SavedDatasetStorage): @@ -108,7 +109,9 @@ def get_historical_features( project: str, full_feature_names: bool = False, ) -> RetrievalJob: - if not isinstance(entity_df, pd.DataFrame): + if not isinstance(entity_df, pd.DataFrame) and not isinstance( + entity_df, dd.DataFrame + ): raise ValueError( f"Please provide an entity_df of type {type(pd.DataFrame)} instead of type {type(entity_df)}" ) @@ -142,25 +145,46 @@ def get_historical_features( # Create lazy function that is only called from the RetrievalJob object def evaluate_historical_retrieval(): - # Make sure all event timestamp fields are tz-aware. We default tz-naive fields to UTC - entity_df[entity_df_event_timestamp_col] = entity_df[ - entity_df_event_timestamp_col - ].apply(lambda x: x if x.tzinfo is not None else x.replace(tzinfo=pytz.utc)) - # Create a copy of entity_df to prevent modifying the original entity_df_with_features = entity_df.copy() - # Convert event timestamp column to datetime and normalize time zone to UTC - # This is necessary to avoid issues with pd.merge_asof - entity_df_with_features[entity_df_event_timestamp_col] = pd.to_datetime( - entity_df_with_features[entity_df_event_timestamp_col], utc=True - ) + entity_df_event_timestamp_col_type = entity_df_with_features.dtypes[ + entity_df_event_timestamp_col + ] + if ( + not hasattr(entity_df_event_timestamp_col_type, "tz") + or entity_df_event_timestamp_col_type.tz != pytz.UTC + ): + # Make sure all event timestamp fields are tz-aware. We default tz-naive fields to UTC + entity_df_with_features[ + entity_df_event_timestamp_col + ] = entity_df_with_features[entity_df_event_timestamp_col].apply( + lambda x: x if x.tzinfo is not None else x.replace(tzinfo=pytz.utc) + ) + + # Convert event timestamp column to datetime and normalize time zone to UTC + # This is necessary to avoid issues with pd.merge_asof + if isinstance(entity_df_with_features, dd.DataFrame): + entity_df_with_features[ + entity_df_event_timestamp_col + ] = dd.to_datetime( + entity_df_with_features[entity_df_event_timestamp_col], utc=True + ) + else: + entity_df_with_features[ + entity_df_event_timestamp_col + ] = pd.to_datetime( + entity_df_with_features[entity_df_event_timestamp_col], utc=True + ) # Sort event timestamp values entity_df_with_features = entity_df_with_features.sort_values( entity_df_event_timestamp_col ) + join_keys = [] + all_join_keys = [] + # Load feature view data from sources and join them incrementally for feature_view, features in feature_views_to_features.items(): event_timestamp_column = ( @@ -170,128 +194,65 @@ def evaluate_historical_retrieval(): feature_view.batch_source.created_timestamp_column ) - # Read offline parquet data in pyarrow format. - filesystem, path = FileSource.create_filesystem_and_path( - feature_view.batch_source.path, - feature_view.batch_source.file_options.s3_endpoint_override, - ) - table = pyarrow.parquet.read_table(path, filesystem=filesystem) - - # Rename columns by the field mapping dictionary if it exists - if feature_view.batch_source.field_mapping is not None: - table = _run_field_mapping( - table, feature_view.batch_source.field_mapping - ) - # Rename entity columns by the join_key_map dictionary if it exists - if feature_view.projection.join_key_map: - table = _run_field_mapping( - table, feature_view.projection.join_key_map - ) - - # Convert pyarrow table to pandas dataframe. Note, if the underlying data has missing values, - # pandas will convert those values to np.nan if the dtypes are numerical (floats, ints, etc.) or boolean - # If the dtype is 'object', then missing values are inferred as python `None`s. - # More details at: - # https://pandas.pydata.org/pandas-docs/stable/user_guide/missing_data.html#values-considered-missing - df_to_join = table.to_pandas() - - # Make sure all timestamp fields are tz-aware. We default tz-naive fields to UTC - df_to_join[event_timestamp_column] = df_to_join[ - event_timestamp_column - ].apply( - lambda x: x if x.tzinfo is not None else x.replace(tzinfo=pytz.utc) - ) - if created_timestamp_column: - df_to_join[created_timestamp_column] = df_to_join[ - created_timestamp_column - ].apply( - lambda x: x - if x.tzinfo is not None - else x.replace(tzinfo=pytz.utc) - ) - - # Sort dataframe by the event timestamp column - df_to_join = df_to_join.sort_values(event_timestamp_column) - - # Build a list of all the features we should select from this source - feature_names = [] - for feature in features: - # Modify the separator for feature refs in column names to double underscore. We are using - # double underscore as separator for consistency with other databases like BigQuery, - # where there are very few characters available for use as separators - if full_feature_names: - formatted_feature_name = ( - f"{feature_view.projection.name_to_use()}__{feature}" - ) - else: - formatted_feature_name = feature - # Add the feature name to the list of columns - feature_names.append(formatted_feature_name) - - # Ensure that the source dataframe feature column includes the feature view name as a prefix - df_to_join.rename( - columns={feature: formatted_feature_name}, inplace=True, - ) - # Build a list of entity columns to join on (from the right table) join_keys = [] + for entity_name in feature_view.entities: entity = registry.get_entity(entity_name, project) join_key = feature_view.projection.join_key_map.get( entity.join_key, entity.join_key ) join_keys.append(join_key) - right_entity_columns = join_keys + right_entity_key_columns = [ - event_timestamp_column - ] + right_entity_columns - - # Remove all duplicate entity keys (using created timestamp) - right_entity_key_sort_columns = right_entity_key_columns - if created_timestamp_column: - # If created_timestamp is available, use it to dedupe deterministically - right_entity_key_sort_columns = right_entity_key_sort_columns + [ - created_timestamp_column - ] - - df_to_join.sort_values(by=right_entity_key_sort_columns, inplace=True) - df_to_join.drop_duplicates( - right_entity_key_sort_columns, - keep="last", - ignore_index=True, - inplace=True, + event_timestamp_column, + created_timestamp_column, + ] + join_keys + right_entity_key_columns = [c for c in right_entity_key_columns if c] + + all_join_keys = list(set(all_join_keys + join_keys)) + + df_to_join = _read_datasource(feature_view.batch_source) + + df_to_join, event_timestamp_column = _field_mapping( + df_to_join, + feature_view, + features, + right_entity_key_columns, + entity_df_event_timestamp_col, + event_timestamp_column, + full_feature_names, ) - # Select only the columns we need to join from the feature dataframe - df_to_join = df_to_join[right_entity_key_columns + feature_names] + df_to_join = _merge(entity_df_with_features, df_to_join, join_keys) + + df_to_join = _normalize_timestamp( + df_to_join, event_timestamp_column, created_timestamp_column + ) - # Do point in-time-join between entity_df and feature dataframe - entity_df_with_features = pd.merge_asof( - entity_df_with_features, + df_to_join = _filter_ttl( df_to_join, - left_on=entity_df_event_timestamp_col, - right_on=event_timestamp_column, - by=right_entity_columns or None, - tolerance=feature_view.ttl, + feature_view, + entity_df_event_timestamp_col, + event_timestamp_column, ) - # Remove right (feature table/view) event_timestamp column. - if event_timestamp_column != entity_df_event_timestamp_col: - entity_df_with_features.drop( - columns=[event_timestamp_column], inplace=True - ) + df_to_join = _drop_duplicates( + df_to_join, + all_join_keys, + event_timestamp_column, + created_timestamp_column, + entity_df_event_timestamp_col, + ) + + entity_df_with_features = _drop_columns( + df_to_join, event_timestamp_column, created_timestamp_column + ) # Ensure that we delete dataframes to free up memory del df_to_join - # Move "event_timestamp" column to front - current_cols = entity_df_with_features.columns.tolist() - current_cols.remove(entity_df_event_timestamp_col) - entity_df_with_features = entity_df_with_features[ - [entity_df_event_timestamp_col] + current_cols - ] - - return entity_df_with_features + return entity_df_with_features.persist() job = FileRetrievalJob( evaluation_function=evaluate_historical_retrieval, @@ -324,20 +285,11 @@ def pull_latest_from_table_or_query( # Create lazy function that is only called from the RetrievalJob object def evaluate_offline_job(): - filesystem, path = FileSource.create_filesystem_and_path( - data_source.path, data_source.file_options.s3_endpoint_override - ) - source_df = pd.read_parquet(path, filesystem=filesystem) - # Make sure all timestamp fields are tz-aware. We default tz-naive fields to UTC - source_df[event_timestamp_column] = source_df[event_timestamp_column].apply( - lambda x: x if x.tzinfo is not None else x.replace(tzinfo=pytz.utc) + source_df = _read_datasource(data_source) + + source_df = _normalize_timestamp( + source_df, event_timestamp_column, created_timestamp_column ) - if created_timestamp_column: - source_df[created_timestamp_column] = source_df[ - created_timestamp_column - ].apply( - lambda x: x if x.tzinfo is not None else x.replace(tzinfo=pytz.utc) - ) source_columns = set(source_df.columns) if not set(join_key_columns).issubset(source_columns): @@ -351,26 +303,32 @@ def evaluate_offline_job(): else [event_timestamp_column] ) - source_df.sort_values(by=ts_columns, inplace=True) + if created_timestamp_column: + source_df = source_df.sort_values(by=created_timestamp_column) + + source_df = source_df.sort_values(by=event_timestamp_column) - filtered_df = source_df[ + source_df = source_df[ (source_df[event_timestamp_column] >= start_date) & (source_df[event_timestamp_column] < end_date) ] + source_df = source_df.persist() + columns_to_extract = set( join_key_columns + feature_name_columns + ts_columns ) if join_key_columns: - last_values_df = filtered_df.drop_duplicates( + source_df = source_df.drop_duplicates( join_key_columns, keep="last", ignore_index=True ) else: - last_values_df = filtered_df - last_values_df[DUMMY_ENTITY_ID] = DUMMY_ENTITY_VAL + source_df[DUMMY_ENTITY_ID] = DUMMY_ENTITY_VAL columns_to_extract.add(DUMMY_ENTITY_ID) - return last_values_df[columns_to_extract] + source_df = source_df.persist() + + return source_df[list(columns_to_extract)].persist() # When materializing a single feature view, we don't need full feature names. On demand transforms aren't materialized return FileRetrievalJob( @@ -419,3 +377,200 @@ def _get_entity_df_event_timestamp_range( entity_df_event_timestamp.min().to_pydatetime(), entity_df_event_timestamp.max().to_pydatetime(), ) + + +def _read_datasource(data_source) -> dd.DataFrame: + storage_options = ( + { + "client_kwargs": { + "endpoint_url": data_source.file_options.s3_endpoint_override + } + } + if data_source.file_options.s3_endpoint_override + else None + ) + + return dd.read_parquet(data_source.path, storage_options=storage_options,) + + +def _field_mapping( + df_to_join: dd.DataFrame, + feature_view: FeatureView, + features: List[str], + right_entity_key_columns: List[str], + entity_df_event_timestamp_col: str, + event_timestamp_column: str, + full_feature_names: bool, +) -> dd.DataFrame: + # Rename columns by the field mapping dictionary if it exists + if feature_view.batch_source.field_mapping: + df_to_join = _run_dask_field_mapping( + df_to_join, feature_view.batch_source.field_mapping + ) + # Rename entity columns by the join_key_map dictionary if it exists + if feature_view.projection.join_key_map: + df_to_join = _run_dask_field_mapping( + df_to_join, feature_view.projection.join_key_map + ) + + # Build a list of all the features we should select from this source + feature_names = [] + columns_map = {} + for feature in features: + # Modify the separator for feature refs in column names to double underscore. We are using + # double underscore as separator for consistency with other databases like BigQuery, + # where there are very few characters available for use as separators + if full_feature_names: + formatted_feature_name = ( + f"{feature_view.projection.name_to_use()}__{feature}" + ) + else: + formatted_feature_name = feature + # Add the feature name to the list of columns + feature_names.append(formatted_feature_name) + columns_map[feature] = formatted_feature_name + + # Ensure that the source dataframe feature column includes the feature view name as a prefix + df_to_join = _run_dask_field_mapping(df_to_join, columns_map) + + # Select only the columns we need to join from the feature dataframe + df_to_join = df_to_join[right_entity_key_columns + feature_names] + df_to_join = df_to_join.persist() + + # Make sure to not have duplicated columns + if entity_df_event_timestamp_col == event_timestamp_column: + df_to_join = _run_dask_field_mapping( + df_to_join, {event_timestamp_column: f"__{event_timestamp_column}"}, + ) + event_timestamp_column = f"__{event_timestamp_column}" + + return df_to_join.persist(), event_timestamp_column + + +def _merge( + entity_df_with_features: dd.DataFrame, + df_to_join: dd.DataFrame, + join_keys: List[str], +) -> dd.DataFrame: + # tmp join keys needed for cross join with null join table view + tmp_join_keys = [] + if not join_keys: + entity_df_with_features["__tmp"] = 1 + df_to_join["__tmp"] = 1 + tmp_join_keys = ["__tmp"] + + # Get only data with requested entities + df_to_join = dd.merge( + entity_df_with_features, + df_to_join, + left_on=join_keys or tmp_join_keys, + right_on=join_keys or tmp_join_keys, + suffixes=("", "__"), + how="left", + ) + + if tmp_join_keys: + df_to_join = df_to_join.drop(tmp_join_keys, axis=1).persist() + else: + df_to_join = df_to_join.persist() + + return df_to_join + + +def _normalize_timestamp( + df_to_join: dd.DataFrame, + event_timestamp_column: str, + created_timestamp_column: str, +) -> dd.DataFrame: + df_to_join_types = df_to_join.dtypes + event_timestamp_column_type = df_to_join_types[event_timestamp_column] + + if created_timestamp_column: + created_timestamp_column_type = df_to_join_types[created_timestamp_column] + + if ( + not hasattr(event_timestamp_column_type, "tz") + or event_timestamp_column_type.tz != pytz.UTC + ): + # Make sure all timestamp fields are tz-aware. We default tz-naive fields to UTC + df_to_join[event_timestamp_column] = df_to_join[event_timestamp_column].apply( + lambda x: x if x.tzinfo is not None else x.replace(tzinfo=pytz.utc), + meta=(event_timestamp_column, "datetime64[ns, UTC]"), + ) + + if created_timestamp_column and ( + not hasattr(created_timestamp_column_type, "tz") + or created_timestamp_column_type.tz != pytz.UTC + ): + df_to_join[created_timestamp_column] = df_to_join[ + created_timestamp_column + ].apply( + lambda x: x if x.tzinfo is not None else x.replace(tzinfo=pytz.utc), + meta=(event_timestamp_column, "datetime64[ns, UTC]"), + ) + + return df_to_join.persist() + + +def _filter_ttl( + df_to_join: dd.DataFrame, + feature_view: FeatureView, + entity_df_event_timestamp_col: str, + event_timestamp_column: str, +) -> dd.DataFrame: + # Filter rows by defined timestamp tolerance + if feature_view.ttl and feature_view.ttl.total_seconds() != 0: + df_to_join = df_to_join[ + ( + df_to_join[event_timestamp_column] + >= df_to_join[entity_df_event_timestamp_col] - feature_view.ttl + ) + & ( + df_to_join[event_timestamp_column] + <= df_to_join[entity_df_event_timestamp_col] + ) + ] + + df_to_join = df_to_join.persist() + + return df_to_join + + +def _drop_duplicates( + df_to_join: dd.DataFrame, + all_join_keys: List[str], + event_timestamp_column: str, + created_timestamp_column: str, + entity_df_event_timestamp_col: str, +) -> dd.DataFrame: + if created_timestamp_column: + df_to_join = df_to_join.sort_values( + by=created_timestamp_column, na_position="first" + ) + df_to_join = df_to_join.persist() + + df_to_join = df_to_join.sort_values(by=event_timestamp_column, na_position="first") + df_to_join = df_to_join.persist() + + df_to_join = df_to_join.drop_duplicates( + all_join_keys + [entity_df_event_timestamp_col], keep="last", ignore_index=True, + ) + + return df_to_join.persist() + + +def _drop_columns( + df_to_join: dd.DataFrame, + event_timestamp_column: str, + created_timestamp_column: str, +) -> dd.DataFrame: + entity_df_with_features = df_to_join.drop( + [event_timestamp_column], axis=1 + ).persist() + + if created_timestamp_column: + entity_df_with_features = entity_df_with_features.drop( + [created_timestamp_column], axis=1 + ).persist() + + return entity_df_with_features diff --git a/sdk/python/feast/infra/offline_stores/file_source.py b/sdk/python/feast/infra/offline_stores/file_source.py index 7d52110985a..59e703dd6fb 100644 --- a/sdk/python/feast/infra/offline_stores/file_source.py +++ b/sdk/python/feast/infra/offline_stores/file_source.py @@ -19,10 +19,10 @@ class FileSource(DataSource): def __init__( self, + path: str, + name: Optional[str] = "", event_timestamp_column: Optional[str] = "", - file_url: Optional[str] = None, - path: Optional[str] = None, - file_format: FileFormat = None, + file_format: Optional[FileFormat] = None, created_timestamp_column: Optional[str] = "", field_mapping: Optional[Dict[str, str]] = None, date_partition_column: Optional[str] = "", @@ -32,52 +32,50 @@ def __init__( Args: + name (optional): Name for the file source. Defaults to the path. path: File path to file containing feature data. Must contain an event_timestamp column, entity columns and feature columns. event_timestamp_column: Event timestamp column used for point in time joins of feature values. created_timestamp_column (optional): Timestamp column when row was created, used for deduplicating rows. - file_url: [Deprecated] Please see path file_format (optional): Explicitly set the file format. Allows Feast to bypass inferring the file format. field_mapping: A dictionary mapping of column names in this data source to feature names in a feature table or view. Only used for feature columns, not entities or timestamp columns. + date_partition_column (optional): Timestamp column used for partitioning. s3_endpoint_override (optional): Overrides AWS S3 enpoint with custom S3 storage Examples: >>> from feast import FileSource >>> file_source = FileSource(path="my_features.parquet", event_timestamp_column="event_timestamp") """ - if path is None and file_url is None: + if path is None: raise ValueError( 'No "path" argument provided. Please set "path" to the location of your file source.' ) - if file_url: - from warnings import warn - - warn( - 'Argument "file_url" is being deprecated. Please use the "path" argument.' - ) - else: - file_url = path - - self._file_options = FileOptions( + self.file_options = FileOptions( file_format=file_format, - file_url=file_url, + file_url=path, s3_endpoint_override=s3_endpoint_override, ) super().__init__( + name if name else path, event_timestamp_column, created_timestamp_column, field_mapping, date_partition_column, ) + # Note: Python requires redefining hash in child classes that override __eq__ + def __hash__(self): + return super().__hash__() + def __eq__(self, other): if not isinstance(other, FileSource): raise TypeError("Comparisons should only involve FileSource class objects.") return ( - self.file_options.file_url == other.file_options.file_url + self.name == other.name + and self.file_options.file_url == other.file_options.file_url and self.file_options.file_format == other.file_options.file_format and self.event_timestamp_column == other.event_timestamp_column and self.created_timestamp_column == other.created_timestamp_column @@ -86,30 +84,17 @@ def __eq__(self, other): == other.file_options.s3_endpoint_override ) - @property - def file_options(self): - """ - Returns the file options of this data source - """ - return self._file_options - - @file_options.setter - def file_options(self, file_options): - """ - Sets the file options of this data source - """ - self._file_options = file_options - @property def path(self): """ - Returns the file path of this feature data source + Returns the path of this file data source. """ - return self._file_options.file_url + return self.file_options.file_url @staticmethod def from_proto(data_source: DataSourceProto): return FileSource( + name=data_source.name, field_mapping=dict(data_source.field_mapping), file_format=FileFormat.from_proto(data_source.file_options.file_format), path=data_source.file_options.file_url, @@ -121,6 +106,7 @@ def from_proto(data_source: DataSourceProto): def to_proto(self) -> DataSourceProto: data_source_proto = DataSourceProto( + name=self.name, type=DataSourceProto.BATCH_FILE, field_mapping=self.field_mapping, file_options=self.file_options.to_proto(), @@ -144,7 +130,7 @@ def get_table_column_names_and_types( self, config: RepoConfig ) -> Iterable[Tuple[str, str]]: filesystem, path = FileSource.create_filesystem_and_path( - self.path, self._file_options.s3_endpoint_override + self.path, self.file_options.s3_endpoint_override ) schema = ParquetFile( path if filesystem is None else filesystem.open_input_file(path) @@ -163,6 +149,9 @@ def create_filesystem_and_path( else: return None, path + def get_table_query_string(self) -> str: + pass + class FileOptions: """ diff --git a/sdk/python/feast/infra/offline_stores/offline_store.py b/sdk/python/feast/infra/offline_stores/offline_store.py index 1e5fe573774..a3065a31c0e 100644 --- a/sdk/python/feast/infra/offline_stores/offline_store.py +++ b/sdk/python/feast/infra/offline_stores/offline_store.py @@ -116,7 +116,6 @@ def to_arrow( Return dataset as pyarrow Table synchronously Args: validation_reference: If provided resulting dataset will be validated against this reference profile. - """ if not self.on_demand_feature_views and not validation_reference: return self._to_arrow_internal() diff --git a/sdk/python/feast/infra/offline_stores/redshift_source.py b/sdk/python/feast/infra/offline_stores/redshift_source.py index 949f1c9221c..19b88544a0e 100644 --- a/sdk/python/feast/infra/offline_stores/redshift_source.py +++ b/sdk/python/feast/infra/offline_stores/redshift_source.py @@ -2,7 +2,11 @@ from feast import type_map from feast.data_source import DataSource -from feast.errors import DataSourceNotFoundException, RedshiftCredentialsError +from feast.errors import ( + DataSourceNoNameException, + DataSourceNotFoundException, + RedshiftCredentialsError, +) from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto from feast.protos.feast.core.SavedDataset_pb2 import ( SavedDatasetStorage as SavedDatasetStorageProto, @@ -15,6 +19,7 @@ class RedshiftSource(DataSource): def __init__( self, + name: Optional[str] = None, event_timestamp_column: Optional[str] = "", table: Optional[str] = None, schema: Optional[str] = None, @@ -27,6 +32,7 @@ def __init__( Creates a RedshiftSource object. Args: + name (optional): Name for the source. Defaults to the table_ref if not specified. event_timestamp_column (optional): Event timestamp column used for point in time joins of feature values. table (optional): Redshift table where the features are stored. @@ -38,7 +44,18 @@ def __init__( date_partition_column (optional): Timestamp column used for partitioning. query (optional): The query to be executed to obtain the features. """ + if table is None and query is None: + raise ValueError('No "table" argument provided.') + _name = name + if not _name: + if table: + _name = table + else: + raise DataSourceNoNameException() + + # TODO(adchia): figure out what to do if user uses the query to start super().__init__( + _name, event_timestamp_column, created_timestamp_column, field_mapping, @@ -48,7 +65,7 @@ def __init__( # The default Redshift schema is named "public". _schema = "public" if table and not schema else schema - self._redshift_options = RedshiftOptions( + self.redshift_options = RedshiftOptions( table=table, schema=_schema, query=query ) @@ -80,7 +97,8 @@ def __eq__(self, other): ) return ( - self.redshift_options.table == other.redshift_options.table + self.name == other.name + and self.redshift_options.table == other.redshift_options.table and self.redshift_options.schema == other.redshift_options.schema and self.redshift_options.query == other.redshift_options.query and self.event_timestamp_column == other.event_timestamp_column @@ -91,27 +109,17 @@ def __eq__(self, other): @property def table(self): """Returns the table of this Redshift source.""" - return self._redshift_options.table + return self.redshift_options.table @property def schema(self): """Returns the schema of this Redshift source.""" - return self._redshift_options.schema + return self.redshift_options.schema @property def query(self): """Returns the Redshift options of this Redshift source.""" - return self._redshift_options.query - - @property - def redshift_options(self): - """Returns the Redshift options of this Redshift source.""" - return self._redshift_options - - @redshift_options.setter - def redshift_options(self, _redshift_options): - """Sets the Redshift options of this Redshift source.""" - self._redshift_options = _redshift_options + return self.redshift_options.query def to_proto(self) -> DataSourceProto: """ diff --git a/sdk/python/feast/infra/offline_stores/snowflake_source.py b/sdk/python/feast/infra/offline_stores/snowflake_source.py index b5d50be0f4d..ff36f1a66a0 100644 --- a/sdk/python/feast/infra/offline_stores/snowflake_source.py +++ b/sdk/python/feast/infra/offline_stores/snowflake_source.py @@ -2,6 +2,7 @@ from feast import type_map from feast.data_source import DataSource +from feast.errors import DataSourceNoNameException from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto from feast.protos.feast.core.SavedDataset_pb2 import ( SavedDatasetStorage as SavedDatasetStorageProto, @@ -14,6 +15,7 @@ class SnowflakeSource(DataSource): def __init__( self, + name: Optional[str] = None, database: Optional[str] = None, schema: Optional[str] = None, table: Optional[str] = None, @@ -27,6 +29,7 @@ def __init__( Creates a SnowflakeSource object. Args: + name (optional): Name for the source. Defaults to the table if not specified. database (optional): Snowflake database where the features are stored. schema (optional): Snowflake schema in which the table is located. table (optional): Snowflake table where the features are stored. @@ -40,7 +43,19 @@ def __init__( date_partition_column (optional): Timestamp column used for partitioning. """ + if table is None and query is None: + raise ValueError('No "table" argument provided.') + + # If no name, use the table as the default name + _name = name + if not _name: + if table: + _name = table + else: + raise DataSourceNoNameException() + super().__init__( + _name, event_timestamp_column, created_timestamp_column, field_mapping, @@ -50,7 +65,7 @@ def __init__( # The default Snowflake schema is named "PUBLIC". _schema = "PUBLIC" if (database and table and not schema) else schema - self._snowflake_options = SnowflakeOptions( + self.snowflake_options = SnowflakeOptions( database=database, schema=_schema, table=table, query=query ) @@ -83,7 +98,8 @@ def __eq__(self, other): ) return ( - self.snowflake_options.database == other.snowflake_options.database + self.name == other.name + and self.snowflake_options.database == other.snowflake_options.database and self.snowflake_options.schema == other.snowflake_options.schema and self.snowflake_options.table == other.snowflake_options.table and self.snowflake_options.query == other.snowflake_options.query @@ -95,32 +111,22 @@ def __eq__(self, other): @property def database(self): """Returns the database of this snowflake source.""" - return self._snowflake_options.database + return self.snowflake_options.database @property def schema(self): """Returns the schema of this snowflake source.""" - return self._snowflake_options.schema + return self.snowflake_options.schema @property def table(self): """Returns the table of this snowflake source.""" - return self._snowflake_options.table + return self.snowflake_options.table @property def query(self): """Returns the snowflake options of this snowflake source.""" - return self._snowflake_options.query - - @property - def snowflake_options(self): - """Returns the snowflake options of this snowflake source.""" - return self._snowflake_options - - @snowflake_options.setter - def snowflake_options(self, _snowflake_options): - """Sets the snowflake options of this snowflake source.""" - self._snowflake_options = _snowflake_options + return self.snowflake_options.query def to_proto(self) -> DataSourceProto: """ diff --git a/sdk/python/feast/infra/online_stores/datastore.py b/sdk/python/feast/infra/online_stores/datastore.py index 5a8d4b71803..a29a8393e2e 100644 --- a/sdk/python/feast/infra/online_stores/datastore.py +++ b/sdk/python/feast/infra/online_stores/datastore.py @@ -336,7 +336,6 @@ class DatastoreTable(InfraObject): """ project: str - name: str project_id: Optional[str] namespace: Optional[str] @@ -347,8 +346,8 @@ def __init__( project_id: Optional[str] = None, namespace: Optional[str] = None, ): + super().__init__(name) self.project = project - self.name = name self.project_id = project_id self.namespace = namespace diff --git a/sdk/python/feast/infra/online_stores/dynamodb.py b/sdk/python/feast/infra/online_stores/dynamodb.py index 46592bf2a3d..66c32c1fb8b 100644 --- a/sdk/python/feast/infra/online_stores/dynamodb.py +++ b/sdk/python/feast/infra/online_stores/dynamodb.py @@ -56,6 +56,10 @@ class DynamoDBOnlineStoreConfig(FeastConfigBaseModel): class DynamoDBOnlineStore(OnlineStore): """ Online feature store for AWS DynamoDB. + + Attributes: + _dynamodb_client: Boto3 DynamoDB client. + _dynamodb_resource: Boto3 DynamoDB resource. """ _dynamodb_client = None @@ -71,6 +75,14 @@ def update( entities_to_keep: Sequence[Entity], partial: bool, ): + """ + Update tables from the DynamoDB Online Store. + + Args: + config: The RepoConfig for the current FeatureStore. + tables_to_delete: Tables to delete from the DynamoDB Online Store. + tables_to_keep: Tables to keep in the DynamoDB Online Store. + """ online_config = config.online_store assert isinstance(online_config, DynamoDBOnlineStoreConfig) dynamodb_client = self._get_dynamodb_client(online_config.region) @@ -109,6 +121,13 @@ def teardown( tables: Sequence[FeatureView], entities: Sequence[Entity], ): + """ + Delete tables from the DynamoDB Online Store. + + Args: + config: The RepoConfig for the current FeatureStore. + tables: Tables to delete from the feature repo. + """ online_config = config.online_store assert isinstance(online_config, DynamoDBOnlineStoreConfig) dynamodb_resource = self._get_dynamodb_resource(online_config.region) @@ -126,6 +145,21 @@ def online_write_batch( ], progress: Optional[Callable[[int], Any]], ) -> None: + """ + Write a batch of feature rows to online DynamoDB store. + + Note: This method applies a ``batch_writer`` to automatically handle any unprocessed items + and resend them as needed, this is useful if you're loading a lot of data at a time. + + Args: + config: The RepoConfig for the current FeatureStore. + table: Feast FeatureView. + data: a list of quadruplets containing Feature data. Each quadruplet contains an Entity Key, + a dict containing feature values, an event timestamp for the row, and + the created timestamp for the row if it exists. + progress: Optional function to be called once every mini-batch of rows is written to + the online store. Can be used to display progress. + """ online_config = config.online_store assert isinstance(online_config, DynamoDBOnlineStoreConfig) dynamodb_resource = self._get_dynamodb_resource(online_config.region) @@ -155,6 +189,17 @@ def online_read( entity_keys: List[EntityKeyProto], requested_features: Optional[List[str]] = None, ) -> List[Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]]: + """ + Retrieve feature values from the online DynamoDB store. + + Note: This method is currently not optimized to retrieve a lot of data at a time + as it does sequential gets from the DynamoDB table. + + Args: + config: The RepoConfig for the current FeatureStore. + table: Feast FeatureView. + entity_keys: a list of entity keys that should be read from the FeatureStore. + """ online_config = config.online_store assert isinstance(online_config, DynamoDBOnlineStoreConfig) dynamodb_resource = self._get_dynamodb_resource(online_config.region) @@ -227,11 +272,10 @@ class DynamoDBTable(InfraObject): region: The region of the table. """ - name: str region: str def __init__(self, name: str, region: str): - self.name = name + super().__init__(name) self.region = region def to_infra_object_proto(self) -> InfraObjectProto: diff --git a/sdk/python/feast/infra/online_stores/redis.py b/sdk/python/feast/infra/online_stores/redis.py index 752ed7d009d..a2e8e27d807 100644 --- a/sdk/python/feast/infra/online_stores/redis.py +++ b/sdk/python/feast/infra/online_stores/redis.py @@ -27,6 +27,7 @@ Union, ) +import pytz from google.protobuf.timestamp_pb2 import Timestamp from pydantic import StrictStr from pydantic.typing import Literal @@ -41,7 +42,7 @@ try: from redis import Redis - from redis.cluster import RedisCluster + from rediscluster import RedisCluster except ImportError as e: from feast.errors import FeastExtrasDependencyImportError @@ -68,6 +69,9 @@ class RedisOnlineStoreConfig(FeastConfigBaseModel): """Connection string containing the host, port, and configuration parameters for Redis format: host:port,parameter1,parameter2 eg. redis:6379,db=0 """ + key_ttl_seconds: Optional[int] = None + """(Optional) redis key bin ttl (in seconds) for expiring entities""" + class RedisOnlineStore(OnlineStore): _client: Optional[Union[Redis, RedisCluster]] = None @@ -75,7 +79,7 @@ class RedisOnlineStore(OnlineStore): def delete_entity_values(self, config: RepoConfig, join_keys: List[str]): client = self._get_client(config.online_store) deleted_count = 0 - pipeline = client.pipeline() + pipeline = client.pipeline(transaction=False) prefix = _redis_key_prefix(join_keys) for _k in client.scan_iter( @@ -188,7 +192,7 @@ def online_write_batch( ts_key = f"_ts:{feature_view}" keys = [] # redis pipelining optimization: send multiple commands to redis server without waiting for every reply - with client.pipeline() as pipe: + with client.pipeline(transaction=False) as pipe: # check if a previous record under the key bin exists # TODO: investigate if check and set is a better approach rather than pulling all entity ts and then setting # it may be significantly slower but avoids potential (rare) race conditions @@ -225,9 +229,11 @@ def online_write_batch( entity_hset[f_key] = val.SerializeToString() pipe.hset(redis_key_bin, mapping=entity_hset) - # TODO: support expiring the entity / features in Redis - # otherwise entity features remain in redis until cleaned up in separate process - # client.expire redis_key_bin based a ttl setting + + if online_store_config.key_ttl_seconds: + pipe.expire( + name=redis_key_bin, time=online_store_config.key_ttl_seconds + ) results = pipe.execute() if progress: progress(len(results)) @@ -262,7 +268,7 @@ def online_read( for entity_key in entity_keys: redis_key_bin = _redis_key(project, entity_key) keys.append(redis_key_bin) - with client.pipeline() as pipe: + with client.pipeline(transaction=False) as pipe: for redis_key_bin in keys: pipe.hmget(redis_key_bin, hset_keys) with tracing_span(name="remote_call"): @@ -297,5 +303,5 @@ def _get_features_for_entity( if not res: return None, None else: - timestamp = datetime.fromtimestamp(res_ts.seconds) + timestamp = datetime.fromtimestamp(res_ts.seconds, tz=pytz.utc) return timestamp, res diff --git a/sdk/python/feast/infra/online_stores/sqlite.py b/sdk/python/feast/infra/online_stores/sqlite.py index 1e7ecf1024a..e65aab4e7be 100644 --- a/sdk/python/feast/infra/online_stores/sqlite.py +++ b/sdk/python/feast/infra/online_stores/sqlite.py @@ -249,12 +249,11 @@ class SqliteTable(InfraObject): """ path: str - name: str conn: sqlite3.Connection def __init__(self, path: str, name: str): + super().__init__(name) self.path = path - self.name = name self.conn = _initialize_conn(path) def to_infra_object_proto(self) -> InfraObjectProto: diff --git a/sdk/python/feast/infra/provider.py b/sdk/python/feast/infra/provider.py index a53030b74f9..b3f10292423 100644 --- a/sdk/python/feast/infra/provider.py +++ b/sdk/python/feast/infra/provider.py @@ -4,6 +4,7 @@ from pathlib import Path from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union +import dask.dataframe as dd import pandas import pyarrow from tqdm import tqdm @@ -312,6 +313,17 @@ def _run_field_mapping( return table +def _run_dask_field_mapping( + table: dd.DataFrame, field_mapping: Dict[str, str], +): + if field_mapping: + # run field mapping in the forward direction + table = table.rename(columns=field_mapping) + table = table.persist() + + return table + + def _coerce_datetime(ts): """ Depending on underlying time resolution, arrow to_pydict() sometimes returns pandas @@ -321,7 +333,6 @@ def _coerce_datetime(ts): same way. We convert it to normal datetime so that consumers downstream don't have to deal with these quirks. """ - if isinstance(ts, pandas.Timestamp): return ts.to_pydatetime() else: diff --git a/sdk/python/feast/infra/utils/aws_utils.py b/sdk/python/feast/infra/utils/aws_utils.py index b25454ca6ad..e7f628795d8 100644 --- a/sdk/python/feast/infra/utils/aws_utils.py +++ b/sdk/python/feast/infra/utils/aws_utils.py @@ -11,7 +11,6 @@ retry, retry_if_exception_type, stop_after_attempt, - stop_after_delay, wait_exponential, ) @@ -103,7 +102,6 @@ class RedshiftStatementNotFinishedError(Exception): @retry( wait=wait_exponential(multiplier=1, max=30), retry=retry_if_exception_type(RedshiftStatementNotFinishedError), - stop=stop_after_delay(300), # 300 seconds reraise=True, ) def wait_for_redshift_statement(redshift_data_client, statement: dict) -> None: diff --git a/sdk/python/feast/infra/utils/snowflake_utils.py b/sdk/python/feast/infra/utils/snowflake_utils.py index f280cfa218b..065a4bad467 100644 --- a/sdk/python/feast/infra/utils/snowflake_utils.py +++ b/sdk/python/feast/infra/utils/snowflake_utils.py @@ -7,9 +7,6 @@ from typing import Dict, Iterator, List, Optional, Tuple, cast import pandas as pd -import snowflake.connector -from snowflake.connector import ProgrammingError, SnowflakeConnection -from snowflake.connector.cursor import SnowflakeCursor from tenacity import ( retry, retry_if_exception_type, @@ -19,6 +16,16 @@ from feast.errors import SnowflakeIncompleteConfig, SnowflakeQueryUnknownError +try: + import snowflake.connector + from snowflake.connector import ProgrammingError, SnowflakeConnection + from snowflake.connector.cursor import SnowflakeCursor +except ImportError as e: + from feast.errors import FeastExtrasDependencyImportError + + raise FeastExtrasDependencyImportError("snowflake", str(e)) + + getLogger("snowflake.connector.cursor").disabled = True getLogger("snowflake.connector.connection").disabled = True getLogger("snowflake.connector.network").disabled = True @@ -36,29 +43,27 @@ def get_snowflake_conn(config, autocommit=True) -> SnowflakeConnection: if config.type == "snowflake.offline": config_header = "connections.feast_offline_store" - config = dict(config) + config_dict = dict(config) # read config file config_reader = configparser.ConfigParser() - config_reader.read([config["config_path"]]) + config_reader.read([config_dict["config_path"]]) if config_reader.has_section(config_header): kwargs = dict(config_reader[config_header]) else: kwargs = {} - kwargs.update((k, v) for k, v in config.items() if v is not None) + kwargs.update((k, v) for k, v in config_dict.items() if v is not None) + [ + kwargs.update({k: '"' + v + '"'}) + for k, v in kwargs.items() + if k in ["role", "warehouse", "database", "schema_"] + ] + kwargs["schema"] = kwargs.pop("schema_") try: conn = snowflake.connector.connect( - account=kwargs["account"], - user=kwargs["user"], - password=kwargs["password"], - role=f'''"{kwargs['role']}"''', - warehouse=f'''"{kwargs['warehouse']}"''', - database=f'''"{kwargs['database']}"''', - schema=f'''"{kwargs['schema_']}"''', - application="feast", - autocommit=autocommit, + application="feast", autocommit=autocommit, **kwargs ) return conn diff --git a/sdk/python/feast/online_response.py b/sdk/python/feast/online_response.py index bb69c6b9d95..f01bd510be9 100644 --- a/sdk/python/feast/online_response.py +++ b/sdk/python/feast/online_response.py @@ -20,10 +20,12 @@ from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesResponse from feast.type_map import feast_value_type_to_python_type +TIMESTAMP_POSTFIX: str = "__ts" + class OnlineResponse: """ - Defines a online response in feast. + Defines an online response in feast. """ def __init__(self, online_response_proto: GetOnlineFeaturesResponse): @@ -44,9 +46,12 @@ def __init__(self, online_response_proto: GetOnlineFeaturesResponse): del result.event_timestamps[idx] break - def to_dict(self) -> Dict[str, Any]: + def to_dict(self, include_event_timestamps: bool = False) -> Dict[str, Any]: """ Converts GetOnlineFeaturesResponse features into a dictionary form. + + Args: + is_with_event_timestamps: bool Optionally include feature timestamps in the dictionary """ response: Dict[str, List[Any]] = {} @@ -58,11 +63,22 @@ def to_dict(self) -> Dict[str, Any]: else: response[feature_ref].append(native_type_value) + if include_event_timestamps: + event_ts = result.event_timestamps[idx].seconds + timestamp_ref = feature_ref + TIMESTAMP_POSTFIX + if timestamp_ref not in response: + response[timestamp_ref] = [event_ts] + else: + response[timestamp_ref].append(event_ts) + return response - def to_df(self) -> pd.DataFrame: + def to_df(self, include_event_timestamps: bool = False) -> pd.DataFrame: """ Converts GetOnlineFeaturesResponse features into Panda dataframe form. + + Args: + is_with_event_timestamps: bool Optionally include feature timestamps in the dataframe """ - return pd.DataFrame(self.to_dict()) + return pd.DataFrame(self.to_dict(include_event_timestamps)) diff --git a/sdk/python/feast/registry.py b/sdk/python/feast/registry.py index 07c4c59b012..cb1261d8c93 100644 --- a/sdk/python/feast/registry.py +++ b/sdk/python/feast/registry.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import json import logging from collections import defaultdict from datetime import datetime, timedelta @@ -20,14 +21,18 @@ from typing import Any, Dict, List, Optional, Set from urllib.parse import urlparse +import dill from google.protobuf.internal.containers import RepeatedCompositeFieldContainer -from google.protobuf.json_format import MessageToDict +from google.protobuf.json_format import MessageToJson from proto import Message from feast.base_feature_view import BaseFeatureView +from feast.data_source import DataSource from feast.entity import Entity from feast.errors import ( ConflictingFeatureViewNames, + DataSourceNotFoundException, + DataSourceObjectNotFoundException, EntityNotFoundException, FeatureServiceNotFoundException, FeatureViewNotFoundException, @@ -64,6 +69,7 @@ class FeastObjectType(Enum): + DATA_SOURCE = "data source" ENTITY = "entity" FEATURE_VIEW = "feature view" ON_DEMAND_FEATURE_VIEW = "on demand feature view" @@ -75,6 +81,7 @@ def get_objects_from_registry( registry: "Registry", project: str ) -> Dict["FeastObjectType", List[Any]]: return { + FeastObjectType.DATA_SOURCE: registry.list_data_sources(project=project), FeastObjectType.ENTITY: registry.list_entities(project=project), FeastObjectType.FEATURE_VIEW: registry.list_feature_views(project=project), FeastObjectType.ON_DEMAND_FEATURE_VIEW: registry.list_on_demand_feature_views( @@ -93,6 +100,7 @@ def get_objects_from_repo_contents( repo_contents: RepoContents, ) -> Dict["FeastObjectType", Set[Any]]: return { + FeastObjectType.DATA_SOURCE: repo_contents.data_sources, FeastObjectType.ENTITY: repo_contents.entities, FeastObjectType.FEATURE_VIEW: repo_contents.feature_views, FeastObjectType.ON_DEMAND_FEATURE_VIEW: repo_contents.on_demand_feature_views, @@ -234,8 +242,8 @@ def apply_entity(self, entity: Entity, project: str, commit: bool = True): now = datetime.utcnow() if not entity.created_timestamp: - entity._created_timestamp = now - entity._last_updated_timestamp = now + entity.created_timestamp = now + entity.last_updated_timestamp = now entity_proto = entity.to_proto() entity_proto.spec.project = project @@ -274,6 +282,70 @@ def list_entities(self, project: str, allow_cache: bool = False) -> List[Entity] entities.append(Entity.from_proto(entity_proto)) return entities + def list_data_sources( + self, project: str, allow_cache: bool = False + ) -> List[DataSource]: + """ + Retrieve a list of data sources from the registry + + Args: + project: Filter data source based on project name + allow_cache: Whether to allow returning data sources from a cached registry + + Returns: + List of data sources + """ + registry_proto = self._get_registry_proto(allow_cache=allow_cache) + data_sources = [] + for data_source_proto in registry_proto.data_sources: + if data_source_proto.project == project: + data_sources.append(DataSource.from_proto(data_source_proto)) + return data_sources + + def apply_data_source( + self, data_source: DataSource, project: str, commit: bool = True + ): + """ + Registers a single data source with Feast + + Args: + data_source: A data source that will be registered + project: Feast project that this data source belongs to + commit: Whether to immediately commit to the registry + """ + registry = self._prepare_registry_for_changes() + + for idx, existing_data_source_proto in enumerate(registry.data_sources): + if existing_data_source_proto.name == data_source.name: + del registry.data_sources[idx] + data_source_proto = data_source.to_proto() + data_source_proto.project = project + registry.data_sources.append(data_source_proto) + if commit: + self.commit() + + def delete_data_source(self, name: str, project: str, commit: bool = True): + """ + Deletes a data source or raises an exception if not found. + + Args: + name: Name of data source + project: Feast project that this data source belongs to + commit: Whether the change should be persisted immediately + """ + self._prepare_registry_for_changes() + assert self.cached_registry_proto + + for idx, data_source_proto in enumerate( + self.cached_registry_proto.data_sources + ): + if data_source_proto.name == name: + del self.cached_registry_proto.data_sources[idx] + if commit: + self.commit() + return + raise DataSourceNotFoundException(name) + def apply_feature_service( self, feature_service: FeatureService, project: str, commit: bool = True ): @@ -463,7 +535,8 @@ def get_on_demand_feature_view( Args: name: Name of on demand feature view - project: Feast project that this on demand feature belongs to + project: Feast project that this on demand feature view belongs to + allow_cache: Whether to allow returning this on demand feature view from a cached registry Returns: Returns either the specified on demand feature view, or raises an exception if @@ -479,6 +552,27 @@ def get_on_demand_feature_view( return OnDemandFeatureView.from_proto(on_demand_feature_view) raise OnDemandFeatureViewNotFoundException(name, project=project) + def get_data_source( + self, name: str, project: str, allow_cache: bool = False + ) -> DataSource: + """ + Retrieves a data source. + + Args: + name: Name of data source + project: Feast project that this data source belongs to + allow_cache: Whether to allow returning this data source from a cached registry + + Returns: + Returns either the specified data source, or raises an exception if none is found + """ + registry = self._get_registry_proto(allow_cache=allow_cache) + + for data_source in registry.data_sources: + if data_source.project == project and data_source.name == name: + return DataSource.from_proto(data_source) + raise DataSourceObjectNotFoundException(name, project=project) + def apply_materialization( self, feature_view: FeatureView, @@ -692,7 +786,7 @@ def delete_entity(self, name: str, project: str, commit: bool = True): raise EntityNotFoundException(name, project) def apply_saved_dataset( - self, saved_dataset: SavedDataset, project: str, commit: bool = True + self, saved_dataset: SavedDataset, project: str, commit: bool = True, ): """ Registers a single entity with Feast @@ -792,46 +886,66 @@ def to_dict(self, project: str) -> Dict[str, List[Any]]: Args: project: Feast project to convert to a dict """ - registry_dict = defaultdict(list) - + registry_dict: Dict[str, Any] = defaultdict(list) + registry_dict["project"] = project + for data_source in sorted( + self.list_data_sources(project=project), key=lambda ds: ds.name + ): + registry_dict["dataSources"].append( + self._message_to_sorted_dict(data_source.to_proto()) + ) for entity in sorted( self.list_entities(project=project), key=lambda entity: entity.name ): - registry_dict["entities"].append(MessageToDict(entity.to_proto())) + registry_dict["entities"].append( + self._message_to_sorted_dict(entity.to_proto()) + ) for feature_view in sorted( self.list_feature_views(project=project), key=lambda feature_view: feature_view.name, ): - registry_dict["featureViews"].append(MessageToDict(feature_view.to_proto())) + registry_dict["featureViews"].append( + self._message_to_sorted_dict(feature_view.to_proto()) + ) for feature_service in sorted( self.list_feature_services(project=project), key=lambda feature_service: feature_service.name, ): registry_dict["featureServices"].append( - MessageToDict(feature_service.to_proto()) + self._message_to_sorted_dict(feature_service.to_proto()) ) for on_demand_feature_view in sorted( self.list_on_demand_feature_views(project=project), key=lambda on_demand_feature_view: on_demand_feature_view.name, ): - registry_dict["onDemandFeatureViews"].append( - MessageToDict(on_demand_feature_view.to_proto()) + odfv_dict = self._message_to_sorted_dict(on_demand_feature_view.to_proto()) + odfv_dict["spec"]["userDefinedFunction"]["body"] = dill.source.getsource( + on_demand_feature_view.udf ) + registry_dict["onDemandFeatureViews"].append(odfv_dict) for request_feature_view in sorted( self.list_request_feature_views(project=project), key=lambda request_feature_view: request_feature_view.name, ): registry_dict["requestFeatureViews"].append( - MessageToDict(request_feature_view.to_proto()) + self._message_to_sorted_dict(request_feature_view.to_proto()) ) for saved_dataset in sorted( self.list_saved_datasets(project=project), key=lambda item: item.name ): registry_dict["savedDatasets"].append( - MessageToDict(saved_dataset.to_proto()) + self._message_to_sorted_dict(saved_dataset.to_proto()) + ) + for infra_object in sorted(self.get_infra(project=project).infra_objects): + registry_dict["infra"].append( + self._message_to_sorted_dict(infra_object.to_proto()) ) return registry_dict + @staticmethod + def _message_to_sorted_dict(message: Message) -> Dict[str, Any]: + return json.loads(MessageToJson(message, sort_keys=True)) + def _prepare_registry_for_changes(self): """Prepares the Registry for changes by refreshing the cache if necessary.""" try: diff --git a/sdk/python/feast/repo_config.py b/sdk/python/feast/repo_config.py index 3f32d18b80b..20edebf5c7c 100644 --- a/sdk/python/feast/repo_config.py +++ b/sdk/python/feast/repo_config.py @@ -39,6 +39,7 @@ "bigquery": "feast.infra.offline_stores.bigquery.BigQueryOfflineStore", "redshift": "feast.infra.offline_stores.redshift.RedshiftOfflineStore", "snowflake.offline": "feast.infra.offline_stores.snowflake.SnowflakeOfflineStore", + "spark": "feast.infra.offline_stores.contrib.spark_offline_store.spark.SparkOfflineStore", } FEATURE_SERVER_CONFIG_CLASS_FOR_TYPE = { diff --git a/sdk/python/feast/repo_contents.py b/sdk/python/feast/repo_contents.py index 9190af11eec..b59adc34db4 100644 --- a/sdk/python/feast/repo_contents.py +++ b/sdk/python/feast/repo_contents.py @@ -13,6 +13,7 @@ # limitations under the License. from typing import NamedTuple, Set +from feast.data_source import DataSource from feast.entity import Entity from feast.feature_service import FeatureService from feast.feature_view import FeatureView @@ -26,6 +27,7 @@ class RepoContents(NamedTuple): Represents the objects in a Feast feature repo. """ + data_sources: Set[DataSource] feature_views: Set[FeatureView] on_demand_feature_views: Set[OnDemandFeatureView] request_feature_views: Set[RequestFeatureView] @@ -34,6 +36,7 @@ class RepoContents(NamedTuple): def to_registry_proto(self) -> RegistryProto: registry_proto = RegistryProto() + registry_proto.data_sources.extend([e.to_proto() for e in self.data_sources]) registry_proto.entities.extend([e.to_proto() for e in self.entities]) registry_proto.feature_views.extend( [fv.to_proto() for fv in self.feature_views] diff --git a/sdk/python/feast/repo_operations.py b/sdk/python/feast/repo_operations.py index 8a3a202c6dd..4bee79bd60a 100644 --- a/sdk/python/feast/repo_operations.py +++ b/sdk/python/feast/repo_operations.py @@ -12,6 +12,7 @@ import click from click.exceptions import BadParameter +from feast.data_source import DataSource from feast.diff.registry_diff import extract_objects_for_keep_delete_update_add from feast.entity import Entity from feast.feature_service import FeatureService @@ -94,6 +95,7 @@ def get_repo_files(repo_root: Path) -> List[Path]: def parse_repo(repo_root: Path) -> RepoContents: """ Collect feature table definitions from feature repo """ res = RepoContents( + data_sources=set(), entities=set(), feature_views=set(), feature_services=set(), @@ -106,6 +108,8 @@ def parse_repo(repo_root: Path) -> RepoContents: module = importlib.import_module(module_path) for attr_name in dir(module): obj = getattr(module, attr_name) + if isinstance(obj, DataSource): + res.data_sources.add(obj) if isinstance(obj, FeatureView): res.feature_views.add(obj) elif isinstance(obj, Entity): @@ -209,8 +213,8 @@ def apply_total_with_repo_instance( ( all_to_apply, all_to_delete, - views_to_delete, views_to_keep, + views_to_delete, ) = extract_objects_for_apply_delete(project, registry, repo) click.echo(registry_diff.to_string()) @@ -224,7 +228,7 @@ def apply_total_with_repo_instance( def log_infra_changes( - views_to_keep: List[FeatureView], views_to_delete: List[FeatureView] + views_to_keep: Set[FeatureView], views_to_delete: Set[FeatureView] ): from colorama import Fore, Style @@ -258,19 +262,12 @@ def teardown(repo_config: RepoConfig, repo_path: Path): @log_exceptions_and_usage def registry_dump(repo_config: RepoConfig, repo_path: Path): """ For debugging only: output contents of the metadata registry """ - from colorama import Fore, Style - registry_config = repo_config.get_registry_config() project = repo_config.project registry = Registry(registry_config=registry_config, repo_path=repo_path) registry_dict = registry.to_dict(project=project) - warning = ( - "Warning: The registry-dump command is for debugging only and may contain " - "breaking changes in the future. No guarantees are made on this interface." - ) - click.echo(f"{Style.BRIGHT}{Fore.YELLOW}{warning}{Style.RESET_ALL}") - click.echo(json.dumps(registry_dict, indent=2)) + click.echo(json.dumps(registry_dict, indent=2, sort_keys=True)) def cli_check_repo(repo_path: Path): diff --git a/sdk/python/feast/saved_dataset.py b/sdk/python/feast/saved_dataset.py index 75b6d2c199f..7a05a9ca221 100644 --- a/sdk/python/feast/saved_dataset.py +++ b/sdk/python/feast/saved_dataset.py @@ -54,6 +54,7 @@ class SavedDataset: full_feature_names: bool storage: SavedDatasetStorage tags: Dict[str, str] + feature_service_name: Optional[str] = None created_timestamp: Optional[datetime] = None last_updated_timestamp: Optional[datetime] = None @@ -71,6 +72,7 @@ def __init__( storage: SavedDatasetStorage, full_feature_names: bool = False, tags: Optional[Dict[str, str]] = None, + feature_service_name: Optional[str] = None, ): self.name = name self.features = features @@ -78,6 +80,7 @@ def __init__( self.storage = storage self.full_feature_names = full_feature_names self.tags = tags or {} + self.feature_service_name = feature_service_name self._retrieval_job = None @@ -121,6 +124,9 @@ def from_proto(saved_dataset_proto: SavedDatasetProto): tags=dict(saved_dataset_proto.spec.tags.items()), ) + if saved_dataset_proto.spec.feature_service_name: + ds.feature_service_name = saved_dataset_proto.spec.feature_service_name + if saved_dataset_proto.meta.HasField("created_timestamp"): ds.created_timestamp = ( saved_dataset_proto.meta.created_timestamp.ToDatetime() @@ -163,6 +169,8 @@ def to_proto(self) -> SavedDatasetProto: storage=self.storage.to_proto(), tags=self.tags, ) + if self.feature_service_name: + spec.feature_service_name = self.feature_service_name feature_service_proto = SavedDatasetProto(spec=spec, meta=meta) return feature_service_proto diff --git a/sdk/python/feast/templates/spark/__init__.py b/sdk/python/feast/templates/spark/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/feast/templates/spark/bootstrap.py b/sdk/python/feast/templates/spark/bootstrap.py new file mode 100644 index 00000000000..155a86bf484 --- /dev/null +++ b/sdk/python/feast/templates/spark/bootstrap.py @@ -0,0 +1,50 @@ +from datetime import datetime, timedelta +from pathlib import Path + +from pyspark.sql import SparkSession + +from feast.driver_test_data import ( + create_customer_daily_profile_df, + create_driver_hourly_stats_df, +) + +CURRENT_DIR = Path(__file__).parent +DRIVER_ENTITIES = [1001, 1002, 1003] +CUSTOMER_ENTITIES = [201, 202, 203] +START_DATE = datetime.strptime("2022-01-01", "%Y-%m-%d") +END_DATE = START_DATE + timedelta(days=7) + + +def bootstrap(): + # Bootstrap() will automatically be called from the init_repo() during `feast init` + generate_example_data( + spark_session=SparkSession.builder.getOrCreate(), base_dir=str(CURRENT_DIR), + ) + + +def example_data_exists(base_dir: str) -> bool: + for path in [ + Path(base_dir) / "data" / "driver_hourly_stats", + Path(base_dir) / "data" / "customer_daily_profile", + ]: + if not path.exists(): + return False + return True + + +def generate_example_data(spark_session: SparkSession, base_dir: str) -> None: + spark_session.createDataFrame( + data=create_driver_hourly_stats_df(DRIVER_ENTITIES, START_DATE, END_DATE) + ).write.parquet( + path=str(Path(base_dir) / "data" / "driver_hourly_stats"), mode="overwrite", + ) + + spark_session.createDataFrame( + data=create_customer_daily_profile_df(CUSTOMER_ENTITIES, START_DATE, END_DATE) + ).write.parquet( + path=str(Path(base_dir) / "data" / "customer_daily_profile"), mode="overwrite", + ) + + +if __name__ == "__main__": + bootstrap() diff --git a/sdk/python/feast/templates/spark/example.py b/sdk/python/feast/templates/spark/example.py new file mode 100644 index 00000000000..ddda73b7872 --- /dev/null +++ b/sdk/python/feast/templates/spark/example.py @@ -0,0 +1,64 @@ +# # # # # # # # # # # # # # # # # # # # # # # # +# This is an example feature definition file # +# # # # # # # # # # # # # # # # # # # # # # # # + +from pathlib import Path + +from google.protobuf.duration_pb2 import Duration + +from feast import Entity, Feature, FeatureView, ValueType +from feast.infra.offline_stores.contrib.spark_offline_store.spark_source import ( + SparkSource, +) + +# Constants related to the generated data sets +CURRENT_DIR = Path(__file__).parent + + +# Entity definitions +driver = Entity(name="driver_id", value_type=ValueType.INT64, description="driver id",) +customer = Entity( + name="customer_id", value_type=ValueType.INT64, description="customer id", +) + +# Sources +driver_hourly_stats = SparkSource( + path=f"{CURRENT_DIR}/data/driver_hourly_stats", + file_format="parquet", + event_timestamp_column="event_timestamp", + created_timestamp_column="created", +) +customer_daily_profile = SparkSource( + path=f"{CURRENT_DIR}/data/customer_daily_profile", + file_format="parquet", + event_timestamp_column="event_timestamp", + created_timestamp_column="created", +) + +# Feature Views +driver_hourly_stats_view = FeatureView( + name="driver_hourly_stats", + entities=["driver_id"], + ttl=Duration(seconds=86400 * 7), # one week + features=[ + Feature(name="conv_rate", dtype=ValueType.FLOAT), + Feature(name="acc_rate", dtype=ValueType.FLOAT), + Feature(name="avg_daily_trips", dtype=ValueType.INT64), + ], + online=True, + batch_source=driver_hourly_stats, + tags={}, +) +customer_daily_profile_view = FeatureView( + name="customer_daily_profile", + entities=["customer_id"], + ttl=Duration(seconds=86400 * 7), # one week + features=[ + Feature(name="current_balance", dtype=ValueType.FLOAT), + Feature(name="avg_passenger_count", dtype=ValueType.FLOAT), + Feature(name="lifetime_trip_count", dtype=ValueType.INT64), + ], + online=True, + batch_source=customer_daily_profile, + tags={}, +) diff --git a/sdk/python/feast/templates/spark/feature_store.yaml b/sdk/python/feast/templates/spark/feature_store.yaml new file mode 100644 index 00000000000..2ea0ddfcc9f --- /dev/null +++ b/sdk/python/feast/templates/spark/feature_store.yaml @@ -0,0 +1,14 @@ +project: my_project +registry: data/registry.db +provider: local +offline_store: + type: spark + spark_conf: + spark.master: "local[*]" + spark.ui.enabled: "false" + spark.eventLog.enabled: "false" + spark.sql.catalogImplementation: "hive" + spark.sql.parser.quotedRegexColumnNames: "true" + spark.sql.session.timeZone: "UTC" +online_store: + path: data/online_store.db diff --git a/sdk/python/feast/type_map.py b/sdk/python/feast/type_map.py index 15ddd147391..713b952d092 100644 --- a/sdk/python/feast/type_map.py +++ b/sdk/python/feast/type_map.py @@ -12,10 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +from collections import defaultdict from datetime import datetime, timezone from typing import ( Any, Dict, + Iterator, List, Optional, Sequence, @@ -300,9 +302,6 @@ def _python_value_to_proto_value( """ # ToDo: make a better sample for type checks (more than one element) sample = next(filter(_non_empty_value, values), None) # first not empty value - if sample is None: - # all input values are None or empty lists - return [ProtoValue()] * len(values) # Detect list type and handle separately if "list" in feast_value_type.name.lower(): @@ -312,7 +311,9 @@ def _python_value_to_proto_value( feast_value_type ] - if not all(type(item) in valid_types for item in sample): + if sample is not None and not all( + type(item) in valid_types for item in sample + ): first_invalid = next( item for item in sample if type(item) not in valid_types ) @@ -327,7 +328,14 @@ def _python_value_to_proto_value( ProtoValue(unix_timestamp_list_val=Int64List(val=ts)) # type: ignore for ts in int_timestamps_lists ] - + if feast_value_type == ValueType.BOOL_LIST: + # ProtoValue does not support conversion of np.bool_ so we need to convert it to support np.bool_. + return [ + ProtoValue(**{field_name: proto_type(val=[bool(e) for e in value])}) # type: ignore + if value is not None + else ProtoValue() + for value in values + ] return [ ProtoValue(**{field_name: proto_type(val=value)}) # type: ignore if value is not None @@ -337,20 +345,37 @@ def _python_value_to_proto_value( # Handle scalar types below else: + if sample is None: + # all input values are None + return [ProtoValue()] * len(values) + if feast_value_type == ValueType.UNIX_TIMESTAMP: int_timestamps = _python_datetime_to_int_timestamp(values) # ProtoValue does actually accept `np.int_` but the typing complains. return [ProtoValue(unix_timestamp_val=ts) for ts in int_timestamps] # type: ignore + ( + field_name, + func, + valid_scalar_types, + ) = PYTHON_SCALAR_VALUE_TYPE_TO_PROTO_VALUE[feast_value_type] + if valid_scalar_types: + assert type(sample) in valid_scalar_types + if feast_value_type == ValueType.BOOL: + # ProtoValue does not support conversion of np.bool_ so we need to convert it to support np.bool_. + return [ + ProtoValue( + **{ + field_name: func( + bool(value) if type(value) is np.bool_ else value # type: ignore + ) + } + ) + if not pd.isnull(value) + else ProtoValue() + for value in values + ] if feast_value_type in PYTHON_SCALAR_VALUE_TYPE_TO_PROTO_VALUE: - ( - field_name, - func, - valid_scalar_types, - ) = PYTHON_SCALAR_VALUE_TYPE_TO_PROTO_VALUE[feast_value_type] - if valid_scalar_types: - assert type(sample) in valid_scalar_types - return [ ProtoValue(**{field_name: func(value)}) if not pd.isnull(value) @@ -563,3 +588,53 @@ def _non_empty_value(value: Any) -> bool: return value is not None and ( not isinstance(value, Sized) or len(value) > 0 or isinstance(value, str) ) + + +def spark_to_feast_value_type(spark_type_as_str: str) -> ValueType: + # TODO not all spark types are convertible + # Current non-convertible types: interval, map, struct, structfield, decimal, binary + type_map: Dict[str, ValueType] = { + "null": ValueType.UNKNOWN, + "byte": ValueType.BYTES, + "string": ValueType.STRING, + "int": ValueType.INT32, + "short": ValueType.INT32, + "bigint": ValueType.INT64, + "long": ValueType.INT64, + "double": ValueType.DOUBLE, + "float": ValueType.FLOAT, + "boolean": ValueType.BOOL, + "timestamp": ValueType.UNIX_TIMESTAMP, + "array": ValueType.BYTES_LIST, + "array": ValueType.STRING_LIST, + "array": ValueType.INT32_LIST, + "array": ValueType.INT64_LIST, + "array": ValueType.DOUBLE_LIST, + "array": ValueType.FLOAT_LIST, + "array": ValueType.BOOL_LIST, + "array": ValueType.UNIX_TIMESTAMP_LIST, + } + # TODO: Find better way of doing this. + if type(spark_type_as_str) != str or spark_type_as_str not in type_map: + return ValueType.NULL + return type_map[spark_type_as_str.lower()] + + +def spark_schema_to_np_dtypes(dtypes: List[Tuple[str, str]]) -> Iterator[np.dtype]: + # TODO recheck all typing (also tz for timestamp) + # https://spark.apache.org/docs/latest/api/python/user_guide/arrow_pandas.html#timestamp-with-time-zone-semantics + + type_map = defaultdict( + lambda: np.dtype("O"), + { + "boolean": np.dtype("bool"), + "double": np.dtype("float64"), + "float": np.dtype("float64"), + "int": np.dtype("int64"), + "bigint": np.dtype("int64"), + "smallint": np.dtype("int64"), + "timestamp": np.dtype("datetime64[ns]"), + }, + ) + + return (type_map[t] for _, t in dtypes) diff --git a/sdk/python/requirements/py3.7-ci-requirements.txt b/sdk/python/requirements/py3.7-ci-requirements.txt index d5f654e515c..6cb8c2931b8 100644 --- a/sdk/python/requirements/py3.7-ci-requirements.txt +++ b/sdk/python/requirements/py3.7-ci-requirements.txt @@ -54,14 +54,14 @@ attrs==21.4.0 # pytest avro==1.10.0 # via feast (setup.py) -azure-core==1.21.1 +azure-core==1.23.0 # via # adlfs # azure-identity # azure-storage-blob azure-datalake-store==0.0.52 # via adlfs -azure-identity==1.7.1 +azure-identity==1.8.0 # via adlfs azure-storage-blob==12.9.0 # via adlfs @@ -69,7 +69,7 @@ babel==2.9.1 # via sphinx backcall==0.2.0 # via ipython -backports.zoneinfo==0.2.1 +backports-zoneinfo==0.2.1 # via # pytz-deprecation-shim # tzlocal @@ -77,11 +77,11 @@ black==19.10b0 # via feast (setup.py) bleach==4.1.0 # via nbconvert -boto3==1.20.46 +boto3==1.21.11 # via # feast (setup.py) # moto -botocore==1.23.46 +botocore==1.24.11 # via # boto3 # moto @@ -104,21 +104,23 @@ cffi==1.15.0 # snowflake-connector-python cfgv==3.3.1 # via pre-commit -charset-normalizer==2.0.11 +charset-normalizer==2.0.12 # via # aiohttp # requests # snowflake-connector-python -click==8.0.3 +click==8.0.4 # via # black # feast (setup.py) # great-expectations # pip-tools # uvicorn +cloudpickle==2.0.0 + # via dask colorama==0.4.4 # via feast (setup.py) -coverage[toml]==6.3 +coverage[toml]==6.3.2 # via pytest-cov cryptography==3.3.2 # via @@ -131,6 +133,8 @@ cryptography==3.3.2 # pyjwt # pyopenssl # snowflake-connector-python +dask==2022.1.1 + # via feast (setup.py) debugpy==1.5.1 # via ipykernel decorator==5.1.1 @@ -139,8 +143,6 @@ decorator==5.1.1 # ipython defusedxml==0.7.1 # via nbconvert -deprecated==1.2.13 - # via redis deprecation==2.1.0 # via testcontainers dill==0.3.4 @@ -155,20 +157,20 @@ docutils==0.17.1 # via # sphinx # sphinx-rtd-theme -entrypoints==0.3 +entrypoints==0.4 # via # altair # jupyter-client # nbconvert execnet==1.9.0 # via pytest-xdist -fastapi==0.73.0 +fastapi==0.74.1 # via feast (setup.py) fastavro==1.4.9 # via # feast (setup.py) # pandavro -filelock==3.4.2 +filelock==3.6.0 # via virtualenv firebase-admin==4.5.2 # via feast (setup.py) @@ -178,11 +180,12 @@ frozenlist==1.3.0 # via # aiohttp # aiosignal -fsspec==2022.1.0 +fsspec==2022.2.0 # via # adlfs + # dask # gcsfs -gcsfs==2022.1.0 +gcsfs==2022.2.0 # via feast (setup.py) google-api-core[grpc]==1.31.5 # via @@ -194,7 +197,7 @@ google-api-core[grpc]==1.31.5 # google-cloud-core # google-cloud-datastore # google-cloud-firestore -google-api-python-client==2.36.0 +google-api-python-client==2.39.0 # via firebase-admin google-auth==1.35.0 # via @@ -207,11 +210,11 @@ google-auth==1.35.0 # google-cloud-storage google-auth-httplib2==0.1.0 # via google-api-python-client -google-auth-oauthlib==0.4.6 +google-auth-oauthlib==0.5.0 # via gcsfs -google-cloud-bigquery==2.32.0 +google-cloud-bigquery==2.34.1 # via feast (setup.py) -google-cloud-bigquery-storage==2.11.0 +google-cloud-bigquery-storage==2.12.0 # via feast (setup.py) google-cloud-core==1.7.2 # via @@ -220,7 +223,7 @@ google-cloud-core==1.7.2 # google-cloud-datastore # google-cloud-firestore # google-cloud-storage -google-cloud-datastore==2.4.0 +google-cloud-datastore==2.5.0 # via feast (setup.py) google-cloud-firestore==2.3.4 # via firebase-admin @@ -240,9 +243,9 @@ googleapis-common-protos==1.52.0 # feast (setup.py) # google-api-core # tensorflow-metadata -great-expectations==0.14.4 +great-expectations==0.14.8 # via feast (setup.py) -grpcio==1.43.0 +grpcio==1.44.0 # via # feast (setup.py) # google-api-core @@ -250,7 +253,7 @@ grpcio==1.43.0 # grpcio-reflection # grpcio-testing # grpcio-tools -grpcio-reflection==1.43.0 +grpcio-reflection==1.44.0 # via feast (setup.py) grpcio-testing==1.34.0 # via feast (setup.py) @@ -260,13 +263,13 @@ h11==0.13.0 # via uvicorn hiredis==2.0.0 # via feast (setup.py) -httplib2==0.20.2 +httplib2==0.20.4 # via # google-api-python-client # google-auth-httplib2 httptools==0.3.0 # via uvicorn -identify==2.4.7 +identify==2.4.11 # via pre-commit idna==3.3 # via @@ -287,17 +290,16 @@ importlib-metadata==4.2.0 # pluggy # pre-commit # pytest - # redis # virtualenv importlib-resources==5.4.0 # via jsonschema iniconfig==1.1.1 # via pytest -ipykernel==6.7.0 +ipykernel==6.9.1 # via # ipywidgets # notebook -ipython==7.31.1 +ipython==7.32.0 # via # ipykernel # ipywidgets @@ -342,7 +344,7 @@ jupyter-client==7.1.2 # ipykernel # nbclient # notebook -jupyter-core==4.9.1 +jupyter-core==4.9.2 # via # jupyter-client # nbconvert @@ -352,11 +354,9 @@ jupyterlab-pygments==0.1.2 # via nbconvert jupyterlab-widgets==1.0.2 # via ipywidgets -libcst==0.4.1 - # via - # google-cloud-bigquery-storage - # google-cloud-datastore -markupsafe==2.0.1 +locket==0.2.1 + # via partd +markupsafe==2.1.0 # via # jinja2 # moto @@ -376,9 +376,9 @@ mmh3==3.0.0 # via feast (setup.py) mock==2.0.0 # via feast (setup.py) -moto==3.0.2 +moto==3.0.5 # via feast (setup.py) -msal==1.16.0 +msal==1.17.0 # via # azure-identity # msal-extensions @@ -399,14 +399,12 @@ multidict==6.0.2 mypy==0.931 # via feast (setup.py) mypy-extensions==0.4.3 - # via - # mypy - # typing-inspect + # via mypy mypy-protobuf==3.1.0 # via feast (setup.py) -nbclient==0.5.10 +nbclient==0.5.11 # via nbconvert -nbconvert==6.4.1 +nbconvert==6.4.2 # via notebook nbformat==5.1.3 # via @@ -439,12 +437,12 @@ oscrypto==1.2.1 packaging==21.3 # via # bleach + # dask # deprecation # google-api-core # google-cloud-bigquery # google-cloud-firestore # pytest - # redis # sphinx pandas==1.3.5 # via @@ -459,9 +457,11 @@ pandocfilters==1.5.0 # via nbconvert parso==0.8.3 # via jedi +partd==1.2.0 + # via dask pathspec==0.9.0 # via black -pbr==5.8.0 +pbr==5.8.1 # via mock pep517==0.12.0 # via pip-tools @@ -469,19 +469,19 @@ pexpect==4.8.0 # via ipython pickleshare==0.7.5 # via ipython -pip-tools==6.4.0 +pip-tools==6.5.1 # via feast (setup.py) -platformdirs==2.4.1 +platformdirs==2.5.1 # via virtualenv pluggy==1.0.0 # via pytest -portalocker==2.3.2 +portalocker==2.4.0 # via msal-extensions pre-commit==2.17.0 # via feast (setup.py) prometheus-client==0.13.1 # via notebook -prompt-toolkit==3.0.26 +prompt-toolkit==3.0.28 # via ipython proto-plus==1.19.6 # via @@ -512,6 +512,8 @@ py==1.11.0 # pytest-forked py-cpuinfo==8.0.0 # via pytest-benchmark +py4j==0.10.9.3 + # via pyspark pyarrow==6.0.1 # via # feast (setup.py) @@ -526,7 +528,7 @@ pycodestyle==2.8.0 # via flake8 pycparser==2.21 # via cffi -pycryptodomex==3.14.0 +pycryptodomex==3.14.1 # via snowflake-connector-python pydantic==1.9.0 # via @@ -554,7 +556,9 @@ pyparsing==2.4.7 # packaging pyrsistent==0.18.1 # via jsonschema -pytest==6.2.5 +pyspark==3.2.1 + # via feast (setup.py) +pytest==7.0.1 # via # feast (setup.py) # pytest-benchmark @@ -604,17 +608,21 @@ pytz-deprecation-shim==0.1.0.post0 # via tzlocal pyyaml==6.0 # via + # dask # feast (setup.py) - # libcst # pre-commit # uvicorn pyzmq==22.3.0 # via # jupyter-client # notebook -redis==4.1.2 +redis==3.5.3 + # via + # feast (setup.py) + # redis-py-cluster +redis-py-cluster==2.1.3 # via feast (setup.py) -regex==2022.1.18 +regex==2022.3.2 # via black requests==2.27.1 # via @@ -640,15 +648,15 @@ requests-oauthlib==1.3.1 # via # google-auth-oauthlib # msrest -responses==0.17.0 +responses==0.18.0 # via moto rsa==4.8 # via google-auth -ruamel.yaml==0.17.17 +ruamel-yaml==0.17.17 # via great-expectations -ruamel.yaml.clib==0.2.6 - # via ruamel.yaml -s3transfer==0.5.0 +ruamel-yaml-clib==0.2.6 + # via ruamel-yaml +s3transfer==0.5.2 # via boto3 scipy==1.7.3 # via great-expectations @@ -673,13 +681,12 @@ six==1.16.0 # pandavro # pyopenssl # python-dateutil - # responses # virtualenv sniffio==1.2.0 # via anyio snowballstemmer==2.2.0 # via sphinx -snowflake-connector-python[pandas]==2.7.3 +snowflake-connector-python[pandas]==2.7.4 # via feast (setup.py) sphinx==4.3.2 # via @@ -705,36 +712,39 @@ tabulate==0.8.9 # via feast (setup.py) tenacity==8.0.1 # via feast (setup.py) -tensorflow-metadata==1.6.0 +tensorflow-metadata==1.7.0 # via feast (setup.py) termcolor==1.1.0 # via great-expectations -terminado==0.13.1 +terminado==0.13.2 # via notebook testcontainers==3.4.2 # via feast (setup.py) -testpath==0.5.0 +testpath==0.6.0 # via nbconvert toml==0.10.2 # via # black # feast (setup.py) # pre-commit - # pytest -tomli==2.0.0 +tomli==2.0.1 # via # coverage # mypy # pep517 + # pytest toolz==0.11.2 - # via altair + # via + # altair + # dask + # partd tornado==6.1 # via # ipykernel # jupyter-client # notebook # terminado -tqdm==4.62.3 +tqdm==4.63.0 # via # feast (setup.py) # great-expectations @@ -754,48 +764,43 @@ typed-ast==1.5.2 # via # black # mypy -types-futures==3.3.8 - # via types-protobuf -types-protobuf==3.19.7 +types-protobuf==3.19.12 # via # feast (setup.py) # mypy-protobuf types-python-dateutil==2.8.9 # via feast (setup.py) -types-pytz==2021.3.4 +types-pytz==2021.3.5 # via feast (setup.py) types-pyyaml==6.0.4 # via feast (setup.py) -types-redis==4.1.13 +types-redis==4.1.17 # via feast (setup.py) -types-requests==2.27.8 +types-requests==2.27.11 # via feast (setup.py) -types-setuptools==57.4.8 +types-setuptools==57.4.9 # via feast (setup.py) types-tabulate==0.8.5 # via feast (setup.py) -types-urllib3==1.26.8 +types-urllib3==1.26.10 # via types-requests -typing-extensions==4.0.1 +typing-extensions==4.1.1 # via # aiohttp # anyio # argon2-cffi # asgiref # async-timeout + # azure-core # great-expectations # h11 # importlib-metadata # jsonschema - # libcst # mypy # pydantic # starlette - # typing-inspect # uvicorn # yarl -typing-inspect==0.7.1 - # via libcst tzdata==2021.5 # via pytz-deprecation-shim tzlocal==4.1 @@ -809,11 +814,11 @@ urllib3==1.26.8 # minio # requests # responses -uvicorn[standard]==0.17.1 +uvicorn[standard]==0.17.5 # via feast (setup.py) uvloop==0.16.0 # via uvicorn -virtualenv==20.13.0 +virtualenv==20.13.2 # via pre-commit watchgod==0.7 # via uvicorn @@ -821,20 +826,18 @@ wcwidth==0.2.5 # via prompt-toolkit webencodings==0.5.1 # via bleach -websocket-client==1.2.3 +websocket-client==1.3.1 # via docker -websockets==10.1 +websockets==10.2 # via uvicorn -werkzeug==2.0.2 +werkzeug==2.0.3 # via moto wheel==0.37.1 # via pip-tools widgetsnbextension==3.5.2 # via ipywidgets wrapt==1.13.3 - # via - # deprecated - # testcontainers + # via testcontainers xmltodict==0.12.0 # via moto yarl==1.7.2 @@ -847,4 +850,4 @@ zipp==3.7.0 # The following packages are considered to be unsafe in a requirements file: # pip -# setuptools +# setuptools \ No newline at end of file diff --git a/sdk/python/requirements/py3.7-requirements.txt b/sdk/python/requirements/py3.7-requirements.txt index c2ad63fdea3..f3c90a6e3bd 100644 --- a/sdk/python/requirements/py3.7-requirements.txt +++ b/sdk/python/requirements/py3.7-requirements.txt @@ -8,44 +8,50 @@ absl-py==1.0.0 # via tensorflow-metadata anyio==3.5.0 # via starlette -asgiref==3.4.1 +asgiref==3.5.0 # via uvicorn attrs==21.4.0 # via jsonschema -cachetools==4.2.4 +cachetools==5.0.0 # via google-auth certifi==2021.10.8 # via requests -charset-normalizer==2.0.10 +charset-normalizer==2.0.12 # via requests -click==8.0.3 +click==8.0.4 # via # feast (setup.py) # uvicorn +cloudpickle==2.0.0 + # via dask colorama==0.4.4 # via feast (setup.py) +dask==2022.1.1 + # via feast (setup.py) dill==0.3.4 # via feast (setup.py) -fastapi==0.72.0 +fastapi==0.74.1 # via feast (setup.py) fastavro==1.4.9 # via # feast (setup.py) # pandavro -google-api-core==2.4.0 +fsspec==2022.2.0 + # via dask +google-api-core==2.5.0 # via feast (setup.py) -google-auth==2.3.3 +google-auth==2.6.0 # via google-api-core googleapis-common-protos==1.52.0 # via # feast (setup.py) # google-api-core # tensorflow-metadata -grpcio==1.43.0 +grpcio==1.44.0 # via # feast (setup.py) # grpcio-reflection -grpcio-reflection==1.43.0 +grpcio-reflection==1.44.0 # via feast (setup.py) h11==0.13.0 # via uvicorn @@ -55,7 +61,7 @@ idna==3.3 # via # anyio # requests -importlib-metadata==4.10.1 +importlib-metadata==4.11.1 # via # click # jsonschema @@ -65,7 +71,9 @@ jinja2==3.0.3 # via feast (setup.py) jsonschema==4.4.0 # via feast (setup.py) -markupsafe==2.0.1 +locket==0.2.1 + # via partd +markupsafe==2.1.0 # via jinja2 mmh3==3.0.0 # via feast (setup.py) @@ -74,15 +82,19 @@ numpy==1.21.5 # pandas # pandavro # pyarrow +packaging==21.3 + # via dask pandas==1.3.5 # via # feast (setup.py) # pandavro pandavro==1.5.2 # via feast (setup.py) +partd==1.2.0 + # via dask proto-plus==1.19.6 # via feast (setup.py) -protobuf==3.19.3 +protobuf==3.19.4 # via # feast (setup.py) # google-api-core @@ -90,7 +102,7 @@ protobuf==3.19.3 # grpcio-reflection # proto-plus # tensorflow-metadata -pyarrow==6.0.1 +pyarrow==7.0.0 # via feast (setup.py) pyasn1==0.4.8 # via @@ -102,6 +114,8 @@ pydantic==1.9.0 # via # fastapi # feast (setup.py) +pyparsing==3.0.7 + # via packaging pyrsistent==0.18.1 # via jsonschema python-dateutil==2.8.2 @@ -112,6 +126,7 @@ pytz==2021.3 # via pandas pyyaml==6.0 # via + # dask # feast (setup.py) # uvicorn requests==2.27.1 @@ -137,9 +152,13 @@ tensorflow-metadata==1.6.0 # via feast (setup.py) toml==0.10.2 # via feast (setup.py) +toolz==0.11.2 + # via + # dask + # partd tqdm==4.62.3 # via feast (setup.py) -typing-extensions==4.0.1 +typing-extensions==4.1.1 # via # anyio # asgiref @@ -151,18 +170,15 @@ typing-extensions==4.0.1 # uvicorn urllib3==1.26.8 # via requests -uvicorn[standard]==0.17.0 +uvicorn[standard]==0.17.5 # via feast (setup.py) uvloop==0.16.0 # via uvicorn watchgod==0.7 # via uvicorn -websockets==10.1 +websockets==10.2 # via uvicorn zipp==3.7.0 # via # importlib-metadata # importlib-resources - -# The following packages are considered to be unsafe in a requirements file: -# setuptools diff --git a/sdk/python/requirements/py3.8-ci-requirements.txt b/sdk/python/requirements/py3.8-ci-requirements.txt index 7a94294c956..f5da5525ba0 100644 --- a/sdk/python/requirements/py3.8-ci-requirements.txt +++ b/sdk/python/requirements/py3.8-ci-requirements.txt @@ -42,10 +42,10 @@ asn1crypto==1.4.0 # snowflake-connector-python assertpy==1.1 # via feast (setup.py) +asttokens==2.0.5 + # via stack-data async-timeout==4.0.2 # via aiohttp -asynctest==0.13.0 - # via aiohttp attrs==21.4.0 # via # aiohttp @@ -54,14 +54,14 @@ attrs==21.4.0 # pytest avro==1.10.0 # via feast (setup.py) -azure-core==1.21.1 +azure-core==1.23.0 # via # adlfs # azure-identity # azure-storage-blob azure-datalake-store==0.0.52 # via adlfs -azure-identity==1.7.1 +azure-identity==1.8.0 # via adlfs azure-storage-blob==12.9.0 # via adlfs @@ -77,11 +77,11 @@ black==19.10b0 # via feast (setup.py) bleach==4.1.0 # via nbconvert -boto3==1.20.46 +boto3==1.21.11 # via # feast (setup.py) # moto -botocore==1.23.46 +botocore==1.24.11 # via # boto3 # moto @@ -104,21 +104,23 @@ cffi==1.15.0 # snowflake-connector-python cfgv==3.3.1 # via pre-commit -charset-normalizer==2.0.11 +charset-normalizer==2.0.12 # via # aiohttp # requests # snowflake-connector-python -click==8.0.3 +click==8.0.4 # via # black # feast (setup.py) # great-expectations # pip-tools # uvicorn +cloudpickle==2.0.0 + # via dask colorama==0.4.4 # via feast (setup.py) -coverage[toml]==6.3 +coverage[toml]==6.3.2 # via pytest-cov cryptography==3.3.2 # via @@ -131,6 +133,8 @@ cryptography==3.3.2 # pyjwt # pyopenssl # snowflake-connector-python +dask==2022.1.1 + # via feast (setup.py) debugpy==1.5.1 # via ipykernel decorator==5.1.1 @@ -139,8 +143,6 @@ decorator==5.1.1 # ipython defusedxml==0.7.1 # via nbconvert -deprecated==1.2.13 - # via redis deprecation==2.1.0 # via testcontainers dill==0.3.4 @@ -155,20 +157,22 @@ docutils==0.17.1 # via # sphinx # sphinx-rtd-theme -entrypoints==0.3 +entrypoints==0.4 # via # altair # jupyter-client # nbconvert execnet==1.9.0 # via pytest-xdist -fastapi==0.73.0 +executing==0.8.3 + # via stack-data +fastapi==0.74.1 # via feast (setup.py) fastavro==1.4.9 # via # feast (setup.py) # pandavro -filelock==3.4.2 +filelock==3.6.0 # via virtualenv firebase-admin==4.5.2 # via feast (setup.py) @@ -178,11 +182,12 @@ frozenlist==1.3.0 # via # aiohttp # aiosignal -fsspec==2022.1.0 +fsspec==2022.2.0 # via # adlfs + # dask # gcsfs -gcsfs==2022.1.0 +gcsfs==2022.2.0 # via feast (setup.py) google-api-core[grpc]==1.31.5 # via @@ -194,7 +199,7 @@ google-api-core[grpc]==1.31.5 # google-cloud-core # google-cloud-datastore # google-cloud-firestore -google-api-python-client==2.36.0 +google-api-python-client==2.39.0 # via firebase-admin google-auth==1.35.0 # via @@ -207,11 +212,11 @@ google-auth==1.35.0 # google-cloud-storage google-auth-httplib2==0.1.0 # via google-api-python-client -google-auth-oauthlib==0.4.6 +google-auth-oauthlib==0.5.0 # via gcsfs -google-cloud-bigquery==2.32.0 +google-cloud-bigquery==2.34.1 # via feast (setup.py) -google-cloud-bigquery-storage==2.11.0 +google-cloud-bigquery-storage==2.12.0 # via feast (setup.py) google-cloud-core==1.7.2 # via @@ -220,7 +225,7 @@ google-cloud-core==1.7.2 # google-cloud-datastore # google-cloud-firestore # google-cloud-storage -google-cloud-datastore==2.4.0 +google-cloud-datastore==2.5.0 # via feast (setup.py) google-cloud-firestore==2.3.4 # via firebase-admin @@ -240,9 +245,9 @@ googleapis-common-protos==1.52.0 # feast (setup.py) # google-api-core # tensorflow-metadata -great-expectations==0.14.4 +great-expectations==0.14.8 # via feast (setup.py) -grpcio==1.43.0 +grpcio==1.44.0 # via # feast (setup.py) # google-api-core @@ -250,7 +255,7 @@ grpcio==1.43.0 # grpcio-reflection # grpcio-testing # grpcio-tools -grpcio-reflection==1.43.0 +grpcio-reflection==1.44.0 # via feast (setup.py) grpcio-testing==1.34.0 # via feast (setup.py) @@ -260,13 +265,13 @@ h11==0.13.0 # via uvicorn hiredis==2.0.0 # via feast (setup.py) -httplib2==0.20.2 +httplib2==0.20.4 # via # google-api-python-client # google-auth-httplib2 httptools==0.3.0 # via uvicorn -identify==2.4.7 +identify==2.4.11 # via pre-commit idna==3.3 # via @@ -276,28 +281,17 @@ idna==3.3 # yarl imagesize==1.3.0 # via sphinx -importlib-metadata==4.2.0 - # via - # click - # flake8 - # great-expectations - # jsonschema - # moto - # pep517 - # pluggy - # pre-commit - # pytest - # redis - # virtualenv +importlib-metadata==4.11.2 + # via great-expectations importlib-resources==5.4.0 # via jsonschema iniconfig==1.1.1 # via pytest -ipykernel==6.7.0 +ipykernel==6.9.1 # via # ipywidgets # notebook -ipython==7.31.1 +ipython==8.1.1 # via # ipykernel # ipywidgets @@ -342,7 +336,7 @@ jupyter-client==7.1.2 # ipykernel # nbclient # notebook -jupyter-core==4.9.1 +jupyter-core==4.9.2 # via # jupyter-client # nbconvert @@ -352,11 +346,9 @@ jupyterlab-pygments==0.1.2 # via nbconvert jupyterlab-widgets==1.0.2 # via ipywidgets -libcst==0.4.1 - # via - # google-cloud-bigquery-storage - # google-cloud-datastore -markupsafe==2.0.1 +locket==0.2.1 + # via partd +markupsafe==2.1.0 # via # jinja2 # moto @@ -376,9 +368,9 @@ mmh3==3.0.0 # via feast (setup.py) mock==2.0.0 # via feast (setup.py) -moto==3.0.2 +moto==3.0.5 # via feast (setup.py) -msal==1.16.0 +msal==1.17.0 # via # azure-identity # msal-extensions @@ -399,14 +391,12 @@ multidict==6.0.2 mypy==0.931 # via feast (setup.py) mypy-extensions==0.4.3 - # via - # mypy - # typing-inspect + # via mypy mypy-protobuf==3.1.0 # via feast (setup.py) -nbclient==0.5.10 +nbclient==0.5.11 # via nbconvert -nbconvert==6.4.1 +nbconvert==6.4.2 # via notebook nbformat==5.1.3 # via @@ -424,7 +414,7 @@ nodeenv==1.6.0 # via pre-commit notebook==6.4.8 # via widgetsnbextension -numpy==1.21.5 +numpy==1.22.2 # via # altair # great-expectations @@ -439,12 +429,12 @@ oscrypto==1.2.1 packaging==21.3 # via # bleach + # dask # deprecation # google-api-core # google-cloud-bigquery # google-cloud-firestore # pytest - # redis # sphinx pandas==1.3.5 # via @@ -459,9 +449,11 @@ pandocfilters==1.5.0 # via nbconvert parso==0.8.3 # via jedi +partd==1.2.0 + # via dask pathspec==0.9.0 # via black -pbr==5.8.0 +pbr==5.8.1 # via mock pep517==0.12.0 # via pip-tools @@ -469,19 +461,19 @@ pexpect==4.8.0 # via ipython pickleshare==0.7.5 # via ipython -pip-tools==6.4.0 +pip-tools==6.5.1 # via feast (setup.py) -platformdirs==2.4.1 +platformdirs==2.5.1 # via virtualenv pluggy==1.0.0 # via pytest -portalocker==2.3.2 +portalocker==2.4.0 # via msal-extensions pre-commit==2.17.0 # via feast (setup.py) prometheus-client==0.13.1 # via notebook -prompt-toolkit==3.0.26 +prompt-toolkit==3.0.28 # via ipython proto-plus==1.19.6 # via @@ -506,12 +498,16 @@ ptyprocess==0.7.0 # via # pexpect # terminado +pure-eval==0.2.2 + # via stack-data py==1.11.0 # via # pytest # pytest-forked py-cpuinfo==8.0.0 # via pytest-benchmark +py4j==0.10.9.3 + # via pyspark pyarrow==6.0.1 # via # feast (setup.py) @@ -526,7 +522,7 @@ pycodestyle==2.8.0 # via flake8 pycparser==2.21 # via cffi -pycryptodomex==3.14.0 +pycryptodomex==3.14.1 # via snowflake-connector-python pydantic==1.9.0 # via @@ -554,7 +550,9 @@ pyparsing==2.4.7 # packaging pyrsistent==0.18.1 # via jsonschema -pytest==6.2.5 +pyspark==3.2.1 + # via feast (setup.py) +pytest==7.0.1 # via # feast (setup.py) # pytest-benchmark @@ -604,17 +602,21 @@ pytz-deprecation-shim==0.1.0.post0 # via tzlocal pyyaml==6.0 # via + # dask # feast (setup.py) - # libcst # pre-commit # uvicorn pyzmq==22.3.0 # via # jupyter-client # notebook -redis==4.1.2 +redis==3.5.3 + # via + # feast (setup.py) + # redis-py-cluster +redis-py-cluster==2.1.3 # via feast (setup.py) -regex==2022.1.18 +regex==2022.3.2 # via black requests==2.27.1 # via @@ -640,7 +642,7 @@ requests-oauthlib==1.3.1 # via # google-auth-oauthlib # msrest -responses==0.17.0 +responses==0.18.0 # via moto rsa==4.8 # via google-auth @@ -648,15 +650,16 @@ ruamel.yaml==0.17.17 # via great-expectations ruamel.yaml.clib==0.2.6 # via ruamel.yaml -s3transfer==0.5.0 +s3transfer==0.5.2 # via boto3 -scipy==1.7.3 +scipy==1.8.0 # via great-expectations send2trash==1.8.0 # via notebook six==1.16.0 # via # absl-py + # asttokens # azure-core # azure-identity # bleach @@ -673,13 +676,12 @@ six==1.16.0 # pandavro # pyopenssl # python-dateutil - # responses # virtualenv sniffio==1.2.0 # via anyio snowballstemmer==2.2.0 # via sphinx -snowflake-connector-python[pandas]==2.7.3 +snowflake-connector-python[pandas]==2.7.4 # via feast (setup.py) sphinx==4.3.2 # via @@ -699,42 +701,47 @@ sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.5 # via sphinx +stack-data==0.2.0 + # via ipython starlette==0.17.1 # via fastapi tabulate==0.8.9 # via feast (setup.py) tenacity==8.0.1 # via feast (setup.py) -tensorflow-metadata==1.6.0 +tensorflow-metadata==1.7.0 # via feast (setup.py) termcolor==1.1.0 # via great-expectations -terminado==0.13.1 +terminado==0.13.2 # via notebook testcontainers==3.4.2 # via feast (setup.py) -testpath==0.5.0 +testpath==0.6.0 # via nbconvert toml==0.10.2 # via # black # feast (setup.py) # pre-commit - # pytest -tomli==2.0.0 +tomli==2.0.1 # via # coverage # mypy # pep517 + # pytest toolz==0.11.2 - # via altair + # via + # altair + # dask + # partd tornado==6.1 # via # ipykernel # jupyter-client # notebook # terminado -tqdm==4.62.3 +tqdm==4.63.0 # via # feast (setup.py) # great-expectations @@ -751,51 +758,33 @@ traitlets==5.1.1 # nbformat # notebook typed-ast==1.5.2 - # via - # black - # mypy -types-futures==3.3.8 - # via types-protobuf -types-protobuf==3.19.7 + # via black +types-protobuf==3.19.12 # via # feast (setup.py) # mypy-protobuf types-python-dateutil==2.8.9 # via feast (setup.py) -types-pytz==2021.3.4 +types-pytz==2021.3.5 # via feast (setup.py) types-pyyaml==6.0.4 # via feast (setup.py) -types-redis==4.1.13 +types-redis==4.1.17 # via feast (setup.py) -types-requests==2.27.8 +types-requests==2.27.11 # via feast (setup.py) -types-setuptools==57.4.8 +types-setuptools==57.4.9 # via feast (setup.py) types-tabulate==0.8.5 # via feast (setup.py) -types-urllib3==1.26.8 +types-urllib3==1.26.10 # via types-requests -typing-extensions==4.0.1 +typing-extensions==4.1.1 # via - # aiohttp - # anyio - # argon2-cffi - # asgiref - # async-timeout + # azure-core # great-expectations - # h11 - # importlib-metadata - # jsonschema - # libcst # mypy # pydantic - # starlette - # typing-inspect - # uvicorn - # yarl -typing-inspect==0.7.1 - # via libcst tzdata==2021.5 # via pytz-deprecation-shim tzlocal==4.1 @@ -809,11 +798,11 @@ urllib3==1.26.8 # minio # requests # responses -uvicorn[standard]==0.17.1 +uvicorn[standard]==0.17.5 # via feast (setup.py) uvloop==0.16.0 # via uvicorn -virtualenv==20.13.0 +virtualenv==20.13.2 # via pre-commit watchgod==0.7 # via uvicorn @@ -821,20 +810,18 @@ wcwidth==0.2.5 # via prompt-toolkit webencodings==0.5.1 # via bleach -websocket-client==1.2.3 +websocket-client==1.3.1 # via docker -websockets==10.1 +websockets==10.2 # via uvicorn -werkzeug==2.0.2 +werkzeug==2.0.3 # via moto wheel==0.37.1 # via pip-tools widgetsnbextension==3.5.2 # via ipywidgets wrapt==1.13.3 - # via - # deprecated - # testcontainers + # via testcontainers xmltodict==0.12.0 # via moto yarl==1.7.2 @@ -843,8 +830,7 @@ zipp==3.7.0 # via # importlib-metadata # importlib-resources - # pep517 # The following packages are considered to be unsafe in a requirements file: # pip -# setuptools +# setuptools \ No newline at end of file diff --git a/sdk/python/requirements/py3.9-ci-requirements.txt b/sdk/python/requirements/py3.9-ci-requirements.txt index 1421d7e3c31..0e7d6defebd 100644 --- a/sdk/python/requirements/py3.9-ci-requirements.txt +++ b/sdk/python/requirements/py3.9-ci-requirements.txt @@ -42,10 +42,10 @@ asn1crypto==1.4.0 # snowflake-connector-python assertpy==1.1 # via feast (setup.py) +asttokens==2.0.5 + # via stack-data async-timeout==4.0.2 # via aiohttp -asynctest==0.13.0 - # via aiohttp attrs==21.4.0 # via # aiohttp @@ -54,14 +54,14 @@ attrs==21.4.0 # pytest avro==1.10.0 # via feast (setup.py) -azure-core==1.21.1 +azure-core==1.23.0 # via # adlfs # azure-identity # azure-storage-blob azure-datalake-store==0.0.52 # via adlfs -azure-identity==1.7.1 +azure-identity==1.8.0 # via adlfs azure-storage-blob==12.9.0 # via adlfs @@ -69,19 +69,15 @@ babel==2.9.1 # via sphinx backcall==0.2.0 # via ipython -backports.zoneinfo==0.2.1 - # via - # pytz-deprecation-shim - # tzlocal black==19.10b0 # via feast (setup.py) bleach==4.1.0 # via nbconvert -boto3==1.20.46 +boto3==1.21.11 # via # feast (setup.py) # moto -botocore==1.23.46 +botocore==1.24.11 # via # boto3 # moto @@ -104,21 +100,23 @@ cffi==1.15.0 # snowflake-connector-python cfgv==3.3.1 # via pre-commit -charset-normalizer==2.0.11 +charset-normalizer==2.0.12 # via # aiohttp # requests # snowflake-connector-python -click==8.0.3 +click==8.0.4 # via # black # feast (setup.py) # great-expectations # pip-tools # uvicorn +cloudpickle==2.0.0 + # via dask colorama==0.4.4 # via feast (setup.py) -coverage[toml]==6.3 +coverage[toml]==6.3.2 # via pytest-cov cryptography==3.3.2 # via @@ -131,6 +129,8 @@ cryptography==3.3.2 # pyjwt # pyopenssl # snowflake-connector-python +dask==2022.1.1 + # via feast (setup.py) debugpy==1.5.1 # via ipykernel decorator==5.1.1 @@ -139,8 +139,6 @@ decorator==5.1.1 # ipython defusedxml==0.7.1 # via nbconvert -deprecated==1.2.13 - # via redis deprecation==2.1.0 # via testcontainers dill==0.3.4 @@ -155,20 +153,22 @@ docutils==0.17.1 # via # sphinx # sphinx-rtd-theme -entrypoints==0.3 +entrypoints==0.4 # via # altair # jupyter-client # nbconvert execnet==1.9.0 # via pytest-xdist -fastapi==0.73.0 +executing==0.8.3 + # via stack-data +fastapi==0.74.1 # via feast (setup.py) fastavro==1.4.9 # via # feast (setup.py) # pandavro -filelock==3.4.2 +filelock==3.6.0 # via virtualenv firebase-admin==4.5.2 # via feast (setup.py) @@ -178,11 +178,12 @@ frozenlist==1.3.0 # via # aiohttp # aiosignal -fsspec==2022.1.0 +fsspec==2022.2.0 # via # adlfs + # dask # gcsfs -gcsfs==2022.1.0 +gcsfs==2022.2.0 # via feast (setup.py) google-api-core[grpc]==1.31.5 # via @@ -194,7 +195,7 @@ google-api-core[grpc]==1.31.5 # google-cloud-core # google-cloud-datastore # google-cloud-firestore -google-api-python-client==2.36.0 +google-api-python-client==2.39.0 # via firebase-admin google-auth==1.35.0 # via @@ -207,11 +208,11 @@ google-auth==1.35.0 # google-cloud-storage google-auth-httplib2==0.1.0 # via google-api-python-client -google-auth-oauthlib==0.4.6 +google-auth-oauthlib==0.5.0 # via gcsfs -google-cloud-bigquery==2.32.0 +google-cloud-bigquery==2.34.1 # via feast (setup.py) -google-cloud-bigquery-storage==2.11.0 +google-cloud-bigquery-storage==2.12.0 # via feast (setup.py) google-cloud-core==1.7.2 # via @@ -220,7 +221,7 @@ google-cloud-core==1.7.2 # google-cloud-datastore # google-cloud-firestore # google-cloud-storage -google-cloud-datastore==2.4.0 +google-cloud-datastore==2.5.0 # via feast (setup.py) google-cloud-firestore==2.3.4 # via firebase-admin @@ -240,9 +241,9 @@ googleapis-common-protos==1.52.0 # feast (setup.py) # google-api-core # tensorflow-metadata -great-expectations==0.14.4 +great-expectations==0.14.8 # via feast (setup.py) -grpcio==1.43.0 +grpcio==1.44.0 # via # feast (setup.py) # google-api-core @@ -250,7 +251,7 @@ grpcio==1.43.0 # grpcio-reflection # grpcio-testing # grpcio-tools -grpcio-reflection==1.43.0 +grpcio-reflection==1.44.0 # via feast (setup.py) grpcio-testing==1.34.0 # via feast (setup.py) @@ -260,13 +261,13 @@ h11==0.13.0 # via uvicorn hiredis==2.0.0 # via feast (setup.py) -httplib2==0.20.2 +httplib2==0.20.4 # via # google-api-python-client # google-auth-httplib2 httptools==0.3.0 # via uvicorn -identify==2.4.7 +identify==2.4.11 # via pre-commit idna==3.3 # via @@ -276,28 +277,15 @@ idna==3.3 # yarl imagesize==1.3.0 # via sphinx -importlib-metadata==4.2.0 - # via - # click - # flake8 - # great-expectations - # jsonschema - # moto - # pep517 - # pluggy - # pre-commit - # pytest - # redis - # virtualenv -importlib-resources==5.4.0 - # via jsonschema +importlib-metadata==4.11.2 + # via great-expectations iniconfig==1.1.1 # via pytest -ipykernel==6.7.0 +ipykernel==6.9.1 # via # ipywidgets # notebook -ipython==7.31.1 +ipython==8.1.1 # via # ipykernel # ipywidgets @@ -342,7 +330,7 @@ jupyter-client==7.1.2 # ipykernel # nbclient # notebook -jupyter-core==4.9.1 +jupyter-core==4.9.2 # via # jupyter-client # nbconvert @@ -352,11 +340,9 @@ jupyterlab-pygments==0.1.2 # via nbconvert jupyterlab-widgets==1.0.2 # via ipywidgets -libcst==0.4.1 - # via - # google-cloud-bigquery-storage - # google-cloud-datastore -markupsafe==2.0.1 +locket==0.2.1 + # via partd +markupsafe==2.1.0 # via # jinja2 # moto @@ -376,9 +362,9 @@ mmh3==3.0.0 # via feast (setup.py) mock==2.0.0 # via feast (setup.py) -moto==3.0.2 +moto==3.0.5 # via feast (setup.py) -msal==1.16.0 +msal==1.17.0 # via # azure-identity # msal-extensions @@ -399,14 +385,12 @@ multidict==6.0.2 mypy==0.931 # via feast (setup.py) mypy-extensions==0.4.3 - # via - # mypy - # typing-inspect + # via mypy mypy-protobuf==3.1.0 # via feast (setup.py) -nbclient==0.5.10 +nbclient==0.5.11 # via nbconvert -nbconvert==6.4.1 +nbconvert==6.4.2 # via notebook nbformat==5.1.3 # via @@ -424,7 +408,7 @@ nodeenv==1.6.0 # via pre-commit notebook==6.4.8 # via widgetsnbextension -numpy==1.21.5 +numpy==1.22.2 # via # altair # great-expectations @@ -439,12 +423,12 @@ oscrypto==1.2.1 packaging==21.3 # via # bleach + # dask # deprecation # google-api-core # google-cloud-bigquery # google-cloud-firestore # pytest - # redis # sphinx pandas==1.3.5 # via @@ -459,9 +443,11 @@ pandocfilters==1.5.0 # via nbconvert parso==0.8.3 # via jedi +partd==1.2.0 + # via dask pathspec==0.9.0 # via black -pbr==5.8.0 +pbr==5.8.1 # via mock pep517==0.12.0 # via pip-tools @@ -469,19 +455,19 @@ pexpect==4.8.0 # via ipython pickleshare==0.7.5 # via ipython -pip-tools==6.4.0 +pip-tools==6.5.1 # via feast (setup.py) -platformdirs==2.4.1 +platformdirs==2.5.1 # via virtualenv pluggy==1.0.0 # via pytest -portalocker==2.3.2 +portalocker==2.4.0 # via msal-extensions pre-commit==2.17.0 # via feast (setup.py) prometheus-client==0.13.1 # via notebook -prompt-toolkit==3.0.26 +prompt-toolkit==3.0.28 # via ipython proto-plus==1.19.6 # via @@ -506,12 +492,16 @@ ptyprocess==0.7.0 # via # pexpect # terminado +pure-eval==0.2.2 + # via stack-data py==1.11.0 # via # pytest # pytest-forked py-cpuinfo==8.0.0 # via pytest-benchmark +py4j==0.10.9.3 + # via pyspark pyarrow==6.0.1 # via # feast (setup.py) @@ -526,7 +516,7 @@ pycodestyle==2.8.0 # via flake8 pycparser==2.21 # via cffi -pycryptodomex==3.14.0 +pycryptodomex==3.14.1 # via snowflake-connector-python pydantic==1.9.0 # via @@ -554,7 +544,9 @@ pyparsing==2.4.7 # packaging pyrsistent==0.18.1 # via jsonschema -pytest==6.2.5 +pyspark==3.2.1 + # via feast (setup.py) +pytest==7.0.1 # via # feast (setup.py) # pytest-benchmark @@ -604,17 +596,21 @@ pytz-deprecation-shim==0.1.0.post0 # via tzlocal pyyaml==6.0 # via + # dask # feast (setup.py) - # libcst # pre-commit # uvicorn pyzmq==22.3.0 # via # jupyter-client # notebook -redis==4.1.2 +redis==3.5.3 + # via + # feast (setup.py) + # redis-py-cluster +redis-py-cluster==2.1.3 # via feast (setup.py) -regex==2022.1.18 +regex==2022.3.2 # via black requests==2.27.1 # via @@ -640,7 +636,7 @@ requests-oauthlib==1.3.1 # via # google-auth-oauthlib # msrest -responses==0.17.0 +responses==0.18.0 # via moto rsa==4.8 # via google-auth @@ -648,15 +644,16 @@ ruamel.yaml==0.17.17 # via great-expectations ruamel.yaml.clib==0.2.6 # via ruamel.yaml -s3transfer==0.5.0 +s3transfer==0.5.2 # via boto3 -scipy==1.7.3 +scipy==1.8.0 # via great-expectations send2trash==1.8.0 # via notebook six==1.16.0 # via # absl-py + # asttokens # azure-core # azure-identity # bleach @@ -673,13 +670,12 @@ six==1.16.0 # pandavro # pyopenssl # python-dateutil - # responses # virtualenv sniffio==1.2.0 # via anyio snowballstemmer==2.2.0 # via sphinx -snowflake-connector-python[pandas]==2.7.3 +snowflake-connector-python[pandas]==2.7.4 # via feast (setup.py) sphinx==4.3.2 # via @@ -699,42 +695,47 @@ sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.5 # via sphinx +stack-data==0.2.0 + # via ipython starlette==0.17.1 # via fastapi tabulate==0.8.9 # via feast (setup.py) tenacity==8.0.1 # via feast (setup.py) -tensorflow-metadata==1.6.0 +tensorflow-metadata==1.7.0 # via feast (setup.py) termcolor==1.1.0 # via great-expectations -terminado==0.13.1 +terminado==0.13.2 # via notebook testcontainers==3.4.2 # via feast (setup.py) -testpath==0.5.0 +testpath==0.6.0 # via nbconvert toml==0.10.2 # via # black # feast (setup.py) # pre-commit - # pytest -tomli==2.0.0 +tomli==2.0.1 # via # coverage # mypy # pep517 + # pytest toolz==0.11.2 - # via altair + # via + # altair + # dask + # partd tornado==6.1 # via # ipykernel # jupyter-client # notebook # terminado -tqdm==4.62.3 +tqdm==4.63.0 # via # feast (setup.py) # great-expectations @@ -751,51 +752,33 @@ traitlets==5.1.1 # nbformat # notebook typed-ast==1.5.2 - # via - # black - # mypy -types-futures==3.3.8 - # via types-protobuf -types-protobuf==3.19.7 + # via black +types-protobuf==3.19.12 # via # feast (setup.py) # mypy-protobuf types-python-dateutil==2.8.9 # via feast (setup.py) -types-pytz==2021.3.4 +types-pytz==2021.3.5 # via feast (setup.py) types-pyyaml==6.0.4 # via feast (setup.py) -types-redis==4.1.13 +types-redis==4.1.17 # via feast (setup.py) -types-requests==2.27.8 +types-requests==2.27.11 # via feast (setup.py) -types-setuptools==57.4.8 +types-setuptools==57.4.9 # via feast (setup.py) types-tabulate==0.8.5 # via feast (setup.py) -types-urllib3==1.26.8 +types-urllib3==1.26.10 # via types-requests -typing-extensions==4.0.1 +typing-extensions==4.1.1 # via - # aiohttp - # anyio - # argon2-cffi - # asgiref - # async-timeout + # azure-core # great-expectations - # h11 - # importlib-metadata - # jsonschema - # libcst # mypy # pydantic - # starlette - # typing-inspect - # uvicorn - # yarl -typing-inspect==0.7.1 - # via libcst tzdata==2021.5 # via pytz-deprecation-shim tzlocal==4.1 @@ -809,11 +792,11 @@ urllib3==1.26.8 # minio # requests # responses -uvicorn[standard]==0.17.1 +uvicorn[standard]==0.17.5 # via feast (setup.py) uvloop==0.16.0 # via uvicorn -virtualenv==20.13.0 +virtualenv==20.13.2 # via pre-commit watchgod==0.7 # via uvicorn @@ -821,29 +804,24 @@ wcwidth==0.2.5 # via prompt-toolkit webencodings==0.5.1 # via bleach -websocket-client==1.2.3 +websocket-client==1.3.1 # via docker -websockets==10.1 +websockets==10.2 # via uvicorn -werkzeug==2.0.2 +werkzeug==2.0.3 # via moto wheel==0.37.1 # via pip-tools widgetsnbextension==3.5.2 # via ipywidgets wrapt==1.13.3 - # via - # deprecated - # testcontainers + # via testcontainers xmltodict==0.12.0 # via moto yarl==1.7.2 # via aiohttp zipp==3.7.0 - # via - # importlib-metadata - # importlib-resources - # pep517 + # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # pip diff --git a/sdk/python/setup.py b/sdk/python/setup.py index 7535987f833..f95dd2b806b 100644 --- a/sdk/python/setup.py +++ b/sdk/python/setup.py @@ -40,7 +40,7 @@ REQUIRES_PYTHON = ">=3.7.0" REQUIRED = [ - "Click==8.*", + "Click>=7.*", "colorama>=0.3.9", "dill==0.3.*", "fastavro>=1.1.0", @@ -66,6 +66,7 @@ "uvicorn[standard]>=0.14.0", "proto-plus<1.19.7", "tensorflow-metadata>=1.0.0,<2.0.0", + "dask>=2021.*,<2022.02.0", ] GCP_REQUIRED = [ @@ -77,7 +78,8 @@ ] REDIS_REQUIRED = [ - "redis>=4.1.0", + "redis==3.5.3", + "redis-py-cluster>=2.1.3", "hiredis>=2.0.0", ] @@ -90,6 +92,10 @@ "snowflake-connector-python[pandas]>=2.7.3", ] +SPARK_REQUIRED = [ + "pyspark>=3.0.0", +] + GE_REQUIRED = [ "great_expectations>=0.14.0,<0.15.0" ] @@ -139,6 +145,7 @@ + REDIS_REQUIRED + AWS_REQUIRED + SNOWFLAKE_REQUIRED + + SPARK_REQUIRED + GE_REQUIRED ) @@ -242,6 +249,7 @@ def run(self): "aws": AWS_REQUIRED, "redis": REDIS_REQUIRED, "snowflake": SNOWFLAKE_REQUIRED, + "spark": SPARK_REQUIRED, "ge": GE_REQUIRED, }, include_package_data=True, diff --git a/sdk/python/tests/benchmarks/test_benchmark_universal_online_retrieval.py b/sdk/python/tests/benchmarks/test_benchmark_universal_online_retrieval.py index 0651383880f..3d2a253dc0e 100644 --- a/sdk/python/tests/benchmarks/test_benchmark_universal_online_retrieval.py +++ b/sdk/python/tests/benchmarks/test_benchmark_universal_online_retrieval.py @@ -1,8 +1,10 @@ import random +from typing import List import pytest from feast import FeatureService +from feast.feast_object import FeastObject from tests.integration.feature_repos.repo_configuration import ( construct_universal_feature_views, ) @@ -16,25 +18,24 @@ @pytest.mark.benchmark @pytest.mark.integration def test_online_retrieval(environment, universal_data_sources, benchmark): - fs = environment.feature_store entities, datasets, data_sources = universal_data_sources feature_views = construct_universal_feature_views(data_sources) feature_service = FeatureService( "convrate_plus100", - features=[feature_views["driver"][["conv_rate"]], feature_views["driver_odfv"]], + features=[feature_views.driver[["conv_rate"]], feature_views.driver_odfv], ) - feast_objects = [] + feast_objects: List[FeastObject] = [] feast_objects.extend(feature_views.values()) feast_objects.extend([driver(), customer(), location(), feature_service]) fs.apply(feast_objects) fs.materialize(environment.start_date, environment.end_date) - sample_drivers = random.sample(entities["driver"], 10) + sample_drivers = random.sample(entities.driver_vals, 10) - sample_customers = random.sample(entities["customer"], 10) + sample_customers = random.sample(entities.customer_vals, 10) entity_rows = [ {"driver": d, "customer_id": c, "val_to_add": 50} diff --git a/sdk/python/tests/conftest.py b/sdk/python/tests/conftest.py index 49f32379a3b..9de146ac12a 100644 --- a/sdk/python/tests/conftest.py +++ b/sdk/python/tests/conftest.py @@ -30,12 +30,12 @@ ) from tests.integration.feature_repos.repo_configuration import ( FULL_REPO_CONFIGS, + REDIS_CLUSTER_CONFIG, REDIS_CONFIG, Environment, + TestData, construct_test_environment, - construct_universal_data_sources, - construct_universal_datasets, - construct_universal_entities, + construct_universal_test_data, ) logger = logging.getLogger(__name__) @@ -170,10 +170,14 @@ def cleanup(): return e -@pytest.fixture() +@pytest.fixture( + params=[REDIS_CONFIG, REDIS_CLUSTER_CONFIG], + scope="session", + ids=[str(c) for c in [REDIS_CONFIG, REDIS_CLUSTER_CONFIG]], +) def local_redis_environment(request, worker_id): e = construct_test_environment( - IntegrationTestRepoConfig(online_store=REDIS_CONFIG), worker_id=worker_id + IntegrationTestRepoConfig(online_store=request.param), worker_id=worker_id ) def cleanup(): @@ -184,21 +188,23 @@ def cleanup(): @pytest.fixture(scope="session") -def universal_data_sources(request, environment): - entities = construct_universal_entities() - datasets = construct_universal_datasets( - entities, environment.start_date, environment.end_date - ) - datasources = construct_universal_data_sources( - datasets, environment.data_source_creator - ) - +def universal_data_sources(request, environment) -> TestData: def cleanup(): # logger.info("Running cleanup in %s, Request: %s", worker_id, request.param) environment.data_source_creator.teardown() request.addfinalizer(cleanup) - return entities, datasets, datasources + return construct_universal_test_data(environment) + + +@pytest.fixture(scope="session") +def redis_universal_data_sources(request, local_redis_environment): + def cleanup(): + # logger.info("Running cleanup in %s, Request: %s", worker_id, request.param) + local_redis_environment.data_source_creator.teardown() + + request.addfinalizer(cleanup) + return construct_universal_test_data(local_redis_environment) @pytest.fixture(scope="session") diff --git a/sdk/python/tests/example_repos/example_feature_repo_1.py b/sdk/python/tests/example_repos/example_feature_repo_1.py index e0e6b92380d..8179906fa45 100644 --- a/sdk/python/tests/example_repos/example_feature_repo_1.py +++ b/sdk/python/tests/example_repos/example_feature_repo_1.py @@ -10,13 +10,15 @@ ) driver_locations_source = BigQuerySource( - table_ref="feast-oss.public.drivers", + table="feast-oss.public.drivers", event_timestamp_column="event_timestamp", created_timestamp_column="created_timestamp", ) customer_profile_source = BigQuerySource( - table_ref="feast-oss.public.customers", event_timestamp_column="event_timestamp", + name="customer_profile_source", + table_ref="feast-oss.public.customers", + event_timestamp_column="event_timestamp", ) customer_driver_combined_source = BigQuerySource( diff --git a/sdk/python/tests/example_repos/example_repo_duplicate_data_source_names.py b/sdk/python/tests/example_repos/example_repo_duplicate_data_source_names.py new file mode 100644 index 00000000000..5ec08b71820 --- /dev/null +++ b/sdk/python/tests/example_repos/example_repo_duplicate_data_source_names.py @@ -0,0 +1,9 @@ +from feast import FileSource + +driver_hourly_stats = FileSource( + path="driver_stats.parquet", # this parquet is not real and will not be read +) + +driver_hourly_stats_clone = FileSource( + path="driver_stats.parquet", # this parquet is not real and will not be read +) diff --git a/sdk/python/tests/integration/e2e/test_universal_e2e.py b/sdk/python/tests/integration/e2e/test_universal_e2e.py index fbbdd14f23e..477c79614c5 100644 --- a/sdk/python/tests/integration/e2e/test_universal_e2e.py +++ b/sdk/python/tests/integration/e2e/test_universal_e2e.py @@ -76,14 +76,26 @@ def check_offline_and_online_features( if full_feature_names: if expected_value: - assert abs(df.to_dict()[f"{fv.name}__value"][0] - expected_value) < 1e-6 + assert ( + abs( + df.to_dict(orient="list")[f"{fv.name}__value"][0] + - expected_value + ) + < 1e-6 + ) else: - assert math.isnan(df.to_dict()[f"{fv.name}__value"][0]) + assert not df.to_dict(orient="list")[f"{fv.name}__value"] or math.isnan( + df.to_dict(orient="list")[f"{fv.name}__value"][0] + ) else: if expected_value: - assert abs(df.to_dict()["value"][0] - expected_value) < 1e-6 + assert ( + abs(df.to_dict(orient="list")["value"][0] - expected_value) < 1e-6 + ) else: - assert math.isnan(df.to_dict()["value"][0]) + assert not df.to_dict(orient="list")["value"] or math.isnan( + df.to_dict(orient="list")["value"][0] + ) def run_offline_online_store_consistency_test( diff --git a/sdk/python/tests/integration/e2e/test_usage_e2e.py b/sdk/python/tests/integration/e2e/test_usage_e2e.py index 0bae9730632..c7b62b3a5da 100644 --- a/sdk/python/tests/integration/e2e/test_usage_e2e.py +++ b/sdk/python/tests/integration/e2e/test_usage_e2e.py @@ -61,7 +61,7 @@ def test_usage_on(dummy_exporter, enabling_toggle): name="driver_car_id", description="Car driver id", value_type=ValueType.STRING, - labels={"team": "matchmaking"}, + tags={"team": "matchmaking"}, ) test_feature_store.apply([entity]) @@ -100,7 +100,7 @@ def test_usage_off(dummy_exporter, enabling_toggle): name="driver_car_id", description="Car driver id", value_type=ValueType.STRING, - labels={"team": "matchmaking"}, + tags={"team": "matchmaking"}, ) test_feature_store.apply([entity]) diff --git a/sdk/python/tests/integration/e2e/test_validation.py b/sdk/python/tests/integration/e2e/test_validation.py index 2bd1e3cbbc9..77706b74d10 100644 --- a/sdk/python/tests/integration/e2e/test_validation.py +++ b/sdk/python/tests/integration/e2e/test_validation.py @@ -67,7 +67,7 @@ def test_historical_retrieval_with_validation(environment, universal_data_source store.apply([driver(), customer(), location(), *feature_views.values()]) - entity_df = datasets["entity"].drop( + entity_df = datasets.entity_df.drop( columns=["order_id", "origin_id", "destination_id"] ) @@ -101,7 +101,7 @@ def test_historical_retrieval_fails_on_validation(environment, universal_data_so store.apply([driver(), customer(), location(), *feature_views.values()]) - entity_df = datasets["entity"].drop( + entity_df = datasets.entity_df.drop( columns=["order_id", "origin_id", "destination_id"] ) diff --git a/sdk/python/tests/integration/feature_repos/repo_configuration.py b/sdk/python/tests/integration/feature_repos/repo_configuration.py index a9953d5977e..89aea727a6e 100644 --- a/sdk/python/tests/integration/feature_repos/repo_configuration.py +++ b/sdk/python/tests/integration/feature_repos/repo_configuration.py @@ -1,18 +1,19 @@ +import dataclasses import importlib import json import os import re import tempfile import uuid -from dataclasses import dataclass, field +from dataclasses import dataclass from datetime import datetime, timedelta from pathlib import Path -from typing import Any, Dict, List, Optional, Union +from typing import Any, List, Optional, Tuple, Union import pandas as pd import yaml -from feast import FeatureStore, FeatureView, driver_test_data +from feast import FeatureStore, FeatureView, OnDemandFeatureView, driver_test_data from feast.constants import FULL_REPO_CONFIGS_MODULE_ENV_NAME from feast.data_source import DataSource from feast.errors import FeastModuleImportError @@ -45,7 +46,14 @@ ) DYNAMO_CONFIG = {"type": "dynamodb", "region": "us-west-2"} -REDIS_CONFIG = {"type": "redis", "connection_string": "localhost:6379,db=0"} +# Port 12345 will chosen as default for redis node configuration because Redis Cluster is started off of nodes 6379 -> 6384. This causes conflicts in cli integration tests so we manually keep them separate. +REDIS_CONFIG = {"type": "redis", "connection_string": "localhost:12345,db=0"} +REDIS_CLUSTER_CONFIG = { + "type": "redis", + "redis_type": "redis_cluster", + # Redis Cluster Port Forwarding is setup in "pr_integration_tests.yaml" under "Setup Redis Cluster". + "connection_string": "127.0.0.1:6001,127.0.0.1:6002,127.0.0.1:6003", +} # FULL_REPO_CONFIGS contains the repo configurations (e.g. provider, offline store, # online store, test data, and more parameters) that most integration tests will test @@ -62,7 +70,9 @@ if os.getenv("FEAST_IS_LOCAL_TEST", "False") != "True": DEFAULT_FULL_REPO_CONFIGS.extend( [ + # Redis configurations IntegrationTestRepoConfig(online_store=REDIS_CONFIG), + IntegrationTestRepoConfig(online_store=REDIS_CLUSTER_CONFIG), # GCP configurations IntegrationTestRepoConfig( provider="gcp", @@ -107,30 +117,48 @@ FULL_REPO_CONFIGS = DEFAULT_FULL_REPO_CONFIGS -def construct_universal_entities() -> Dict[str, List[Any]]: - return { - "customer": list(range(1001, 1020)), - "driver": list(range(5001, 5020)), - "location": list(range(1, 50)), - } +@dataclass +class UniversalEntities: + customer_vals: List[Any] + driver_vals: List[Any] + location_vals: List[Any] + + +def construct_universal_entities() -> UniversalEntities: + return UniversalEntities( + customer_vals=list(range(1001, 1020)), + driver_vals=list(range(5001, 5020)), + location_vals=list(range(1, 50)), + ) + + +@dataclass +class UniversalDatasets: + customer_df: pd.DataFrame + driver_df: pd.DataFrame + location_df: pd.DataFrame + orders_df: pd.DataFrame + global_df: pd.DataFrame + field_mapping_df: pd.DataFrame + entity_df: pd.DataFrame def construct_universal_datasets( - entities: Dict[str, List[Any]], start_time: datetime, end_time: datetime -) -> Dict[str, pd.DataFrame]: + entities: UniversalEntities, start_time: datetime, end_time: datetime +) -> UniversalDatasets: customer_df = driver_test_data.create_customer_daily_profile_df( - entities["customer"], start_time, end_time + entities.customer_vals, start_time, end_time ) driver_df = driver_test_data.create_driver_hourly_stats_df( - entities["driver"], start_time, end_time + entities.driver_vals, start_time, end_time ) location_df = driver_test_data.create_location_stats_df( - entities["location"], start_time, end_time + entities.location_vals, start_time, end_time ) orders_df = driver_test_data.create_orders_df( - customers=entities["customer"], - drivers=entities["driver"], - locations=entities["location"], + customers=entities.customer_vals, + drivers=entities.driver_vals, + locations=entities.location_vals, start_date=start_time, end_date=end_time, order_count=20, @@ -148,92 +176,111 @@ def construct_universal_datasets( ] ] - return { - "customer": customer_df, - "driver": driver_df, - "location": location_df, - "orders": orders_df, - "global": global_df, - "field_mapping": field_mapping_df, - "entity": entity_df, - } + return UniversalDatasets( + customer_df=customer_df, + driver_df=driver_df, + location_df=location_df, + orders_df=orders_df, + global_df=global_df, + field_mapping_df=field_mapping_df, + entity_df=entity_df, + ) + + +@dataclass +class UniversalDataSources: + customer: DataSource + driver: DataSource + location: DataSource + orders: DataSource + global_ds: DataSource + field_mapping: DataSource def construct_universal_data_sources( - datasets: Dict[str, pd.DataFrame], data_source_creator: DataSourceCreator -) -> Dict[str, DataSource]: + datasets: UniversalDatasets, data_source_creator: DataSourceCreator +) -> UniversalDataSources: customer_ds = data_source_creator.create_data_source( - datasets["customer"], + datasets.customer_df, destination_name="customer_profile", event_timestamp_column="event_timestamp", created_timestamp_column="created", ) driver_ds = data_source_creator.create_data_source( - datasets["driver"], + datasets.driver_df, destination_name="driver_hourly", event_timestamp_column="event_timestamp", created_timestamp_column="created", ) location_ds = data_source_creator.create_data_source( - datasets["location"], + datasets.location_df, destination_name="location_hourly", event_timestamp_column="event_timestamp", created_timestamp_column="created", ) orders_ds = data_source_creator.create_data_source( - datasets["orders"], + datasets.orders_df, destination_name="orders", event_timestamp_column="event_timestamp", created_timestamp_column=None, ) global_ds = data_source_creator.create_data_source( - datasets["global"], + datasets.global_df, destination_name="global", event_timestamp_column="event_timestamp", created_timestamp_column="created", ) field_mapping_ds = data_source_creator.create_data_source( - datasets["field_mapping"], + datasets.field_mapping_df, destination_name="field_mapping", event_timestamp_column="event_timestamp", created_timestamp_column="created", field_mapping={"column_name": "feature_name"}, ) - return { - "customer": customer_ds, - "driver": driver_ds, - "location": location_ds, - "orders": orders_ds, - "global": global_ds, - "field_mapping": field_mapping_ds, - } + return UniversalDataSources( + customer=customer_ds, + driver=driver_ds, + location=location_ds, + orders=orders_ds, + global_ds=global_ds, + field_mapping=field_mapping_ds, + ) + + +@dataclass +class UniversalFeatureViews: + customer: FeatureView + global_fv: FeatureView + driver: FeatureView + driver_odfv: OnDemandFeatureView + driver_age_request_fv: FeatureView + order: FeatureView + location: FeatureView + field_mapping: FeatureView + + def values(self): + return dataclasses.asdict(self).values() def construct_universal_feature_views( - data_sources: Dict[str, DataSource], -) -> Dict[str, FeatureView]: - driver_hourly_stats = create_driver_hourly_stats_feature_view( - data_sources["driver"] - ) - return { - "customer": create_customer_daily_profile_feature_view( - data_sources["customer"] - ), - "global": create_global_stats_feature_view(data_sources["global"]), - "driver": driver_hourly_stats, - "driver_odfv": conv_rate_plus_100_feature_view( + data_sources: UniversalDataSources, +) -> UniversalFeatureViews: + driver_hourly_stats = create_driver_hourly_stats_feature_view(data_sources.driver) + return UniversalFeatureViews( + customer=create_customer_daily_profile_feature_view(data_sources.customer), + global_fv=create_global_stats_feature_view(data_sources.global_ds), + driver=driver_hourly_stats, + driver_odfv=conv_rate_plus_100_feature_view( { "driver": driver_hourly_stats, "input_request": create_conv_rate_request_data_source(), } ), - "driver_age_request_fv": create_driver_age_request_feature_view(), - "order": create_order_feature_view(data_sources["orders"]), - "location": create_location_stats_feature_view(data_sources["location"]), - "field_mapping": create_field_mapping_feature_view( - data_sources["field_mapping"] - ), - } + driver_age_request_fv=create_driver_age_request_feature_view(), + order=create_order_feature_view(data_sources.orders), + location=create_location_stats_feature_view(data_sources.location), + field_mapping=create_field_mapping_feature_view(data_sources.field_mapping), + ) @dataclass @@ -245,11 +292,8 @@ class Environment: python_feature_server: bool worker_id: str - end_date: datetime = field( - default=datetime.utcnow().replace(microsecond=0, second=0, minute=0) - ) - def __post_init__(self): + self.end_date = datetime.utcnow().replace(microsecond=0, second=0, minute=0) self.start_date: datetime = self.end_date - timedelta(days=3) def get_feature_server_endpoint(self) -> str: @@ -280,7 +324,6 @@ def construct_test_environment( test_suite_name: str = "integration_test", worker_id: str = "worker_id", ) -> Environment: - _uuid = str(uuid.uuid4()).replace("-", "")[:6] run_id = os.getenv("GITHUB_RUN_ID", default=None) @@ -344,3 +387,18 @@ def construct_test_environment( ) return environment + + +TestData = Tuple[UniversalEntities, UniversalDatasets, UniversalDataSources] + + +def construct_universal_test_data(environment: Environment) -> TestData: + entities = construct_universal_entities() + datasets = construct_universal_datasets( + entities, environment.start_date, environment.end_date + ) + data_sources = construct_universal_data_sources( + datasets, environment.data_source_creator + ) + + return entities, datasets, data_sources diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/snowflake.py b/sdk/python/tests/integration/feature_repos/universal/data_sources/snowflake.py index 1ecae0317bf..f76656f5b71 100644 --- a/sdk/python/tests/integration/feature_repos/universal/data_sources/snowflake.py +++ b/sdk/python/tests/integration/feature_repos/universal/data_sources/snowflake.py @@ -30,6 +30,7 @@ def __init__(self, project_name: str): role=os.environ["SNOWFLAKE_CI_ROLE"], warehouse=os.environ["SNOWFLAKE_CI_WAREHOUSE"], database="FEAST", + schema="OFFLINE", ) def create_data_source( diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/spark_data_source_creator.py b/sdk/python/tests/integration/feature_repos/universal/data_sources/spark_data_source_creator.py new file mode 100644 index 00000000000..4284c3cf4c4 --- /dev/null +++ b/sdk/python/tests/integration/feature_repos/universal/data_sources/spark_data_source_creator.py @@ -0,0 +1,108 @@ +import uuid +from typing import Dict, List + +import pandas as pd +from pyspark import SparkConf +from pyspark.sql import SparkSession + +from feast.data_source import DataSource +from feast.infra.offline_stores.contrib.spark_offline_store.spark import ( + SparkOfflineStoreConfig, +) +from feast.infra.offline_stores.contrib.spark_offline_store.spark_source import ( + SavedDatasetSparkStorage, + SparkSource, +) +from tests.integration.feature_repos.universal.data_source_creator import ( + DataSourceCreator, +) + + +class SparkDataSourceCreator(DataSourceCreator): + tables: List[str] = [] + spark_offline_store_config = None + spark_session = None + + def __init__(self, project_name: str): + self.spark_conf = { + "master": "local[*]", + "spark.ui.enabled": "false", + "spark.eventLog.enabled": "false", + "spark.sql.parser.quotedRegexColumnNames": "true", + "spark.sql.session.timeZone": "UTC", + } + self.project_name = project_name + if not self.spark_offline_store_config: + self.create_offline_store_config() + if not self.spark_session: + self.spark_session = ( + SparkSession.builder.config( + conf=SparkConf().setAll( + [(k, v) for k, v in self.spark_conf.items()] + ) + ) + .appName("pytest-pyspark-local-testing") + .getOrCreate() + ) + self.tables: List[str] = [] + + def teardown(self): + self.spark_session.stop() + + def create_offline_store_config(self): + self.spark_offline_store_config = SparkOfflineStoreConfig() + self.spark_offline_store_config.type = "spark" + self.spark_offline_store_config.spark_conf = self.spark_conf + return self.spark_offline_store_config + + def create_data_source( + self, + df: pd.DataFrame, + destination_name: str, + event_timestamp_column="ts", + created_timestamp_column="created_ts", + field_mapping: Dict[str, str] = None, + **kwargs, + ) -> DataSource: + if event_timestamp_column in df: + df[event_timestamp_column] = pd.to_datetime( + df[event_timestamp_column], utc=True + ) + # Make sure the field mapping is correct and convert the datetime datasources. + if field_mapping: + timestamp_mapping = {value: key for key, value in field_mapping.items()} + if ( + event_timestamp_column in timestamp_mapping + and timestamp_mapping[event_timestamp_column] in df + ): + col = timestamp_mapping[event_timestamp_column] + df[col] = pd.to_datetime(df[col], utc=True) + destination_name = self.get_prefixed_table_name(destination_name) + if not self.spark_session: + self.spark_session = ( + SparkSession.builder.config( + conf=SparkConf().setAll( + [(k, v) for k, v in self.spark_conf.items()] + ) + ) + .appName("pytest-pyspark-local-testing") + .getOrCreate() + ) + self.spark_session.createDataFrame(df).createOrReplaceTempView(destination_name) + self.tables.append(destination_name) + + return SparkSource( + table=destination_name, + event_timestamp_column=event_timestamp_column, + created_timestamp_column=created_timestamp_column, + date_partition_column="", + # maps certain column names to other names + field_mapping=field_mapping or {"ts_1": "ts"}, + ) + + def create_saved_dataset_destination(self) -> SavedDatasetSparkStorage: + table = f"persisted_{str(uuid.uuid4()).replace('-', '_')}" + return SavedDatasetSparkStorage(table_ref=table, query="") + + def get_prefixed_table_name(self, suffix: str) -> str: + return f"{self.project_name}_{suffix}" diff --git a/sdk/python/tests/integration/offline_store/test_s3_custom_endpoint.py b/sdk/python/tests/integration/offline_store/test_s3_custom_endpoint.py index 3eb3f4da6f5..6066009a6d6 100644 --- a/sdk/python/tests/integration/offline_store/test_s3_custom_endpoint.py +++ b/sdk/python/tests/integration/offline_store/test_s3_custom_endpoint.py @@ -1,5 +1,8 @@ +from typing import List + import pytest +from feast.feature_store import FeastObject from tests.integration.feature_repos.repo_configuration import ( IntegrationTestRepoConfig, construct_test_environment, @@ -14,7 +17,7 @@ @pytest.mark.skip( reason="No way to run this test today. Credentials conflict with real AWS credentials in CI" ) -def test_registration_and_retrieval_from_custom_s3_endpoint(universal_data_sources): +def test_registration_and_retrieval_from_custom_s3_endpoint(universal_data_sources,): config = IntegrationTestRepoConfig( offline_store_creator="tests.integration.feature_repos.universal.data_sources.file.S3FileDataSourceCreator" ) @@ -35,7 +38,7 @@ def test_registration_and_retrieval_from_custom_s3_endpoint(universal_data_sourc entities, datasets, data_sources = universal_data_sources feature_views = construct_universal_feature_views(data_sources) - feast_objects = [] + feast_objects: List[FeastObject] = [] feast_objects.extend(feature_views.values()) feast_objects.extend([driver(), customer()]) fs.apply(feast_objects) diff --git a/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py b/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py index 4a396c7e4d8..ab9b9515f39 100644 --- a/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py +++ b/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py @@ -282,9 +282,10 @@ def test_historical_features(environment, universal_data_sources, full_feature_n store = environment.feature_store (entities, datasets, data_sources) = universal_data_sources + feature_views = construct_universal_feature_views(data_sources) - entity_df_with_request_data = datasets["entity"].copy(deep=True) + entity_df_with_request_data = datasets.entity_df.copy(deep=True) entity_df_with_request_data["val_to_add"] = [ i for i in range(len(entity_df_with_request_data)) ] @@ -295,20 +296,20 @@ def test_historical_features(environment, universal_data_sources, full_feature_n feature_service = FeatureService( name="convrate_plus100", features=[ - feature_views["driver"][["conv_rate"]], - feature_views["driver_odfv"], - feature_views["driver_age_request_fv"], + feature_views.driver[["conv_rate"]], + feature_views.driver_odfv, + feature_views.driver_age_request_fv, ], ) feature_service_entity_mapping = FeatureService( name="entity_mapping", features=[ - feature_views["location"] - .with_name("origin") - .with_join_key_map({"location_id": "origin_id"}), - feature_views["location"] - .with_name("destination") - .with_join_key_map({"location_id": "destination_id"}), + feature_views.location.with_name("origin").with_join_key_map( + {"location_id": "origin_id"} + ), + feature_views.location.with_name("destination").with_join_key_map( + {"location_id": "destination_id"} + ), ], ) @@ -325,22 +326,22 @@ def test_historical_features(environment, universal_data_sources, full_feature_n event_timestamp = ( DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL - if DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL in datasets["orders"].columns + if DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL in datasets.orders_df.columns else "e_ts" ) full_expected_df = get_expected_training_df( - datasets["customer"], - feature_views["customer"], - datasets["driver"], - feature_views["driver"], - datasets["orders"], - feature_views["order"], - datasets["location"], - feature_views["location"], - datasets["global"], - feature_views["global"], - datasets["field_mapping"], - feature_views["field_mapping"], + datasets.customer_df, + feature_views.customer, + datasets.driver_df, + feature_views.driver, + datasets.orders_df, + feature_views.order, + datasets.location_df, + feature_views.location, + datasets.global_df, + feature_views.global_fv, + datasets.field_mapping_df, + feature_views.field_mapping, entity_df_with_request_data, event_timestamp, full_feature_names, @@ -426,7 +427,7 @@ def test_historical_features_with_missing_request_data( # If request data is missing that's needed for on demand transform, throw an error with pytest.raises(RequestDataNotFoundInEntityDfException): store.get_historical_features( - entity_df=datasets["entity"], + entity_df=datasets.entity_df, features=[ "customer_profile:current_balance", "customer_profile:avg_passenger_count", @@ -443,7 +444,7 @@ def test_historical_features_with_missing_request_data( # If request data is missing that's needed for a request feature view, throw an error with pytest.raises(RequestDataNotFoundInEntityDfException): store.get_historical_features( - entity_df=datasets["entity"], + entity_df=datasets.entity_df, features=[ "customer_profile:current_balance", "customer_profile:avg_passenger_count", @@ -468,7 +469,7 @@ def test_historical_features_with_entities_from_query( (entities, datasets, data_sources) = universal_data_sources feature_views = construct_universal_feature_views(data_sources) - orders_table = table_name_from_data_source(data_sources["orders"]) + orders_table = table_name_from_data_source(data_sources.orders) if not orders_table: raise pytest.skip("Offline source is not sql-based") @@ -503,23 +504,23 @@ def test_historical_features_with_entities_from_query( event_timestamp = ( DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL - if DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL in datasets["orders"].columns + if DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL in datasets.orders_df.columns else "e_ts" ) full_expected_df = get_expected_training_df( - datasets["customer"], - feature_views["customer"], - datasets["driver"], - feature_views["driver"], - datasets["orders"], - feature_views["order"], - datasets["location"], - feature_views["location"], - datasets["global"], - feature_views["global"], - datasets["field_mapping"], - feature_views["field_mapping"], - datasets["entity"], + datasets.customer_df, + feature_views.customer, + datasets.driver_df, + feature_views.driver, + datasets.orders_df, + feature_views.order, + datasets.location_df, + feature_views.location, + datasets.global_df, + feature_views.global_fv, + datasets.field_mapping_df, + feature_views.field_mapping, + datasets.entity_df, event_timestamp, full_feature_names, ) @@ -567,7 +568,7 @@ def test_historical_features_persisting( store.apply([driver(), customer(), location(), *feature_views.values()]) - entity_df = datasets["entity"].drop( + entity_df = datasets.entity_df.drop( columns=["order_id", "origin_id", "destination_id"] ) @@ -594,18 +595,18 @@ def test_historical_features_persisting( event_timestamp = DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL expected_df = get_expected_training_df( - datasets["customer"], - feature_views["customer"], - datasets["driver"], - feature_views["driver"], - datasets["orders"], - feature_views["order"], - datasets["location"], - feature_views["location"], - datasets["global"], - feature_views["global"], - datasets["field_mapping"], - feature_views["field_mapping"], + datasets.customer_df, + feature_views.customer, + datasets.driver_df, + feature_views.driver, + datasets.orders_df, + feature_views.order, + datasets.location_df, + feature_views.location, + datasets.global_df, + feature_views.global_fv, + datasets.field_mapping_df, + feature_views.field_mapping, entity_df, event_timestamp, full_feature_names, diff --git a/sdk/python/tests/integration/online_store/test_universal_online.py b/sdk/python/tests/integration/online_store/test_universal_online.py index f483d54f6b3..bdbdfb35552 100644 --- a/sdk/python/tests/integration/online_store/test_universal_online.py +++ b/sdk/python/tests/integration/online_store/test_universal_online.py @@ -4,19 +4,22 @@ import time import unittest from datetime import timedelta -from typing import Any, Dict, List, Union +from typing import Any, Dict, List, Tuple, Union import assertpy import numpy as np import pandas as pd import pytest import requests +from botocore.exceptions import BotoCoreError from feast import Entity, Feature, FeatureService, FeatureView, ValueType from feast.errors import ( FeatureNameCollisionError, RequestDataNotFoundInEntityRowsException, ) +from feast.online_response import TIMESTAMP_POSTFIX +from feast.wait import wait_retry_backoff from tests.integration.feature_repos.repo_configuration import ( Environment, construct_universal_feature_views, @@ -33,6 +36,65 @@ from tests.utils.data_source_utils import prep_file_source +@pytest.mark.integration +def test_entity_ttl_online_store(local_redis_environment, redis_universal_data_sources): + if os.getenv("FEAST_IS_LOCAL_TEST", "False") == "True": + return + fs = local_redis_environment.feature_store + # setting ttl setting in online store to 1 second + fs.config.online_store.key_ttl_seconds = 1 + entities, datasets, data_sources = redis_universal_data_sources + driver_hourly_stats = create_driver_hourly_stats_feature_view(data_sources.driver) + driver_entity = driver() + + # Register Feature View and Entity + fs.apply([driver_hourly_stats, driver_entity]) + + # fake data to ingest into Online Store + data = { + "driver_id": [1], + "conv_rate": [0.5], + "acc_rate": [0.6], + "avg_daily_trips": [4], + "event_timestamp": [pd.Timestamp(datetime.datetime.utcnow()).round("ms")], + "created": [pd.Timestamp(datetime.datetime.utcnow()).round("ms")], + } + df_ingest = pd.DataFrame(data) + + # directly ingest data into the Online Store + fs.write_to_online_store("driver_stats", df_ingest) + + # assert the right data is in the Online Store + df = fs.get_online_features( + features=[ + "driver_stats:avg_daily_trips", + "driver_stats:acc_rate", + "driver_stats:conv_rate", + ], + entity_rows=[{"driver": 1}], + ).to_df() + assertpy.assert_that(df["avg_daily_trips"].iloc[0]).is_equal_to(4) + assertpy.assert_that(df["acc_rate"].iloc[0]).is_close_to(0.6, 1e-6) + assertpy.assert_that(df["conv_rate"].iloc[0]).is_close_to(0.5, 1e-6) + + # simulate time passing for testing ttl + time.sleep(1) + + # retrieve the same entity again + df = fs.get_online_features( + features=[ + "driver_stats:avg_daily_trips", + "driver_stats:acc_rate", + "driver_stats:conv_rate", + ], + entity_rows=[{"driver": 1}], + ).to_df() + # assert that the entity features expired in the online store + assertpy.assert_that(df["avg_daily_trips"].iloc[0]).is_none() + assertpy.assert_that(df["acc_rate"].iloc[0]).is_none() + assertpy.assert_that(df["conv_rate"].iloc[0]).is_none() + + # TODO: make this work with all universal (all online store types) @pytest.mark.integration def test_write_to_online_store_event_check(local_redis_environment): @@ -137,12 +199,11 @@ def test_write_to_online_store_event_check(local_redis_environment): @pytest.mark.integration +@pytest.mark.universal def test_write_to_online_store(environment, universal_data_sources): fs = environment.feature_store entities, datasets, data_sources = universal_data_sources - driver_hourly_stats = create_driver_hourly_stats_feature_view( - data_sources["driver"] - ) + driver_hourly_stats = create_driver_hourly_stats_feature_view(data_sources.driver) driver_entity = driver() # Register Feature View and Entity @@ -262,6 +323,70 @@ def get_online_features_dict( return dict1 +@pytest.mark.integration +@pytest.mark.universal +@pytest.mark.parametrize("full_feature_names", [True, False], ids=lambda v: str(v)) +def test_online_retrieval_with_event_timestamps( + environment, universal_data_sources, full_feature_names +): + fs = environment.feature_store + entities, datasets, data_sources = universal_data_sources + feature_views = construct_universal_feature_views(data_sources) + + fs.apply([driver(), feature_views.driver, feature_views.global_fv]) + + # fake data to ingest into Online Store + data = { + "driver_id": [1, 2], + "conv_rate": [0.5, 0.3], + "acc_rate": [0.6, 0.4], + "avg_daily_trips": [4, 5], + "event_timestamp": [ + pd.to_datetime(1646263500, utc=True, unit="s"), + pd.to_datetime(1646263600, utc=True, unit="s"), + ], + "created": [ + pd.to_datetime(1646263500, unit="s"), + pd.to_datetime(1646263600, unit="s"), + ], + } + df_ingest = pd.DataFrame(data) + + # directly ingest data into the Online Store + fs.write_to_online_store("driver_stats", df_ingest) + + response = fs.get_online_features( + features=[ + "driver_stats:avg_daily_trips", + "driver_stats:acc_rate", + "driver_stats:conv_rate", + ], + entity_rows=[{"driver": 1}, {"driver": 2}], + ) + df = response.to_df(True) + assertpy.assert_that(len(df)).is_equal_to(2) + assertpy.assert_that(df["driver_id"].iloc[0]).is_equal_to(1) + assertpy.assert_that(df["driver_id"].iloc[1]).is_equal_to(2) + assertpy.assert_that(df["avg_daily_trips" + TIMESTAMP_POSTFIX].iloc[0]).is_equal_to( + 1646263500 + ) + assertpy.assert_that(df["avg_daily_trips" + TIMESTAMP_POSTFIX].iloc[1]).is_equal_to( + 1646263600 + ) + assertpy.assert_that(df["acc_rate" + TIMESTAMP_POSTFIX].iloc[0]).is_equal_to( + 1646263500 + ) + assertpy.assert_that(df["acc_rate" + TIMESTAMP_POSTFIX].iloc[1]).is_equal_to( + 1646263600 + ) + assertpy.assert_that(df["conv_rate" + TIMESTAMP_POSTFIX].iloc[0]).is_equal_to( + 1646263500 + ) + assertpy.assert_that(df["conv_rate" + TIMESTAMP_POSTFIX].iloc[1]).is_equal_to( + 1646263600 + ) + + @pytest.mark.integration @pytest.mark.universal @pytest.mark.parametrize("full_feature_names", [True, False], ids=lambda v: str(v)) @@ -273,20 +398,20 @@ def test_online_retrieval(environment, universal_data_sources, full_feature_name feature_service = FeatureService( "convrate_plus100", features=[ - feature_views["driver"][["conv_rate"]], - feature_views["driver_odfv"], - feature_views["driver_age_request_fv"], + feature_views.driver[["conv_rate"]], + feature_views.driver_odfv, + feature_views.driver_age_request_fv, ], ) feature_service_entity_mapping = FeatureService( name="entity_mapping", features=[ - feature_views["location"] - .with_name("origin") - .with_join_key_map({"location_id": "origin_id"}), - feature_views["location"] - .with_name("destination") - .with_join_key_map({"location_id": "destination_id"}), + feature_views.location.with_name("origin").with_join_key_map( + {"location_id": "origin_id"} + ), + feature_views.location.with_name("destination").with_join_key_map( + {"location_id": "destination_id"} + ), ], ) @@ -307,38 +432,38 @@ def test_online_retrieval(environment, universal_data_sources, full_feature_name environment.end_date + timedelta(days=1), ) - entity_sample = datasets["orders"].sample(10)[ + entity_sample = datasets.orders_df.sample(10)[ ["customer_id", "driver_id", "order_id", "event_timestamp"] ] - orders_df = datasets["orders"][ + orders_df = datasets.orders_df[ ( - datasets["orders"]["customer_id"].isin(entity_sample["customer_id"]) - & datasets["orders"]["driver_id"].isin(entity_sample["driver_id"]) + datasets.orders_df["customer_id"].isin(entity_sample["customer_id"]) + & datasets.orders_df["driver_id"].isin(entity_sample["driver_id"]) ) ] sample_drivers = entity_sample["driver_id"] - drivers_df = datasets["driver"][ - datasets["driver"]["driver_id"].isin(sample_drivers) + drivers_df = datasets.driver_df[ + datasets.driver_df["driver_id"].isin(sample_drivers) ] sample_customers = entity_sample["customer_id"] - customers_df = datasets["customer"][ - datasets["customer"]["customer_id"].isin(sample_customers) + customers_df = datasets.customer_df[ + datasets.customer_df["customer_id"].isin(sample_customers) ] - location_pairs = np.array(list(itertools.permutations(entities["location"], 2))) + location_pairs = np.array(list(itertools.permutations(entities.location_vals, 2))) sample_location_pairs = location_pairs[ np.random.choice(len(location_pairs), 10) ].T.tolist() - origins_df = datasets["location"][ - datasets["location"]["location_id"].isin(sample_location_pairs[0]) + origins_df = datasets.location_df[ + datasets.location_df["location_id"].isin(sample_location_pairs[0]) ] - destinations_df = datasets["location"][ - datasets["location"]["location_id"].isin(sample_location_pairs[1]) + destinations_df = datasets.location_df[ + datasets.location_df["location_id"].isin(sample_location_pairs[1]) ] - global_df = datasets["global"] + global_df = datasets.global_df entity_rows = [ {"driver": d, "customer_id": c, "val_to_add": 50, "driver_age": 25} @@ -524,14 +649,15 @@ def test_online_store_cleanup(environment, universal_data_sources): """ fs = environment.feature_store entities, datasets, data_sources = universal_data_sources - driver_stats_fv = construct_universal_feature_views(data_sources)["driver"] + driver_stats_fv = construct_universal_feature_views(data_sources).driver + driver_entities = entities.driver_vals df = pd.DataFrame( { - "ts_1": [environment.end_date] * len(entities["driver"]), - "created_ts": [environment.end_date] * len(entities["driver"]), - "driver_id": entities["driver"], - "value": np.random.random(size=len(entities["driver"])), + "ts_1": [environment.end_date] * len(driver_entities), + "created_ts": [environment.end_date] * len(driver_entities), + "driver_id": driver_entities, + "value": np.random.random(size=len(driver_entities)), } ) @@ -552,7 +678,7 @@ def test_online_store_cleanup(environment, universal_data_sources): expected_values = df.sort_values(by="driver_id") features = [f"{simple_driver_fv.name}:value"] - entity_rows = [{"driver": driver_id} for driver_id in sorted(entities["driver"])] + entity_rows = [{"driver": driver_id} for driver_id in sorted(driver_entities)] online_features = fs.get_online_features( features=features, entity_rows=entity_rows @@ -569,7 +695,18 @@ def test_online_store_cleanup(environment, universal_data_sources): assert np.allclose(expected_values["value"], online_features["value"]) fs.apply(objects=[], objects_to_delete=[simple_driver_fv], partial=False) - fs.apply([simple_driver_fv]) + + def eventually_apply() -> Tuple[None, bool]: + try: + fs.apply([simple_driver_fv]) + except BotoCoreError: + return None, False + + return None, True + + # Online store backend might have eventual consistency in schema update + # So recreating table that was just deleted might need some retries + wait_retry_backoff(eventually_apply, timeout_secs=60) online_features = fs.get_online_features( features=features, entity_rows=entity_rows diff --git a/sdk/python/tests/integration/registration/test_cli.py b/sdk/python/tests/integration/registration/test_cli.py index bba12056ce8..c79d672fb94 100644 --- a/sdk/python/tests/integration/registration/test_cli.py +++ b/sdk/python/tests/integration/registration/test_cli.py @@ -14,7 +14,7 @@ from tests.integration.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.repo_configuration import FULL_REPO_CONFIGS +from tests.integration.feature_repos.repo_configuration import Environment from tests.integration.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) @@ -32,8 +32,8 @@ @pytest.mark.integration -@pytest.mark.parametrize("test_repo_config", FULL_REPO_CONFIGS) -def test_universal_cli(test_repo_config) -> None: +@pytest.mark.universal +def test_universal_cli(environment: Environment): project = f"test_universal_cli_{str(uuid.uuid4()).replace('-', '')[:8]}" runner = CliRunner() @@ -41,7 +41,7 @@ def test_universal_cli(test_repo_config) -> None: try: repo_path = Path(repo_dir_name) feature_store_yaml = make_feature_store_yaml( - project, test_repo_config, repo_path + project, environment.test_repo_config, repo_path ) repo_config = repo_path / "feature_store.yaml" @@ -56,10 +56,9 @@ def test_universal_cli(test_repo_config) -> None: # Store registry contents, to be compared later. fs = FeatureStore(repo_path=str(repo_path)) registry_dict = fs.registry.to_dict(project=project) - # Save only the specs, not the metadata. registry_specs = { - key: [fco["spec"] for fco in value] + key: [fco["spec"] if "spec" in fco else fco for fco in value] for key, value in registry_dict.items() } @@ -70,6 +69,8 @@ def test_universal_cli(test_repo_config) -> None: assertpy.assert_that(result.returncode).is_equal_to(0) result = runner.run(["feature-services", "list"], cwd=repo_path) assertpy.assert_that(result.returncode).is_equal_to(0) + result = runner.run(["data-sources", "list"], cwd=repo_path) + assertpy.assert_that(result.returncode).is_equal_to(0) # entity & feature view describe commands should succeed when objects exist result = runner.run(["entities", "describe", "driver"], cwd=repo_path) @@ -84,6 +85,11 @@ def test_universal_cli(test_repo_config) -> None: ) assertpy.assert_that(result.returncode).is_equal_to(0) assertpy.assert_that(fs.list_feature_views()).is_length(3) + result = runner.run( + ["data-sources", "describe", "customer_profile_source"], cwd=repo_path, + ) + assertpy.assert_that(result.returncode).is_equal_to(0) + assertpy.assert_that(fs.list_data_sources()).is_length(3) # entity & feature view describe commands should fail when objects don't exist result = runner.run(["entities", "describe", "foo"], cwd=repo_path) @@ -92,6 +98,8 @@ def test_universal_cli(test_repo_config) -> None: assertpy.assert_that(result.returncode).is_equal_to(1) result = runner.run(["feature-services", "describe", "foo"], cwd=repo_path) assertpy.assert_that(result.returncode).is_equal_to(1) + result = runner.run(["data-sources", "describe", "foo"], cwd=repo_path) + assertpy.assert_that(result.returncode).is_equal_to(1) # Doing another apply should be a no op, and should not cause errors result = runner.run(["apply"], cwd=repo_path) @@ -105,7 +113,7 @@ def test_universal_cli(test_repo_config) -> None: registry_dict = fs.registry.to_dict(project=project) assertpy.assert_that(registry_specs).is_equal_to( { - key: [fco["spec"] for fco in value] + key: [fco["spec"] if "spec" in fco else fco for fco in value] for key, value in registry_dict.items() } ) @@ -135,9 +143,11 @@ def make_feature_store_yaml(project, test_repo_config, repo_dir_name: Path): isinstance(config_dict["online_store"], dict) and "redis_type" in config_dict["online_store"] ): - del config_dict["online_store"]["redis_type"] + if str(config_dict["online_store"]["redis_type"]) == "RedisType.redis_cluster": + config_dict["online_store"]["redis_type"] = "redis_cluster" + elif str(config_dict["online_store"]["redis_type"]) == "RedisType.redis": + config_dict["online_store"]["redis_type"] = "redis" config_dict["repo_path"] = str(config_dict["repo_path"]) - return yaml.safe_dump(config_dict) diff --git a/sdk/python/tests/integration/registration/test_cli_apply_duplicated_featureview_names.py b/sdk/python/tests/integration/registration/test_cli_apply_duplicates.py similarity index 88% rename from sdk/python/tests/integration/registration/test_cli_apply_duplicated_featureview_names.py rename to sdk/python/tests/integration/registration/test_cli_apply_duplicates.py index 6987066e8d1..bad3b50a807 100644 --- a/sdk/python/tests/integration/registration/test_cli_apply_duplicated_featureview_names.py +++ b/sdk/python/tests/integration/registration/test_cli_apply_duplicates.py @@ -6,10 +6,20 @@ def test_cli_apply_duplicated_featureview_names() -> None: - """ - Test apply feature views with duplicated names and single py file in a feature repo using CLI - """ + run_simple_apply_test( + example_repo_file_name="example_feature_repo_with_duplicated_featureview_names.py", + expected_error=b"Please ensure that all feature view names are case-insensitively unique", + ) + +def test_cli_apply_duplicate_data_source_names() -> None: + run_simple_apply_test( + example_repo_file_name="example_repo_duplicate_data_source_names.py", + expected_error=b"Please ensure that all data source names are case-insensitively unique", + ) + + +def run_simple_apply_test(example_repo_file_name: str, expected_error: bytes): with tempfile.TemporaryDirectory() as repo_dir_name, tempfile.TemporaryDirectory() as data_dir_name: runner = CliRunner() # Construct an example repo in a temporary dir @@ -31,18 +41,10 @@ def test_cli_apply_duplicated_featureview_names() -> None: ) repo_example = repo_path / "example.py" - repo_example.write_text( - get_example_repo( - "example_feature_repo_with_duplicated_featureview_names.py" - ) - ) + repo_example.write_text(get_example_repo(example_repo_file_name)) rc, output = runner.run_with_output(["apply"], cwd=repo_path) - assert ( - rc != 0 - and b"Please ensure that all feature view names are case-insensitively unique" - in output - ) + assert rc != 0 and expected_error in output def test_cli_apply_imported_featureview() -> None: diff --git a/sdk/python/tests/integration/registration/test_feature_store.py b/sdk/python/tests/integration/registration/test_feature_store.py index d605865960e..d5496a6de75 100644 --- a/sdk/python/tests/integration/registration/test_feature_store.py +++ b/sdk/python/tests/integration/registration/test_feature_store.py @@ -95,7 +95,7 @@ def test_apply_entity_success(test_feature_store): name="driver_car_id", description="Car driver id", value_type=ValueType.STRING, - labels={"team": "matchmaking"}, + tags={"team": "matchmaking"}, ) # Register Entity @@ -109,8 +109,8 @@ def test_apply_entity_success(test_feature_store): and entity.name == "driver_car_id" and entity.value_type == ValueType(ValueProto.ValueType.STRING) and entity.description == "Car driver id" - and "team" in entity.labels - and entity.labels["team"] == "matchmaking" + and "team" in entity.tags + and entity.tags["team"] == "matchmaking" ) test_feature_store.teardown() @@ -129,7 +129,7 @@ def test_apply_entity_integration(test_feature_store): name="driver_car_id", description="Car driver id", value_type=ValueType.STRING, - labels={"team": "matchmaking"}, + tags={"team": "matchmaking"}, ) # Register Entity @@ -143,8 +143,8 @@ def test_apply_entity_integration(test_feature_store): and entity.name == "driver_car_id" and entity.value_type == ValueType(ValueProto.ValueType.STRING) and entity.description == "Car driver id" - and "team" in entity.labels - and entity.labels["team"] == "matchmaking" + and "team" in entity.tags + and entity.tags["team"] == "matchmaking" ) entity = test_feature_store.get_entity("driver_car_id") @@ -152,8 +152,8 @@ def test_apply_entity_integration(test_feature_store): entity.name == "driver_car_id" and entity.value_type == ValueType(ValueProto.ValueType.STRING) and entity.description == "Car driver id" - and "team" in entity.labels - and entity.labels["team"] == "matchmaking" + and "team" in entity.tags + and entity.tags["team"] == "matchmaking" ) test_feature_store.teardown() diff --git a/sdk/python/tests/integration/registration/test_inference.py b/sdk/python/tests/integration/registration/test_inference.py index ca5f56c435e..c334013b51e 100644 --- a/sdk/python/tests/integration/registration/test_inference.py +++ b/sdk/python/tests/integration/registration/test_inference.py @@ -1,9 +1,22 @@ import pandas as pd import pytest -from feast import Entity, Feature, RepoConfig, ValueType +from feast import ( + BigQuerySource, + Entity, + Feature, + FileSource, + RedshiftSource, + RepoConfig, + SnowflakeSource, + ValueType, +) from feast.data_source import RequestDataSource -from feast.errors import RegistryInferenceFailure, SpecifiedFeaturesNotPresentError +from feast.errors import ( + DataSourceNoNameException, + RegistryInferenceFailure, + SpecifiedFeaturesNotPresentError, +) from feast.feature_view import FeatureView from feast.inference import ( update_data_sources_with_inferred_event_timestamp_col, @@ -58,6 +71,38 @@ def test_update_entities_with_inferred_types_from_feature_views( ) +def test_infer_datasource_names_file(): + file_path = "path/to/test.csv" + data_source = FileSource(path=file_path) + assert data_source.name == file_path + + source_name = "my_name" + data_source = FileSource(name=source_name, path=file_path) + assert data_source.name == source_name + + +def test_infer_datasource_names_dwh(): + table = "project.table" + dwh_classes = [BigQuerySource, RedshiftSource, SnowflakeSource] + + for dwh_class in dwh_classes: + data_source = dwh_class(table=table) + assert data_source.name == table + + source_name = "my_name" + data_source_with_table = dwh_class(name=source_name, table=table) + assert data_source_with_table.name == source_name + data_source_with_query = dwh_class( + name=source_name, query=f"SELECT * from {table}" + ) + assert data_source_with_query.name == source_name + + # If we have a query and no name, throw an error + with pytest.raises(DataSourceNoNameException): + print(f"Testing dwh {dwh_class}") + data_source = dwh_class(query="test_query") + + @pytest.mark.integration def test_update_data_sources_with_inferred_event_timestamp_col(simple_dataset_1): df_with_two_viable_timestamp_cols = simple_dataset_1.copy(deep=True) @@ -137,3 +182,56 @@ def test_view_with_missing_feature(features_df: pd.DataFrame) -> pd.DataFrame: with pytest.raises(SpecifiedFeaturesNotPresentError): test_view_with_missing_feature.infer_features() + + +def test_datasource_inference(): + # Create Feature Views + date_request = RequestDataSource( + name="date_request", schema={"some_date": ValueType.UNIX_TIMESTAMP} + ) + + @on_demand_feature_view( + inputs={"date_request": date_request}, + features=[ + Feature("output", ValueType.UNIX_TIMESTAMP), + Feature("string_output", ValueType.STRING), + ], + ) + def test_view(features_df: pd.DataFrame) -> pd.DataFrame: + data = pd.DataFrame() + data["output"] = features_df["some_date"] + data["string_output"] = features_df["some_date"].astype(pd.StringDtype()) + return data + + test_view.infer_features() + + @on_demand_feature_view( + inputs={"date_request": date_request}, + features=[ + Feature("output", ValueType.UNIX_TIMESTAMP), + Feature("object_output", ValueType.STRING), + ], + ) + def invalid_test_view(features_df: pd.DataFrame) -> pd.DataFrame: + data = pd.DataFrame() + data["output"] = features_df["some_date"] + data["object_output"] = features_df["some_date"].astype(str) + return data + + with pytest.raises(ValueError, match="Value with native type object"): + invalid_test_view.infer_features() + + @on_demand_feature_view( + inputs={"date_request": date_request}, + features=[ + Feature("output", ValueType.UNIX_TIMESTAMP), + Feature("missing", ValueType.STRING), + ], + ) + def test_view_with_missing_feature(features_df: pd.DataFrame) -> pd.DataFrame: + data = pd.DataFrame() + data["output"] = features_df["some_date"] + return data + + with pytest.raises(SpecifiedFeaturesNotPresentError): + test_view_with_missing_feature.infer_features() diff --git a/sdk/python/tests/integration/registration/test_registry.py b/sdk/python/tests/integration/registration/test_registry.py index f3d2b37aac0..535497634d4 100644 --- a/sdk/python/tests/integration/registration/test_registry.py +++ b/sdk/python/tests/integration/registration/test_registry.py @@ -32,14 +32,14 @@ @pytest.fixture -def local_registry(): +def local_registry() -> Registry: fd, registry_path = mkstemp() registry_config = RegistryConfig(path=registry_path, cache_ttl_seconds=600) return Registry(registry_config, None) @pytest.fixture -def gcs_registry(): +def gcs_registry() -> Registry: from google.cloud import storage storage_client = storage.Client() @@ -58,7 +58,7 @@ def gcs_registry(): @pytest.fixture -def s3_registry(): +def s3_registry() -> Registry: registry_config = RegistryConfig( path=f"s3://feast-integration-tests/registries/{int(time.time() * 1000)}/registry.db", cache_ttl_seconds=600, @@ -74,7 +74,7 @@ def test_apply_entity_success(test_registry): name="driver_car_id", description="Car driver id", value_type=ValueType.STRING, - labels={"team": "matchmaking"}, + tags={"team": "matchmaking"}, ) project = "project" @@ -90,8 +90,8 @@ def test_apply_entity_success(test_registry): and entity.name == "driver_car_id" and entity.value_type == ValueType(ValueProto.ValueType.STRING) and entity.description == "Car driver id" - and "team" in entity.labels - and entity.labels["team"] == "matchmaking" + and "team" in entity.tags + and entity.tags["team"] == "matchmaking" ) entity = test_registry.get_entity("driver_car_id", project) @@ -99,8 +99,8 @@ def test_apply_entity_success(test_registry): entity.name == "driver_car_id" and entity.value_type == ValueType(ValueProto.ValueType.STRING) and entity.description == "Car driver id" - and "team" in entity.labels - and entity.labels["team"] == "matchmaking" + and "team" in entity.tags + and entity.tags["team"] == "matchmaking" ) test_registry.delete_entity("driver_car_id", project) @@ -123,7 +123,7 @@ def test_apply_entity_integration(test_registry): name="driver_car_id", description="Car driver id", value_type=ValueType.STRING, - labels={"team": "matchmaking"}, + tags={"team": "matchmaking"}, ) project = "project" @@ -139,8 +139,8 @@ def test_apply_entity_integration(test_registry): and entity.name == "driver_car_id" and entity.value_type == ValueType(ValueProto.ValueType.STRING) and entity.description == "Car driver id" - and "team" in entity.labels - and entity.labels["team"] == "matchmaking" + and "team" in entity.tags + and entity.tags["team"] == "matchmaking" ) entity = test_registry.get_entity("driver_car_id", project) @@ -148,8 +148,8 @@ def test_apply_entity_integration(test_registry): entity.name == "driver_car_id" and entity.value_type == ValueType(ValueProto.ValueType.STRING) and entity.description == "Car driver id" - and "team" in entity.labels - and entity.labels["team"] == "matchmaking" + and "team" in entity.tags + and entity.tags["team"] == "matchmaking" ) test_registry.teardown() @@ -428,6 +428,70 @@ def test_apply_feature_view_integration(test_registry): test_registry._get_registry_proto() +@pytest.mark.integration +@pytest.mark.parametrize( + "test_registry", [lazy_fixture("gcs_registry"), lazy_fixture("s3_registry")], +) +def test_apply_data_source(test_registry: Registry): + # Create Feature Views + batch_source = FileSource( + name="test_source", + file_format=ParquetFormat(), + path="file://feast/*", + event_timestamp_column="ts_col", + created_timestamp_column="timestamp", + date_partition_column="date_partition_col", + ) + + fv1 = FeatureView( + name="my_feature_view_1", + features=[ + Feature(name="fs1_my_feature_1", dtype=ValueType.INT64), + Feature(name="fs1_my_feature_2", dtype=ValueType.STRING), + Feature(name="fs1_my_feature_3", dtype=ValueType.STRING_LIST), + Feature(name="fs1_my_feature_4", dtype=ValueType.BYTES_LIST), + ], + entities=["fs1_my_entity_1"], + tags={"team": "matchmaking"}, + batch_source=batch_source, + ttl=timedelta(minutes=5), + ) + + project = "project" + + # Register data source and feature view + test_registry.apply_data_source(batch_source, project, commit=False) + test_registry.apply_feature_view(fv1, project, commit=True) + + registry_feature_views = test_registry.list_feature_views(project) + registry_data_sources = test_registry.list_data_sources(project) + assert len(registry_feature_views) == 1 + assert len(registry_data_sources) == 1 + registry_feature_view = registry_feature_views[0] + assert registry_feature_view.batch_source == batch_source + registry_data_source = registry_data_sources[0] + assert registry_data_source == batch_source + + # Check that change to batch source propagates + batch_source.event_timestamp_column = "new_ts_col" + test_registry.apply_data_source(batch_source, project, commit=False) + test_registry.apply_feature_view(fv1, project, commit=True) + registry_feature_views = test_registry.list_feature_views(project) + registry_data_sources = test_registry.list_data_sources(project) + assert len(registry_feature_views) == 1 + assert len(registry_data_sources) == 1 + registry_feature_view = registry_feature_views[0] + assert registry_feature_view.batch_source == batch_source + registry_batch_source = test_registry.list_data_sources(project)[0] + assert registry_batch_source == batch_source + + test_registry.teardown() + + # Will try to reload registry, which will fail because the file has been deleted + with pytest.raises(FileNotFoundError): + test_registry._get_registry_proto() + + def test_commit(): fd, registry_path = mkstemp() registry_config = RegistryConfig(path=registry_path, cache_ttl_seconds=600) @@ -437,7 +501,7 @@ def test_commit(): name="driver_car_id", description="Car driver id", value_type=ValueType.STRING, - labels={"team": "matchmaking"}, + tags={"team": "matchmaking"}, ) project = "project" @@ -454,8 +518,8 @@ def test_commit(): and entity.name == "driver_car_id" and entity.value_type == ValueType(ValueProto.ValueType.STRING) and entity.description == "Car driver id" - and "team" in entity.labels - and entity.labels["team"] == "matchmaking" + and "team" in entity.tags + and entity.tags["team"] == "matchmaking" ) entity = test_registry.get_entity("driver_car_id", project, allow_cache=True) @@ -463,8 +527,8 @@ def test_commit(): entity.name == "driver_car_id" and entity.value_type == ValueType(ValueProto.ValueType.STRING) and entity.description == "Car driver id" - and "team" in entity.labels - and entity.labels["team"] == "matchmaking" + and "team" in entity.tags + and entity.tags["team"] == "matchmaking" ) # Create new registry that points to the same store @@ -489,8 +553,8 @@ def test_commit(): and entity.name == "driver_car_id" and entity.value_type == ValueType(ValueProto.ValueType.STRING) and entity.description == "Car driver id" - and "team" in entity.labels - and entity.labels["team"] == "matchmaking" + and "team" in entity.tags + and entity.tags["team"] == "matchmaking" ) entity = test_registry.get_entity("driver_car_id", project) @@ -498,8 +562,8 @@ def test_commit(): entity.name == "driver_car_id" and entity.value_type == ValueType(ValueProto.ValueType.STRING) and entity.description == "Car driver id" - and "team" in entity.labels - and entity.labels["team"] == "matchmaking" + and "team" in entity.tags + and entity.tags["team"] == "matchmaking" ) test_registry.teardown() diff --git a/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py b/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py index ee3180f863e..e8cc1552e2a 100644 --- a/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py +++ b/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py @@ -25,9 +25,7 @@ def test_infer_odfv_features(environment, universal_data_sources, infer_features (entities, datasets, data_sources) = universal_data_sources - driver_hourly_stats = create_driver_hourly_stats_feature_view( - data_sources["driver"] - ) + driver_hourly_stats = create_driver_hourly_stats_feature_view(data_sources.driver) request_data_source = create_conv_rate_request_data_source() driver_odfv = conv_rate_plus_100_feature_view( {"driver": driver_hourly_stats, "input_request": request_data_source}, @@ -79,9 +77,7 @@ def test_infer_odfv_features_with_error(environment, universal_data_sources): (entities, datasets, data_sources) = universal_data_sources features = [Feature("conv_rate_plus_200", ValueType.DOUBLE)] - driver_hourly_stats = create_driver_hourly_stats_feature_view( - data_sources["driver"] - ) + driver_hourly_stats = create_driver_hourly_stats_feature_view(data_sources.driver) request_data_source = create_conv_rate_request_data_source() driver_odfv = conv_rate_plus_100_feature_view( {"driver": driver_hourly_stats, "input_request": request_data_source}, diff --git a/sdk/python/tests/integration/registration/test_universal_types.py b/sdk/python/tests/integration/registration/test_universal_types.py index 663ba55ccb3..59ca119f98a 100644 --- a/sdk/python/tests/integration/registration/test_universal_types.py +++ b/sdk/python/tests/integration/registration/test_universal_types.py @@ -221,7 +221,12 @@ def test_feature_get_online_features_types_match(online_types_test_fixtures): features = [fv.name + ":value"] entity = driver(value_type=config.entity_type) fs.apply([fv, entity]) - fs.materialize(environment.start_date, environment.end_date) + fs.materialize( + environment.start_date, + environment.end_date + - timedelta(hours=1) # throwing out last record to make sure + # we can successfully infer type even from all empty values + ) driver_id_value = "1" if config.entity_type == ValueType.STRING else 1 online_features = fs.get_online_features( @@ -239,9 +244,15 @@ def test_feature_get_online_features_types_match(online_types_test_fixtures): expected_dtype = feature_list_dtype_to_expected_online_response_value_type[ config.feature_dtype ] + + assert len(online_features["value"]) == 1 + if config.feature_is_list: for feature in online_features["value"]: - assert isinstance(feature, list) + assert isinstance(feature, list), "Feature value should be a list" + assert ( + config.has_empty_list or len(feature) > 0 + ), "List of values should not be empty" for element in feature: assert isinstance(element, expected_dtype) else: diff --git a/sdk/python/tests/unit/test_entity.py b/sdk/python/tests/unit/test_entity.py index b8381451fd1..ec3ed70253f 100644 --- a/sdk/python/tests/unit/test_entity.py +++ b/sdk/python/tests/unit/test_entity.py @@ -21,21 +21,21 @@ def test_join_key_default(): assert entity.join_key == "my-entity" -def test_entity_class_contains_labels(): +def test_entity_class_contains_tags(): entity = Entity( "my-entity", description="My entity", value_type=ValueType.STRING, - labels={"key1": "val1", "key2": "val2"}, + tags={"key1": "val1", "key2": "val2"}, ) - assert "key1" in entity.labels.keys() and entity.labels["key1"] == "val1" - assert "key2" in entity.labels.keys() and entity.labels["key2"] == "val2" + assert "key1" in entity.tags.keys() and entity.tags["key1"] == "val1" + assert "key2" in entity.tags.keys() and entity.tags["key2"] == "val2" -def test_entity_without_labels_empty_dict(): +def test_entity_without_tags_empty_dict(): entity = Entity("my-entity", description="My entity", value_type=ValueType.STRING) - assert entity.labels == dict() - assert len(entity.labels) == 0 + assert entity.tags == dict() + assert len(entity.tags) == 0 def test_entity_without_description(): diff --git a/sdk/python/tests/utils/data_source_utils.py b/sdk/python/tests/utils/data_source_utils.py index 12870186bfc..5a5baceef07 100644 --- a/sdk/python/tests/utils/data_source_utils.py +++ b/sdk/python/tests/utils/data_source_utils.py @@ -52,6 +52,7 @@ def simple_bq_source_using_query_arg(df, event_timestamp_column=None) -> BigQuer df, event_timestamp_column ) return BigQuerySource( + name=bq_source_using_table_ref.table_ref, query=f"SELECT * FROM {bq_source_using_table_ref.table_ref}", event_timestamp_column=event_timestamp_column, ) diff --git a/ui/README.md b/ui/README.md new file mode 100644 index 00000000000..9a5171bd1fb --- /dev/null +++ b/ui/README.md @@ -0,0 +1,61 @@ +# [WIP] Feast Web UI + +![Sample UI](sample.png) + +This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). + +## Project structure +The Web UI is powered by a JSON registry dump from Feast (running `feast registry-dump`). Running `yarn start` launches a UI +powered by test data. +- `public/` contains assets as well as demo data loaded by the Web UI. + - There is a `projects-list.json` which represents all Feast projects the UI shows. + - There is also a `registry.json` which is the registry dump for the feature repo. +- `feature_repo/` contains a sample Feast repo which generates the `registry.json` +- `src/` contains the Web UI source code. This parses the registry json blob in `src/parsers` to make this data +available for the rest of the UI. +- `src/custom-tabs` includes sample custom tabs. This is a WIP plugin system where users can inject their own tabs and +data to the UI. + + +## Available Scripts + +In the project directory, you can run: + +### `yarn start` + +Runs the app in the development mode.\ +Open [http://localhost:3000](http://localhost:3000) to view it in the browser. + +The page will reload if you make edits.\ +You will also see any lint errors in the console. + +### `yarn test` + +Launches the test runner in the interactive watch mode.\ +See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. + +### `yarn build` + +Builds the app for production to the `build` folder.\ +It correctly bundles React in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.\ +Your app is ready to be deployed! + +See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. + +### `yarn eject` + +**Note: this is a one-way operation. Once you `eject`, you can’t go back!** + +If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. + +Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. + +You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. + +## Learn More + +You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). + +To learn React, check out the [React documentation](https://reactjs.org/). diff --git a/ui/feature_repo/README.md b/ui/feature_repo/README.md new file mode 100644 index 00000000000..db706e709e4 --- /dev/null +++ b/ui/feature_repo/README.md @@ -0,0 +1,72 @@ +# Feast repo + +## Overview + +This pulls from the dataset used in https://github.com/feast-dev/feast-aws-credit-scoring-tutorial but adds metadata for a full set of Feast FCOs. + +This also adds an on demand feature view + feature services + a saved dataset. + +## Setting up Feast + +Install a dev build Feast using pip + +Clone a feast repo: +```bash +git clone https://github.com/feast-dev/feast.git +``` + +Install a dev build of feast +```bash +cd feast +pip install -e "sdk/python[dev]" +``` + +Then for this demo, you'll actually need to fix a bug by adding this to `type_map.py#L144`: +```python +if isinstance(value, np.bool_): + return ValueType.BOOL +``` + +## Test features +We have already set up a feature repository here using test data from [data](data)). Features have already been pre-materialized to a local sqlite online store. The results of `feast registry-dump` have been thrown into [registry.json](../public/registry.json) + +To query against this registry, you can use run the `test_get_features.py` +```bash +python test_get_features.py +``` + +Output: +``` +--- Historical features (from saved dataset) --- + mortgage_due credit_card_due missed_payments_1y total_wages dob_ssn event_timestamp state tax_returns_filed location_type population city zipcode +0 741165 2944 3 71067272 19781116_7723 2021-04-12 08:12:10+00:00 MI 2424 PRIMARY 4421 WEIDMAN 48893 +1 91803 8419 0 534687864 19530219_5179 2021-04-12 10:59:42+00:00 GA 19583 PRIMARY 38542 DALTON 30721 +2 1553523 5936 0 226748453 19500806_6783 2021-04-12 15:01:12+00:00 TX 6827 PRIMARY 12902 CLEBURNE 76031 +3 976522 833 0 34796963 19931128_5771 2021-04-12 16:40:26+00:00 VA 1287 PRIMARY 2342 GLADE HILL 24092 + +--- Online features --- +city : ['DALTON'] +credit_card_due : [8419] +dob_ssn : ['19530219_5179'] +location_type : ['PRIMARY'] +missed_payments_1y : [0] +mortgage_due : [91803] +population : [38542] +state : ['GA'] +tax_returns_filed : [19583] +total_wages : [534687864] +zipcode : [30721] +city : ['DALTON'] +credit_card_due : [8419] +dob_ssn : ['19530219_5179'] +location_type : ['PRIMARY'] +missed_payments_1y : [0] +mortgage_due : [91803] +population : [38542] +state : ['GA'] +tax_returns_filed : [19583] +total_wages : [534687864] +transaction_gt_last_credit_card_due : [False] +zipcode : [30721] + +``` diff --git a/ui/feature_repo/data/credit_history.parquet b/ui/feature_repo/data/credit_history.parquet new file mode 100644 index 00000000000..a368ae5bbf7 Binary files /dev/null and b/ui/feature_repo/data/credit_history.parquet differ diff --git a/ui/feature_repo/data/credit_history_sample.csv b/ui/feature_repo/data/credit_history_sample.csv new file mode 100644 index 00000000000..7b1ffca1c15 --- /dev/null +++ b/ui/feature_repo/data/credit_history_sample.csv @@ -0,0 +1,1001 @@ +event_timestamp,dob_ssn,credit_card_due,mortgage_due,student_loan_due,vehicle_loan_due,hard_pulls,missed_payments_2y,missed_payments_1y,missed_payments_6m,bankruptcies,created_timestamp +2020-04-26 18:01:04.746575,19530219_5179,8419,91803,22328,15078,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19781116_7723,2944,741165,2515,28605,0,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19931128_5771,833,976522,33000,21733,9,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19500806_6783,5936,1553523,48955,26219,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620322_7692,1575,1067381,9501,15814,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19521115_8793,6263,1957370,35510,17095,3,2,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860608_5766,4378,490394,34057,935,8,3,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19690214_3370,9794,1325678,37003,17179,3,1,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19710204_2474,8840,1333759,21991,27414,9,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670810_4552,888,170320,41180,7930,6,0,2,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570513_7405,3214,157339,42470,23401,5,3,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910429_8449,9983,1236123,26476,14290,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19971102_8169,8330,1142638,48371,5272,6,1,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19470930_7727,7509,1715027,31185,1114,9,4,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19961104_6715,3994,1278825,1411,24239,2,4,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670424_9712,9407,179919,32748,21171,0,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19871021_4913,1397,1403895,4965,6585,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990119_7587,8006,1687,476,6638,9,5,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19671011_6421,3032,1489421,22412,4639,0,4,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700719_4951,8537,443259,45625,3998,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560119_8484,6766,994051,21635,27550,5,7,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19450619_1838,136,734472,24385,12226,7,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860229_1269,1775,545713,7870,11279,10,7,1,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550716_6489,7581,1014560,32337,21698,0,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770909_3749,625,1755851,10071,28928,5,0,2,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19460708_1744,4325,643538,1496,4396,5,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960408_6067,6766,81299,17294,647,2,6,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19510206_8540,550,689556,15164,1261,5,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480409_1765,781,1788837,45060,15703,8,4,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010711_5288,3669,523107,34903,26987,4,2,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900515_9945,6308,712633,2530,15023,2,2,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570224_7610,829,452402,7489,14154,2,4,1,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19680319_9760,5420,1609049,12413,22708,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19880126_6480,6893,690613,10648,4220,5,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19651201_6947,5902,574178,26526,6275,2,5,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910205_1576,7060,1377225,13496,27732,1,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570218_5198,9914,1731608,8670,26764,5,0,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520103_7721,6901,1672088,38186,16850,0,2,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19650605_9597,4572,1846820,35528,15177,6,6,3,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19640413_7209,228,842260,31911,10490,8,5,3,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19680829_6939,2035,1093857,15884,24599,7,2,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010108_2924,8732,1722568,41986,17998,5,3,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670430_8377,3293,591913,42962,21909,8,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19741208_1968,5091,1012610,27470,19975,3,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910313_3758,5601,1969556,32415,21626,1,5,3,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950216_6438,1800,978437,37814,22455,9,3,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19531122_1254,9134,1371146,22673,2523,7,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600528_8373,7590,1243939,38863,14312,2,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19781127_9734,7064,223815,7077,24236,3,6,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530526_5385,5788,1103821,16667,26447,7,6,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19901015_2547,3676,119483,29373,20428,3,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19850425_5098,9691,624622,24312,1339,4,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19711214_9964,6412,951385,18397,11622,8,0,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19691030_6048,4645,81572,46230,3409,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600107_9670,6343,1679435,48059,3999,6,6,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19680520_5879,6740,1674732,46648,5924,7,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19460203_1497,3530,769990,13311,934,5,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700612_6032,1904,1945098,20776,28875,3,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19611204_2856,6845,1122678,10904,20002,2,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600712_3825,4654,807475,19002,10652,10,3,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630201_1104,9562,869403,6171,25284,3,6,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19781020_4506,5350,1406781,9976,5932,6,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530904_8321,3124,1889716,49815,13545,10,5,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19481028_1851,3701,1897684,44357,28979,0,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570508_3454,467,386000,42973,15043,10,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910102_5025,8223,1505476,29470,22983,10,2,1,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990707_7635,2987,529361,39841,18339,1,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670330_6469,4647,232371,30691,2246,2,5,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19841116_6859,316,462286,7886,26795,8,1,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19511213_4328,1547,934992,42886,23907,4,0,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19710628_9679,4869,400643,26086,14076,7,3,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19510702_6043,9969,1179344,14965,17222,10,6,1,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19501216_8061,1590,196668,9858,10902,1,7,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19800406_8439,2476,1448321,16995,5072,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19661119_1383,8405,696650,7694,28501,4,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19930713_8300,3680,220278,593,1057,9,4,0,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480403_9058,7282,1448150,25088,19202,9,3,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890305_9125,6649,481125,10226,11764,2,3,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840706_3904,8005,258167,47845,16561,9,1,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490411_3733,8195,1058510,28128,17354,4,5,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600103_8778,9924,409032,22741,19081,6,7,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19930717_4009,8366,208728,32523,28665,3,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630206_1406,7771,1502676,5712,16097,9,6,0,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19650510_1847,8661,1683950,31588,7983,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620827_2752,8560,653796,4470,1465,7,2,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920527_2599,3155,1426405,33529,3392,4,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19760601_8988,8689,1196760,35979,2019,7,2,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19891024_5166,7477,105750,39785,20144,10,7,3,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19760415_2873,3646,1340488,1975,7241,10,1,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700503_6631,2865,284724,390,2074,9,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920818_7772,8233,898934,9757,23500,1,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820321_2520,8758,1145058,11013,4008,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19980418_6975,4318,425750,49574,24519,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630809_4111,5965,1059057,39499,7886,0,1,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810126_4227,9385,1043186,13254,22303,0,4,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19611219_9380,3067,17798,4920,67,9,1,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19970912_1311,6454,512020,39107,1663,8,1,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610821_4440,741,77743,45754,29855,8,4,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19731120_7231,2302,1475520,45108,1590,8,5,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490324_4176,7069,50394,43999,17305,7,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520224_5297,8390,94186,22192,3933,8,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480925_1215,8020,845472,39852,24538,3,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740218_3169,950,1588250,30682,16717,10,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830227_2409,2930,586180,26945,25278,6,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700704_9426,4148,929766,911,2006,4,3,2,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19731028_8188,5315,962752,42172,28962,0,5,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19941227_1572,5473,1051110,38026,6504,3,0,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670425_2855,7779,1035799,26269,8462,9,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19991014_3843,5079,769289,7514,6027,6,2,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19521021_5466,7975,194506,32614,10385,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010720_4849,4481,1226035,31168,8619,8,1,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560104_6116,845,60874,6798,27548,4,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19930222_8671,8464,818311,15641,13495,7,2,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780113_2322,4162,1661508,28015,9574,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540808_8685,8373,1234790,42972,9985,1,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010717_9793,3355,397649,13816,20498,7,6,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520707_2576,8262,219959,3699,9905,7,3,3,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490511_5108,5130,531970,48998,12817,5,2,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700111_1690,8410,902917,6830,3230,8,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19510315_2267,4661,1475505,10441,21415,6,1,1,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560810_5371,7806,391735,35396,5966,3,1,3,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920704_7897,455,1567504,7001,27140,9,3,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19590613_3608,7794,18936,1465,10584,4,0,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700122_8413,2175,1133433,7028,3087,0,3,2,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950316_6954,7539,658280,19736,4797,4,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19640720_2122,6598,194099,19411,10525,6,3,2,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580411_9996,6499,1819439,27592,11735,1,4,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490420_5866,3948,1205588,18506,8539,5,6,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870709_3589,2168,1179204,7460,22664,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820409_5890,9316,1767281,23743,16008,1,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19940711_2500,4136,160955,26466,27816,8,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700926_3180,8404,203007,11532,27533,9,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830512_2877,135,274016,5150,24507,7,6,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550204_2997,7289,900588,25381,423,9,0,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19450103_1272,308,399149,44470,25345,10,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19831011_5231,9317,598170,29936,881,1,6,0,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000420_9428,2311,743923,9713,10835,0,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19790506_6477,7669,773690,8208,15767,8,3,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900330_1524,4883,1709559,46917,11904,0,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870312_3552,9761,1656830,12054,3372,5,2,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19731020_1834,432,1562103,7674,28808,9,5,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19710220_8235,5682,171533,16517,19648,5,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830306_7067,6301,35226,11020,28269,9,7,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550628_7691,7871,1291222,10552,8996,6,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19760118_7610,57,245751,17091,5661,8,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670411_1107,1081,949071,27918,25150,0,7,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730605_6441,1083,791170,48033,26152,10,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900503_1072,711,742435,31650,26852,1,0,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890522_9087,6717,336460,33739,23435,2,7,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19680815_9970,7776,85145,28235,16405,7,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19930125_8099,513,1415527,40500,10739,3,3,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19500128_9622,8801,1976772,47084,8101,10,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520424_1840,3079,1789243,15882,7427,9,7,0,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870114_1971,1687,750973,13509,5607,5,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950204_9632,5907,1167846,19918,27481,1,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19850330_1348,3444,962469,38305,16751,8,7,3,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830320_5111,2041,1414928,17343,29735,3,0,3,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730523_3223,1369,1588660,42824,20316,4,4,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19801113_7955,9196,368704,20886,3603,0,6,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19720111_8293,9186,12667,17161,12770,6,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830908_4067,4761,786215,4859,22333,7,2,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560623_6174,2133,10336,34928,13148,9,2,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570121_5654,8911,434147,6797,7945,10,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19851030_2417,2206,31400,908,25402,8,2,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840627_5481,9268,1561211,2585,17435,10,5,2,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550813_3982,8281,1329078,45176,25975,3,5,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610822_3926,916,379198,13669,14034,9,1,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700130_8637,6394,497642,24904,17005,5,1,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19581005_1003,6063,1285392,40009,21940,10,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610515_2615,6959,700790,46288,11612,0,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520322_8880,319,1992495,23913,3476,3,2,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19750725_4014,4327,501607,7793,16312,0,3,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19720104_5235,9382,1647134,16382,8247,9,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990104_8788,1787,41405,22782,10877,9,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19680504_8011,9504,1169583,28405,17900,3,7,1,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19850522_5065,2253,1605121,32891,6019,3,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19940408_6468,9505,1056253,24951,21304,9,0,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19590917_6176,4998,1092518,47227,22161,3,0,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19970421_2759,130,1394475,1953,15493,0,6,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19510614_3614,7491,1066727,3319,7469,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890406_9601,5517,1960888,44351,9693,7,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19931101_8895,4865,1884658,29614,3899,0,6,1,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19451001_6728,9720,1460786,46121,5676,0,7,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19621114_7877,5262,1559354,15189,10954,4,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560627_2936,5540,436549,41561,27958,3,0,2,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19641107_5294,7101,1150072,17075,20193,5,6,0,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19850114_9358,135,1186565,31986,10901,9,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490901_2485,2808,952104,10659,5717,0,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19640417_4011,2955,1077263,31766,23573,9,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530912_4661,3523,789422,11390,3983,8,0,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19951116_8514,1864,1388160,41066,29628,4,1,3,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770207_2813,6563,1760262,39288,1094,9,2,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000812_5374,1542,68151,24828,5514,2,1,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000725_1097,6508,1132816,29622,3571,0,6,1,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19640417_5210,4819,369939,2628,17794,5,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700418_7109,6572,468361,5941,19485,9,3,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19510504_9959,6530,294120,42918,12802,10,2,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830409_3875,809,311505,47596,14210,10,0,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19581105_6041,9064,285215,7255,10557,2,3,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780205_8464,1081,764415,19887,15160,0,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19761127_4157,2609,1258259,9047,704,3,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770408_5832,9175,120891,30802,1701,8,6,3,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19880501_2798,5131,1433498,48469,8333,6,4,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610302_7840,6574,1923196,18531,24428,2,0,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870514_3720,2822,960854,16845,307,1,2,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19611126_7484,4538,163346,23159,2272,7,4,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19611014_1081,5459,202830,49153,27162,7,5,3,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19491213_1371,4073,1247441,26379,21997,4,6,3,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860122_2342,8773,1697312,4556,757,2,4,1,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19660410_9925,5892,1735353,12732,24314,1,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600306_4676,8829,1266465,24578,3936,5,5,1,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20011116_7090,8031,855819,33189,14883,0,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19831017_6397,8931,194709,22386,29045,3,0,0,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19531203_2353,3310,1332415,36072,28314,4,1,3,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490128_3952,21,980335,9635,22234,0,1,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19720719_9120,5514,1034611,45053,13389,4,6,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19801013_3901,5393,1974500,28648,24370,6,1,1,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19980327_5767,3639,1565171,28097,839,6,6,3,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19891121_2714,2335,1679891,10115,15740,8,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19760719_6739,3317,1627919,17852,29101,7,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19750530_5770,2342,1044578,20363,27588,6,3,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19771121_1901,1066,1072604,41100,15873,7,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780807_8461,6127,212185,9404,3658,5,2,2,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630705_5046,9122,1845021,23097,20083,4,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19581217_4819,1479,1924266,1071,9216,4,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19690708_2092,8103,366200,5512,1569,5,1,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19880229_7028,1542,1170080,7055,217,4,0,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580726_5312,1677,391234,19319,11092,3,3,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19850604_7301,8713,1053432,13596,12542,9,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530117_8633,6980,1000654,40575,28232,9,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810704_5141,5621,402282,30082,9400,1,1,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19471215_9342,8714,326671,1291,6920,5,3,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010127_7232,5364,1580727,47445,21445,4,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19710110_7951,4408,418912,44621,12763,2,1,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19680109_5272,4221,1797142,44355,5462,7,1,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19710818_8630,6746,1782842,15611,16441,1,5,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19781106_1825,257,1537277,30909,19528,5,6,3,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19500514_4837,9583,810132,26662,2630,10,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19451208_8411,8377,1214951,31592,13243,10,4,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670525_7565,1718,1018591,8487,29503,4,0,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520611_9229,3024,1635249,12141,27469,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19781006_1975,507,538720,11610,9751,3,2,2,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870518_5031,5492,921858,21541,5020,10,1,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19790525_4042,7319,357150,45961,19103,9,6,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19941009_9610,646,1598905,30873,21013,3,6,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19800624_4503,7864,1239928,11874,29651,9,7,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570601_1281,9700,1998639,41605,9040,1,7,1,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780309_8183,3414,837379,26141,9688,7,0,3,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580624_1339,2297,369645,7484,24173,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19651117_7821,7742,1769602,27123,11235,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810717_5916,2803,1313201,9518,15353,7,4,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19601207_6784,9259,303940,10291,25623,7,6,2,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530726_5480,922,34381,22539,20859,9,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19571124_2357,7914,385048,41676,12669,7,2,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870718_6795,2743,168968,32692,7114,2,0,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530504_1649,6198,144555,34956,28844,6,5,1,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19741130_8823,6729,838947,26462,26754,5,1,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19591020_6402,9504,256862,31767,21971,7,0,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560427_1219,6265,1668623,13257,3838,2,2,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19800901_1571,6405,12738,49219,26706,0,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520623_3179,9210,209316,37155,12154,1,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490812_8051,4726,725766,4895,15796,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580616_3873,6196,1841317,11258,16477,0,4,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820223_6526,9202,752242,30144,8538,0,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19551026_4206,4316,1353149,32623,1467,2,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19761201_2521,124,550317,33000,6820,8,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580620_4235,3139,1477674,25990,20828,4,4,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19640108_9514,578,1561224,21982,23795,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540507_7760,2954,1089675,48109,6799,3,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19970701_6408,4352,1763038,6147,18829,7,1,3,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19640106_6587,7827,911228,32796,17141,7,3,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580425_8735,6502,313316,42683,12193,3,1,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860319_9967,1326,858012,43067,21626,7,3,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480921_8602,2513,54915,45942,9902,2,0,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19970721_7421,2836,1053154,17731,29329,9,5,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19470523_2423,868,1615035,41020,28706,10,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670211_3281,678,1435227,42679,3002,9,4,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620725_2939,6866,1448982,15432,9429,8,5,2,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960629_7239,2452,1099702,27430,2354,0,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950802_8979,9665,547531,7941,5642,6,4,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19460905_4528,7875,631474,29582,13844,10,0,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890916_7865,7214,1107664,29698,584,1,0,2,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560410_9641,5541,1763580,21212,21950,8,4,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730706_3530,9673,1268964,29185,703,10,2,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19710802_2306,8214,1161378,24423,18795,10,5,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960307_9663,1566,992302,16800,5320,5,5,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960624_2145,7211,619434,30367,24524,10,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19691108_4576,7296,25590,31737,20372,9,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19940329_8535,6626,519063,434,7984,4,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830529_9554,7163,1380911,12126,26324,8,5,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730909_6557,1181,1962803,3420,1521,4,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19521206_7714,708,63639,16860,25142,3,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600707_2475,6907,1006769,92,28962,2,5,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610318_9363,8484,1447530,44169,28476,1,0,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480329_4957,8269,73103,44314,11845,9,4,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19970318_8198,4560,1777266,35984,18096,7,5,1,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700507_9717,145,622855,24766,12580,1,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630530_8270,3147,1766405,35553,10303,0,6,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570310_9494,330,1018737,45759,27263,4,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700723_7524,7424,1338401,17110,7603,8,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990107_3795,1085,619307,11026,6185,9,3,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19750315_6841,7455,1972328,21561,7650,8,5,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950804_5076,9181,1952752,45044,7220,1,0,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19721002_3073,2071,1530468,11320,1752,1,6,2,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820719_1658,6928,1575203,22532,3291,3,7,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860128_4694,3391,687372,31728,11450,3,3,2,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780316_4996,4209,931958,23738,11243,3,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670410_4188,8405,220953,2653,8452,4,6,3,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19531028_8117,4274,1427649,18492,26720,1,7,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19871220_7407,8050,1614005,41381,102,5,5,3,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870822_5956,2364,1477874,32325,29210,7,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770515_4747,7738,260662,30874,29399,3,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520314_5139,5635,210962,2861,14992,9,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990903_8506,8532,1176255,4791,7521,8,4,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20001214_8741,1555,129102,20692,29722,10,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630814_2881,2434,499564,32286,21509,7,3,3,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19681218_5072,3653,1533920,13462,20705,7,3,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19731126_7943,254,650514,34028,15623,4,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000310_6553,8645,228039,29372,11685,0,2,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830703_9556,6750,431164,27311,10841,3,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820524_8008,6971,1345494,14736,5167,6,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19571225_3652,6548,1061390,43050,10365,9,7,2,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19690920_1417,6181,78926,35538,12410,0,4,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19941221_9141,3608,1568258,24874,28196,8,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730522_8934,915,1131085,24990,21424,0,5,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610913_1038,460,1032108,1960,6081,8,0,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630728_2854,643,579049,12286,29049,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900526_1409,6690,1139562,4591,2609,6,4,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19790506_1620,5154,1760425,1368,26796,4,4,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820502_6236,2261,1381301,12614,6220,10,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900302_6772,4455,753932,11250,4302,8,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19711110_8437,3925,1400572,18818,22440,5,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19761009_8287,4178,909170,45117,5718,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19551009_5163,5883,1658413,27514,9496,6,3,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820123_7820,4042,1533154,28255,27377,2,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19710512_2756,1668,1635995,40285,29097,4,1,2,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520325_3871,9406,135779,13443,6961,0,4,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19761216_9088,3410,396065,28036,28589,8,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19901002_3387,3494,1530598,13496,25642,0,5,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19831211_5503,3495,1424057,29138,776,7,1,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19481229_7418,5244,1143094,24905,5730,4,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490223_9792,5575,1260767,5042,21248,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900630_1281,1510,1220611,45544,23917,0,0,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010621_4546,7727,1481657,12933,28930,10,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19590615_4456,9095,1158293,9999,23327,1,3,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550926_6723,6300,1636135,11238,10251,1,3,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19710417_5834,2518,10625,10034,3618,5,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000404_8057,2653,1982188,41810,24690,10,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840601_9083,9769,1428913,38489,13053,5,5,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19861101_5236,671,1151912,8632,20941,8,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530220_5996,786,1107236,29118,7535,4,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730310_6109,4858,564675,49969,24557,5,7,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19760209_3437,6659,1142889,46073,5041,0,6,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600221_6870,9069,769069,39266,18793,0,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19590213_8141,8387,1094588,9123,24973,1,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600330_2722,6645,242870,17100,28476,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19450121_1948,1847,1087420,9668,24302,8,2,3,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550104_2726,6920,1801736,11207,777,10,1,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19981112_2032,9435,188083,3501,2048,8,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520419_9095,2364,1187232,41219,10538,7,2,0,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19500304_9503,5886,1911627,46972,7340,10,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19940103_5023,7021,1042203,22797,27094,6,5,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19501024_5370,4968,1029173,24953,12887,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550224_6576,2467,1756347,16968,16458,5,3,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19750313_7219,3148,176953,36730,4315,9,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740321_5832,5951,121939,1704,942,0,7,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900230_6117,2654,607319,4950,20863,3,4,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19621016_4278,3414,1499170,20388,14835,8,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600505_1049,1475,606336,39652,4246,1,2,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860115_9541,1517,1609987,10045,13310,0,2,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540902_7497,8574,1550153,1329,15309,9,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700210_5961,9173,1733147,4391,1398,10,0,2,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490911_3993,231,879682,13032,20247,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890324_2132,8463,698827,6870,22220,5,7,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480409_7165,162,248755,28198,8058,10,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000530_1192,6876,87058,40131,4955,7,4,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19500720_8108,7087,603086,43556,4730,4,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000615_1138,5920,1439845,39411,24970,4,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990206_1856,6460,410229,7231,3020,7,1,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19901004_6930,5088,1076103,24223,19991,9,2,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19750816_8065,8946,763670,20593,15578,5,2,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19941003_3037,1449,1756195,17042,5059,7,2,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860714_6198,5177,356048,4845,22930,2,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19871112_9583,3647,861620,31289,22810,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480228_8153,1311,27693,1812,490,7,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770811_1481,2822,1201154,2643,11821,6,5,2,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19500417_5718,9860,377876,33522,22187,10,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900709_4000,8150,129381,43768,3667,1,5,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19821129_6016,9064,28807,14713,19765,0,6,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920406_5316,2147,1068581,8640,14592,3,6,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19970801_5781,1114,1588536,35024,13548,6,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770308_6447,2260,152973,17262,25913,1,3,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19590104_8830,563,1467066,26406,2218,3,0,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19880909_8027,3181,422550,42714,24565,5,7,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600921_8398,9170,567556,42250,29127,1,4,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19591218_3705,5207,1309334,18045,18939,9,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010527_7404,3965,1370960,49439,8645,10,1,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19581215_5562,5405,189474,12303,27111,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480404_8230,2253,656885,30400,5255,8,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19510525_6932,7799,1165517,41827,13082,5,2,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19710803_7436,7620,320715,42753,5316,8,0,3,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540726_5549,3011,1328842,31458,28859,7,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900406_9156,4172,51918,39787,19910,2,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860411_1022,6261,1619306,5086,2632,7,5,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19501110_9626,8714,564230,4780,6352,4,1,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610430_8330,4858,1963624,29617,29245,8,2,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19680416_6049,5061,793179,7916,29208,3,4,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19571023_2396,8693,1489011,25499,25100,4,7,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19741102_7907,5920,287975,40016,28091,10,1,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950615_5554,8562,365388,31794,11981,7,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19750806_5422,9122,1747755,48430,22134,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19970203_9000,506,895792,40505,23548,5,3,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890519_6703,1241,240283,41804,25629,8,1,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990723_7316,5020,727083,41935,14294,9,6,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740918_6658,9587,40172,25678,18659,0,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960118_8379,7255,646031,37704,8887,6,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19760412_8143,1720,573278,33825,12117,6,0,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19941020_7621,8665,67592,6109,6883,9,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19501027_8693,5919,211033,46063,17401,1,6,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530424_4573,543,742733,35387,11572,3,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700223_9361,3167,674707,20372,16582,9,1,3,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890808_2864,202,843264,39686,27115,5,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900207_4508,9010,1854213,21936,2695,0,0,1,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19911204_3761,5100,244681,15136,3323,3,2,3,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19930309_4305,480,1241695,626,24276,10,5,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580416_8056,9874,191173,34114,25348,3,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19771104_4107,7523,1061011,18871,13780,10,6,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19811203_9648,771,1147262,24419,19930,6,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860730_7507,7523,1465976,36933,1305,5,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990216_9726,2989,1437969,22015,5802,0,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570216_1189,5193,289335,39177,26639,4,3,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19851225_8605,1270,1499946,40389,3140,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730911_6435,3774,32429,23785,22683,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700403_5006,9424,1243624,5851,29983,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19861203_9882,6316,234339,2406,26620,2,2,1,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19850228_9364,7431,1498674,20080,15435,8,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990716_3708,9607,1031511,45156,10250,7,5,3,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620104_2940,1776,1542728,47095,5018,0,4,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610813_8423,6062,741943,48612,18916,1,4,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860428_6838,3539,1130501,30834,12250,5,0,2,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19681206_4718,7683,1060424,29886,29418,8,4,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19470701_8246,4623,1809895,11901,23534,0,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830526_7767,155,181312,42245,13971,7,1,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670428_6193,900,159895,14295,3658,6,0,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19821121_8961,4424,1870027,1824,21058,2,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19790804_9455,1046,1288411,44074,486,5,1,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19701112_5153,9637,737331,220,27376,5,3,3,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540807_7367,1221,1780992,30942,29416,2,1,3,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19750721_3533,8163,728566,23083,22975,3,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19980418_7792,6303,980596,21487,23400,2,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730524_3481,9319,1357606,18804,28555,5,7,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540709_9064,8406,1637065,13583,507,6,0,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19790607_9811,5316,1705444,32059,29136,0,1,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950922_2891,7067,1735860,18109,10865,3,4,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19921211_8796,8202,129428,40323,4135,7,3,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670408_9908,3705,1390675,47799,27915,4,0,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530701_7672,719,755925,20450,18941,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960609_3512,4051,663341,4489,15199,2,7,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630229_5124,1134,1258649,31045,11437,8,6,1,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830827_9098,5220,1492917,41429,9784,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960803_2800,4167,1787318,47397,14714,0,0,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900328_7369,8719,1522097,46628,28132,2,7,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820106_8384,4608,1856030,8617,13122,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740303_8529,5637,22918,19321,19641,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19450101_7094,6964,193665,13414,14755,8,3,3,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840201_7138,7880,559256,39534,6642,6,7,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19720119_9484,5029,1129084,23205,15588,4,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920702_2210,1222,799882,44801,13672,1,6,2,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890918_9773,2805,897167,22949,8391,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19470217_3593,1927,1749843,46684,27263,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520525_5848,4979,1786227,8507,13265,9,4,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19561111_6418,6938,1933437,46893,6045,2,2,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780823_4048,7629,1326066,43502,312,4,5,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19881212_7063,230,1712066,48763,18013,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840930_4667,1687,1460452,29424,3883,10,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19631025_4056,8135,112217,3584,10492,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19781006_6621,1895,529708,30294,29019,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010709_9121,7436,776242,3798,25940,0,6,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19621020_7458,1363,1998985,43535,20261,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19971017_7081,3027,1734408,25894,27285,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19660521_9321,1802,944914,28675,2643,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580823_5703,1313,259331,46974,29557,8,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780415_6668,4977,1930997,8617,14111,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19980923_5576,7704,1514420,12877,24027,5,3,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19921107_8381,7075,930421,28874,28869,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19801012_1100,1027,849561,14032,24055,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910502_4545,9010,1041912,11264,17928,6,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810210_6773,3831,1025,44226,22025,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740214_4006,4476,653740,44916,5748,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910504_7231,7722,892717,4407,902,0,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560117_9117,7905,1203707,38666,9092,6,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19991108_9115,9092,1962910,40976,3394,6,7,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19720907_6044,2413,254925,27606,27033,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19951026_2513,3575,163326,7395,10826,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000223_8798,407,917900,33279,27709,1,7,0,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19690823_3118,9966,1454283,20955,9265,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19980320_1300,2989,1003173,1119,17848,9,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900218_1433,3446,1718931,1795,17759,1,4,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19660124_4783,2947,3674,35748,10378,6,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19641108_9208,609,705011,29148,17017,10,4,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19691022_4508,9964,1185800,14839,16130,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19521217_5723,5480,1844890,8317,12279,7,5,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700501_3157,9002,220128,47444,17233,6,2,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19521008_1497,2694,498398,18569,12487,7,4,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19690417_6017,258,1337416,41954,8137,2,0,1,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920229_6143,4030,39445,43080,12768,9,0,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810825_3000,2100,1901401,33456,23558,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900907_5477,3916,455370,2074,19510,1,2,2,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19720818_4771,1549,761273,11091,12115,8,3,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580114_5494,889,84422,23287,11373,4,6,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19821026_3177,6331,558601,40573,24979,1,2,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700816_9785,1270,1230138,3459,26671,5,4,0,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19861014_6009,7803,340442,41936,3757,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19930207_7101,9981,1131655,36283,25416,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550426_3977,4938,118246,4749,22769,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19721110_9272,9110,1717402,34170,15245,3,3,0,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19470127_9959,8265,903737,7353,224,5,0,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19650115_3263,7008,1478611,6015,26668,5,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19500514_4484,8551,332747,21256,11499,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19711228_5941,213,949339,25192,20664,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770601_6229,4022,332902,3310,5970,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990903_1872,2921,1685802,36219,19796,1,2,0,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950808_2573,3754,1150817,3793,13042,5,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870319_7187,6687,1246323,39275,28219,4,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19760607_7442,9059,31430,25110,27628,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19771113_8208,2872,831146,19439,6552,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670414_9892,4830,1027715,37931,20019,5,7,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610103_6250,5894,1276330,48979,25555,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19771012_9219,8718,1011647,38951,22806,0,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810818_8129,5317,1015741,16085,16488,6,2,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19551129_6675,6494,765720,15089,16740,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19470315_3276,4385,63340,26124,22938,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840929_4740,5272,367327,29972,23949,8,2,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19660619_3131,7211,689660,35629,29036,10,3,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19680110_4949,2052,254550,4466,8866,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950824_9603,4353,767634,17329,3644,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19940409_8397,5732,1838305,44017,20033,8,3,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860107_5936,4866,1888104,20066,13956,9,6,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19741120_8440,4607,227471,33847,17253,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550521_1931,9524,1861010,30899,2316,7,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19761214_3529,9634,1130155,3708,29887,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19750825_1000,6869,256106,37344,10891,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730121_8910,6091,613151,1395,2221,6,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19510508_7667,3415,800513,24532,27188,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19501119_2541,1988,922510,7800,6192,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730903_2704,547,781642,34272,15456,0,2,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830805_5070,655,1319356,17531,11090,1,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600717_8913,7793,1969098,27803,28747,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19460811_2582,6944,1791232,16226,8895,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19501227_8672,9432,465880,21940,28083,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19501126_4258,4665,776569,32226,28045,0,5,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770113_1522,4842,262804,47677,12218,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550324_9424,9901,1850911,27130,12416,1,7,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19941211_7144,1163,776801,28120,15066,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19980918_1054,101,1648606,25693,7842,10,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19591008_1374,4810,1321033,9823,22732,4,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19880626_9020,3346,5296,6533,16562,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890915_2068,8971,256202,7979,21380,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19471009_4453,1323,55642,3783,17979,9,1,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810415_1705,6134,457220,15397,9686,2,7,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860501_3723,3517,832926,27282,22941,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960424_1879,9838,497250,38742,13934,0,3,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480209_5862,5219,315704,8825,23407,0,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830407_9294,7660,506196,25920,7001,8,3,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570412_4658,6808,1833865,42919,14051,5,0,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740826_6060,4008,10762,41062,27519,6,4,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000621_7495,3084,1224608,9720,47,5,6,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820216_9505,2768,304849,35731,23361,6,5,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19800319_9070,4480,572994,15598,4724,5,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580415_6344,6310,1836444,32362,17222,3,0,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990517_7961,9442,1962829,44915,13083,5,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19721220_2515,3906,1126215,18923,7883,4,0,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770802_2996,967,1905881,28933,16483,4,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19850929_8843,6490,866312,19081,19410,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19631129_1988,877,89909,24607,18274,7,3,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990322_6528,9311,566689,43070,11935,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770703_6831,7075,1215187,12059,27660,1,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540325_5864,540,929355,38604,9918,4,7,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840708_9545,4071,1246631,11874,8418,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19940403_7138,3267,981600,40478,17217,5,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19460404_9455,1839,320461,9156,20110,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19491218_4780,7214,167786,9921,8627,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610613_5646,4670,73986,46874,1797,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19821028_7050,1963,1257065,43473,17838,8,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490630_8620,3298,563492,18856,23299,7,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860703_8053,2723,912226,13840,13577,8,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560502_4759,8423,225827,26014,7858,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19931118_3677,1208,1838814,34047,17178,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19971219_3037,2612,324889,44649,26866,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19821008_1841,8056,1094201,26864,7534,4,5,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600716_6906,8565,335517,30121,16309,2,2,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000613_7335,4588,1452127,43772,28311,3,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570105_5539,6256,835118,26258,28785,4,5,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910425_3907,7759,26562,16483,29518,6,4,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910710_3555,9869,121986,13804,3779,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780925_4583,5026,262903,14099,9888,7,2,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19930104_2199,3697,767495,4680,28048,5,3,3,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010518_3381,8611,738701,22370,3592,7,1,1,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830524_3647,8011,589301,8746,23884,2,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19470308_7630,2841,1678516,14251,22363,7,3,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830414_6907,6920,1965746,4690,16716,2,0,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19571230_3672,1788,1554014,33973,13416,2,0,1,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19790224_5729,9285,10512,26421,5134,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19500322_3793,972,1939598,49079,5294,5,1,3,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870716_7527,2557,1182742,27105,4684,6,2,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780108_3034,2040,1827989,45868,27115,4,1,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19731025_7764,1756,471028,8766,5982,3,4,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900909_5392,1800,1380534,34668,20258,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730409_7357,4529,340835,6911,6616,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19661015_7183,4143,201013,2843,11699,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600427_1134,8278,286970,336,15537,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19500330_9694,9179,1088273,31663,525,5,0,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19531203_6673,9190,474592,8006,21650,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19521025_3379,3159,494690,32898,19444,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730321_1334,8676,537257,12210,25015,0,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820623_5294,5704,1763975,27204,8721,8,3,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19851111_1374,3336,422364,19186,19964,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19710526_9600,1959,994040,22044,23583,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19850605_7568,5136,1601042,15077,21221,3,0,1,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19851102_7901,1055,1785923,20309,1073,5,7,1,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19880123_1442,3216,1615993,40477,28062,8,3,2,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19680220_6462,7316,1773267,23007,4901,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19801207_1816,7875,634333,39295,28043,6,5,2,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490823_5581,2912,1813396,38818,23159,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19871218_1206,319,1592047,44056,21489,5,0,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920622_8465,2210,321858,28953,29966,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960818_7938,379,86296,30008,5666,2,0,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19710406_7909,4238,1294543,9322,25506,0,7,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920821_1678,4224,40146,45518,18361,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19930602_7202,1858,469273,33032,25337,4,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19470611_2775,9004,1725524,17068,10750,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740706_7023,5769,1933600,48645,13127,5,2,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960812_9904,6428,22241,23920,2478,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19471106_1310,5965,1674752,20860,8630,2,2,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540706_5694,8980,1103556,47211,11272,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580414_7667,2023,1423045,5703,17777,10,3,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19991119_8865,1086,1098218,34586,1524,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610709_2519,7613,1702614,39379,7768,10,4,0,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19720725_3618,1936,1076715,10855,15200,10,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19811120_6815,8781,258974,20367,28854,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19531101_9099,7590,1330943,23113,15215,4,1,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19790702_6314,4947,626477,25121,9918,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19541203_7070,2538,1630332,48361,18027,10,5,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530403_8509,8249,1413089,47932,18932,2,0,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19510127_4101,7573,449685,14931,28776,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19461121_1559,1091,242440,16862,8135,8,7,1,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19450505_2553,5149,671437,12439,6944,0,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480802_8829,7965,1499826,34704,2829,2,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840618_6592,5041,972810,48346,19927,2,7,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700108_5521,1689,207846,11786,3143,4,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740408_9807,170,51053,1335,17251,9,1,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700313_1131,3887,1568394,20329,29132,8,0,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19850416_2483,9986,366748,3665,27018,6,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19461109_2332,5618,1829446,44625,5990,1,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920429_3079,3299,373063,46877,8,4,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550108_5590,795,810838,42580,10655,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19771115_4226,3385,487757,43041,11148,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480828_7717,3811,1687761,17632,13618,9,2,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19930514_8568,9268,1331912,3302,4021,5,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820308_4185,8125,62557,11332,6562,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780719_5333,9854,975149,24078,4836,7,4,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19640522_3095,3833,416580,35283,10106,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920407_9314,665,1741783,31888,9117,2,3,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810108_2021,6447,67264,11283,14205,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19511223_3864,9221,1280494,3398,29986,4,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19601028_8662,6308,1638474,22366,16864,4,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19761123_9319,9432,1116321,20435,21922,2,3,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620817_3412,2095,658199,26977,15707,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19650528_7503,9253,133574,29572,8002,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920216_5987,8912,1474645,32958,6375,9,3,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910413_9479,4733,517227,49781,29484,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810701_4524,903,1078037,11234,28273,1,2,3,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19981112_4581,37,1347609,19812,135,1,0,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730430_4427,8960,1505418,12864,27405,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860204_7527,6789,1978524,48544,23797,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19800804_1841,790,1967934,14166,13745,7,4,1,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010905_3101,3278,1674893,20649,21597,9,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620108_4013,9686,210909,28576,16931,8,4,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19511225_5116,305,587050,39012,7570,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780912_2710,5110,258972,35427,20633,8,7,0,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20011014_9383,5621,222437,32823,27515,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19801012_7097,1919,1797572,33116,10408,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520624_6803,1182,1050925,29521,10180,3,4,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000802_4943,7805,268969,20702,20721,0,4,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19651104_2938,8333,596584,25493,10004,9,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610713_4963,6196,1521126,10451,4612,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550220_3330,7902,229958,44272,20752,1,3,3,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19781029_8031,3021,473382,25502,23331,5,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540712_1096,7792,1764765,4312,4607,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960625_1585,3135,596949,21741,23819,4,0,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19561011_4262,6729,1262971,36351,4459,6,1,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19650514_9766,5349,595860,40387,3447,9,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19790809_8840,949,735374,17701,23649,0,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950129_8433,558,1745117,19633,11398,0,3,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19541109_5583,8890,544786,24925,9015,1,3,0,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19760625_1790,3664,794156,41250,17161,8,7,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550602_2382,816,1165055,39672,16923,2,1,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19750822_6596,6485,1071820,5883,19875,8,3,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630307_4887,2907,900464,24862,15843,3,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610815_2924,7123,1443641,45153,1391,3,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19471104_6428,8547,1870282,44643,9312,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19971109_7201,331,1969295,8141,4615,8,7,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19660822_2572,7295,1656891,33822,26194,4,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550515_8001,622,843097,38749,16601,6,5,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480207_2649,457,1668797,20054,1708,2,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19961020_7400,4183,1195967,45363,15805,10,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810115_9355,987,255634,33124,10992,4,3,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770322_4056,8323,138775,45198,24580,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19790118_9386,9468,1944802,40264,10000,9,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19571204_1221,4518,1215423,1910,25734,5,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950411_2361,753,1620797,26623,22066,4,6,1,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610130_5714,1304,128870,16927,16906,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19611127_2836,8931,1536300,46853,797,0,7,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780824_4045,9932,868793,31416,22664,2,3,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490303_8116,5138,1124821,12619,14029,1,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000205_5999,1255,812092,36252,8393,2,6,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610105_4117,3199,228598,15189,23313,0,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910413_2356,9007,554760,32594,284,8,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860225_7672,6812,1109280,8364,7435,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520514_2009,7640,477057,23570,3442,6,7,1,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540411_5230,5880,1959826,48196,7290,9,5,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19460121_7522,3708,964122,99,8622,6,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19571226_5752,2709,486381,15338,10577,2,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520905_9849,596,1462286,35299,9321,4,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610330_1445,1827,229974,45368,5238,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780420_4135,1168,8341,25343,23551,1,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570129_7032,6647,632109,41552,20146,8,1,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19681220_3284,5194,495313,9536,19568,8,6,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19660520_4478,9336,409207,31514,16199,3,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620614_5395,1041,886280,28238,18864,5,6,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19760619_8036,773,928640,32637,26272,0,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19771229_3619,8621,1614872,39152,25144,10,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19500307_1108,9945,807205,31198,4743,3,5,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950101_7993,5590,921781,31315,29975,8,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19961114_4939,8737,1593853,10974,20229,9,4,0,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700722_8726,9234,460934,19440,27813,7,7,3,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700108_5078,8009,1856332,41213,17184,7,1,2,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19991004_7196,7083,1897739,31453,9842,1,5,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610816_4407,96,93189,30436,20418,6,2,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830805_9944,2345,199447,689,20844,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19650705_5054,3373,1389531,23899,24257,9,3,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19470329_8439,1355,1589167,27197,21541,0,4,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19761109_8028,673,1144250,30278,25166,2,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540411_3911,7145,1875094,16825,23831,8,4,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19460804_2445,3011,1102793,47400,2616,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900319_7981,1216,1626849,35147,11861,7,7,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870725_2205,1842,568650,2314,17708,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19980803_9617,4570,1979271,40700,16726,10,2,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19590204_4112,9425,857957,3491,15552,9,0,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19451230_9902,5048,1897753,27159,19113,4,5,2,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19611123_4812,6553,236812,755,21051,9,0,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19621211_1243,433,1889092,25664,11604,3,6,0,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20001216_9148,845,1429251,30214,17162,6,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960220_6248,8597,952179,26119,2012,9,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910312_9908,2506,1038384,43223,7163,8,0,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19571219_5037,8849,442563,12396,24206,8,7,1,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19871224_2096,57,957223,9197,17491,10,5,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810219_3084,7496,1243069,42452,16849,5,3,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910126_1593,6932,1433682,20762,13797,2,7,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520523_6520,3037,300789,3220,18106,0,1,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19951011_3479,9721,715493,11218,19230,6,3,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19471219_2972,1631,1734631,1407,7480,7,6,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19650727_7587,5163,1062466,17636,25473,10,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600602_3915,6556,4125,26950,6633,9,3,2,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19601014_8062,8828,782569,2055,2757,5,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870824_3762,9258,1652944,6620,23889,5,7,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19841117_1177,1538,930042,23567,6960,10,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920707_1060,974,1068438,44219,13570,8,2,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570926_9019,4437,174351,31681,27204,1,6,2,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560615_8020,3867,1291824,29955,18006,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19590915_9394,3114,1857785,26621,13593,4,4,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19831219_5062,6524,789862,36554,112,3,0,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19651130_2322,5533,904439,31338,22897,5,5,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20011127_9138,7139,1866616,7337,6028,1,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530905_2116,152,1590436,2221,10595,7,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19491030_6244,7751,1705222,10514,1587,3,4,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010812_4108,1188,1966998,7926,4778,5,5,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19650128_3434,3396,1824712,35774,19320,3,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19511213_5001,2299,9350,43009,6597,2,6,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730519_2353,1925,410394,33608,3750,5,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19900109_4314,1611,1153715,18359,18488,10,5,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910123_6331,8729,1047741,22119,17971,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19450314_5717,9752,811146,7972,17551,5,0,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19710306_3906,9883,206601,14862,22460,10,5,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490923_7590,9495,32554,4721,9632,5,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19691208_8749,6448,374838,27214,7190,0,5,2,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19880824_4131,5840,1613612,23996,12396,3,4,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19831114_9561,1831,442220,16601,15773,4,6,1,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19821124_4146,7547,1355767,24872,16435,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19650122_6960,180,917345,42374,20788,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19660330_9230,4470,9744,20095,16434,7,5,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540224_7834,7796,1158157,32776,29000,5,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810326_9597,5215,224256,43228,9079,7,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920816_8258,305,1947294,38570,6368,3,6,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570612_1699,2260,1096585,47774,6667,6,2,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870630_6668,7444,508589,47706,23146,9,3,1,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620307_9787,2230,1603201,34309,8276,0,5,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19790603_8438,353,60510,3057,9419,2,3,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870109_8394,3394,1569842,23180,12237,10,0,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19961005_2199,9216,1863378,20649,11856,6,5,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19461101_4080,1922,778940,33246,25736,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19880914_8361,5817,903804,36333,13942,5,1,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19651002_2255,6625,298886,48250,19426,1,5,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910924_8883,2192,179254,23287,18439,8,3,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820602_5920,3974,104294,29999,18635,5,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730416_9650,8786,665980,35556,14938,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600605_5105,5107,904221,11994,13430,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19631115_7359,8252,1839267,6795,20685,0,1,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010323_5200,7140,817546,49864,5976,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580708_9255,6896,1163821,26204,28281,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480304_9822,2963,1861513,12534,18996,7,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19801030_8657,3254,41286,8703,17756,10,5,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19470713_6333,4343,1256947,46304,18087,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19640217_8776,8111,1696946,42118,25621,8,7,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20001206_3008,2086,661006,13543,13258,9,6,0,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19940612_3243,8331,842546,38791,25238,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19450506_6478,3933,704464,49804,10962,1,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19750217_5642,8101,1614291,26214,25576,7,0,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670701_9387,9007,75203,40314,6034,8,1,0,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19811105_1206,7439,814885,33202,2495,5,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530909_8409,4602,907716,17348,16271,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19750821_5648,6440,1127648,22739,18629,0,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19501006_3934,5530,389826,27489,10678,3,7,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810420_2707,7368,1142810,16179,2707,6,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19571116_2108,6727,1401327,16784,21022,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19720907_8374,9681,324628,1837,27967,1,2,1,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700914_3498,7943,658760,23393,6778,2,6,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19880609_8035,819,1103862,46581,16971,9,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19741007_1077,4926,1879820,43392,1773,7,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780322_2677,7482,1188050,45412,5093,7,5,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19650612_3982,7103,1262424,17073,15039,5,1,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19450329_4686,3919,620169,39985,29769,10,3,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19590811_6504,1628,504360,7854,3569,3,7,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19861223_5971,443,75090,43096,21324,2,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19680425_2532,9099,1603824,24935,4516,5,5,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740121_9114,6521,914508,47921,6279,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890728_6556,9415,1053131,47262,3817,10,6,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950718_6824,2382,304363,7712,29565,5,7,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19671022_7156,5077,690793,24055,20496,6,2,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700421_7805,5659,2777,16339,23146,10,7,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840411_7324,6243,342363,32597,24589,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19520621_8445,6924,860020,45231,419,8,5,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19701108_7020,3640,670562,39589,5186,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19991004_3003,3796,1784607,9259,28985,9,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480901_7786,3470,1882701,17839,23345,9,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19870813_4277,2343,812047,31553,29947,2,4,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670504_9914,8281,1759049,34291,28373,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490301_5297,2423,220404,31335,15904,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19660101_5288,814,281374,41531,26091,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480118_7612,88,1936270,49388,5912,10,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19970313_5336,2301,1975060,41338,3633,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010801_5078,9291,395400,17902,18612,7,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480505_9707,276,975944,30926,12930,10,3,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530802_3718,1647,449663,9255,15492,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010110_1542,8575,1096298,31234,3493,2,5,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19950921_6689,4458,1006247,38405,5233,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19790212_5448,4628,1699509,44591,12396,2,4,0,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19930226_9817,2467,255662,47199,10081,10,5,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19880226_3862,1464,1081757,11296,3992,0,1,0,0,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19530527_8507,8985,18720,11392,7322,10,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19650316_4473,7489,325128,41184,1617,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19690724_6258,7795,684614,35151,19285,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19561115_1198,8215,1262656,47243,18740,1,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19980103_4508,4246,528834,17594,545,8,1,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560525_9036,3335,597973,48633,19958,10,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19581104_7373,5064,1498892,29480,24820,5,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19460411_2542,2845,1509647,12847,12429,6,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490917_1761,9399,822897,18030,4694,8,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19541016_1799,8425,45114,12235,28706,3,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620119_4712,5318,516917,24769,25016,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19541028_3985,3293,839599,22594,753,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19861022_5505,3773,1607163,39094,19572,3,3,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19460322_4600,5170,615064,49213,1196,9,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19821211_8169,3652,1636297,7588,20707,0,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19850906_7562,5719,165103,36625,6361,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19621211_3311,2788,682966,43825,25302,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19970118_3939,2846,596217,3643,5831,7,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960423_8655,4724,1377417,30368,1548,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19540425_5777,1457,1739769,44341,4517,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810519_8434,9582,1010015,25698,1496,3,2,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19751001_4398,160,348448,25119,29479,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740529_1953,1680,97684,42157,21181,5,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960623_4080,426,1386539,5885,25943,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19970811_7599,6367,454287,45268,19410,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010714_1945,6576,1968475,17778,16775,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600622_9523,6933,753951,30507,22231,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920710_1397,9491,919902,44652,10395,7,6,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19980807_3406,1415,767672,28627,499,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19800603_2683,1687,1700725,21181,9293,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19800129_2731,5704,594334,35778,11918,1,4,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920908_5248,4920,623094,4750,3652,7,3,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19800611_6733,6313,613519,19796,19095,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19490630_4829,5879,1410721,44324,17700,4,4,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740105_5509,2479,893232,42929,13452,2,7,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19640712_7824,4569,1748741,8428,20811,0,7,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19760323_5319,6725,1000252,42197,18540,5,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19670411_4288,1086,1951422,22522,3417,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630507_6850,1373,30190,46315,3934,10,1,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19941106_1729,394,212749,2517,20261,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19551123_2122,2171,1184301,20175,819,5,0,3,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19521201_5893,839,413448,20964,24917,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19590914_9692,8637,14981,43660,2025,5,5,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19800518_2646,4400,892312,38568,7177,9,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860524_9463,7801,1834236,18866,488,10,2,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480304_1618,6727,659839,16725,25039,0,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19510930_9524,9334,898610,29336,19956,9,0,2,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19680322_5844,3941,841584,43311,19414,0,2,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19501116_7639,528,161917,22608,13793,8,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19971111_4140,6484,154637,39839,6665,4,3,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19580201_3253,388,1451685,5990,10338,2,5,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620310_2878,2579,80314,15189,29770,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610427_1191,7119,1681691,41185,24864,0,5,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620725_5885,9006,916396,47445,4032,10,4,3,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19690819_1041,7284,1464101,2473,22820,9,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19470112_3348,9194,17477,3349,23786,4,7,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890814_4424,8054,1642180,8383,14066,7,7,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19761208_5389,5954,1841286,12357,15167,6,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890920_5993,6571,482177,17217,2848,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550201_7568,1104,1804228,41245,7381,1,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19511125_7324,6530,1080376,13776,25508,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19481026_2416,6750,311879,12875,11238,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630817_5763,607,949835,10158,28462,7,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620628_8045,3294,762639,47612,2194,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770721_4351,5963,1474119,28168,6374,6,1,2,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19730726_3598,2716,1189462,22199,4514,2,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960102_1171,505,1799895,27182,2859,1,4,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19700502_5252,1936,1885918,8380,2003,2,2,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19650219_6817,5106,1004413,13249,11398,6,0,3,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840730_4201,3372,1976778,38291,25727,9,1,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840623_8653,3766,598872,4347,13664,8,0,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19640503_2285,270,732419,19162,5160,0,5,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740923_3905,3476,202971,12952,5152,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19931010_7223,2068,531424,35112,21721,8,0,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830604_6588,8330,1251337,3280,27780,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19570330_2085,9844,1406283,3952,24974,9,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19500202_2810,5184,1007109,5158,8876,6,6,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20010522_8271,1397,820844,40346,17266,5,3,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740613_7387,424,1967313,1675,9801,3,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19830427_2274,6468,144795,18200,2691,9,0,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19960804_8591,7037,1371794,29029,25302,0,0,2,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20011201_2504,2486,1152560,38187,14591,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19770121_5904,5766,1962060,22914,15280,0,6,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19810707_6980,5539,1763331,35687,24235,1,6,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19761219_6586,9477,35227,49711,8845,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890828_5653,1867,1983718,31358,16873,0,3,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890724_7147,2852,1444462,24630,18980,2,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19470511_3100,9343,552793,29378,26598,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990705_8795,893,4469,27635,28786,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19880607_8437,7183,1792971,35872,2475,7,4,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19761013_5348,9404,1251420,5904,14718,7,7,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19721017_6988,2418,1000002,12362,3265,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560514_9117,4280,1750696,18726,5772,8,6,2,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19970827_7762,7162,1548528,46724,4638,1,3,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19990806_2169,6713,1924473,31339,10800,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19951214_6232,9422,1543,24320,7388,0,7,0,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19940822_8482,797,47006,45918,15587,7,3,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19980116_6512,8574,365762,1633,13851,2,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19790828_7976,7181,100095,21383,21541,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820402_8799,326,392795,15585,14276,0,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19890316_1073,3253,1690938,28859,28250,7,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19480525_5204,3878,1462836,3099,24787,9,1,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550802_1922,9296,905530,3909,22673,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820211_3919,2101,1112244,5695,25487,3,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19510501_3676,9101,984109,7375,22916,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19500221_2732,3525,490135,7612,913,9,3,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860101_1674,6324,1066739,46125,29634,7,5,1,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19631106_8101,9497,972912,38990,27563,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600304_9365,7788,550399,10245,6738,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19800728_1114,5975,639269,29985,12896,9,4,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19660927_5866,2833,775705,38797,12944,1,7,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19720513_2501,2472,51984,36396,4573,8,7,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19860118_3421,9719,1275004,13829,29357,5,7,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19880812_8965,7625,1066119,25437,2525,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19831019_9200,6027,713344,47523,13360,10,1,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630908_7599,480,1715315,17704,26226,9,3,2,0,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19661129_2834,620,1313269,49737,2476,4,0,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19720728_1317,4516,793457,29978,13240,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19550812_6788,4561,783298,16214,29136,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630409_4180,9257,410794,44362,19401,0,2,2,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840205_5389,9971,62402,1161,7880,5,4,3,1,2,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19600319_9941,5759,605797,21698,12016,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19680216_4828,7133,1151678,39388,15917,0,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19761209_3409,1814,1228812,16017,29041,1,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19840409_7269,6225,679931,24794,9436,2,3,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19630424_7266,8382,320434,44844,4882,0,0,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19610129_7231,9340,1803690,38162,21139,1,3,0,1,1,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19920328_8074,8469,1889454,14610,14513,4,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19831221_4630,3834,183678,21806,24195,4,2,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19740808_2210,7603,1534448,17374,2051,9,6,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19980425_3372,439,365829,1244,26381,1,6,1,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19510702_8221,2901,377972,6665,12628,7,2,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19861210_1873,7114,1497898,38631,17144,5,2,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19780427_7787,2699,877131,36832,22990,3,3,1,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19560604_1575,4631,1962804,28055,28937,1,1,0,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,20000930_8267,1830,1815361,13955,25201,8,4,3,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19930221_6706,3128,1581332,25196,6536,0,1,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19640928_1758,8112,1904178,388,27059,1,7,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19820319_5187,1215,1099774,14355,11878,2,0,3,0,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19910515_1988,1399,1342082,20844,18659,3,2,0,1,0,2020-04-26 18:01:04.746575 +2020-04-26 18:01:04.746575,19620713_6239,6396,777741,48944,8429,10,0,2,1,2,2020-04-26 18:01:04.746575 diff --git a/ui/feature_repo/data/loan_table.parquet b/ui/feature_repo/data/loan_table.parquet new file mode 100644 index 00000000000..0bdb68d8a69 Binary files /dev/null and b/ui/feature_repo/data/loan_table.parquet differ diff --git a/ui/feature_repo/data/loan_table_sample.csv b/ui/feature_repo/data/loan_table_sample.csv new file mode 100644 index 00000000000..6acdfc9a94a --- /dev/null +++ b/ui/feature_repo/data/loan_table_sample.csv @@ -0,0 +1,1001 @@ +loan_id,dob_ssn,zipcode,person_age,person_income,person_home_ownership,person_emp_length,loan_intent,loan_amnt,loan_int_rate,loan_status,event_timestamp,created_timestamp +12208,19790429_9552,30721,24,30000,RENT,2.0,EDUCATION,3000,6.03,0,2021-07-28 17:09:19.623000+00:00,2021-07-28 17:09:19.623000+00:00 +16140,19971025_8002,48893,21,21000,RENT,2.0,EDUCATION,6250,13.85,0,2021-06-08 14:21:52.761000+00:00,2021-06-08 14:21:52.761000+00:00 +16135,19670812_9247,24092,22,19200,RENT,2.0,DEBTCONSOLIDATION,6250,7.51,1,2021-06-08 15:53:38.924000+00:00,2021-06-08 15:53:38.924000+00:00 +14945,19511027_9100,76031,24,116300,RENT,6.0,HOMEIMPROVEMENT,5000,14.96,0,2021-06-23 19:54:45.803000+00:00,2021-06-23 19:54:45.803000+00:00 +35168,19850301_1492,85358,30,66000,MORTGAGE,15.0,DEBTCONSOLIDATION,15000,11.14,0,2020-10-09 01:44:17.497000+00:00,2020-10-09 01:44:17.497000+00:00 +23054,19710919_6605,37931,24,26400,OWN,8.0,VENTURE,3000,10.59,0,2021-03-12 11:23:10.074000+00:00,2021-03-12 11:23:10.074000+00:00 +29947,19640320_6051,2703,28,48500,RENT,3.0,VENTURE,7500,12.86,0,2020-12-14 14:49:53.272000+00:00,2020-12-14 14:49:53.272000+00:00 +15853,19601117_2584,48612,22,50000,OWN,2.0,EDUCATION,5600,11.86,0,2021-06-12 06:09:26.538000+00:00,2021-06-12 06:09:26.538000+00:00 +36666,20000623_4827,56621,39,51000,OWN,12.0,EDUCATION,12000,11.34,0,2020-09-19 23:30:10.956000+00:00,2020-09-19 23:30:10.956000+00:00 +35660,19480723_9980,59262,45,85000,RENT,0.0,PERSONAL,26000,14.27,1,2020-10-02 19:14:11.023000+00:00,2020-10-02 19:14:11.023000+00:00 +13394,19750702_1909,30477,21,40000,RENT,3.0,EDUCATION,4000,7.51,0,2021-07-13 14:21:37.676000+00:00,2021-07-13 14:21:37.676000+00:00 +17964,19710418_4488,76010,23,60000,RENT,0.0,VENTURE,8000,11.14,0,2021-05-16 08:24:24.369000+00:00,2021-05-16 08:24:24.369000+00:00 +16830,19980702_5793,89403,22,40000,RENT,0.0,DEBTCONSOLIDATION,7000,10.65,0,2021-05-30 19:17:42.218000+00:00,2021-05-30 19:17:42.218000+00:00 +13546,19570301_6673,62262,22,80000,RENT,6.0,EDUCATION,4000,11.12,0,2021-07-11 15:51:50.310000+00:00,2021-07-11 15:51:50.310000+00:00 +23482,19770302_1970,91066,21,62004,RENT,0.0,VENTURE,15000,7.29,0,2021-03-07 00:27:42.490000+00:00,2021-03-07 00:27:42.490000+00:00 +37320,19780515_5157,94559,36,72500,RENT,2.0,MEDICAL,10000,7.9,0,2020-09-11 15:26:44.789000+00:00,2020-09-11 15:26:44.789000+00:00 +36960,20001207_6128,62249,39,24000,RENT,9.0,EDUCATION,5000,11.14,0,2020-09-16 05:34:08.550000+00:00,2020-09-16 05:34:08.550000+00:00 +21987,19530513_1827,43215,24,95000,MORTGAGE,3.0,DEBTCONSOLIDATION,35000,11.99,0,2021-03-26 01:46:45.334000+00:00,2021-03-26 01:46:45.334000+00:00 +31554,19551119_7032,55124,27,59004,RENT,3.0,EDUCATION,10000,16.32,0,2020-11-24 03:15:12.370000+00:00,2020-11-24 03:15:12.370000+00:00 +38535,19580830_6315,35219,56,70000,MORTGAGE,7.0,PERSONAL,15000,10.38,0,2020-08-27 03:46:47.094000+00:00,2020-08-27 03:46:47.094000+00:00 +37859,19920823_7844,6355,36,53550,RENT,1.0,MEDICAL,1600,12.21,1,2020-09-04 18:34:00.379000+00:00,2020-09-04 18:34:00.379000+00:00 +21780,19840727_3972,21502,23,91000,MORTGAGE,5.0,VENTURE,10000,16.32,0,2021-03-28 17:06:00.496000+00:00,2021-03-28 17:06:00.496000+00:00 +32289,19540228_8674,24350,34,84000,MORTGAGE,6.0,EDUCATION,2400,7.49,0,2020-11-14 18:25:06.357000+00:00,2020-11-14 18:25:06.357000+00:00 +22045,19520219_1192,85740,21,83000,MORTGAGE,5.0,PERSONAL,15000,12.84,1,2021-03-25 08:02:13.839000+00:00,2021-03-25 08:02:13.839000+00:00 +37119,19911106_2989,62889,48,66948,MORTGAGE,1.0,VENTURE,24000,10.62,0,2020-09-14 04:55:52.556000+00:00,2020-09-14 04:55:52.556000+00:00 +13444,19770902_5041,42343,26,39672,MORTGAGE,10.0,PERSONAL,11500,15.7,0,2021-07-12 23:03:56.042000+00:00,2021-07-12 23:03:56.042000+00:00 +10681,19810917_9838,48722,21,21600,MORTGAGE,2.0,DEBTCONSOLIDATION,10000,11.14,0,2021-08-17 04:15:41.912000+00:00,2021-08-17 04:15:41.912000+00:00 +36662,19560701_1098,4979,37,51000,MORTGAGE,3.0,DEBTCONSOLIDATION,12800,12.84,0,2020-09-20 00:43:35.886000+00:00,2020-09-20 00:43:35.886000+00:00 +35581,19840628_1262,33617,34,55000,MORTGAGE,4.0,EDUCATION,7000,13.49,0,2020-10-03 19:24:08.404000+00:00,2020-10-03 19:24:08.404000+00:00 +35571,19870615_1213,97520,29,40000,OWN,0.0,MEDICAL,5000,5.42,0,2020-10-03 22:27:40.730000+00:00,2020-10-03 22:27:40.730000+00:00 +20823,19691221_2001,31044,22,74000,MORTGAGE,3.0,PERSONAL,10000,11.83,1,2021-04-09 21:50:40.163000+00:00,2021-04-09 21:50:40.163000+00:00 +13566,19490701_3352,2135,26,131000,RENT,10.0,HOMEIMPROVEMENT,4000,12.84,0,2021-07-11 09:44:45.656000+00:00,2021-07-11 09:44:45.656000+00:00 +28421,19850629_2882,6280,28,24000,RENT,8.0,VENTURE,8875,10.65,1,2021-01-03 01:37:54.328000+00:00,2021-01-03 01:37:54.328000+00:00 +11632,19480301_4934,72928,23,30000,MORTGAGE,7.0,MEDICAL,4600,7.9,0,2021-08-05 01:21:09.642000+00:00,2021-08-05 01:21:09.642000+00:00 +14291,19761225_2494,63336,22,34500,RENT,2.0,MEDICAL,5000,16.89,1,2021-07-02 03:58:11.970000+00:00,2021-07-02 03:58:11.970000+00:00 +30722,19650822_8482,68505,34,42240,RENT,3.0,PERSONAL,8775,13.06,0,2020-12-04 17:45:37.952000+00:00,2020-12-04 17:45:37.952000+00:00 +27024,19540608_9214,77396,31,21000,RENT,13.0,EDUCATION,3000,15.28,0,2021-01-20 20:58:16.370000+00:00,2021-01-20 20:58:16.370000+00:00 +30714,20000424_9349,11214,27,68000,RENT,4.0,HOMEIMPROVEMENT,8700,7.88,0,2020-12-04 20:12:27.814000+00:00,2020-12-04 20:12:27.814000+00:00 +36920,19830202_7159,15957,42,50000,RENT,3.0,HOMEIMPROVEMENT,8000,10.14,0,2020-09-16 17:48:17.857000+00:00,2020-09-16 17:48:17.857000+00:00 +11769,19600828_2486,13660,21,35360,RENT,1.0,EDUCATION,2200,7.49,0,2021-08-03 07:26:40.766000+00:00,2021-08-03 07:26:40.766000+00:00 +29299,19710326_8048,38452,33,44400,MORTGAGE,3.0,MEDICAL,2000,14.22,1,2020-12-22 21:03:12.043000+00:00,2020-12-22 21:03:12.043000+00:00 +26921,19910410_8856,87415,32,24000,RENT,2.0,MEDICAL,2500,10.37,0,2021-01-22 04:28:43.335000+00:00,2021-01-22 04:28:43.335000+00:00 +19922,19720812_3570,43138,22,49000,RENT,6.0,PERSONAL,10000,16.45,1,2021-04-21 09:27:30.799000+00:00,2021-04-21 09:27:30.799000+00:00 +17495,19690625_9793,53577,22,32000,RENT,0.0,PERSONAL,7875,14.91,1,2021-05-22 07:52:22.492000+00:00,2021-05-22 07:52:22.492000+00:00 +14324,19670305_2983,1330,23,43000,MORTGAGE,3.0,VENTURE,3600,15.62,0,2021-07-01 17:52:31.292000+00:00,2021-07-01 17:52:31.292000+00:00 +11248,19720926_4616,58275,21,26400,OWN,2.0,VENTURE,4000,7.51,0,2021-08-09 22:49:02.988000+00:00,2021-08-09 22:49:02.988000+00:00 +37071,19720415_9928,62060,47,65000,MORTGAGE,21.0,HOMEIMPROVEMENT,7000,14.35,0,2020-09-14 19:36:51.724000+00:00,2020-09-14 19:36:51.724000+00:00 +19306,19461130_2059,97818,23,35000,RENT,3.0,DEBTCONSOLIDATION,10000,13.22,0,2021-04-29 05:53:30.125000+00:00,2021-04-29 05:53:30.125000+00:00 +12808,19620214_7176,7802,25,36000,MORTGAGE,3.0,MEDICAL,5300,7.49,0,2021-07-21 01:37:00.021000+00:00,2021-07-21 01:37:00.021000+00:00 +29544,19750509_3504,89116,27,53004,MORTGAGE,10.0,EDUCATION,5600,11.86,0,2020-12-19 18:06:30.039000+00:00,2020-12-19 18:06:30.039000+00:00 +29673,19730215_7839,98040,27,54996,OWN,5.0,PERSONAL,16400,13.98,0,2020-12-18 02:38:51.024000+00:00,2020-12-18 02:38:51.024000+00:00 +16093,19740421_5101,94026,25,50988,OWN,9.0,HOMEIMPROVEMENT,4200,9.99,0,2021-06-09 04:44:30.697000+00:00,2021-06-09 04:44:30.697000+00:00 +13575,19740315_4016,60914,24,26000,RENT,0.0,PERSONAL,4200,16.0,1,2021-07-11 06:59:34.562000+00:00,2021-07-11 06:59:34.562000+00:00 +18680,19651021_5802,78640,23,45000,RENT,4.0,EDUCATION,9000,5.99,0,2021-05-07 05:23:01.777000+00:00,2021-05-07 05:23:01.777000+00:00 +17498,19830407_5547,6403,23,58560,MORTGAGE,7.0,MEDICAL,8000,12.21,0,2021-05-22 06:57:18.794000+00:00,2021-05-22 06:57:18.794000+00:00 +11834,19690820_2550,17067,25,30720,RENT,4.0,MEDICAL,2400,7.9,0,2021-08-02 11:33:40.642000+00:00,2021-08-02 11:33:40.642000+00:00 +28564,19511005_8160,72333,28,59600,RENT,2.0,HOMEIMPROVEMENT,5000,5.79,0,2021-01-01 05:53:18.056000+00:00,2021-01-01 05:53:18.056000+00:00 +18810,19740925_9648,35653,25,65000,MORTGAGE,1.0,PERSONAL,15000,11.12,0,2021-05-05 13:37:01.529000+00:00,2021-05-05 13:37:01.529000+00:00 +20524,19651005_6967,57577,25,78000,MORTGAGE,4.0,DEBTCONSOLIDATION,2400,11.86,0,2021-04-13 17:18:28.731000+00:00,2021-04-13 17:18:28.731000+00:00 +14025,19951023_3236,70598,25,42000,MORTGAGE,9.0,HOMEIMPROVEMENT,12000,9.91,0,2021-07-05 13:20:19.860000+00:00,2021-07-05 13:20:19.860000+00:00 +11890,19740629_8255,63023,22,24000,RENT,0.0,DEBTCONSOLIDATION,2450,7.9,0,2021-08-01 18:25:51.613000+00:00,2021-08-01 18:25:51.613000+00:00 +21828,19450318_8032,33597,25,36960,RENT,8.0,DEBTCONSOLIDATION,12500,14.61,1,2021-03-28 02:25:01.328000+00:00,2021-03-28 02:25:01.328000+00:00 +38454,19801222_5014,37036,59,40000,MORTGAGE,5.0,PERSONAL,3600,7.49,0,2020-08-28 04:33:26.940000+00:00,2020-08-28 04:33:26.940000+00:00 +28923,19671125_4301,5065,32,27000,RENT,2.0,MEDICAL,6000,12.73,0,2020-12-27 16:04:15.527000+00:00,2020-12-27 16:04:15.527000+00:00 +21578,19691106_6462,91221,26,125000,RENT,3.0,MEDICAL,12000,6.99,0,2021-03-31 06:53:29.496000+00:00,2021-03-31 06:53:29.496000+00:00 +30594,19821118_1872,23518,29,105500,RENT,4.0,PERSONAL,8000,7.49,0,2020-12-06 08:54:55.734000+00:00,2020-12-06 08:54:55.734000+00:00 +20908,19751202_9380,78933,24,80689,MORTGAGE,1.0,DEBTCONSOLIDATION,16000,13.22,0,2021-04-08 19:50:35.386000+00:00,2021-04-08 19:50:35.386000+00:00 +14637,19580516_5644,70174,26,34000,RENT,1.0,MEDICAL,8500,7.88,0,2021-06-27 18:07:45.466000+00:00,2021-06-27 18:07:45.466000+00:00 +36708,19941118_5554,62979,40,75000,RENT,3.0,EDUCATION,6500,7.9,0,2020-09-19 10:39:19.183000+00:00,2020-09-19 10:39:19.183000+00:00 +11498,19780924_4710,13469,26,45000,RENT,5.0,MEDICAL,1800,14.11,0,2021-08-06 18:20:34.820000+00:00,2021-08-06 18:20:34.820000+00:00 +37558,19900526_2107,92881,36,90000,MORTGAGE,13.0,EDUCATION,12000,6.62,0,2020-09-08 14:38:31.413000+00:00,2020-09-08 14:38:31.413000+00:00 +22221,20010906_1070,14424,24,98000,MORTGAGE,5.0,HOMEIMPROVEMENT,10000,11.71,0,2021-03-23 02:11:56.889000+00:00,2021-03-23 02:11:56.889000+00:00 +36390,19500129_2822,5676,39,44000,MORTGAGE,2.0,MEDICAL,8000,9.63,0,2020-09-23 11:55:51.173000+00:00,2020-09-23 11:55:51.173000+00:00 +27908,19890524_1632,35007,30,30000,RENT,3.0,EDUCATION,4500,13.92,0,2021-01-09 14:33:26.688000+00:00,2021-01-09 14:33:26.688000+00:00 +36114,19871005_8543,37033,44,37000,RENT,0.0,MEDICAL,3500,12.87,0,2020-09-27 00:21:31.390000+00:00,2020-09-27 00:21:31.390000+00:00 +26177,19590111_3670,50479,30,72000,RENT,5.0,EDUCATION,20000,13.79,0,2021-01-31 16:04:00.442000+00:00,2021-01-31 16:04:00.442000+00:00 +26100,19640419_3706,38352,31,72000,RENT,6.0,DEBTCONSOLIDATION,21000,11.99,1,2021-02-01 15:37:15.358000+00:00,2021-02-01 15:37:15.358000+00:00 +12228,19570612_1699,48626,24,30960,RENT,5.0,MEDICAL,3000,15.62,0,2021-07-28 11:02:14.970000+00:00,2021-07-28 11:02:14.970000+00:00 +34787,19561204_2796,97032,35,48000,MORTGAGE,8.0,MEDICAL,2000,11.97,0,2020-10-13 22:17:07.144000+00:00,2020-10-13 22:17:07.144000+00:00 +28531,19550620_9829,93535,32,45000,MORTGAGE,3.0,DEBTCONSOLIDATION,5000,5.79,0,2021-01-01 15:58:58.734000+00:00,2021-01-01 15:58:58.734000+00:00 +21157,19641113_3550,54944,24,38000,OWN,6.0,MEDICAL,1000,10.08,0,2021-04-05 15:40:28.450000+00:00,2021-04-05 15:40:28.450000+00:00 +27970,19970424_7944,13167,35,17000,RENT,0.0,MEDICAL,4750,9.32,1,2021-01-08 19:35:30.263000+00:00,2021-01-08 19:35:30.263000+00:00 +16912,19910624_1983,91768,25,46000,RENT,5.0,EDUCATION,7000,10.25,0,2021-05-29 18:12:41.139000+00:00,2021-05-29 18:12:41.139000+00:00 +29832,19901116_1769,36480,28,75000,RENT,8.0,DEBTCONSOLIDATION,7200,9.88,0,2020-12-16 02:00:35.029000+00:00,2020-12-16 02:00:35.029000+00:00 +17856,19930307_9563,75023,24,60000,MORTGAGE,8.0,VENTURE,12000,9.62,0,2021-05-17 17:26:37.498000+00:00,2021-05-17 17:26:37.498000+00:00 +25214,19481123_7671,99587,24,48000,OWN,5.0,VENTURE,4400,5.99,0,2021-02-12 22:38:47.504000+00:00,2021-02-12 22:38:47.504000+00:00 +29497,19831226_5835,77272,29,52800,MORTGAGE,7.0,EDUCATION,25475,16.29,0,2020-12-20 08:29:07.974000+00:00,2020-12-20 08:29:07.974000+00:00 +15260,19760601_5360,5661,24,120000,RENT,0.0,VENTURE,5775,6.17,0,2021-06-19 19:33:17.511000+00:00,2021-06-19 19:33:17.511000+00:00 +37816,19860321_5183,62963,50,116000,MORTGAGE,22.0,PERSONAL,5000,10.25,0,2020-09-05 07:43:13.384000+00:00,2020-09-05 07:43:13.384000+00:00 +38026,19970827_4324,39095,47,187000,MORTGAGE,5.0,HOMEIMPROVEMENT,14000,8.9,0,2020-09-02 15:28:54.523000+00:00,2020-09-02 15:28:54.523000+00:00 +32636,19560501_9346,40111,28,42000,RENT,9.0,MEDICAL,12250,14.59,1,2020-11-10 08:16:18.620000+00:00,2020-11-10 08:16:18.620000+00:00 +12122,19770809_4812,52342,23,24000,RENT,2.0,MEDICAL,2800,11.49,1,2021-07-29 19:27:45.633000+00:00,2021-07-29 19:27:45.633000+00:00 +14438,19941002_9685,3766,23,43600,MORTGAGE,4.0,EDUCATION,7000,7.49,0,2021-06-30 07:00:10.767000+00:00,2021-06-30 07:00:10.767000+00:00 +15951,19750905_2595,96793,24,50000,MORTGAGE,2.0,VENTURE,12500,9.32,0,2021-06-11 00:10:45.736000+00:00,2021-06-11 00:10:45.736000+00:00 +18152,19830813_8953,13083,22,27000,RENT,6.0,DEBTCONSOLIDATION,5000,9.32,0,2021-05-13 22:53:52.627000+00:00,2021-05-13 22:53:52.627000+00:00 +20349,19620624_1342,43212,26,75873,MORTGAGE,6.0,PERSONAL,1200,10.25,0,2021-04-15 22:50:24.449000+00:00,2021-04-15 22:50:24.449000+00:00 +16662,19960313_6268,95444,25,75000,RENT,5.0,PERSONAL,6400,15.99,0,2021-06-01 22:41:09.307000+00:00,2021-06-01 22:41:09.307000+00:00 +11798,19941022_2374,98363,26,30000,MORTGAGE,0.0,EDUCATION,4000,7.14,0,2021-08-02 22:34:25.019000+00:00,2021-08-02 22:34:25.019000+00:00 +33726,19601012_5125,90608,28,91800,MORTGAGE,6.0,MEDICAL,10000,16.89,1,2020-10-27 10:50:35.008000+00:00,2020-10-27 10:50:35.008000+00:00 +30945,19550115_3170,28594,33,59000,RENT,17.0,MEDICAL,9600,9.91,0,2020-12-01 21:32:43.067000+00:00,2020-12-01 21:32:43.067000+00:00 +25354,19930815_1988,32238,23,47233,RENT,7.0,DEBTCONSOLIDATION,5000,11.36,0,2021-02-11 03:49:14.930000+00:00,2021-02-11 03:49:14.930000+00:00 +33583,19570114_5191,34134,32,27500,OWN,1.0,VENTURE,5000,14.59,0,2020-10-29 06:35:11.280000+00:00,2020-10-29 06:35:11.280000+00:00 +35932,19730604_8828,78104,37,44000,RENT,0.0,PERSONAL,1700,10.59,1,2020-09-29 08:01:55.736000+00:00,2020-09-29 08:01:55.736000+00:00 +10065,19530901_1621,22182,21,12000,OWN,6.0,EDUCATION,3000,13.61,1,2021-08-25 00:41:41.237000+00:00,2021-08-25 00:41:41.237000+00:00 +37999,19481128_5369,93673,37,160000,MORTGAGE,14.0,HOMEIMPROVEMENT,10000,7.51,0,2020-09-02 23:44:27.805000+00:00,2020-09-02 23:44:27.805000+00:00 +12667,19661216_1173,95553,21,35004,OWN,5.0,VENTURE,1500,9.62,0,2021-07-22 20:44:53.827000+00:00,2021-07-22 20:44:53.827000+00:00 +32783,19660617_5520,52531,31,92000,MORTGAGE,2.0,HOMEIMPROVEMENT,3500,5.79,0,2020-11-08 11:18:17.417000+00:00,2020-11-08 11:18:17.417000+00:00 +18641,19530822_8321,85204,22,40000,RENT,2.0,EDUCATION,9000,10.59,0,2021-05-07 17:18:49.851000+00:00,2021-05-07 17:18:49.851000+00:00 +36453,19940823_7643,76307,43,71015,RENT,8.0,VENTURE,5000,11.14,0,2020-09-22 16:39:33.515000+00:00,2020-09-22 16:39:33.515000+00:00 +38272,19951202_6841,32777,44,61000,RENT,2.0,DEBTCONSOLIDATION,11000,16.02,1,2020-08-30 12:13:51.286000+00:00,2020-08-30 12:13:51.286000+00:00 +15711,19550503_7933,13108,26,44000,MORTGAGE,6.0,EDUCATION,10000,5.42,1,2021-06-14 01:35:41.577000+00:00,2021-06-14 01:35:41.577000+00:00 +38246,19610623_9145,53179,37,24000,RENT,2.0,DEBTCONSOLIDATION,5000,14.65,0,2020-08-30 20:11:03.335000+00:00,2020-08-30 20:11:03.335000+00:00 +31577,19871210_3692,39474,35,60000,RENT,7.0,PERSONAL,10000,11.11,0,2020-11-23 20:13:04.018000+00:00,2020-11-23 20:13:04.018000+00:00 +36675,19790922_3586,44093,40,68000,RENT,12.0,HOMEIMPROVEMENT,7000,7.51,0,2020-09-19 20:44:59.862000+00:00,2020-09-19 20:44:59.862000+00:00 +34689,19960715_8599,64506,30,71000,RENT,2.0,PERSONAL,12000,8.9,0,2020-10-15 04:15:47.946000+00:00,2020-10-15 04:15:47.946000+00:00 +30849,19660326_3937,78147,28,19200,RENT,0.0,MEDICAL,9250,14.22,1,2020-12-03 02:54:41.403000+00:00,2020-12-03 02:54:41.403000+00:00 +23291,19920505_5607,75633,26,14400,RENT,1.0,PERSONAL,1500,9.25,0,2021-03-09 10:53:17.931000+00:00,2021-03-09 10:53:17.931000+00:00 +10598,19640113_6316,31795,23,54504,RENT,1.0,PERSONAL,20000,16.7,1,2021-08-18 05:39:04.224000+00:00,2021-08-18 05:39:04.224000+00:00 +27250,19980601_1483,91977,28,80000,RENT,7.0,VENTURE,3025,9.99,0,2021-01-17 23:50:17.786000+00:00,2021-01-17 23:50:17.786000+00:00 +34031,19810306_4085,51301,28,57000,RENT,2.0,VENTURE,15000,14.11,1,2020-10-23 13:32:39.044000+00:00,2020-10-23 13:32:39.044000+00:00 +29704,19830721_3688,48470,33,36000,RENT,5.0,DEBTCONSOLIDATION,7000,5.79,1,2020-12-17 17:09:52.811000+00:00,2020-12-17 17:09:52.811000+00:00 +34918,19611012_2049,55805,29,127000,MORTGAGE,1.0,MEDICAL,24250,11.36,0,2020-10-12 06:12:45.665000+00:00,2020-10-12 06:12:45.665000+00:00 +35076,19720423_7339,2817,28,60000,MORTGAGE,5.0,PERSONAL,6000,10.99,0,2020-10-10 05:52:50.903000+00:00,2020-10-10 05:52:50.903000+00:00 +28135,19471207_8523,45695,30,93500,RENT,3.0,EDUCATION,9925,12.09,0,2021-01-06 17:07:06.872000+00:00,2021-01-06 17:07:06.872000+00:00 +27291,19800217_9841,91615,32,35000,MORTGAGE,9.0,VENTURE,12000,9.63,0,2021-01-17 11:17:47.246000+00:00,2021-01-17 11:17:47.246000+00:00 +20569,19650605_8562,32465,22,72644,MORTGAGE,3.0,PERSONAL,5900,7.49,1,2021-04-13 03:32:33.261000+00:00,2021-04-13 03:32:33.261000+00:00 +33370,19840427_4080,64746,27,106000,MORTGAGE,11.0,HOMEIMPROVEMENT,4000,11.71,0,2020-10-31 23:44:33.839000+00:00,2020-10-31 23:44:33.839000+00:00 +18712,19710706_6125,19057,25,65000,MORTGAGE,1.0,PERSONAL,12000,7.49,0,2021-05-06 19:35:42.331000+00:00,2021-05-06 19:35:42.331000+00:00 +17231,19891012_7651,28515,26,36000,RENT,10.0,VENTURE,7500,10.59,0,2021-05-25 16:37:47.917000+00:00,2021-05-25 16:37:47.917000+00:00 +36754,19531122_7874,43783,36,41000,RENT,1.0,PERSONAL,7000,9.63,0,2020-09-18 20:35:02.481000+00:00,2020-09-18 20:35:02.481000+00:00 +34050,19970304_6968,28449,30,131004,MORTGAGE,14.0,VENTURE,5000,8.49,0,2020-10-23 07:43:55.623000+00:00,2020-10-23 07:43:55.623000+00:00 +21519,19741217_9741,77342,25,96000,RENT,1.0,HOMEIMPROVEMENT,12000,9.99,0,2021-04-01 00:56:22.224000+00:00,2021-04-01 00:56:22.224000+00:00 +20961,19530119_2516,38506,24,81996,MORTGAGE,4.0,EDUCATION,14000,7.88,0,2021-04-08 03:37:50.054000+00:00,2021-04-08 03:37:50.054000+00:00 +21544,19920310_7740,78402,24,65450,MORTGAGE,8.0,MEDICAL,5000,16.77,1,2021-03-31 17:17:31.407000+00:00,2021-03-31 17:17:31.407000+00:00 +37414,19790408_2169,72131,49,74000,MORTGAGE,20.0,DEBTCONSOLIDATION,12000,17.99,1,2020-09-10 10:41:28.918000+00:00,2020-09-10 10:41:28.918000+00:00 +24125,19540902_7647,7061,23,78000,MORTGAGE,7.0,DEBTCONSOLIDATION,4200,13.06,0,2021-02-26 19:46:09.883000+00:00,2021-02-26 19:46:09.883000+00:00 +28760,20011207_6345,85630,34,47000,OWN,8.0,VENTURE,14000,9.99,0,2020-12-29 17:55:56.453000+00:00,2020-12-29 17:55:56.453000+00:00 +34067,19470104_5144,4780,30,134500,MORTGAGE,9.0,DEBTCONSOLIDATION,24000,15.96,0,2020-10-23 02:31:54.668000+00:00,2020-10-23 02:31:54.668000+00:00 +36792,19831030_9701,61548,42,40000,RENT,0.0,DEBTCONSOLIDATION,7200,10.75,0,2020-09-18 08:57:35.639000+00:00,2020-09-18 08:57:35.639000+00:00 +19013,19590207_8723,80002,26,66000,MORTGAGE,6.0,DEBTCONSOLIDATION,7000,9.63,0,2021-05-02 23:31:11.297000+00:00,2021-05-02 23:31:11.297000+00:00 +24540,19710506_8913,29056,22,38000,MORTGAGE,6.0,DEBTCONSOLIDATION,4500,5.79,0,2021-02-21 12:49:18.324000+00:00,2021-02-21 12:49:18.324000+00:00 +17681,19580304_8660,42041,22,31200,RENT,0.0,PERSONAL,8000,14.3,1,2021-05-19 22:58:33.215000+00:00,2021-05-19 22:58:33.215000+00:00 +16069,19800304_9440,46260,21,50460,OWN,4.0,VENTURE,6000,13.49,0,2021-06-09 12:05:00.281000+00:00,2021-06-09 12:05:00.281000+00:00 +35548,19570818_6418,70749,28,54000,RENT,2.0,HOMEIMPROVEMENT,12000,15.31,1,2020-10-04 05:29:49.082000+00:00,2020-10-04 05:29:49.082000+00:00 +35379,19520406_3523,25565,32,100000,RENT,7.0,DEBTCONSOLIDATION,14400,13.35,0,2020-10-06 09:11:37.403000+00:00,2020-10-06 09:11:37.403000+00:00 +26165,19761103_7537,96161,27,66000,RENT,3.0,DEBTCONSOLIDATION,20000,10.62,0,2021-01-31 19:44:15.234000+00:00,2021-01-31 19:44:15.234000+00:00 +35769,19831110_4953,75206,39,58000,RENT,5.0,EDUCATION,21000,10.83,1,2020-10-01 09:53:36.662000+00:00,2020-10-01 09:53:36.662000+00:00 +26066,19920908_6532,27896,28,18000,OWN,2.0,MEDICAL,6350,13.57,1,2021-02-02 02:01:17.268000+00:00,2021-02-02 02:01:17.268000+00:00 +17450,19821018_1579,97301,23,58000,OWN,4.0,MEDICAL,15000,10.25,0,2021-05-22 21:38:17.962000+00:00,2021-05-22 21:38:17.962000+00:00 +38153,19630811_9728,50533,37,22800,OWN,18.0,EDUCATION,7000,6.03,0,2020-09-01 00:37:57.974000+00:00,2020-09-01 00:37:57.974000+00:00 +16275,19490917_1398,12498,24,82000,RENT,8.0,EDUCATION,7000,10.0,0,2021-06-06 21:04:06.350000+00:00,2021-06-06 21:04:06.350000+00:00 +30884,19930919_7687,60190,32,70000,RENT,1.0,DEBTCONSOLIDATION,9450,10.83,0,2020-12-02 16:12:18.259000+00:00,2020-12-02 16:12:18.259000+00:00 +31709,19680505_6620,51439,30,75000,MORTGAGE,2.0,HOMEIMPROVEMENT,21000,14.35,0,2020-11-22 03:50:21.306000+00:00,2020-11-22 03:50:21.306000+00:00 +20274,19780130_4840,49922,24,75000,MORTGAGE,1.0,EDUCATION,2000,8.94,0,2021-04-16 21:46:56.899000+00:00,2021-04-16 21:46:56.899000+00:00 +38046,19680817_3924,72044,36,290000,MORTGAGE,6.0,PERSONAL,25000,15.65,0,2020-09-02 09:21:49.870000+00:00,2020-09-02 09:21:49.870000+00:00 +14726,19940301_5862,8092,22,45000,MORTGAGE,6.0,EDUCATION,10000,7.88,0,2021-06-26 14:54:15.758000+00:00,2021-06-26 14:54:15.758000+00:00 +36579,19601202_7706,57567,39,44500,RENT,5.0,MEDICAL,6000,7.88,0,2020-09-21 02:06:58.198000+00:00,2020-09-21 02:06:58.198000+00:00 +10232,19730313_4796,46990,24,180000,OWN,8.0,EDUCATION,21000,11.48,0,2021-08-22 21:36:35.381000+00:00,2021-08-22 21:36:35.381000+00:00 +21221,19740801_6924,19086,23,85000,MORTGAGE,1.0,VENTURE,21400,13.49,0,2021-04-04 20:05:49.560000+00:00,2021-04-04 20:05:49.560000+00:00 +13055,19810707_4516,60130,25,35220,RENT,2.0,DEBTCONSOLIDATION,10500,7.29,0,2021-07-17 22:03:35.551000+00:00,2021-07-17 22:03:35.551000+00:00 +35013,19820120_9786,44615,31,89000,RENT,1.0,MEDICAL,10000,10.99,0,2020-10-11 01:09:08.561000+00:00,2020-10-11 01:09:08.561000+00:00 +37421,19640122_4276,28390,36,33600,RENT,3.0,EDUCATION,12000,11.36,1,2020-09-10 08:33:00.289000+00:00,2020-09-10 08:33:00.289000+00:00 +31374,19951125_2412,68134,31,47000,RENT,5.0,EDUCATION,10000,11.99,0,2020-11-26 10:18:54.251000+00:00,2020-11-26 10:18:54.251000+00:00 +11780,19531111_7277,76861,23,75000,RENT,0.0,VENTURE,2200,7.9,0,2021-08-03 04:04:47.207000+00:00,2021-08-03 04:04:47.207000+00:00 +16180,19861210_1873,15234,25,60000,RENT,0.0,MEDICAL,7000,9.25,0,2021-06-08 02:07:43.454000+00:00,2021-06-08 02:07:43.454000+00:00 +23721,19591009_8668,83544,26,150000,MORTGAGE,8.0,MEDICAL,35000,15.96,0,2021-03-03 23:21:07.882000+00:00,2021-03-03 23:21:07.882000+00:00 +29689,20010219_3501,23882,27,55000,MORTGAGE,5.0,PERSONAL,5000,6.62,0,2020-12-17 21:45:11.301000+00:00,2020-12-17 21:45:11.301000+00:00 +20642,19560101_4944,22435,25,80000,MORTGAGE,4.0,MEDICAL,25000,13.49,0,2021-04-12 05:12:43.276000+00:00,2021-04-12 05:12:43.276000+00:00 +21440,19640130_1657,52031,26,86004,RENT,0.0,EDUCATION,12000,12.99,0,2021-04-02 01:06:19.605000+00:00,2021-04-02 01:06:19.605000+00:00 +25243,19970111_2119,94005,25,38000,RENT,9.0,EDUCATION,4800,11.71,0,2021-02-12 13:46:31.757000+00:00,2021-02-12 13:46:31.757000+00:00 +37463,19810929_8057,68144,38,82000,OWN,4.0,HOMEIMPROVEMENT,10000,11.99,0,2020-09-09 19:42:08.517000+00:00,2020-09-09 19:42:08.517000+00:00 +34492,19940607_9238,92027,29,250000,MORTGAGE,13.0,EDUCATION,20000,13.79,0,2020-10-17 16:31:30.782000+00:00,2020-10-17 16:31:30.782000+00:00 +15744,19510408_7251,49229,23,50000,RENT,4.0,DEBTCONSOLIDATION,6000,11.49,0,2021-06-13 15:30:00.899000+00:00,2021-06-13 15:30:00.899000+00:00 +25487,19520915_1114,97004,24,85000,RENT,5.0,MEDICAL,25000,10.62,0,2021-02-09 11:08:10.985000+00:00,2021-02-09 11:08:10.985000+00:00 +32452,19710506_3801,63440,32,80000,RENT,3.0,HOMEIMPROVEMENT,12000,6.62,0,2020-11-12 16:33:25.431000+00:00,2020-11-12 16:33:25.431000+00:00 +27098,19601130_3346,63361,33,41277,RENT,3.0,EDUCATION,3000,10.0,1,2021-01-19 22:20:05.152000+00:00,2021-01-19 22:20:05.152000+00:00 +13367,19471122_6915,12918,23,36300,RENT,0.0,VENTURE,4000,7.68,0,2021-07-13 22:37:10.958000+00:00,2021-07-13 22:37:10.958000+00:00 +17982,19901001_7173,97106,23,54000,MORTGAGE,7.0,DEBTCONSOLIDATION,5000,14.96,1,2021-05-16 02:54:02.181000+00:00,2021-05-16 02:54:02.181000+00:00 +17861,19861201_1241,99503,24,60000,MORTGAGE,2.0,MEDICAL,9700,8.88,0,2021-05-17 15:54:51.334000+00:00,2021-05-17 15:54:51.334000+00:00 +16776,19630530_3579,17584,24,33600,RENT,0.0,PERSONAL,7000,13.61,0,2021-05-31 11:48:48.782000+00:00,2021-05-31 11:48:48.782000+00:00 +31541,19940404_4477,14519,34,57000,RENT,1.0,EDUCATION,10000,11.14,0,2020-11-24 07:13:48.395000+00:00,2020-11-24 07:13:48.395000+00:00 +27264,19850319_6145,63135,27,33600,RENT,4.0,PERSONAL,3200,11.99,0,2021-01-17 19:33:20.529000+00:00,2021-01-17 19:33:20.529000+00:00 +22606,19710526_9600,1450,23,105000,MORTGAGE,4.0,VENTURE,7200,7.51,0,2021-03-18 04:25:42.310000+00:00,2021-03-18 04:25:42.310000+00:00 +13522,19680327_2208,71306,23,67450,RENT,8.0,EDUCATION,4000,6.76,0,2021-07-11 23:12:19.894000+00:00,2021-07-11 23:12:19.894000+00:00 +38331,19660315_5107,5079,44,95000,MORTGAGE,4.0,EDUCATION,10000,10.95,0,2020-08-29 18:10:58.558000+00:00,2020-08-29 18:10:58.558000+00:00 +29254,19900816_4754,27020,28,75000,RENT,4.0,EDUCATION,6000,6.92,0,2020-12-23 10:49:07.513000+00:00,2020-12-23 10:49:07.513000+00:00 +38435,19511121_3548,3745,60,29000,RENT,0.0,HOMEIMPROVEMENT,2500,15.33,1,2020-08-28 10:22:10.361000+00:00,2020-08-28 10:22:10.361000+00:00 +33423,19771004_1938,77571,32,108202,MORTGAGE,6.0,MEDICAL,9600,13.79,0,2020-10-31 07:31:48.508000+00:00,2020-10-31 07:31:48.508000+00:00 +12897,19751229_7032,22733,26,36000,MORTGAGE,3.0,HOMEIMPROVEMENT,5400,7.51,0,2021-07-19 22:23:30.313000+00:00,2021-07-19 22:23:30.313000+00:00 +22779,19621211_3311,8518,25,109000,MORTGAGE,5.0,VENTURE,5000,8.49,0,2021-03-15 23:30:29.058000+00:00,2021-03-15 23:30:29.058000+00:00 +38173,19700917_6945,63071,46,60000,MORTGAGE,7.0,PERSONAL,3600,6.99,0,2020-08-31 18:30:53.320000+00:00,2020-08-31 18:30:53.320000+00:00 +25226,20010514_4088,68760,23,48000,OWN,8.0,VENTURE,6000,12.87,0,2021-02-12 18:58:32.712000+00:00,2021-02-12 18:58:32.712000+00:00 +12001,19571119_4668,11548,22,31200,MORTGAGE,2.0,DEBTCONSOLIDATION,1050,7.51,1,2021-07-31 08:28:34.786000+00:00,2021-07-31 08:28:34.786000+00:00 +27374,19730520_3988,62567,35,36000,OWN,1.0,VENTURE,3925,9.99,0,2021-01-16 09:54:24.935000+00:00,2021-01-16 09:54:24.935000+00:00 +23211,19951024_2900,57446,25,25000,RENT,1.0,DEBTCONSOLIDATION,1600,9.99,0,2021-03-10 11:21:36.544000+00:00,2021-03-10 11:21:36.544000+00:00 +12316,19540218_3486,40159,26,48000,RENT,4.0,MEDICAL,3000,10.14,0,2021-07-27 08:07:06.495000+00:00,2021-07-27 08:07:06.495000+00:00 +22487,19840625_1648,37923,24,100800,MORTGAGE,4.0,EDUCATION,21000,11.49,0,2021-03-19 16:49:48.998000+00:00,2021-03-19 16:49:48.998000+00:00 +28001,19690113_2819,11705,30,31000,RENT,1.0,MEDICAL,4800,13.43,0,2021-01-08 10:06:32.050000+00:00,2021-01-08 10:06:32.050000+00:00 +29190,19751225_4092,28757,27,50000,MORTGAGE,2.0,HOMEIMPROVEMENT,10750,13.48,0,2020-12-24 06:23:46.404000+00:00,2020-12-24 06:23:46.404000+00:00 +38324,19670302_8138,22565,42,75000,RENT,6.0,MEDICAL,17000,7.9,0,2020-08-29 20:19:27.187000+00:00,2020-08-29 20:19:27.187000+00:00 +31962,19790712_7638,38850,28,79000,MORTGAGE,4.0,VENTURE,2000,16.0,0,2020-11-18 22:26:49.440000+00:00,2020-11-18 22:26:49.440000+00:00 +33105,19630813_8026,30153,32,63000,RENT,11.0,EDUCATION,14000,6.91,0,2020-11-04 08:48:20.497000+00:00,2020-11-04 08:48:20.497000+00:00 +34924,19500627_4737,79097,30,219300,MORTGAGE,7.0,MEDICAL,35000,19.69,1,2020-10-12 04:22:38.269000+00:00,2020-10-12 04:22:38.269000+00:00 +38174,19490818_7594,30903,39,201000,RENT,6.0,VENTURE,13500,11.49,0,2020-08-31 18:12:32.088000+00:00,2020-08-31 18:12:32.088000+00:00 +18412,19610509_4145,13672,24,62677,MORTGAGE,2.0,MEDICAL,6000,10.2,0,2021-05-10 15:21:52.132000+00:00,2021-05-10 15:21:52.132000+00:00 +31920,19670809_3020,43462,29,60000,RENT,2.0,VENTURE,11200,14.22,0,2020-11-19 11:17:41.212000+00:00,2020-11-19 11:17:41.212000+00:00 +17567,19670311_1481,12723,26,59500,MORTGAGE,9.0,VENTURE,12000,6.62,0,2021-05-21 09:50:53.739000+00:00,2021-05-21 09:50:53.739000+00:00 +29112,19641010_2875,71030,29,50000,OWN,6.0,MEDICAL,4000,5.42,0,2020-12-25 06:15:22.553000+00:00,2020-12-25 06:15:22.553000+00:00 +16842,19660820_4704,30184,23,40000,RENT,4.0,MEDICAL,7000,11.58,0,2021-05-30 15:37:27.426000+00:00,2021-05-30 15:37:27.426000+00:00 +11392,19960903_3617,26105,21,36000,RENT,0.0,EDUCATION,1500,10.37,0,2021-08-08 02:46:05.483000+00:00,2021-08-08 02:46:05.483000+00:00 +31284,19511213_6264,77963,35,70000,OWN,6.0,VENTURE,17000,9.88,0,2020-11-27 13:50:45.191000+00:00,2020-11-27 13:50:45.191000+00:00 +10126,19530429_3321,32907,23,52000,RENT,1.0,PERSONAL,25000,13.22,1,2021-08-24 06:02:06.045000+00:00,2021-08-24 06:02:06.045000+00:00 +29078,20010225_3064,61744,30,50000,MORTGAGE,2.0,EDUCATION,3975,10.99,0,2020-12-25 16:39:24.463000+00:00,2020-12-25 16:39:24.463000+00:00 +14949,19460918_9720,55768,22,114000,RENT,2.0,VENTURE,5000,15.31,1,2021-06-23 18:41:20.872000+00:00,2021-06-23 18:41:20.872000+00:00 +23066,19890804_1120,13668,21,117000,MORTGAGE,3.0,PERSONAL,4800,14.54,0,2021-03-12 07:42:55.282000+00:00,2021-03-12 07:42:55.282000+00:00 +21248,19710629_3106,64427,26,41000,RENT,8.0,DEBTCONSOLIDATION,3000,12.42,0,2021-04-04 11:50:16.277000+00:00,2021-04-04 11:50:16.277000+00:00 +30445,19701002_3781,8901,30,24000,RENT,14.0,EDUCATION,5000,11.11,1,2020-12-08 06:29:39.402000+00:00,2020-12-08 06:29:39.402000+00:00 +16620,19620312_4269,33493,22,54000,MORTGAGE,5.0,MEDICAL,7000,10.65,0,2021-06-02 11:32:01.079000+00:00,2021-06-02 11:32:01.079000+00:00 +29454,19810930_9111,2539,33,30000,RENT,0.0,PERSONAL,6500,8.49,0,2020-12-20 21:38:20.979000+00:00,2020-12-20 21:38:20.979000+00:00 +14478,19880606_6310,62207,24,44000,MORTGAGE,8.0,EDUCATION,2000,5.79,0,2021-06-29 18:46:01.460000+00:00,2021-06-29 18:46:01.460000+00:00 +19275,19640908_3903,50650,23,68500,MORTGAGE,7.0,EDUCATION,4200,11.66,0,2021-04-29 15:22:28.337000+00:00,2021-04-29 15:22:28.337000+00:00 +27941,19521126_2255,31758,28,49000,RENT,12.0,HOMEIMPROVEMENT,4500,14.27,1,2021-01-09 04:27:46.010000+00:00,2021-01-09 04:27:46.010000+00:00 +17106,19910918_5172,56375,25,67500,RENT,2.0,EDUCATION,7200,7.88,0,2021-05-27 06:52:02.001000+00:00,2021-05-27 06:52:02.001000+00:00 +17155,19970507_5690,55448,24,56000,MORTGAGE,3.0,EDUCATION,15000,8.49,0,2021-05-26 15:52:41.600000+00:00,2021-05-26 15:52:41.600000+00:00 +30375,19590310_9111,10451,27,60000,MORTGAGE,3.0,HOMEIMPROVEMENT,10000,12.53,0,2020-12-09 03:54:25.689000+00:00,2020-12-09 03:54:25.689000+00:00 +17038,19531129_4322,30065,26,38400,RENT,2.0,MEDICAL,7200,9.91,0,2021-05-28 03:40:05.822000+00:00,2021-05-28 03:40:05.822000+00:00 +20553,19671202_7605,65473,25,82000,RENT,9.0,PERSONAL,11200,5.42,0,2021-04-13 08:26:12.984000+00:00,2021-04-13 08:26:12.984000+00:00 +10350,19610522_3933,90007,23,103000,RENT,6.0,PERSONAL,24250,15.7,0,2021-08-21 09:30:49.926000+00:00,2021-08-21 09:30:49.926000+00:00 +22845,19770601_6229,83858,23,110000,MORTGAGE,8.0,VENTURE,7500,13.72,0,2021-03-15 03:19:07.702000+00:00,2021-03-15 03:19:07.702000+00:00 +29093,19680125_9116,2467,28,50000,RENT,0.0,PERSONAL,6000,10.59,0,2020-12-25 12:04:05.973000+00:00,2020-12-25 12:04:05.973000+00:00 +27800,19921010_6299,51638,30,39962,MORTGAGE,5.0,DEBTCONSOLIDATION,3200,9.7,0,2021-01-10 23:35:39.817000+00:00,2021-01-10 23:35:39.817000+00:00 +14325,19590630_8466,87571,22,43000,OWN,5.0,VENTURE,3500,11.49,0,2021-07-01 17:34:10.059000+00:00,2021-07-01 17:34:10.059000+00:00 +21727,19701030_7635,92562,24,78000,MORTGAGE,0.0,DEBTCONSOLIDATION,19500,15.31,1,2021-03-29 09:18:45.828000+00:00,2021-03-29 09:18:45.828000+00:00 +14243,19700209_7465,93463,25,42240,OWN,10.0,HOMEIMPROVEMENT,8000,6.62,0,2021-07-02 18:39:11.138000+00:00,2021-07-02 18:39:11.138000+00:00 +13442,19980326_7550,7024,24,44000,RENT,1.0,DEBTCONSOLIDATION,4000,17.58,1,2021-07-12 23:40:38.507000+00:00,2021-07-12 23:40:38.507000+00:00 +19895,19620609_6991,98331,25,66800,MORTGAGE,3.0,DEBTCONSOLIDATION,12000,9.63,1,2021-04-21 17:43:04.081000+00:00,2021-04-21 17:43:04.081000+00:00 +11876,19530506_9333,68464,23,56000,RENT,2.0,MEDICAL,2400,8.9,0,2021-08-01 22:42:48.870000+00:00,2021-08-01 22:42:48.870000+00:00 +28213,19450216_7637,70121,27,36000,MORTGAGE,9.0,DEBTCONSOLIDATION,15200,16.35,1,2021-01-05 17:15:30.724000+00:00,2021-01-05 17:15:30.724000+00:00 +26120,19481212_5954,48325,30,20000,OWN,14.0,HOMEIMPROVEMENT,3800,6.99,0,2021-02-01 09:30:10.704000+00:00,2021-02-01 09:30:10.704000+00:00 +14753,19890330_3512,24747,21,59800,RENT,5.0,PERSONAL,5000,11.36,0,2021-06-26 06:38:42.476000+00:00,2021-06-26 06:38:42.476000+00:00 +14922,20010124_6565,73051,22,39600,MORTGAGE,6.0,DEBTCONSOLIDATION,4650,10.28,1,2021-06-24 02:56:54.154000+00:00,2021-06-24 02:56:54.154000+00:00 +27956,19560828_9073,44702,34,40000,OWN,18.0,MEDICAL,8000,11.36,0,2021-01-08 23:52:27.520000+00:00,2021-01-08 23:52:27.520000+00:00 +21080,19990112_3904,83607,24,25000,RENT,3.0,EDUCATION,3000,8.32,0,2021-04-06 15:13:43.366000+00:00,2021-04-06 15:13:43.366000+00:00 +34505,19940217_4038,87506,27,290000,MORTGAGE,0.0,MEDICAL,7875,9.99,0,2020-10-17 12:32:54.758000+00:00,2020-10-17 12:32:54.758000+00:00 +12169,19600716_5309,10583,25,17400,RENT,0.0,EDUCATION,3000,11.83,1,2021-07-29 05:05:07.698000+00:00,2021-07-29 05:05:07.698000+00:00 +12991,19930420_4807,54227,22,36480,RENT,2.0,VENTURE,10800,8.88,0,2021-07-18 17:38:14.442000+00:00,2021-07-18 17:38:14.442000+00:00 +13441,19450626_5454,17846,26,33660,MORTGAGE,0.0,DEBTCONSOLIDATION,4500,5.99,1,2021-07-12 23:58:59.740000+00:00,2021-07-12 23:58:59.740000+00:00 +28049,19880421_9596,6053,28,56000,RENT,5.0,DEBTCONSOLIDATION,4800,16.45,1,2021-01-07 19:25:32.882000+00:00,2021-01-07 19:25:32.882000+00:00 +15961,19640219_1473,27922,24,69996,RENT,0.0,HOMEIMPROVEMENT,6000,13.06,0,2021-06-10 21:07:13.409000+00:00,2021-06-10 21:07:13.409000+00:00 +30376,19460103_2268,19456,27,60000,MORTGAGE,3.0,PERSONAL,6000,11.48,0,2020-12-09 03:36:04.456000+00:00,2020-12-09 03:36:04.456000+00:00 +11183,19750506_9991,86446,23,28600,RENT,7.0,EDUCATION,1000,7.9,0,2021-08-10 18:42:03.111000+00:00,2021-08-10 18:42:03.111000+00:00 +36546,19730920_9744,85344,48,42000,MORTGAGE,3.0,DEBTCONSOLIDATION,14400,12.87,1,2020-09-21 12:12:38.876000+00:00,2020-09-21 12:12:38.876000+00:00 +17630,19900917_8780,72064,23,60000,MORTGAGE,7.0,MEDICAL,7000,7.9,0,2021-05-20 14:34:36.081000+00:00,2021-05-20 14:34:36.081000+00:00 +22782,19540425_5777,37334,25,109000,MORTGAGE,5.0,DEBTCONSOLIDATION,15000,10.25,0,2021-03-15 22:35:25.360000+00:00,2021-03-15 22:35:25.360000+00:00 +31512,19850324_5443,96781,32,73000,MORTGAGE,7.0,PERSONAL,9600,7.9,0,2020-11-24 16:06:04.142000+00:00,2020-11-24 16:06:04.142000+00:00 +10133,19790915_8427,28208,22,210000,MORTGAGE,6.0,VENTURE,16000,10.62,0,2021-08-24 03:53:37.416000+00:00,2021-08-24 03:53:37.416000+00:00 +38216,19930114_5390,18013,42,31000,MORTGAGE,5.0,DEBTCONSOLIDATION,7200,11.99,0,2020-08-31 05:21:40.316000+00:00,2020-08-31 05:21:40.316000+00:00 +37408,19810108_3374,46552,36,80000,MORTGAGE,5.0,EDUCATION,20000,10.99,0,2020-09-10 12:31:36.314000+00:00,2020-09-10 12:31:36.314000+00:00 +31199,19481020_3358,24579,29,70000,OWN,13.0,PERSONAL,25000,15.62,0,2020-11-28 15:50:49.968000+00:00,2020-11-28 15:50:49.968000+00:00 +12171,19550213_1841,3218,21,17916,RENT,1.0,MEDICAL,3000,6.0,1,2021-07-29 04:28:25.232000+00:00,2021-07-29 04:28:25.232000+00:00 +30397,19491201_5532,85280,28,60000,OTHER,5.0,PERSONAL,16000,12.18,0,2020-12-08 21:10:38.570000+00:00,2020-12-08 21:10:38.570000+00:00 +13090,19590910_7782,39648,26,54996,RENT,1.0,HOMEIMPROVEMENT,10250,7.29,0,2021-07-17 11:21:12.408000+00:00,2021-07-17 11:21:12.408000+00:00 +21326,19480815_1572,6231,23,85000,MORTGAGE,7.0,EDUCATION,20000,13.22,0,2021-04-03 11:58:40.129000+00:00,2021-04-03 11:58:40.129000+00:00 +14825,19801201_5126,52747,23,66000,RENT,7.0,VENTURE,5000,10.39,0,2021-06-25 08:37:13.723000+00:00,2021-06-25 08:37:13.723000+00:00 +20819,19490205_2993,30629,23,80000,MORTGAGE,5.0,VENTURE,20000,14.96,0,2021-04-09 23:04:05.093000+00:00,2021-04-09 23:04:05.093000+00:00 +15902,19661225_5079,77223,21,21600,RENT,6.0,EDUCATION,7000,13.98,1,2021-06-11 15:10:06.137000+00:00,2021-06-11 15:10:06.137000+00:00 +36113,20010602_1772,41189,39,36000,MORTGAGE,1.0,PERSONAL,7125,7.9,0,2020-09-27 00:39:52.623000+00:00,2020-09-27 00:39:52.623000+00:00 +16378,19720521_7275,56373,26,28000,RENT,7.0,MEDICAL,6500,7.51,0,2021-06-05 13:33:39.385000+00:00,2021-06-05 13:33:39.385000+00:00 +16198,19840409_7269,16353,24,51500,MORTGAGE,2.0,VENTURE,6300,5.79,0,2021-06-07 20:37:21.266000+00:00,2021-06-07 20:37:21.266000+00:00 +29031,19500706_4853,96113,27,40800,RENT,11.0,PERSONAL,6000,7.66,0,2020-12-26 07:02:02.399000+00:00,2020-12-26 07:02:02.399000+00:00 +19072,19890405_6360,1721,26,66504,MORTGAGE,10.0,EDUCATION,12000,12.53,0,2021-05-02 05:28:18.570000+00:00,2021-05-02 05:28:18.570000+00:00 +11519,19721205_7203,78070,23,30000,RENT,0.0,PERSONAL,1925,12.18,0,2021-08-06 11:55:08.934000+00:00,2021-08-06 11:55:08.934000+00:00 +32154,19870217_4068,99115,27,36000,RENT,2.0,DEBTCONSOLIDATION,12000,14.09,1,2020-11-16 11:42:52.767000+00:00,2020-11-16 11:42:52.767000+00:00 +19246,19940529_9085,60181,26,32000,RENT,6.0,PERSONAL,10000,6.99,1,2021-04-30 00:14:44.085000+00:00,2021-04-30 00:14:44.085000+00:00 +15929,19800423_2210,1746,24,58668,RENT,8.0,MEDICAL,6000,15.05,1,2021-06-11 06:54:32.855000+00:00,2021-06-11 06:54:32.855000+00:00 +29011,19900411_4842,54626,31,49500,MORTGAGE,3.0,DEBTCONSOLIDATION,10000,10.75,0,2020-12-26 13:09:07.052000+00:00,2020-12-26 13:09:07.052000+00:00 +18403,19830916_6494,64074,22,150000,RENT,2.0,EDUCATION,8200,6.99,0,2021-05-10 18:07:03.226000+00:00,2021-05-10 18:07:03.226000+00:00 +26363,19500514_4765,65061,27,102616,RENT,4.0,MEDICAL,18000,13.99,1,2021-01-29 07:10:11.165000+00:00,2021-01-29 07:10:11.165000+00:00 +16973,19970526_4469,62278,22,54000,RENT,1.0,EDUCATION,7000,13.47,0,2021-05-28 23:33:05.946000+00:00,2021-05-28 23:33:05.946000+00:00 +28067,19841104_8948,97292,32,41000,MORTGAGE,2.0,PERSONAL,8000,15.05,0,2021-01-07 13:55:10.694000+00:00,2021-01-07 13:55:10.694000+00:00 +29793,19490930_4839,23148,35,32000,RENT,3.0,MEDICAL,7200,12.61,0,2020-12-16 13:56:23.104000+00:00,2020-12-16 13:56:23.104000+00:00 +10157,19961109_2655,93004,26,200000,MORTGAGE,4.0,EDUCATION,15000,14.79,0,2021-08-23 20:33:07.832000+00:00,2021-08-23 20:33:07.832000+00:00 +35214,19490711_1919,64640,30,28000,OWN,5.0,HOMEIMPROVEMENT,6300,11.99,0,2020-10-08 11:40:00.794000+00:00,2020-10-08 11:40:00.794000+00:00 +32555,19890416_8777,94579,28,99996,RENT,6.0,VENTURE,12000,13.61,0,2020-11-11 09:02:58.466000+00:00,2020-11-11 09:02:58.466000+00:00 +11741,19770911_6921,28386,22,32000,RENT,0.0,DEBTCONSOLIDATION,14000,13.49,1,2021-08-03 16:00:35.281000+00:00,2021-08-03 16:00:35.281000+00:00 +36337,19620401_9648,46031,36,30000,RENT,1.0,DEBTCONSOLIDATION,5000,11.14,0,2020-09-24 04:08:36.504000+00:00,2020-09-24 04:08:36.504000+00:00 +20205,19510318_7857,5461,22,75000,MORTGAGE,6.0,PERSONAL,9000,7.14,0,2021-04-17 18:53:21.953000+00:00,2021-04-17 18:53:21.953000+00:00 +29399,19491101_4166,45232,35,52000,MORTGAGE,7.0,DEBTCONSOLIDATION,7000,6.03,0,2020-12-21 14:27:48.776000+00:00,2020-12-21 14:27:48.776000+00:00 +14590,19940408_8669,6855,26,45000,MORTGAGE,4.0,PERSONAL,11000,8.9,0,2021-06-28 08:30:23.401000+00:00,2021-06-28 08:30:23.401000+00:00 +37570,19921013_2895,4062,39,90000,MORTGAGE,15.0,VENTURE,10500,7.66,0,2020-09-08 10:58:16.621000+00:00,2020-09-08 10:58:16.621000+00:00 +36789,19931224_9100,62054,38,55000,MORTGAGE,3.0,MEDICAL,14000,13.22,0,2020-09-18 09:52:39.337000+00:00,2020-09-18 09:52:39.337000+00:00 +24780,19871122_7489,2454,23,55000,MORTGAGE,4.0,VENTURE,8000,7.49,0,2021-02-18 11:24:22.483000+00:00,2021-02-18 11:24:22.483000+00:00 +37158,19720905_6281,49938,41,36000,RENT,5.0,DEBTCONSOLIDATION,10000,6.03,0,2020-09-13 17:00:04.481000+00:00,2020-09-13 17:00:04.481000+00:00 +27105,19660329_8158,11955,28,48876,RENT,5.0,PERSONAL,3000,14.59,0,2021-01-19 20:11:36.523000+00:00,2021-01-19 20:11:36.523000+00:00 +13991,19551019_7436,93457,25,41520,OWN,9.0,MEDICAL,4400,7.29,0,2021-07-05 23:44:21.771000+00:00,2021-07-05 23:44:21.771000+00:00 +14557,19510101_5183,93458,24,44600,MORTGAGE,5.0,MEDICAL,20000,11.89,0,2021-06-28 18:36:04.079000+00:00,2021-06-28 18:36:04.079000+00:00 +13350,19470423_6247,46171,25,35000,RENT,4.0,VENTURE,4000,16.29,0,2021-07-14 03:49:11.913000+00:00,2021-07-14 03:49:11.913000+00:00 +20048,19630330_4458,76044,22,45000,RENT,6.0,PERSONAL,4000,7.9,0,2021-04-19 18:54:55.483000+00:00,2021-04-19 18:54:55.483000+00:00 +29938,19841006_5546,35772,27,45000,RENT,0.0,PERSONAL,7500,12.73,0,2020-12-14 17:35:04.366000+00:00,2020-12-14 17:35:04.366000+00:00 +24685,19830202_7128,92122,26,52000,MORTGAGE,6.0,PERSONAL,3300,10.99,0,2021-02-19 16:27:59.587000+00:00,2021-02-19 16:27:59.587000+00:00 +30901,19730906_2494,16405,27,19498,RENT,3.0,HOMEIMPROVEMENT,9575,6.62,1,2020-12-02 11:00:17.304000+00:00,2020-12-02 11:00:17.304000+00:00 +10802,19580123_5981,38305,21,36000,RENT,3.0,EDUCATION,18500,10.91,1,2021-08-15 15:14:52.759000+00:00,2021-08-15 15:14:52.759000+00:00 +20342,20001221_6791,43430,25,75600,MORTGAGE,2.0,PERSONAL,14500,9.63,0,2021-04-16 00:58:53.077000+00:00,2021-04-16 00:58:53.077000+00:00 +29909,19600309_2325,48457,27,56331,MORTGAGE,7.0,EDUCATION,10000,10.36,0,2020-12-15 02:27:20.114000+00:00,2020-12-15 02:27:20.114000+00:00 +12137,19710911_5659,29201,23,28000,RENT,2.0,VENTURE,2875,15.23,0,2021-07-29 14:52:27.143000+00:00,2021-07-29 14:52:27.143000+00:00 +26481,19460619_7783,56267,30,68000,RENT,5.0,EDUCATION,16000,14.09,0,2021-01-27 19:04:25.710000+00:00,2021-01-27 19:04:25.710000+00:00 +24890,19780229_6229,50107,23,105000,RENT,7.0,MEDICAL,7200,11.71,0,2021-02-17 01:45:26.890000+00:00,2021-02-17 01:45:26.890000+00:00 +16284,19480722_3017,49862,23,83236,RENT,6.0,EDUCATION,7000,6.92,0,2021-06-06 18:18:55.256000+00:00,2021-06-06 18:18:55.256000+00:00 +22832,19611127_2836,89112,22,110000,MORTGAGE,2.0,VENTURE,9000,11.11,0,2021-03-15 07:17:43.727000+00:00,2021-03-15 07:17:43.727000+00:00 +22103,19780106_1403,60642,25,73000,RENT,9.0,PERSONAL,13600,11.99,0,2021-03-24 14:17:42.344000+00:00,2021-03-24 14:17:42.344000+00:00 +20832,19760701_9246,55379,25,80000,MORTGAGE,10.0,EDUCATION,25000,15.31,0,2021-04-09 19:05:29.069000+00:00,2021-04-09 19:05:29.069000+00:00 +27178,19530315_5005,58220,27,34560,MORTGAGE,8.0,HOMEIMPROVEMENT,10625,16.4,0,2021-01-18 21:51:46.538000+00:00,2021-01-18 21:51:46.538000+00:00 +16421,19751117_2029,46746,22,52500,MORTGAGE,6.0,DEBTCONSOLIDATION,8000,15.23,0,2021-06-05 00:24:26.380000+00:00,2021-06-05 00:24:26.380000+00:00 +32483,19571002_1156,18417,30,84300,RENT,4.0,PERSONAL,12000,8.88,0,2020-11-12 07:04:27.219000+00:00,2020-11-12 07:04:27.219000+00:00 +26862,19840725_5252,29611,27,37200,RENT,0.0,MEDICAL,13500,10.78,1,2021-01-22 22:31:36.062000+00:00,2021-01-22 22:31:36.062000+00:00 +16393,19891024_1528,87317,26,52000,MORTGAGE,0.0,EDUCATION,3600,11.89,0,2021-06-05 08:58:20.895000+00:00,2021-06-05 08:58:20.895000+00:00 +14466,19860307_6905,37361,22,60000,RENT,6.0,EDUCATION,9000,7.14,0,2021-06-29 22:26:16.252000+00:00,2021-06-29 22:26:16.252000+00:00 +37785,19860422_2703,56588,37,110000,MORTGAGE,11.0,HOMEIMPROVEMENT,12000,7.88,0,2020-09-05 17:12:11.597000+00:00,2020-09-05 17:12:11.597000+00:00 +26586,19520901_1639,77501,30,34000,RENT,2.0,DEBTCONSOLIDATION,1500,14.61,1,2021-01-26 10:57:16.280000+00:00,2021-01-26 10:57:16.280000+00:00 +12065,19740506_1650,94115,24,32000,MORTGAGE,5.0,HOMEIMPROVEMENT,6000,5.42,0,2021-07-30 12:53:55.895000+00:00,2021-07-30 12:53:55.895000+00:00 +12005,19880906_6060,42240,26,22406,RENT,5.0,PERSONAL,2500,6.76,1,2021-07-31 07:15:09.856000+00:00,2021-07-31 07:15:09.856000+00:00 +15257,19660419_6721,36026,25,147750,RENT,3.0,HOMEIMPROVEMENT,5750,9.99,0,2021-06-19 20:28:21.210000+00:00,2021-06-19 20:28:21.210000+00:00 +35465,19500418_5864,78633,30,44760,RENT,1.0,MEDICAL,3300,11.71,0,2020-10-05 06:53:11.394000+00:00,2020-10-05 06:53:11.394000+00:00 +33343,19481214_2015,46163,27,105000,MORTGAGE,9.0,PERSONAL,24000,6.17,0,2020-11-01 08:00:07.121000+00:00,2020-11-01 08:00:07.121000+00:00 +18268,19630110_6337,36078,25,69000,RENT,1.0,HOMEIMPROVEMENT,8000,13.99,1,2021-05-12 11:24:49.637000+00:00,2021-05-12 11:24:49.637000+00:00 +23448,19511127_2917,36726,24,60000,RENT,7.0,HOMEIMPROVEMENT,15000,13.85,0,2021-03-07 10:51:44.401000+00:00,2021-03-07 10:51:44.401000+00:00 +14347,19861210_8269,64085,24,37000,MORTGAGE,7.0,DEBTCONSOLIDATION,6250,7.14,1,2021-07-01 10:50:22.940000+00:00,2021-07-01 10:50:22.940000+00:00 +25215,19790115_5596,92251,22,34000,RENT,4.0,MEDICAL,3800,18.25,1,2021-02-12 22:20:26.271000+00:00,2021-02-12 22:20:26.271000+00:00 +18710,19660816_8652,80512,24,65000,MORTGAGE,5.0,EDUCATION,9600,11.99,0,2021-05-06 20:12:24.796000+00:00,2021-05-06 20:12:24.796000+00:00 +30080,19700113_2978,75189,30,58239,MORTGAGE,3.0,VENTURE,10500,6.62,0,2020-12-12 22:08:49.327000+00:00,2020-12-12 22:08:49.327000+00:00 +21650,19850410_2023,81328,25,90000,MORTGAGE,9.0,VENTURE,5600,9.99,0,2021-03-30 08:52:00.744000+00:00,2021-03-30 08:52:00.744000+00:00 +17929,19720315_2142,44224,24,56000,RENT,2.0,MEDICAL,8000,7.51,0,2021-05-16 19:06:47.513000+00:00,2021-05-16 19:06:47.513000+00:00 +12945,19611008_2362,78723,21,50000,RENT,4.0,EDUCATION,11000,10.0,0,2021-07-19 07:42:31.145000+00:00,2021-07-19 07:42:31.145000+00:00 +25782,19831221_8581,10471,31,240000,MORTGAGE,15.0,MEDICAL,5500,5.42,0,2021-02-05 16:53:47.347000+00:00,2021-02-05 16:53:47.347000+00:00 +23702,19840309_5504,16508,23,74000,RENT,1.0,VENTURE,15000,15.65,1,2021-03-04 05:09:51.303000+00:00,2021-03-04 05:09:51.303000+00:00 +25351,19630312_4863,55386,22,24000,MORTGAGE,4.0,EDUCATION,1300,5.42,0,2021-02-11 04:44:18.628000+00:00,2021-02-11 04:44:18.628000+00:00 +10068,19470413_6684,27707,26,12000,OWN,2.0,EDUCATION,6100,7.51,1,2021-08-24 23:46:37.539000+00:00,2021-08-24 23:46:37.539000+00:00 +24348,19840413_6050,37121,25,58650,MORTGAGE,4.0,MEDICAL,20000,14.09,1,2021-02-23 23:33:14.997000+00:00,2021-02-23 23:33:14.997000+00:00 +11261,19580522_9064,7723,24,26650,MORTGAGE,6.0,MEDICAL,1000,12.53,0,2021-08-09 18:50:26.963000+00:00,2021-08-09 18:50:26.963000+00:00 +25786,19891006_3639,84057,29,240000,MORTGAGE,10.0,EDUCATION,5000,7.88,0,2021-02-05 15:40:22.416000+00:00,2021-02-05 15:40:22.416000+00:00 +24402,19900419_7120,25443,22,60000,MORTGAGE,1.0,PERSONAL,7500,11.66,0,2021-02-23 07:02:08.433000+00:00,2021-02-23 07:02:08.433000+00:00 +19880,19920216_3482,42262,21,47520,RENT,5.0,MEDICAL,10000,15.33,1,2021-04-21 22:18:22.571000+00:00,2021-04-21 22:18:22.571000+00:00 +37472,19740511_1621,75555,39,24000,RENT,0.0,HOMEIMPROVEMENT,3000,14.12,1,2020-09-09 16:56:57.423000+00:00,2020-09-09 16:56:57.423000+00:00 +32721,19481103_4053,50071,29,78000,MORTGAGE,7.0,HOMEIMPROVEMENT,18000,9.38,1,2020-11-09 06:16:13.843000+00:00,2020-11-09 06:16:13.843000+00:00 +26938,19450727_3414,47145,29,32108,RENT,4.0,VENTURE,2500,15.68,1,2021-01-21 23:16:42.379000+00:00,2021-01-21 23:16:42.379000+00:00 +13366,19611014_6261,19804,26,36000,RENT,0.0,PERSONAL,4000,10.14,0,2021-07-13 22:55:32.190000+00:00,2021-07-13 22:55:32.190000+00:00 +18873,19840121_8217,45898,23,40574,RENT,2.0,HOMEIMPROVEMENT,9500,14.74,1,2021-05-04 18:20:43.871000+00:00,2021-05-04 18:20:43.871000+00:00 +31837,19770206_8911,76448,31,77000,MORTGAGE,4.0,VENTURE,10000,14.65,0,2020-11-20 12:41:03.524000+00:00,2020-11-20 12:41:03.524000+00:00 +33028,19470804_1996,46562,33,97000,MORTGAGE,0.0,HOMEIMPROVEMENT,25000,16.0,0,2020-11-05 08:21:35.413000+00:00,2020-11-05 08:21:35.413000+00:00 +36062,19830910_8159,65804,37,55200,RENT,9.0,MEDICAL,12000,11.71,0,2020-09-27 16:15:55.489000+00:00,2020-09-27 16:15:55.489000+00:00 +11528,19980723_8466,73135,25,12000,RENT,2.0,HOMEIMPROVEMENT,2000,11.89,1,2021-08-06 09:09:57.840000+00:00,2021-08-06 09:09:57.840000+00:00 +17899,19570206_9751,46737,24,54000,RENT,3.0,MEDICAL,8000,8.07,0,2021-05-17 04:17:24.493000+00:00,2021-05-17 04:17:24.493000+00:00 +27700,19451214_8404,80444,34,30000,RENT,0.0,MEDICAL,4000,9.63,0,2021-01-12 06:11:03.084000+00:00,2021-01-12 06:11:03.084000+00:00 +36585,19740218_7612,70615,37,50000,MORTGAGE,15.0,VENTURE,8400,6.03,0,2020-09-21 00:16:50.802000+00:00,2020-09-21 00:16:50.802000+00:00 +16622,19640222_7849,28528,25,38000,RENT,3.0,VENTURE,6400,7.88,0,2021-06-02 10:55:18.614000+00:00,2021-06-02 10:55:18.614000+00:00 +14665,19810613_9053,50072,25,44000,RENT,9.0,MEDICAL,8500,14.27,1,2021-06-27 09:33:50.951000+00:00,2021-06-27 09:33:50.951000+00:00 +14795,19810903_8001,92815,24,64151,RENT,0.0,VENTURE,5000,11.86,0,2021-06-25 17:47:50.704000+00:00,2021-06-25 17:47:50.704000+00:00 +24169,19500222_6154,28119,25,78600,RENT,0.0,MEDICAL,8400,13.48,0,2021-02-26 06:18:35.645000+00:00,2021-02-26 06:18:35.645000+00:00 +21443,19760730_8887,84084,24,87000,RENT,0.0,VENTURE,12000,8.88,0,2021-04-02 00:11:15.907000+00:00,2021-04-02 00:11:15.907000+00:00 +23091,19460417_8163,44871,22,118812,MORTGAGE,6.0,MEDICAL,15000,13.35,0,2021-03-12 00:04:04.465000+00:00,2021-03-12 00:04:04.465000+00:00 +15718,19890227_7986,98418,24,50000,MORTGAGE,7.0,VENTURE,11000,16.89,0,2021-06-13 23:27:12.948000+00:00,2021-06-13 23:27:12.948000+00:00 +36790,19760509_6741,63623,37,29000,RENT,5.0,PERSONAL,7200,19.03,1,2020-09-18 09:34:18.104000+00:00,2020-09-18 09:34:18.104000+00:00 +10166,19620708_1065,98038,25,200000,MORTGAGE,9.0,PERSONAL,23050,14.35,0,2021-08-23 17:47:56.738000+00:00,2021-08-23 17:47:56.738000+00:00 +19518,19791126_8004,77272,22,70000,MORTGAGE,5.0,VENTURE,21000,8.88,0,2021-04-26 13:02:28.798000+00:00,2021-04-26 13:02:28.798000+00:00 +19034,19570504_7835,95112,21,66000,MORTGAGE,4.0,DEBTCONSOLIDATION,7000,7.88,0,2021-05-02 17:05:45.411000+00:00,2021-05-02 17:05:45.411000+00:00 +36821,19510602_3795,35011,44,48000,RENT,4.0,MEDICAL,7500,11.49,0,2020-09-18 00:05:19.892000+00:00,2020-09-18 00:05:19.892000+00:00 +23121,20000504_5024,71670,25,120000,MORTGAGE,5.0,PERSONAL,28000,7.9,0,2021-03-11 14:53:27.485000+00:00,2021-03-11 14:53:27.485000+00:00 +27812,19990405_4432,10546,31,39996,OWN,8.0,HOMEIMPROVEMENT,4000,14.35,0,2021-01-10 19:55:25.025000+00:00,2021-01-10 19:55:25.025000+00:00 +23622,19890728_4868,16621,23,56525,RENT,1.0,MEDICAL,15000,11.48,1,2021-03-05 05:38:09.916000+00:00,2021-03-05 05:38:09.916000+00:00 +27615,19710524_9794,42027,28,94000,RENT,3.0,EDUCATION,3700,7.9,0,2021-01-13 08:11:07.861000+00:00,2021-01-13 08:11:07.861000+00:00 +32686,19510116_2607,32724,31,90000,MORTGAGE,3.0,HOMEIMPROVEMENT,12000,13.48,0,2020-11-09 16:58:36.986000+00:00,2020-11-09 16:58:36.986000+00:00 +12397,19730910_6841,67731,24,34000,MORTGAGE,0.0,MEDICAL,10000,12.18,0,2021-07-26 07:20:26.649000+00:00,2021-07-26 07:20:26.649000+00:00 +33709,19571101_6901,23430,31,120000,MORTGAGE,6.0,MEDICAL,28000,8.9,0,2020-10-27 16:02:35.964000+00:00,2020-10-27 16:02:35.964000+00:00 +28174,19990624_4086,99218,28,42000,MORTGAGE,0.0,DEBTCONSOLIDATION,12000,9.62,0,2021-01-06 05:11:18.798000+00:00,2021-01-06 05:11:18.798000+00:00 +17240,19830714_7087,24646,23,38000,RENT,0.0,MEDICAL,7500,7.88,0,2021-05-25 13:52:36.823000+00:00,2021-05-25 13:52:36.823000+00:00 +34812,19770703_7036,1742,33,72000,MORTGAGE,6.0,VENTURE,4250,5.42,0,2020-10-13 14:38:16.328000+00:00,2020-10-13 14:38:16.328000+00:00 +28863,19630703_1257,43164,29,48000,OWN,6.0,HOMEIMPROVEMENT,8000,13.49,0,2020-12-28 10:25:29.488000+00:00,2020-12-28 10:25:29.488000+00:00 +35849,19610525_6509,28519,36,130000,RENT,0.0,MEDICAL,18000,11.71,0,2020-09-30 09:25:18.048000+00:00,2020-09-30 09:25:18.048000+00:00 +20315,19821014_7092,88061,24,69000,MORTGAGE,1.0,EDUCATION,4900,10.96,1,2021-04-16 09:14:26.359000+00:00,2021-04-16 09:14:26.359000+00:00 +14993,19640106_7239,64501,21,32000,RENT,5.0,PERSONAL,5325,14.27,0,2021-06-23 05:13:46.635000+00:00,2021-06-23 05:13:46.635000+00:00 +20875,19761107_4249,94515,26,40000,RENT,2.0,MEDICAL,12000,7.51,0,2021-04-09 05:56:16.064000+00:00,2021-04-09 05:56:16.064000+00:00 +26988,19900812_7043,44230,32,115000,RENT,1.0,HOMEIMPROVEMENT,2500,11.89,0,2021-01-21 07:59:00.746000+00:00,2021-01-21 07:59:00.746000+00:00 +34122,19460406_6958,16405,31,138000,MORTGAGE,15.0,MEDICAL,24000,10.62,0,2020-10-22 09:42:26.871000+00:00,2020-10-22 09:42:26.871000+00:00 +13091,19750501_8888,45223,25,60000,RENT,3.0,HOMEIMPROVEMENT,10250,6.62,0,2021-07-17 11:02:51.175000+00:00,2021-07-17 11:02:51.175000+00:00 +22690,19780925_4583,97346,26,30000,OWN,3.0,EDUCATION,7500,11.14,0,2021-03-17 02:43:58.766000+00:00,2021-03-17 02:43:58.766000+00:00 +34289,19470214_1107,85018,30,150000,OWN,14.0,PERSONAL,24000,11.83,0,2020-10-20 06:37:21.015000+00:00,2020-10-20 06:37:21.015000+00:00 +17865,19760702_5710,34610,23,60000,MORTGAGE,6.0,EDUCATION,7000,6.54,0,2021-05-17 14:41:26.403000+00:00,2021-05-17 14:41:26.403000+00:00 +20761,19811225_1473,43319,26,34000,RENT,2.0,PERSONAL,12000,14.96,1,2021-04-10 16:48:36.588000+00:00,2021-04-10 16:48:36.588000+00:00 +36689,19500812_8568,70441,36,52000,MORTGAGE,2.0,HOMEIMPROVEMENT,8000,7.51,0,2020-09-19 16:28:02.604000+00:00,2020-09-19 16:28:02.604000+00:00 +16563,19920716_8577,30511,22,65700,RENT,7.0,PERSONAL,6800,10.37,0,2021-06-03 04:58:11.341000+00:00,2021-06-03 04:58:11.341000+00:00 +29878,19571110_3708,82414,33,56000,MORTGAGE,2.0,PERSONAL,11500,7.14,0,2020-12-15 11:56:18.327000+00:00,2020-12-15 11:56:18.327000+00:00 +36431,19880615_5861,68758,36,45000,MORTGAGE,2.0,EDUCATION,7000,7.14,0,2020-09-22 23:23:20.633000+00:00,2020-09-22 23:23:20.633000+00:00 +32107,19951230_5395,60511,27,39996,OWN,1.0,VENTURE,8000,12.53,0,2020-11-17 02:05:30.703000+00:00,2020-11-17 02:05:30.703000+00:00 +17532,19720730_1867,16360,21,53000,MORTGAGE,4.0,PERSONAL,14400,7.49,1,2021-05-21 20:33:16.883000+00:00,2021-05-21 20:33:16.883000+00:00 +13562,19960924_1552,25136,21,40000,OWN,0.0,EDUCATION,2500,14.27,0,2021-07-11 10:58:10.587000+00:00,2021-07-11 10:58:10.587000+00:00 +19719,19500928_5441,22432,25,42000,RENT,3.0,VENTURE,10000,13.8,1,2021-04-23 23:33:21.031000+00:00,2021-04-23 23:33:21.031000+00:00 +36375,19581226_6191,21218,41,45600,RENT,18.0,MEDICAL,5000,6.17,0,2020-09-23 16:31:09.663000+00:00,2020-09-23 16:31:09.663000+00:00 +24876,19900319_2888,1831,24,24000,RENT,2.0,EDUCATION,3500,15.65,1,2021-02-17 06:02:24.147000+00:00,2021-02-17 06:02:24.147000+00:00 +16906,19661112_4480,84412,23,55000,MORTGAGE,0.0,EDUCATION,11075,13.49,0,2021-05-29 20:02:48.535000+00:00,2021-05-29 20:02:48.535000+00:00 +24505,19880205_4971,39154,25,45000,RENT,0.0,EDUCATION,5000,10.74,0,2021-02-21 23:31:41.468000+00:00,2021-02-21 23:31:41.468000+00:00 +10438,19960423_9503,16218,21,18701,MORTGAGE,0.0,PERSONAL,4200,14.11,1,2021-08-20 06:35:41.451000+00:00,2021-08-20 06:35:41.451000+00:00 +17289,19471015_6100,47855,24,57000,MORTGAGE,8.0,VENTURE,14000,14.91,0,2021-05-24 22:53:16.422000+00:00,2021-05-24 22:53:16.422000+00:00 +17337,19800821_6712,29676,25,57200,MORTGAGE,1.0,EDUCATION,2400,7.49,0,2021-05-24 08:12:17.254000+00:00,2021-05-24 08:12:17.254000+00:00 +13901,19840428_4196,60012,22,34900,MORTGAGE,4.0,DEBTCONSOLIDATION,3600,15.7,1,2021-07-07 03:16:12.711000+00:00,2021-07-07 03:16:12.711000+00:00 +21063,19841010_2032,19956,25,83004,MORTGAGE,9.0,PERSONAL,5000,6.76,0,2021-04-06 20:25:44.322000+00:00,2021-04-06 20:25:44.322000+00:00 +13997,19720304_9112,46542,24,41600,MORTGAGE,0.0,HOMEIMPROVEMENT,10000,8.94,0,2021-07-05 21:54:14.375000+00:00,2021-07-05 21:54:14.375000+00:00 +33573,19650225_6508,1803,27,113800,MORTGAGE,3.0,MEDICAL,7500,8.63,0,2020-10-29 09:38:43.607000+00:00,2020-10-29 09:38:43.607000+00:00 +20179,19710409_9932,23141,26,75000,MORTGAGE,2.0,VENTURE,4000,5.79,0,2021-04-18 02:50:34.003000+00:00,2021-04-18 02:50:34.003000+00:00 +35335,19910201_3603,92168,28,55000,OWN,13.0,MEDICAL,18000,7.9,0,2020-10-06 22:39:11.641000+00:00,2020-10-06 22:39:11.641000+00:00 +29175,19990930_1921,36590,32,22800,RENT,1.0,VENTURE,7125,15.28,1,2020-12-24 10:59:04.894000+00:00,2020-12-24 10:59:04.894000+00:00 +32136,20000822_3089,74883,30,34000,RENT,0.0,DEBTCONSOLIDATION,12000,12.87,1,2020-11-16 17:13:14.955000+00:00,2020-11-16 17:13:14.955000+00:00 +11296,19680501_4466,25067,24,36000,RENT,5.0,EDUCATION,1200,11.49,0,2021-08-09 08:08:03.819000+00:00,2021-08-09 08:08:03.819000+00:00 +23907,19980203_5138,55053,24,94000,RENT,8.0,HOMEIMPROVEMENT,16000,11.89,0,2021-03-01 14:27:18.605000+00:00,2021-03-01 14:27:18.605000+00:00 +31204,19800518_5838,19343,29,70000,MORTGAGE,6.0,DEBTCONSOLIDATION,4200,10.99,0,2020-11-28 14:19:03.805000+00:00,2020-11-28 14:19:03.805000+00:00 +35244,19581115_1767,29584,27,56000,RENT,2.0,PERSONAL,14000,10.65,0,2020-10-08 02:29:23.814000+00:00,2020-10-08 02:29:23.814000+00:00 +11670,19570409_1102,93620,24,40000,RENT,2.0,PERSONAL,2000,11.99,0,2021-08-04 13:43:42.800000+00:00,2021-08-04 13:43:42.800000+00:00 +31479,19860121_9051,44454,29,72000,MORTGAGE,9.0,HOMEIMPROVEMENT,1000,7.68,0,2020-11-25 02:11:44.820000+00:00,2020-11-25 02:11:44.820000+00:00 +12097,19620606_9691,66048,24,32000,MORTGAGE,7.0,VENTURE,4500,6.76,0,2021-07-30 03:06:36.450000+00:00,2021-07-30 03:06:36.450000+00:00 +32116,19730127_4796,44212,28,39000,RENT,0.0,DEBTCONSOLIDATION,12000,12.53,1,2020-11-16 23:20:19.609000+00:00,2020-11-16 23:20:19.609000+00:00 +26212,19890714_9960,46017,27,88000,RENT,4.0,DEBTCONSOLIDATION,20000,10.38,0,2021-01-31 05:21:37.298000+00:00,2021-01-31 05:21:37.298000+00:00 +16506,19880310_6939,71138,24,56000,RENT,2.0,VENTURE,6650,12.69,0,2021-06-03 22:24:21.603000+00:00,2021-06-03 22:24:21.603000+00:00 +28847,19980909_4940,56289,31,99000,RENT,0.0,HOMEIMPROVEMENT,5675,13.23,0,2020-12-28 15:19:09.210000+00:00,2020-12-28 15:19:09.210000+00:00 +19818,19480503_8590,30523,23,50000,RENT,5.0,MEDICAL,10000,8.94,0,2021-04-22 17:16:18.997000+00:00,2021-04-22 17:16:18.997000+00:00 +23261,19960913_5222,6825,24,108000,MORTGAGE,1.0,DEBTCONSOLIDATION,25000,13.99,1,2021-03-09 20:03:54.911000+00:00,2021-03-09 20:03:54.911000+00:00 +26687,19990304_9642,80962,29,120000,RENT,3.0,DEBTCONSOLIDATION,15000,9.63,0,2021-01-25 04:03:31.780000+00:00,2021-01-25 04:03:31.780000+00:00 +26025,19560520_4839,94140,30,105000,RENT,4.0,VENTURE,24250,15.65,0,2021-02-02 14:33:47.808000+00:00,2021-02-02 14:33:47.808000+00:00 +25886,19610324_6600,48422,33,190000,MORTGAGE,10.0,HOMEIMPROVEMENT,20000,14.11,0,2021-02-04 09:04:59.149000+00:00,2021-02-04 09:04:59.149000+00:00 +24136,19460514_4704,8731,24,49000,MORTGAGE,0.0,HOMEIMPROVEMENT,5000,12.18,1,2021-02-26 16:24:16.324000+00:00,2021-02-26 16:24:16.324000+00:00 +21465,19960605_9058,4084,23,90000,RENT,0.0,MEDICAL,12000,8.9,0,2021-04-01 17:27:28.788000+00:00,2021-04-01 17:27:28.788000+00:00 +27031,19700913_8016,27976,33,33000,MORTGAGE,3.0,EDUCATION,4000,12.69,0,2021-01-20 18:49:47.741000+00:00,2021-01-20 18:49:47.741000+00:00 +22437,19700826_5706,11432,22,140000,RENT,0.0,MEDICAL,14000,13.11,0,2021-03-20 08:07:30.632000+00:00,2021-03-20 08:07:30.632000+00:00 +34817,19900307_2768,93454,30,70000,MORTGAGE,9.0,PERSONAL,7000,8.9,0,2020-10-13 13:06:30.164000+00:00,2020-10-13 13:06:30.164000+00:00 +31488,19500116_9170,73542,28,53000,RENT,2.0,MEDICAL,10000,11.89,0,2020-11-24 23:26:33.726000+00:00,2020-11-24 23:26:33.726000+00:00 +30308,19721125_2866,32937,32,51400,RENT,1.0,HOMEIMPROVEMENT,8000,7.51,0,2020-12-10 00:24:08.278000+00:00,2020-12-10 00:24:08.278000+00:00 +34066,19500520_6295,74940,29,134000,MORTGAGE,2.0,PERSONAL,8000,14.22,0,2020-10-23 02:50:15.900000+00:00,2020-10-23 02:50:15.900000+00:00 +22163,19630229_2611,51450,21,96000,OWN,1.0,EDUCATION,7000,12.53,0,2021-03-23 19:56:28.383000+00:00,2021-03-23 19:56:28.383000+00:00 +35605,19920416_1122,31560,31,101000,RENT,2.0,VENTURE,7500,13.22,0,2020-10-03 12:03:38.820000+00:00,2020-10-03 12:03:38.820000+00:00 +27500,19671218_8697,97236,27,48000,RENT,3.0,DEBTCONSOLIDATION,10800,15.99,1,2021-01-14 19:21:49.618000+00:00,2021-01-14 19:21:49.618000+00:00 +22741,19850929_8843,13602,26,108000,MORTGAGE,4.0,HOMEIMPROVEMENT,7200,9.62,0,2021-03-16 11:07:55.900000+00:00,2021-03-16 11:07:55.900000+00:00 +27742,19831229_8608,75075,29,39000,MORTGAGE,12.0,PERSONAL,16000,5.99,0,2021-01-11 17:20:11.312000+00:00,2021-01-11 17:20:11.312000+00:00 +31379,19710625_7661,59635,34,72000,OWN,2.0,MEDICAL,13150,6.03,0,2020-11-26 08:47:08.087000+00:00,2020-11-26 08:47:08.087000+00:00 +21787,19911227_3438,30411,24,91000,MORTGAGE,5.0,MEDICAL,15000,7.88,0,2021-03-28 14:57:31.868000+00:00,2021-03-28 14:57:31.868000+00:00 +31465,19950807_4776,29669,28,72000,MORTGAGE,12.0,VENTURE,15000,8.94,0,2020-11-25 06:28:42.078000+00:00,2020-11-25 06:28:42.078000+00:00 +30096,19491228_4585,51501,28,58800,MORTGAGE,11.0,VENTURE,5500,6.76,0,2020-12-12 17:15:09.604000+00:00,2020-12-12 17:15:09.604000+00:00 +17327,19560119_4823,3833,26,57006,MORTGAGE,10.0,DEBTCONSOLIDATION,6000,6.17,0,2021-05-24 11:15:49.580000+00:00,2021-05-24 11:15:49.580000+00:00 +12886,19500617_4745,12209,24,36000,MORTGAGE,8.0,VENTURE,3250,6.39,0,2021-07-20 01:45:23.872000+00:00,2021-07-20 01:45:23.872000+00:00 +32167,19550723_3969,62448,28,81000,MORTGAGE,11.0,HOMEIMPROVEMENT,6000,6.17,0,2020-11-16 07:44:16.743000+00:00,2020-11-16 07:44:16.743000+00:00 +38018,19650210_2955,35759,47,178000,OWN,31.0,VENTURE,9000,10.99,0,2020-09-02 17:55:44.384000+00:00,2020-09-02 17:55:44.384000+00:00 +21338,19580107_6181,12570,22,85000,MORTGAGE,1.0,MEDICAL,25000,12.53,0,2021-04-03 08:18:25.337000+00:00,2021-04-03 08:18:25.337000+00:00 +10373,19830416_6544,23607,26,62004,RENT,9.0,DEBTCONSOLIDATION,24000,7.9,1,2021-08-21 02:28:41.575000+00:00,2021-08-21 02:28:41.575000+00:00 +30494,19991106_4360,38821,29,55000,MORTGAGE,0.0,VENTURE,5000,12.73,1,2020-12-07 15:30:19.001000+00:00,2020-12-07 15:30:19.001000+00:00 +30699,19510622_4732,77661,27,32000,RENT,2.0,MEDICAL,8600,16.02,1,2020-12-05 00:47:46.304000+00:00,2020-12-05 00:47:46.304000+00:00 +33511,19580407_9371,10466,29,110000,MORTGAGE,0.0,VENTURE,15000,8.94,0,2020-10-30 04:36:40.033000+00:00,2020-10-30 04:36:40.033000+00:00 +11298,19510715_6024,75074,21,40000,RENT,5.0,VENTURE,1200,15.58,0,2021-08-09 07:31:21.354000+00:00,2021-08-09 07:31:21.354000+00:00 +34538,19760509_7255,18421,31,741600,MORTGAGE,3.0,MEDICAL,12000,10.25,0,2020-10-17 02:27:14.080000+00:00,2020-10-17 02:27:14.080000+00:00 +31930,19920610_7089,54530,33,70000,RENT,0.0,EDUCATION,11200,8.94,0,2020-11-19 08:14:08.886000+00:00,2020-11-19 08:14:08.886000+00:00 +26170,19540422_2550,71351,27,70000,RENT,4.0,EDUCATION,20000,11.48,0,2021-01-31 18:12:29.071000+00:00,2021-01-31 18:12:29.071000+00:00 +37566,19910914_9213,12926,38,90000,MORTGAGE,1.0,DEBTCONSOLIDATION,7000,6.99,0,2020-09-08 12:11:41.552000+00:00,2020-09-08 12:11:41.552000+00:00 +31122,19500614_6573,92377,28,63000,MORTGAGE,5.0,DEBTCONSOLIDATION,9000,13.72,1,2020-11-29 15:24:04.884000+00:00,2020-11-29 15:24:04.884000+00:00 +19653,19620513_7237,50006,26,48000,RENT,10.0,MEDICAL,4200,6.92,0,2021-04-24 19:44:42.388000+00:00,2021-04-24 19:44:42.388000+00:00 +27209,19910530_1082,37414,31,64800,RENT,3.0,VENTURE,3000,13.98,0,2021-01-18 12:22:48.325000+00:00,2021-01-18 12:22:48.325000+00:00 +11811,19460609_4577,80918,24,20000,RENT,0.0,DEBTCONSOLIDATION,2400,15.62,1,2021-08-02 18:35:48.994000+00:00,2021-08-02 18:35:48.994000+00:00 +22899,19600605_5105,36869,22,110196,MORTGAGE,6.0,MEDICAL,25000,11.49,0,2021-03-14 10:48:01.138000+00:00,2021-03-14 10:48:01.138000+00:00 +28894,19500811_3625,12734,28,20400,RENT,12.0,EDUCATION,6000,6.03,0,2020-12-28 00:56:31.275000+00:00,2020-12-28 00:56:31.275000+00:00 +28255,19780609_3754,16507,27,40000,RENT,1.0,MEDICAL,5000,11.99,0,2021-01-05 04:24:38.952000+00:00,2021-01-05 04:24:38.952000+00:00 +17647,19520419_7564,13440,23,29000,RENT,7.0,EDUCATION,8000,12.73,1,2021-05-20 09:22:35.126000+00:00,2021-05-20 09:22:35.126000+00:00 +20977,19450704_8207,43616,26,82000,MORTGAGE,10.0,PERSONAL,3200,5.99,0,2021-04-07 22:44:10.331000+00:00,2021-04-07 22:44:10.331000+00:00 +16341,19960102_1171,94558,22,50724,RENT,7.0,EDUCATION,6300,15.96,0,2021-06-06 00:52:44.994000+00:00,2021-06-06 00:52:44.994000+00:00 +29489,19770822_2710,42722,28,59000,RENT,0.0,HOMEIMPROVEMENT,6500,16.35,1,2020-12-20 10:55:57.836000+00:00,2020-12-20 10:55:57.836000+00:00 +34030,19580820_4102,38574,28,130000,MORTGAGE,1.0,EDUCATION,5600,15.65,0,2020-10-23 13:51:00.276000+00:00,2020-10-23 13:51:00.276000+00:00 +13605,19580503_9191,95961,22,60000,RENT,0.0,EDUCATION,4400,15.23,0,2021-07-10 21:48:57.582000+00:00,2021-07-10 21:48:57.582000+00:00 +23938,19700122_3062,49831,23,195000,MORTGAGE,0.0,EDUCATION,20000,9.63,0,2021-03-01 04:58:20.392000+00:00,2021-03-01 04:58:20.392000+00:00 +21377,19510407_5225,37880,23,86000,MORTGAGE,5.0,EDUCATION,21000,8.9,0,2021-04-02 20:22:37.263000+00:00,2021-04-02 20:22:37.263000+00:00 +38398,19820419_1456,78335,57,15000,MORTGAGE,1.0,DEBTCONSOLIDATION,3000,12.68,1,2020-08-28 21:41:15.969000+00:00,2020-08-28 21:41:15.969000+00:00 +27634,19690506_2859,12477,28,55000,RENT,2.0,MEDICAL,3900,11.99,0,2021-01-13 02:22:24.440000+00:00,2021-01-13 02:22:24.440000+00:00 +33424,19461113_2724,35582,35,108717,MORTGAGE,9.0,DEBTCONSOLIDATION,16000,6.99,0,2020-10-31 07:13:27.275000+00:00,2020-10-31 07:13:27.275000+00:00 +27118,19551107_5811,14784,32,46000,RENT,0.0,HOMEIMPROVEMENT,3000,16.29,1,2021-01-19 16:13:00.499000+00:00,2021-01-19 16:13:00.499000+00:00 +23593,19511001_8249,26555,26,138000,MORTGAGE,0.0,DEBTCONSOLIDATION,7500,6.03,0,2021-03-05 14:30:25.664000+00:00,2021-03-05 14:30:25.664000+00:00 +31240,19821005_6770,23306,27,70000,OWN,2.0,HOMEIMPROVEMENT,2250,10.36,0,2020-11-28 03:18:19.429000+00:00,2020-11-28 03:18:19.429000+00:00 +36446,19990823_8068,98324,37,59000,RENT,0.0,PERSONAL,5000,14.84,1,2020-09-22 18:48:02.143000+00:00,2020-09-22 18:48:02.143000+00:00 +19106,19880528_1268,36776,23,67000,MORTGAGE,2.0,DEBTCONSOLIDATION,5600,7.49,0,2021-05-01 19:04:16.659000+00:00,2021-05-01 19:04:16.659000+00:00 +37298,19471127_3941,33016,37,65000,RENT,2.0,DEBTCONSOLIDATION,10000,5.42,0,2020-09-11 22:10:31.908000+00:00,2020-09-11 22:10:31.908000+00:00 +26505,19970319_6443,48383,29,38000,RENT,5.0,EDUCATION,1000,7.88,0,2021-01-27 11:43:56.126000+00:00,2021-01-27 11:43:56.126000+00:00 +33734,19760924_9148,32082,27,50000,RENT,1.0,VENTURE,15000,13.16,0,2020-10-27 08:23:45.147000+00:00,2020-10-27 08:23:45.147000+00:00 +17662,19490806_4167,21843,24,60000,MORTGAGE,8.0,EDUCATION,3000,10.65,0,2021-05-20 04:47:16.636000+00:00,2021-05-20 04:47:16.636000+00:00 +31701,19951225_8760,37769,29,75000,MORTGAGE,3.0,PERSONAL,4000,10.75,0,2020-11-22 06:17:11.167000+00:00,2020-11-22 06:17:11.167000+00:00 +38617,19581220_3576,44901,56,70000,MORTGAGE,7.0,PERSONAL,15000,10.38,0,2020-08-26 02:41:46.014000+00:00,2020-08-26 02:41:46.014000+00:00 +12757,19790318_1562,87402,22,38400,RENT,4.0,EDUCATION,3500,13.99,0,2021-07-21 17:13:02.887000+00:00,2021-07-21 17:13:02.887000+00:00 +29516,19561122_2280,88013,34,53000,MORTGAGE,7.0,DEBTCONSOLIDATION,3100,7.9,0,2020-12-20 02:40:24.553000+00:00,2020-12-20 02:40:24.553000+00:00 +17790,19551025_5350,30147,26,45000,RENT,3.0,PERSONAL,8000,15.33,0,2021-05-18 13:37:58.854000+00:00,2021-05-18 13:37:58.854000+00:00 +25573,19490418_3424,62015,22,48000,RENT,1.0,EDUCATION,7200,9.62,0,2021-02-08 08:49:44.975000+00:00,2021-02-08 08:49:44.975000+00:00 +12336,19551112_1917,45140,23,52000,RENT,0.0,EDUCATION,3000,5.99,0,2021-07-27 02:00:01.842000+00:00,2021-07-27 02:00:01.842000+00:00 +17995,19850730_1705,17229,22,60000,MORTGAGE,6.0,DEBTCONSOLIDATION,6000,13.11,0,2021-05-15 22:55:26.156000+00:00,2021-05-15 22:55:26.156000+00:00 +30548,19590901_6830,40701,30,73008,RENT,5.0,VENTURE,8000,9.99,0,2020-12-06 22:59:12.437000+00:00,2020-12-06 22:59:12.437000+00:00 +24898,19451008_8370,53922,22,24432,RENT,0.0,EDUCATION,2000,11.36,0,2021-02-16 23:18:37.028000+00:00,2021-02-16 23:18:37.028000+00:00 +16570,19751112_5580,52561,25,70000,RENT,5.0,HOMEIMPROVEMENT,6800,5.42,0,2021-06-03 02:49:42.712000+00:00,2021-06-03 02:49:42.712000+00:00 +15119,19520314_5139,40052,26,51600,RENT,10.0,HOMEIMPROVEMENT,5500,11.99,1,2021-06-21 14:41:11.318000+00:00,2021-06-21 14:41:11.318000+00:00 +13412,19480802_2047,57567,22,42000,RENT,3.0,MEDICAL,4000,8.88,0,2021-07-13 08:51:15.488000+00:00,2021-07-13 08:51:15.488000+00:00 +36819,19771227_8119,54626,39,57000,MORTGAGE,16.0,EDUCATION,6300,10.99,0,2020-09-18 00:42:02.357000+00:00,2020-09-18 00:42:02.357000+00:00 +26659,19610123_4370,66213,31,29760,MORTGAGE,0.0,MEDICAL,10000,9.63,0,2021-01-25 12:37:26.295000+00:00,2021-01-25 12:37:26.295000+00:00 +38476,19830614_1921,40555,63,37000,RENT,24.0,DEBTCONSOLIDATION,5450,15.96,1,2020-08-27 21:49:39.821000+00:00,2020-08-27 21:49:39.821000+00:00 +30342,19701009_8821,42754,27,56400,RENT,4.0,PERSONAL,8000,16.77,0,2020-12-09 14:00:06.367000+00:00,2020-12-09 14:00:06.367000+00:00 +34965,19700808_4478,54474,29,200000,RENT,14.0,PERSONAL,16000,12.69,0,2020-10-11 15:50:07.729000+00:00,2020-10-11 15:50:07.729000+00:00 +16461,20010813_9747,60517,26,46800,MORTGAGE,0.0,MEDICAL,5000,12.87,1,2021-06-04 12:10:17.074000+00:00,2021-06-04 12:10:17.074000+00:00 +37598,19560911_1699,48005,39,90000,MORTGAGE,9.0,HOMEIMPROVEMENT,22000,12.67,0,2020-09-08 02:24:22.106000+00:00,2020-09-08 02:24:22.106000+00:00 +38537,19761123_3267,36785,56,71884,OWN,11.0,PERSONAL,7425,9.99,0,2020-08-27 03:10:04.628000+00:00,2020-08-27 03:10:04.628000+00:00 +32384,19680305_2152,62549,29,62050,MORTGAGE,13.0,MEDICAL,3600,17.99,1,2020-11-13 13:21:29.253000+00:00,2020-11-13 13:21:29.253000+00:00 +24366,19971215_9589,36037,23,84000,RENT,0.0,EDUCATION,12500,6.54,0,2021-02-23 18:02:52.809000+00:00,2021-02-23 18:02:52.809000+00:00 +11360,19600923_9625,60184,23,30000,RENT,1.0,DEBTCONSOLIDATION,1500,7.51,0,2021-08-08 12:33:24.928000+00:00,2021-08-08 12:33:24.928000+00:00 +21274,19681017_9396,92513,22,42000,RENT,6.0,PERSONAL,3000,11.49,0,2021-04-04 03:53:04.228000+00:00,2021-04-04 03:53:04.228000+00:00 +33972,19870929_1651,22737,27,116899,MORTGAGE,12.0,DEBTCONSOLIDATION,12000,10.75,1,2020-10-24 07:35:31.771000+00:00,2020-10-24 07:35:31.771000+00:00 +30960,20010721_2412,71419,30,71400,RENT,0.0,HOMEIMPROVEMENT,9600,12.61,0,2020-12-01 16:57:24.576000+00:00,2020-12-01 16:57:24.576000+00:00 +26218,19610525_5134,67570,27,81500,RENT,2.0,HOMEIMPROVEMENT,20000,17.51,1,2021-01-31 03:31:29.902000+00:00,2021-01-31 03:31:29.902000+00:00 +34312,19980726_4104,71369,30,151800,MORTGAGE,14.0,HOMEIMPROVEMENT,17525,12.72,0,2020-10-19 23:35:12.663000+00:00,2020-10-19 23:35:12.663000+00:00 +22738,19990517_7961,24366,22,35000,RENT,0.0,VENTURE,2000,12.99,0,2021-03-16 12:02:59.598000+00:00,2021-03-16 12:02:59.598000+00:00 +27480,19950315_2466,12546,34,93000,RENT,11.0,HOMEIMPROVEMENT,11000,12.53,0,2021-01-15 01:28:54.272000+00:00,2021-01-15 01:28:54.272000+00:00 +34799,19791129_7157,47142,33,103000,RENT,0.0,EDUCATION,9000,14.65,1,2020-10-13 18:36:52.352000+00:00,2020-10-13 18:36:52.352000+00:00 +17158,19960225_2287,18651,22,45999,RENT,1.0,VENTURE,7300,7.88,0,2021-05-26 14:57:37.902000+00:00,2021-05-26 14:57:37.902000+00:00 +35661,19711012_6432,68132,40,233000,MORTGAGE,6.0,MEDICAL,15000,11.83,0,2020-10-02 18:55:49.790000+00:00,2020-10-02 18:55:49.790000+00:00 +34244,19540905_7240,35739,29,83500,RENT,1.0,HOMEIMPROVEMENT,15000,13.43,0,2020-10-20 20:23:16.485000+00:00,2020-10-20 20:23:16.485000+00:00 +23297,19870501_9457,2140,25,16200,RENT,2.0,MEDICAL,1500,6.91,0,2021-03-09 09:03:10.535000+00:00,2021-03-09 09:03:10.535000+00:00 +27407,19940915_6221,10590,27,25000,RENT,0.0,PERSONAL,3600,13.16,0,2021-01-15 23:48:44.257000+00:00,2021-01-15 23:48:44.257000+00:00 +36530,19910801_6982,1719,38,48000,MORTGAGE,1.0,PERSONAL,18000,8.49,0,2020-09-21 17:06:18.599000+00:00,2020-09-21 17:06:18.599000+00:00 +32624,19640723_1144,53177,33,36000,RENT,5.0,EDUCATION,12200,9.99,1,2020-11-10 11:56:33.412000+00:00,2020-11-10 11:56:33.412000+00:00 +34601,19591021_9217,79520,35,62475,MORTGAGE,5.0,MEDICAL,9600,14.61,1,2020-10-16 07:10:56.421000+00:00,2020-10-16 07:10:56.421000+00:00 +33226,19990219_5275,99672,27,100000,MORTGAGE,2.0,MEDICAL,2000,8.0,0,2020-11-02 19:47:31.344000+00:00,2020-11-02 19:47:31.344000+00:00 +15847,19491124_9988,62640,24,59400,RENT,8.0,DEBTCONSOLIDATION,6000,7.9,0,2021-06-12 07:59:33.934000+00:00,2021-06-12 07:59:33.934000+00:00 +23067,19650126_1601,46405,26,26400,OWN,8.0,HOMEIMPROVEMENT,8000,5.79,0,2021-03-12 07:24:34.049000+00:00,2021-03-12 07:24:34.049000+00:00 +24124,20010608_6991,37160,24,45000,RENT,8.0,PERSONAL,8000,12.73,0,2021-02-26 20:04:31.116000+00:00,2021-02-26 20:04:31.116000+00:00 +21827,19550615_4211,8837,24,92000,MORTGAGE,7.0,PERSONAL,15000,11.11,0,2021-03-28 02:43:22.561000+00:00,2021-03-28 02:43:22.561000+00:00 +28593,19540626_2082,98043,33,66000,RENT,17.0,EDUCATION,5000,7.29,0,2020-12-31 21:01:02.309000+00:00,2020-12-31 21:01:02.309000+00:00 +30966,20000216_4918,38390,32,80000,RENT,6.0,DEBTCONSOLIDATION,9600,11.14,0,2020-12-01 15:07:17.180000+00:00,2020-12-01 15:07:17.180000+00:00 +24815,19510223_6038,76059,25,51000,MORTGAGE,6.0,EDUCATION,16750,16.4,0,2021-02-18 00:41:59.340000+00:00,2021-02-18 00:41:59.340000+00:00 +22970,19921103_6067,91125,23,114000,OWN,7.0,VENTURE,6000,8.49,0,2021-03-13 13:04:53.618000+00:00,2021-03-13 13:04:53.618000+00:00 +31802,19790604_1488,43532,30,85000,RENT,4.0,HOMEIMPROVEMENT,10000,6.62,0,2020-11-20 23:23:26.667000+00:00,2020-11-20 23:23:26.667000+00:00 +18145,19720929_2910,91916,22,61000,MORTGAGE,6.0,MEDICAL,12000,13.49,0,2021-05-14 01:02:21.256000+00:00,2021-05-14 01:02:21.256000+00:00 +34282,19840325_7595,49544,29,150000,MORTGAGE,0.0,HOMEIMPROVEMENT,10700,14.22,0,2020-10-20 08:45:49.643000+00:00,2020-10-20 08:45:49.643000+00:00 +30480,19470828_5778,49525,30,61000,MORTGAGE,2.0,DEBTCONSOLIDATION,4000,7.9,0,2020-12-07 19:47:16.259000+00:00,2020-12-07 19:47:16.259000+00:00 +31371,19940317_5655,95919,35,71500,MORTGAGE,1.0,HOMEIMPROVEMENT,19200,10.99,0,2020-11-26 11:13:57.949000+00:00,2020-11-26 11:13:57.949000+00:00 +25731,19961013_1223,48021,30,300000,MORTGAGE,13.0,EDUCATION,4000,10.65,0,2021-02-06 08:29:50.213000+00:00,2021-02-06 08:29:50.213000+00:00 +23256,19460121_8415,54428,21,51000,RENT,5.0,VENTURE,1600,15.62,1,2021-03-09 21:35:41.074000+00:00,2021-03-09 21:35:41.074000+00:00 +19150,19950320_6494,4488,22,67440,MORTGAGE,6.0,EDUCATION,5500,10.25,0,2021-05-01 05:36:42.421000+00:00,2021-05-01 05:36:42.421000+00:00 +29992,19671028_9161,65534,27,51600,MORTGAGE,2.0,VENTURE,13650,16.29,1,2020-12-14 01:03:57.802000+00:00,2020-12-14 01:03:57.802000+00:00 +23960,19610817_1645,3826,24,135000,RENT,3.0,EDUCATION,16000,16.69,0,2021-02-28 22:14:33.274000+00:00,2021-02-28 22:14:33.274000+00:00 +35809,20000124_8454,75487,40,73100,RENT,0.0,MEDICAL,20000,14.54,1,2020-09-30 21:39:27.355000+00:00,2020-09-30 21:39:27.355000+00:00 +30164,19940108_8290,97101,32,29000,RENT,0.0,EDUCATION,8000,18.25,1,2020-12-11 20:27:05.783000+00:00,2020-12-11 20:27:05.783000+00:00 +22354,19951008_5271,62051,26,75000,RENT,4.0,EDUCATION,14000,11.11,0,2021-03-21 09:30:52.943000+00:00,2021-03-21 09:30:52.943000+00:00 +15328,19610515_2615,59841,24,48000,MORTGAGE,5.0,HOMEIMPROVEMENT,17000,6.91,0,2021-06-18 22:45:13.690000+00:00,2021-06-18 22:45:13.690000+00:00 +24513,19610625_2694,68745,25,47000,RENT,1.0,VENTURE,8500,8.9,0,2021-02-21 21:04:51.607000+00:00,2021-02-21 21:04:51.607000+00:00 +27164,19811005_2518,38963,31,55000,RENT,3.0,HOMEIMPROVEMENT,12000,13.23,0,2021-01-19 02:08:43.796000+00:00,2021-01-19 02:08:43.796000+00:00 +12773,19680130_2278,72650,24,44000,RENT,3.0,EDUCATION,3500,12.69,0,2021-07-21 12:19:23.164000+00:00,2021-07-21 12:19:23.164000+00:00 +23465,19780829_8413,14757,23,130000,MORTGAGE,7.0,DEBTCONSOLIDATION,6000,5.79,0,2021-03-07 05:39:43.446000+00:00,2021-03-07 05:39:43.446000+00:00 +19971,19450726_6507,13734,24,59600,RENT,8.0,HOMEIMPROVEMENT,10000,5.99,0,2021-04-20 18:28:10.398000+00:00,2021-04-20 18:28:10.398000+00:00 +21876,19460824_5649,21234,23,93000,MORTGAGE,5.0,DEBTCONSOLIDATION,2000,7.9,0,2021-03-27 11:44:02.160000+00:00,2021-03-27 11:44:02.160000+00:00 +35742,19790809_8840,36088,39,55059,RENT,16.0,DEBTCONSOLIDATION,24000,12.53,1,2020-10-01 18:09:09.944000+00:00,2020-10-01 18:09:09.944000+00:00 +32892,19920219_5973,78739,27,33600,OWN,1.0,PERSONAL,21250,8.88,0,2020-11-07 01:57:43.056000+00:00,2020-11-07 01:57:43.056000+00:00 +34015,19930830_8701,24431,34,130000,MORTGAGE,5.0,MEDICAL,6450,13.23,0,2020-10-23 18:26:18.767000+00:00,2020-10-23 18:26:18.767000+00:00 +27994,19721118_8989,31605,31,25000,RENT,0.0,MEDICAL,4800,11.54,0,2021-01-08 12:15:00.679000+00:00,2021-01-08 12:15:00.679000+00:00 +18431,19880511_4031,27807,22,32000,RENT,3.0,EDUCATION,8400,11.49,0,2021-05-10 09:33:08.712000+00:00,2021-05-10 09:33:08.712000+00:00 +37210,19950611_9270,47438,37,70000,MORTGAGE,7.0,MEDICAL,25000,9.76,0,2020-09-13 01:05:40.383000+00:00,2020-09-13 01:05:40.383000+00:00 +21450,19750621_1855,32328,24,87000,MORTGAGE,7.0,HOMEIMPROVEMENT,25000,10.99,0,2021-04-01 22:02:47.278000+00:00,2021-04-01 22:02:47.278000+00:00 +37151,19950608_9060,16373,37,32000,RENT,4.0,DEBTCONSOLIDATION,10000,13.79,1,2020-09-13 19:08:33.110000+00:00,2020-09-13 19:08:33.110000+00:00 +21764,19461005_6797,66781,25,46200,RENT,1.0,DEBTCONSOLIDATION,2700,15.96,1,2021-03-28 21:59:40.219000+00:00,2021-03-28 21:59:40.219000+00:00 +30456,19711116_1945,76034,34,60100,MORTGAGE,6.0,EDUCATION,1500,6.03,0,2020-12-08 03:07:45.843000+00:00,2020-12-08 03:07:45.843000+00:00 +33358,19770804_8916,37130,33,90000,RENT,8.0,DEBTCONSOLIDATION,14500,14.65,0,2020-11-01 03:24:48.631000+00:00,2020-11-01 03:24:48.631000+00:00 +30863,19480222_5478,72956,29,54996,RENT,8.0,MEDICAL,9300,9.32,0,2020-12-02 22:37:44.146000+00:00,2020-12-02 22:37:44.146000+00:00 +11796,19731009_8512,47038,25,44400,RENT,6.0,EDUCATION,2350,13.98,0,2021-08-02 23:11:07.484000+00:00,2021-08-02 23:11:07.484000+00:00 +10237,19500102_1085,46366,25,66300,RENT,3.0,MEDICAL,25000,17.93,1,2021-08-22 20:04:49.218000+00:00,2021-08-22 20:04:49.218000+00:00 +33347,19910104_4528,21403,34,105000,MORTGAGE,2.0,MEDICAL,10000,7.51,0,2020-11-01 06:46:42.191000+00:00,2020-11-01 06:46:42.191000+00:00 +21295,19490717_5702,58344,23,85000,MORTGAGE,3.0,EDUCATION,4000,6.76,0,2021-04-03 21:27:38.342000+00:00,2021-04-03 21:27:38.342000+00:00 +11686,19550102_1482,81323,26,62400,RENT,3.0,PERSONAL,2000,12.53,0,2021-08-04 08:50:03.078000+00:00,2021-08-04 08:50:03.078000+00:00 +34453,19660204_1508,46240,29,300000,RENT,1.0,HOMEIMPROVEMENT,16000,11.58,0,2020-10-18 04:27:18.857000+00:00,2020-10-18 04:27:18.857000+00:00 +35166,19490220_6803,7432,27,66240,RENT,7.0,MEDICAL,5000,5.79,0,2020-10-09 02:20:59.962000+00:00,2020-10-09 02:20:59.962000+00:00 +19731,19860521_3415,29729,26,72000,MORTGAGE,10.0,MEDICAL,17000,10.65,0,2021-04-23 19:53:06.239000+00:00,2021-04-23 19:53:06.239000+00:00 +32628,19470903_9768,60044,28,28800,RENT,1.0,VENTURE,12250,10.59,1,2020-11-10 10:43:08.481000+00:00,2020-11-10 10:43:08.481000+00:00 +25168,19820206_8182,21919,23,32640,RENT,5.0,VENTURE,4800,11.99,0,2021-02-13 12:43:04.207000+00:00,2021-02-13 12:43:04.207000+00:00 +32265,19710123_6186,31778,28,83135,MORTGAGE,3.0,EDUCATION,8000,13.99,0,2020-11-15 01:45:35.941000+00:00,2020-11-15 01:45:35.941000+00:00 +12135,19510118_6401,77624,23,32004,OWN,0.0,EDUCATION,9250,17.19,0,2021-07-29 15:29:09.608000+00:00,2021-07-29 15:29:09.608000+00:00 +13792,19450220_8508,45810,22,40000,MORTGAGE,6.0,DEBTCONSOLIDATION,7000,9.32,0,2021-07-08 12:36:47.073000+00:00,2021-07-08 12:36:47.073000+00:00 +25405,19740507_4208,37857,21,65004,MORTGAGE,5.0,EDUCATION,5000,9.99,0,2021-02-10 12:13:12.064000+00:00,2021-02-10 12:13:12.064000+00:00 +36874,19480326_5471,38625,42,30000,RENT,5.0,VENTURE,8000,14.96,0,2020-09-17 07:52:34.560000+00:00,2020-09-17 07:52:34.560000+00:00 +12131,19480312_9985,73143,22,29376,RENT,1.0,EDUCATION,2800,7.43,0,2021-07-29 16:42:34.539000+00:00,2021-07-29 16:42:34.539000+00:00 +20570,19730416_9675,80904,26,61754,MORTGAGE,7.0,MEDICAL,10000,14.83,1,2021-04-13 03:14:12.028000+00:00,2021-04-13 03:14:12.028000+00:00 +10780,19690621_4640,38732,23,39600,RENT,5.0,EDUCATION,19000,10.62,1,2021-08-15 21:58:39.878000+00:00,2021-08-15 21:58:39.878000+00:00 +18239,19910430_3275,63301,26,62000,MORTGAGE,1.0,DEBTCONSOLIDATION,8400,6.62,0,2021-05-12 20:17:05.385000+00:00,2021-05-12 20:17:05.385000+00:00 +25547,19841109_1212,22842,21,47500,RENT,2.0,EDUCATION,7500,10.99,0,2021-02-08 16:46:57.025000+00:00,2021-02-08 16:46:57.025000+00:00 +11912,19590125_6131,51240,26,77508,RENT,10.0,VENTURE,13500,12.87,0,2021-08-01 11:42:04.494000+00:00,2021-08-01 11:42:04.494000+00:00 +35869,19881208_1257,70452,36,25000,MORTGAGE,0.0,HOMEIMPROVEMENT,3000,8.7,0,2020-09-30 03:18:13.394000+00:00,2020-09-30 03:18:13.394000+00:00 +12643,19870606_1700,74652,22,75000,RENT,6.0,EDUCATION,3200,10.28,0,2021-07-23 04:05:23.412000+00:00,2021-07-23 04:05:23.412000+00:00 +10183,19661226_9065,29689,25,72612,RENT,9.0,MEDICAL,25000,13.11,1,2021-08-23 12:35:55.782000+00:00,2021-08-23 12:35:55.782000+00:00 +30399,19700406_4808,40941,29,60000,MORTGAGE,8.0,HOMEIMPROVEMENT,16000,14.96,0,2020-12-08 20:33:56.105000+00:00,2020-12-08 20:33:56.105000+00:00 +26719,19691014_7980,67457,27,51000,RENT,1.0,HOMEIMPROVEMENT,2000,7.74,0,2021-01-24 18:16:12.334000+00:00,2021-01-24 18:16:12.334000+00:00 +37241,19970209_1933,2667,50,72000,MORTGAGE,13.0,MEDICAL,8000,11.49,0,2020-09-12 15:36:42.170000+00:00,2020-09-12 15:36:42.170000+00:00 +27227,19710212_2724,17257,33,75500,RENT,5.0,VENTURE,3000,12.42,0,2021-01-18 06:52:26.137000+00:00,2021-01-18 06:52:26.137000+00:00 +36117,19510809_4123,13411,41,39000,RENT,2.0,PERSONAL,3500,13.11,0,2020-09-26 23:26:27.692000+00:00,2020-09-26 23:26:27.692000+00:00 +13867,19780230_3383,90806,26,45000,RENT,1.0,MEDICAL,4800,5.42,0,2021-07-07 13:40:14.622000+00:00,2021-07-07 13:40:14.622000+00:00 +24296,19600201_4209,27609,22,27996,RENT,0.0,EDUCATION,2200,15.95,1,2021-02-24 15:27:39.096000+00:00,2021-02-24 15:27:39.096000+00:00 +34822,19860304_5438,63332,29,64000,RENT,3.0,DEBTCONSOLIDATION,15000,15.27,1,2020-10-13 11:34:44.001000+00:00,2020-10-13 11:34:44.001000+00:00 +17559,19800308_6778,98338,24,27000,RENT,3.0,VENTURE,8000,8.9,0,2021-05-21 12:17:43.601000+00:00,2021-05-21 12:17:43.601000+00:00 +15749,19520113_6906,71105,25,50000,RENT,1.0,MEDICAL,6000,14.79,0,2021-06-13 13:58:14.735000+00:00,2021-06-13 13:58:14.735000+00:00 +37361,19450317_3985,27619,38,77250,OWN,4.0,VENTURE,3000,8.59,0,2020-09-11 02:54:14.249000+00:00,2020-09-11 02:54:14.249000+00:00 +32135,19480621_2491,13153,28,34000,RENT,0.0,EDUCATION,12000,14.61,1,2020-11-16 17:31:36.188000+00:00,2020-11-16 17:31:36.188000+00:00 +30159,19700506_2597,18346,28,33000,RENT,12.0,DEBTCONSOLIDATION,8000,14.65,1,2020-12-11 21:58:51.946000+00:00,2020-12-11 21:58:51.946000+00:00 +24243,19520315_8466,44646,22,30000,RENT,4.0,EDUCATION,10000,11.86,1,2021-02-25 07:40:24.428000+00:00,2021-02-25 07:40:24.428000+00:00 +10708,19670704_6846,44830,22,22000,MORTGAGE,6.0,PERSONAL,7200,7.14,0,2021-08-16 20:00:08.630000+00:00,2021-08-16 20:00:08.630000+00:00 +34025,19920522_8812,60434,33,118000,MORTGAGE,5.0,DEBTCONSOLIDATION,25000,14.96,1,2020-10-23 15:22:46.440000+00:00,2020-10-23 15:22:46.440000+00:00 +38038,19890221_1496,27878,42,300000,RENT,26.0,MEDICAL,16000,9.63,0,2020-09-02 11:48:39.731000+00:00,2020-09-02 11:48:39.731000+00:00 +12666,19750124_1330,61028,24,35004,MORTGAGE,5.0,EDUCATION,7000,5.42,0,2021-07-22 21:03:15.060000+00:00,2021-07-22 21:03:15.060000+00:00 +37283,19850806_8554,43525,46,74500,MORTGAGE,0.0,VENTURE,10500,12.09,0,2020-09-12 02:45:50.398000+00:00,2020-09-12 02:45:50.398000+00:00 +24414,19711002_7371,84765,24,51000,MORTGAGE,4.0,EDUCATION,8500,8.94,0,2021-02-23 03:21:53.641000+00:00,2021-02-23 03:21:53.641000+00:00 +20353,19870730_5089,68002,26,59497,OWN,2.0,MEDICAL,7000,17.88,1,2021-04-15 21:36:59.518000+00:00,2021-04-15 21:36:59.518000+00:00 +38099,19760512_5496,75931,39,84000,OWN,12.0,VENTURE,9875,7.51,0,2020-09-01 17:09:04.538000+00:00,2020-09-01 17:09:04.538000+00:00 +28161,19521203_3450,97388,27,28968,RENT,1.0,PERSONAL,5000,13.16,0,2021-01-06 09:09:54.823000+00:00,2021-01-06 09:09:54.823000+00:00 +37342,19780913_4168,45246,38,76000,MORTGAGE,4.0,PERSONAL,9000,5.99,0,2020-09-11 08:42:57.670000+00:00,2020-09-11 08:42:57.670000+00:00 +26467,19700105_2778,76503,28,55000,RENT,5.0,PERSONAL,16000,13.98,0,2021-01-27 23:21:22.967000+00:00,2021-01-27 23:21:22.967000+00:00 +22169,19971012_1674,61434,24,42996,RENT,2.0,MEDICAL,14000,7.51,1,2021-03-23 18:06:20.987000+00:00,2021-03-23 18:06:20.987000+00:00 +25340,19780612_9832,74960,26,45000,MORTGAGE,6.0,VENTURE,5000,6.99,0,2021-02-11 08:06:12.188000+00:00,2021-02-11 08:06:12.188000+00:00 +32989,19570829_3300,12542,29,84000,MORTGAGE,6.0,DEBTCONSOLIDATION,8000,14.96,1,2020-11-05 20:17:23.487000+00:00,2020-11-05 20:17:23.487000+00:00 +35091,19460914_1042,98597,30,66888,MORTGAGE,6.0,HOMEIMPROVEMENT,15000,12.23,0,2020-10-10 01:17:32.412000+00:00,2020-10-10 01:17:32.412000+00:00 +33284,19821216_3789,24550,29,102000,OWN,10.0,MEDICAL,18000,9.33,0,2020-11-02 02:02:59.849000+00:00,2020-11-02 02:02:59.849000+00:00 +32079,20000126_1542,55005,27,35000,RENT,0.0,EDUCATION,12000,7.29,1,2020-11-17 10:39:25.218000+00:00,2020-11-17 10:39:25.218000+00:00 +36910,19880811_5009,15825,42,60000,MORTGAGE,4.0,HOMEIMPROVEMENT,8850,10.37,0,2020-09-16 20:51:50.184000+00:00,2020-09-16 20:51:50.184000+00:00 +34569,19870430_8371,47995,28,72000,MORTGAGE,9.0,HOMEIMPROVEMENT,18000,11.89,0,2020-10-16 16:58:15.867000+00:00,2020-10-16 16:58:15.867000+00:00 +27921,19890823_9776,16262,35,39000,RENT,8.0,DEBTCONSOLIDATION,4500,6.62,0,2021-01-09 10:34:50.664000+00:00,2021-01-09 10:34:50.664000+00:00 +24659,19601129_4223,16410,26,45000,MORTGAGE,9.0,PERSONAL,10000,16.89,0,2021-02-20 00:25:11.637000+00:00,2021-02-20 00:25:11.637000+00:00 +26328,19750409_4895,68638,27,64000,RENT,3.0,MEDICAL,18000,11.11,0,2021-01-29 17:52:34.309000+00:00,2021-01-29 17:52:34.309000+00:00 +37715,19941224_9758,35611,39,100000,MORTGAGE,0.0,VENTURE,6000,14.11,0,2020-09-06 14:36:57.884000+00:00,2020-09-06 14:36:57.884000+00:00 +24614,19790325_8007,5037,26,48000,RENT,5.0,DEBTCONSOLIDATION,25000,18.43,1,2021-02-20 14:11:07.107000+00:00,2021-02-20 14:11:07.107000+00:00 +18299,19970303_2510,71031,24,85000,RENT,0.0,HOMEIMPROVEMENT,8000,13.06,0,2021-05-12 01:55:51.424000+00:00,2021-05-12 01:55:51.424000+00:00 +32741,19550317_6465,59803,30,91000,MORTGAGE,7.0,EDUCATION,33950,7.9,0,2020-11-09 00:09:09.189000+00:00,2020-11-09 00:09:09.189000+00:00 +36674,19850917_3339,37659,36,51996,OWN,7.0,HOMEIMPROVEMENT,8500,11.49,0,2020-09-19 21:03:21.094000+00:00,2020-09-19 21:03:21.094000+00:00 +16932,19590601_1477,98036,23,55000,MORTGAGE,2.0,EDUCATION,5000,11.11,0,2021-05-29 12:05:36.486000+00:00,2021-05-29 12:05:36.486000+00:00 +32996,19521009_8624,3086,31,84000,MORTGAGE,3.0,HOMEIMPROVEMENT,25000,17.34,1,2020-11-05 18:08:54.858000+00:00,2020-11-05 18:08:54.858000+00:00 +34856,19490916_9161,92654,30,51000,RENT,14.0,PERSONAL,4800,12.69,0,2020-10-13 01:10:42.090000+00:00,2020-10-13 01:10:42.090000+00:00 +27758,19550522_5423,51453,31,41000,RENT,7.0,VENTURE,4000,10.99,0,2021-01-11 12:26:31.589000+00:00,2021-01-11 12:26:31.589000+00:00 +37358,19890126_7407,31210,48,55000,RENT,9.0,MEDICAL,10200,13.92,0,2020-09-11 03:49:17.947000+00:00,2020-09-11 03:49:17.947000+00:00 +32584,19541129_7340,29704,29,89849,MORTGAGE,13.0,EDUCATION,6000,13.98,0,2020-11-11 00:10:42.719000+00:00,2020-11-11 00:10:42.719000+00:00 +34516,19640427_3737,80654,33,300000,OWN,8.0,MEDICAL,25000,14.42,0,2020-10-17 09:11:01.198000+00:00,2020-10-17 09:11:01.198000+00:00 +25248,19821024_5625,20732,23,157500,RENT,1.0,EDUCATION,10000,12.69,0,2021-02-12 12:14:45.593000+00:00,2021-02-12 12:14:45.593000+00:00 +34463,19991223_4134,93664,34,225000,MORTGAGE,4.0,MEDICAL,3000,13.35,0,2020-10-18 01:23:46.530000+00:00,2020-10-18 01:23:46.530000+00:00 +20559,20010604_7016,98651,22,78413,MORTGAGE,6.0,EDUCATION,17500,10.65,0,2021-04-13 06:36:05.588000+00:00,2021-04-13 06:36:05.588000+00:00 +17660,19970822_5090,38915,22,30000,RENT,2.0,DEBTCONSOLIDATION,8000,11.11,1,2021-05-20 05:23:59.101000+00:00,2021-05-20 05:23:59.101000+00:00 +33236,20001204_1738,25570,29,100000,MORTGAGE,7.0,MEDICAL,15000,12.04,0,2020-11-02 16:43:59.017000+00:00,2020-11-02 16:43:59.017000+00:00 +16605,19880709_9925,10011,26,31836,RENT,1.0,VENTURE,6400,14.35,0,2021-06-02 16:07:19.569000+00:00,2021-06-02 16:07:19.569000+00:00 +28400,20000517_4791,84317,27,88000,RENT,11.0,DEBTCONSOLIDATION,9000,6.91,0,2021-01-03 08:03:20.214000+00:00,2021-01-03 08:03:20.214000+00:00 +27949,19500708_3201,75713,29,70000,RENT,2.0,PERSONAL,4500,5.42,0,2021-01-09 02:00:56.149000+00:00,2021-01-09 02:00:56.149000+00:00 +29042,19451210_3991,63436,32,36000,RENT,4.0,MEDICAL,6000,16.07,1,2020-12-26 03:40:08.839000+00:00,2020-12-26 03:40:08.839000+00:00 +21168,19901115_3595,15834,22,65400,RENT,1.0,EDUCATION,12000,13.06,0,2021-04-05 12:18:34.891000+00:00,2021-04-05 12:18:34.891000+00:00 +11015,19980918_9319,72632,24,72000,RENT,0.0,DEBTCONSOLIDATION,16875,6.54,0,2021-08-12 22:05:30.200000+00:00,2021-08-12 22:05:30.200000+00:00 +23803,20000219_1345,56501,25,39000,RENT,9.0,VENTURE,15200,16.0,1,2021-03-02 22:16:06.803000+00:00,2021-03-02 22:16:06.803000+00:00 +31056,19600625_4745,69044,29,30000,RENT,3.0,EDUCATION,10000,16.82,1,2020-11-30 11:35:26.240000+00:00,2020-11-30 11:35:26.240000+00:00 +10475,19801206_7479,61238,25,51060,RENT,9.0,VENTURE,21250,6.91,1,2021-08-19 19:16:35.842000+00:00,2021-08-19 19:16:35.842000+00:00 +23871,19501008_3936,48628,22,165500,MORTGAGE,6.0,EDUCATION,12000,12.99,0,2021-03-02 01:28:02.981000+00:00,2021-03-02 01:28:02.981000+00:00 +24420,19471228_5728,66451,22,47800,MORTGAGE,5.0,PERSONAL,1500,13.43,0,2021-02-23 01:31:46.245000+00:00,2021-02-23 01:31:46.245000+00:00 +16436,19800110_7264,14814,26,52700,MORTGAGE,7.0,PERSONAL,4000,7.4,0,2021-06-04 19:49:07.890000+00:00,2021-06-04 19:49:07.890000+00:00 +35726,19560411_8302,33849,36,127000,RENT,20.0,DEBTCONSOLIDATION,25000,14.59,1,2020-10-01 23:02:49.666000+00:00,2020-10-01 23:02:49.666000+00:00 +13363,19780309_8183,87199,22,30000,RENT,1.0,EDUCATION,4000,14.96,1,2021-07-13 23:50:35.888000+00:00,2021-07-13 23:50:35.888000+00:00 +17794,20000317_1989,13413,24,60000,MORTGAGE,8.0,MEDICAL,13000,7.29,0,2021-05-18 12:24:33.923000+00:00,2021-05-18 12:24:33.923000+00:00 +26732,19790208_2696,66866,27,69000,RENT,1.0,MEDICAL,2000,6.99,0,2021-01-24 14:17:36.310000+00:00,2021-01-24 14:17:36.310000+00:00 +25641,19520304_1262,33917,24,54000,MORTGAGE,8.0,PERSONAL,4000,9.99,0,2021-02-07 12:01:41.154000+00:00,2021-02-07 12:01:41.154000+00:00 +37947,19650829_5030,91784,43,142500,MORTGAGE,7.0,MEDICAL,20000,11.49,0,2020-09-03 15:38:51.904000+00:00,2020-09-03 15:38:51.904000+00:00 +13597,19510311_7617,14085,23,40000,MORTGAGE,3.0,MEDICAL,5000,5.42,0,2021-07-11 00:15:47.443000+00:00,2021-07-11 00:15:47.443000+00:00 +15947,19640125_6629,93422,24,50000,MORTGAGE,8.0,EDUCATION,3000,13.47,0,2021-06-11 01:24:10.666000+00:00,2021-06-11 01:24:10.666000+00:00 +17629,19800220_8140,97119,22,34000,RENT,2.0,DEBTCONSOLIDATION,8000,9.91,0,2021-05-20 14:52:57.314000+00:00,2021-05-20 14:52:57.314000+00:00 +23726,19571214_6062,92571,23,85000,RENT,7.0,PERSONAL,15000,10.99,0,2021-03-03 21:49:21.719000+00:00,2021-03-03 21:49:21.719000+00:00 +29649,19601016_7021,95666,34,54072,MORTGAGE,12.0,PERSONAL,7000,11.89,0,2020-12-18 09:59:20.608000+00:00,2020-12-18 09:59:20.608000+00:00 +28911,19650107_9702,54301,31,48000,OWN,0.0,HOMEIMPROVEMENT,20000,10.62,0,2020-12-27 19:44:30.319000+00:00,2020-12-27 19:44:30.319000+00:00 +17821,19640221_8062,26377,22,60000,MORTGAGE,6.0,VENTURE,7800,7.29,0,2021-05-18 04:09:00.641000+00:00,2021-05-18 04:09:00.641000+00:00 +26606,19541019_6076,85078,27,28500,MORTGAGE,3.0,VENTURE,1600,13.49,1,2021-01-26 04:50:11.626000+00:00,2021-01-26 04:50:11.626000+00:00 +14745,19670129_8967,84070,26,45000,MORTGAGE,3.0,EDUCATION,4000,14.35,0,2021-06-26 09:05:32.337000+00:00,2021-06-26 09:05:32.337000+00:00 +30348,20010118_5122,81526,27,60000,MORTGAGE,3.0,PERSONAL,5000,16.45,0,2020-12-09 12:09:58.971000+00:00,2020-12-09 12:09:58.971000+00:00 +32477,19980613_8887,31801,27,86004,MORTGAGE,8.0,HOMEIMPROVEMENT,16000,14.42,0,2020-11-12 08:54:34.615000+00:00,2020-11-12 08:54:34.615000+00:00 +32970,19950214_3891,37397,33,96000,MORTGAGE,0.0,VENTURE,8000,13.72,0,2020-11-06 02:06:06.908000+00:00,2020-11-06 02:06:06.908000+00:00 +24413,19480923_4101,2660,24,72000,RENT,4.0,EDUCATION,15000,10.99,0,2021-02-23 03:40:14.874000+00:00,2021-02-23 03:40:14.874000+00:00 +18816,19760804_7354,72336,22,31000,RENT,7.0,MEDICAL,9250,14.11,1,2021-05-05 11:46:54.133000+00:00,2021-05-05 11:46:54.133000+00:00 +19975,19850618_4159,68752,25,60000,RENT,9.0,VENTURE,10000,9.91,0,2021-04-20 17:14:45.468000+00:00,2021-04-20 17:14:45.468000+00:00 +30800,19860425_8873,78539,34,47700,RENT,2.0,DEBTCONSOLIDATION,9000,7.14,0,2020-12-03 17:54:01.804000+00:00,2020-12-03 17:54:01.804000+00:00 +12493,19671228_8355,32305,22,58992,RENT,0.0,MEDICAL,3000,12.84,1,2021-07-25 01:58:28.312000+00:00,2021-07-25 01:58:28.312000+00:00 +35307,19790506_1791,43521,27,19200,MORTGAGE,3.0,DEBTCONSOLIDATION,1400,16.77,1,2020-10-07 07:13:06.156000+00:00,2020-10-07 07:13:06.156000+00:00 +26818,19651116_6841,27102,30,29004,RENT,13.0,MEDICAL,2400,17.93,1,2021-01-23 11:59:10.300000+00:00,2021-01-23 11:59:10.300000+00:00 +35188,19580121_3344,89701,28,28320,RENT,4.0,VENTURE,8700,14.61,1,2020-10-08 19:37:12.843000+00:00,2020-10-08 19:37:12.843000+00:00 +33608,20010526_6233,54970,33,115000,MORTGAGE,6.0,MEDICAL,10500,13.49,0,2020-10-28 22:56:20.464000+00:00,2020-10-28 22:56:20.464000+00:00 +11733,19500219_4645,14048,26,110000,RENT,0.0,DEBTCONSOLIDATION,2100,7.12,0,2021-08-03 18:27:25.142000+00:00,2021-08-03 18:27:25.142000+00:00 +36571,19900328_1265,92110,36,38160,RENT,3.0,EDUCATION,6000,12.61,0,2020-09-21 04:33:48.059000+00:00,2020-09-21 04:33:48.059000+00:00 +25677,19461206_7518,53556,25,25716,RENT,1.0,MEDICAL,9250,6.54,1,2021-02-07 01:00:56.777000+00:00,2021-02-07 01:00:56.777000+00:00 +33570,19580705_1279,71327,29,42000,RENT,5.0,PERSONAL,15000,10.99,1,2020-10-29 10:33:47.305000+00:00,2020-10-29 10:33:47.305000+00:00 +15006,19560427_7774,54848,23,35000,RENT,7.0,PERSONAL,5400,10.59,0,2021-06-23 01:15:10.610000+00:00,2021-06-23 01:15:10.610000+00:00 +15928,19970908_9926,23703,25,57500,RENT,4.0,VENTURE,6000,11.28,1,2021-06-11 07:12:54.087000+00:00,2021-06-11 07:12:54.087000+00:00 +20564,19540129_8592,1376,23,78500,MORTGAGE,7.0,DEBTCONSOLIDATION,4800,7.14,0,2021-04-13 05:04:19.424000+00:00,2021-04-13 05:04:19.424000+00:00 +34104,19541220_1198,18518,34,135600,MORTGAGE,10.0,EDUCATION,1000,5.42,0,2020-10-22 15:12:49.059000+00:00,2020-10-22 15:12:49.059000+00:00 +31609,19650806_1345,78940,28,75000,MORTGAGE,3.0,HOMEIMPROVEMENT,15000,8.9,0,2020-11-23 10:25:44.573000+00:00,2020-11-23 10:25:44.573000+00:00 +15993,19590913_4204,62360,22,50000,OWN,6.0,MEDICAL,15000,8.63,0,2021-06-10 11:19:53.964000+00:00,2021-06-10 11:19:53.964000+00:00 +25552,19801210_5822,1072,22,33685,MORTGAGE,6.0,DEBTCONSOLIDATION,5000,13.85,0,2021-02-08 15:15:10.861000+00:00,2021-02-08 15:15:10.861000+00:00 +37796,19750118_4263,46182,38,112224,MORTGAGE,5.0,EDUCATION,25000,6.99,0,2020-09-05 13:50:18.037000+00:00,2020-09-05 13:50:18.037000+00:00 +29683,19900620_6973,71073,29,39996,RENT,3.0,PERSONAL,7000,9.32,0,2020-12-17 23:35:18.697000+00:00,2020-12-17 23:35:18.697000+00:00 +24369,19530101_9929,54888,20,188004,MORTGAGE,4.0,PERSONAL,2000,8.59,0,2021-02-23 17:07:49.111000+00:00,2021-02-23 17:07:49.111000+00:00 +34021,19520207_6672,61025,35,130000,MORTGAGE,3.0,DEBTCONSOLIDATION,9000,12.73,0,2020-10-23 16:36:11.370000+00:00,2020-10-23 16:36:11.370000+00:00 +37136,19860716_9552,62258,39,68000,MORTGAGE,1.0,PERSONAL,16000,13.49,0,2020-09-13 23:43:51.600000+00:00,2020-09-13 23:43:51.600000+00:00 +11943,19930107_1287,56368,23,75000,RENT,3.0,VENTURE,13200,6.17,0,2021-08-01 02:13:06.281000+00:00,2021-08-01 02:13:06.281000+00:00 +20871,19900406_8998,75480,24,80004,MORTGAGE,8.0,HOMEIMPROVEMENT,6000,6.17,0,2021-04-09 07:09:40.994000+00:00,2021-04-09 07:09:40.994000+00:00 +14409,19671005_8397,30224,24,48000,RENT,3.0,EDUCATION,5000,11.89,0,2021-06-30 15:52:26.515000+00:00,2021-06-30 15:52:26.515000+00:00 +18215,19970502_7007,29071,22,61500,MORTGAGE,5.0,VENTURE,30000,6.62,0,2021-05-13 03:37:34.969000+00:00,2021-05-13 03:37:34.969000+00:00 +10956,19780901_1846,80918,25,44000,RENT,6.0,EDUCATION,17500,12.53,1,2021-08-13 16:08:22.928000+00:00,2021-08-13 16:08:22.928000+00:00 +32282,19780304_8864,74431,27,26208,RENT,0.0,EDUCATION,3000,13.98,0,2020-11-14 20:33:34.985000+00:00,2020-11-14 20:33:34.985000+00:00 +34349,19541007_8325,84526,28,158367,MORTGAGE,5.0,MEDICAL,12000,6.62,0,2020-10-19 12:16:07.054000+00:00,2020-10-19 12:16:07.054000+00:00 +13782,19870617_6419,27573,22,40000,OWN,0.0,EDUCATION,6000,11.48,0,2021-07-08 15:40:19.399000+00:00,2021-07-08 15:40:19.399000+00:00 +25685,19920326_2575,97624,32,1200000,MORTGAGE,1.0,VENTURE,12000,7.51,0,2021-02-06 22:34:06.916000+00:00,2021-02-06 22:34:06.916000+00:00 +33738,19621202_3047,94114,28,50000,RENT,1.0,EDUCATION,15000,10.28,0,2020-10-27 07:10:20.216000+00:00,2020-10-27 07:10:20.216000+00:00 +19983,19491225_7277,27973,23,74000,MORTGAGE,4.0,VENTURE,20000,11.48,0,2021-04-20 14:47:55.606000+00:00,2021-04-20 14:47:55.606000+00:00 +19107,19920613_7381,97411,22,23000,RENT,6.0,MEDICAL,10000,9.88,1,2021-05-01 18:45:55.426000+00:00,2021-05-01 18:45:55.426000+00:00 +37328,19560903_8682,40066,43,80000,RENT,5.0,HOMEIMPROVEMENT,10000,11.49,0,2020-09-11 12:59:54.927000+00:00,2020-09-11 12:59:54.927000+00:00 +33714,19460507_1447,47640,29,120000,MORTGAGE,7.0,DEBTCONSOLIDATION,20000,12.42,0,2020-10-27 14:30:49.800000+00:00,2020-10-27 14:30:49.800000+00:00 +18772,19840716_9517,5158,26,29000,RENT,10.0,DEBTCONSOLIDATION,9200,7.49,1,2021-05-06 01:14:28.371000+00:00,2021-05-06 01:14:28.371000+00:00 +29229,20000619_8396,12992,30,50000,MORTGAGE,3.0,HOMEIMPROVEMENT,5000,10.95,0,2020-12-23 18:27:58.330000+00:00,2020-12-23 18:27:58.330000+00:00 +16817,19880401_9015,18929,23,54996,MORTGAGE,7.0,PERSONAL,8000,14.35,0,2021-05-30 23:16:18.243000+00:00,2021-05-30 23:16:18.243000+00:00 +19123,19670902_1880,77903,23,24960,RENT,0.0,PERSONAL,10000,9.64,1,2021-05-01 13:52:15.703000+00:00,2021-05-01 13:52:15.703000+00:00 +34113,19760129_4733,28741,28,124886,MORTGAGE,12.0,HOMEIMPROVEMENT,5000,11.99,1,2020-10-22 12:27:37.965000+00:00,2020-10-22 12:27:37.965000+00:00 +17446,19750123_7667,24343,23,58000,OWN,4.0,MEDICAL,6400,13.48,0,2021-05-22 22:51:42.893000+00:00,2021-05-22 22:51:42.893000+00:00 +13332,19760912_2249,48120,23,38400,OWN,7.0,PERSONAL,6000,13.24,0,2021-07-14 09:19:34.101000+00:00,2021-07-14 09:19:34.101000+00:00 +36020,19980718_7492,64502,47,72000,RENT,5.0,VENTURE,2500,15.05,0,2020-09-28 05:06:47.261000+00:00,2020-09-28 05:06:47.261000+00:00 +29441,19730321_1883,29822,27,52000,MORTGAGE,6.0,PERSONAL,11500,7.14,0,2020-12-21 01:36:57.004000+00:00,2020-12-21 01:36:57.004000+00:00 +31847,19851103_8214,78411,30,77000,MORTGAGE,4.0,DEBTCONSOLIDATION,8000,7.14,0,2020-11-20 09:37:31.197000+00:00,2020-11-20 09:37:31.197000+00:00 +25936,19721225_5495,52229,29,92200,RENT,7.0,VENTURE,25000,14.96,0,2021-02-03 17:47:17.516000+00:00,2021-02-03 17:47:17.516000+00:00 +14161,19591204_6177,48317,22,32968,RENT,2.0,DEBTCONSOLIDATION,5000,14.61,1,2021-07-03 19:44:12.217000+00:00,2021-07-03 19:44:12.217000+00:00 +25012,19681114_6916,38039,23,30000,RENT,8.0,EDUCATION,10625,6.92,1,2021-02-15 12:26:16.504000+00:00,2021-02-15 12:26:16.504000+00:00 +29530,19630417_2688,33567,29,53000,MORTGAGE,13.0,DEBTCONSOLIDATION,10750,13.11,0,2020-12-19 22:23:27.296000+00:00,2020-12-19 22:23:27.296000+00:00 +10363,20010523_1924,17225,23,47004,RENT,1.0,VENTURE,24000,11.58,1,2021-08-21 05:32:13.901000+00:00,2021-08-21 05:32:13.901000+00:00 +17991,19520918_9666,15539,25,21000,RENT,0.0,DEBTCONSOLIDATION,5175,12.53,1,2021-05-16 00:08:51.087000+00:00,2021-05-16 00:08:51.087000+00:00 +12178,19870416_6117,64720,26,32450,MORTGAGE,5.0,MEDICAL,3250,6.99,0,2021-07-29 02:19:56.604000+00:00,2021-07-29 02:19:56.604000+00:00 +34611,19520313_7280,61410,29,117000,RENT,6.0,EDUCATION,21000,10.65,0,2020-10-16 04:07:24.095000+00:00,2020-10-16 04:07:24.095000+00:00 +11426,19461118_1378,32446,26,51996,RENT,10.0,VENTURE,1500,13.85,0,2021-08-07 16:22:03.572000+00:00,2021-08-07 16:22:03.572000+00:00 +18107,19710213_4280,77502,25,24000,RENT,3.0,EDUCATION,5000,6.92,0,2021-05-14 12:39:48.097000+00:00,2021-05-14 12:39:48.097000+00:00 +30949,19720715_7529,36541,34,60000,MORTGAGE,18.0,EDUCATION,3000,11.99,1,2020-12-01 20:19:18.136000+00:00,2020-12-01 20:19:18.136000+00:00 +38395,19550816_5423,93612,53,304800,RENT,6.0,VENTURE,5000,8.88,0,2020-08-28 22:36:19.667000+00:00,2020-08-28 22:36:19.667000+00:00 +25102,19831011_8872,49456,25,51492,MORTGAGE,2.0,EDUCATION,13800,10.38,0,2021-02-14 08:54:25.563000+00:00,2021-02-14 08:54:25.563000+00:00 +37402,19521016_7977,10933,36,80000,MORTGAGE,3.0,VENTURE,12025,10.65,0,2020-09-10 14:21:43.710000+00:00,2020-09-10 14:21:43.710000+00:00 +38484,19861012_5786,28751,60,49008,OWN,5.0,PERSONAL,12000,13.79,0,2020-08-27 19:22:49.960000+00:00,2020-08-27 19:22:49.960000+00:00 +32963,19980608_1974,60188,29,71400,MORTGAGE,1.0,MEDICAL,8000,8.49,1,2020-11-06 04:14:35.536000+00:00,2020-11-06 04:14:35.536000+00:00 +16412,19500615_6768,23459,21,43000,RENT,5.0,EDUCATION,6500,12.73,0,2021-06-05 03:09:37.474000+00:00,2021-06-05 03:09:37.474000+00:00 +18692,19651012_8609,73502,23,65000,MORTGAGE,5.0,EDUCATION,4000,11.49,0,2021-05-07 01:42:46.985000+00:00,2021-05-07 01:42:46.985000+00:00 +32118,19790817_5102,48708,28,80000,MORTGAGE,8.0,EDUCATION,13000,13.47,0,2020-11-16 22:43:37.143000+00:00,2020-11-16 22:43:37.143000+00:00 +19662,19790905_9453,14805,23,55000,RENT,7.0,MEDICAL,4200,9.91,0,2021-04-24 16:59:31.294000+00:00,2021-04-24 16:59:31.294000+00:00 +28271,19740703_6655,98247,28,42000,RENT,4.0,MEDICAL,5000,5.42,0,2021-01-04 23:30:59.229000+00:00,2021-01-04 23:30:59.229000+00:00 +24345,19820504_8810,2135,22,38000,MORTGAGE,6.0,DEBTCONSOLIDATION,8500,5.42,0,2021-02-24 00:28:18.695000+00:00,2021-02-24 00:28:18.695000+00:00 +30899,19670830_6170,57106,29,77040,RENT,1.0,EDUCATION,9500,12.84,0,2020-12-02 11:36:59.769000+00:00,2020-12-02 11:36:59.769000+00:00 +10009,19780808_9123,71260,21,10000,OWN,6.0,VENTURE,1600,14.74,1,2021-08-25 17:49:30.267000+00:00,2021-08-25 17:49:30.267000+00:00 +27472,19570725_4176,68841,28,69996,RENT,1.0,VENTURE,11000,13.79,0,2021-01-15 03:55:44.133000+00:00,2021-01-15 03:55:44.133000+00:00 +29246,20011202_2398,27314,29,74000,RENT,2.0,HOMEIMPROVEMENT,6000,5.42,0,2020-12-23 13:15:57.375000+00:00,2020-12-23 13:15:57.375000+00:00 +23779,19971008_4402,88013,25,150000,MORTGAGE,9.0,MEDICAL,12125,8.7,0,2021-03-03 05:36:36.387000+00:00,2021-03-03 05:36:36.387000+00:00 +17774,19680521_1163,72016,26,43000,RENT,1.0,MEDICAL,8000,12.87,0,2021-05-18 18:31:38.577000+00:00,2021-05-18 18:31:38.577000+00:00 +26065,19850929_2789,70339,28,58704,RENT,5.0,DEBTCONSOLIDATION,23500,14.72,1,2021-02-02 02:19:38.501000+00:00,2021-02-02 02:19:38.501000+00:00 +35124,19500503_4897,13039,27,80000,MORTGAGE,11.0,VENTURE,5000,8.0,0,2020-10-09 15:11:51.734000+00:00,2020-10-09 15:11:51.734000+00:00 +16810,19531112_6653,93654,24,37000,RENT,2.0,MEDICAL,7000,7.51,0,2021-05-31 01:24:46.871000+00:00,2021-05-31 01:24:46.871000+00:00 +37197,19730307_1277,46360,45,36000,RENT,1.0,VENTURE,4300,10.91,0,2020-09-13 05:04:16.407000+00:00,2020-09-13 05:04:16.407000+00:00 +24803,19990102_7440,24067,22,54000,MORTGAGE,5.0,MEDICAL,7000,10.65,0,2021-02-18 04:22:14.132000+00:00,2021-02-18 04:22:14.132000+00:00 +36314,19761209_5898,32462,41,121200,RENT,1.0,VENTURE,10000,6.03,0,2020-09-24 11:10:44.856000+00:00,2020-09-24 11:10:44.856000+00:00 +31986,19991109_2807,47404,27,38500,RENT,0.0,DEBTCONSOLIDATION,11500,12.42,0,2020-11-18 15:06:19.856000+00:00,2020-11-18 15:06:19.856000+00:00 +36830,19561212_2700,78557,38,64800,RENT,15.0,PERSONAL,7500,9.63,0,2020-09-17 21:20:08.798000+00:00,2020-09-17 21:20:08.798000+00:00 +14350,19520113_9018,62201,25,43000,MORTGAGE,5.0,DEBTCONSOLIDATION,10000,7.88,0,2021-07-01 09:55:19.242000+00:00,2021-07-01 09:55:19.242000+00:00 +36261,19920311_4228,29909,36,40000,OWN,2.0,PERSONAL,5000,7.88,0,2020-09-25 03:23:30.187000+00:00,2020-09-25 03:23:30.187000+00:00 +25873,19520329_4764,30031,35,192000,MORTGAGE,11.0,HOMEIMPROVEMENT,10000,11.99,0,2021-02-04 13:03:35.174000+00:00,2021-02-04 13:03:35.174000+00:00 +14128,19770819_6548,18224,21,30000,RENT,3.0,VENTURE,5000,13.92,0,2021-07-04 05:49:52.895000+00:00,2021-07-04 05:49:52.895000+00:00 +38552,19650412_2624,93160,55,34000,RENT,0.0,DEBTCONSOLIDATION,12000,6.92,1,2020-08-26 22:34:46.138000+00:00,2020-08-26 22:34:46.138000+00:00 +14867,19950326_6863,16748,25,76000,RENT,1.0,DEBTCONSOLIDATION,5000,7.9,0,2021-06-24 19:46:21.951000+00:00,2021-06-24 19:46:21.951000+00:00 +37447,19990913_6732,47449,44,80160,MORTGAGE,13.0,DEBTCONSOLIDATION,5500,13.92,0,2020-09-10 00:35:48.240000+00:00,2020-09-10 00:35:48.240000+00:00 +26458,19870230_8723,10023,35,44000,RENT,3.0,PERSONAL,16000,13.99,1,2021-01-28 02:06:34.061000+00:00,2021-01-28 02:06:34.061000+00:00 +17077,19521111_8053,61370,25,52000,RENT,3.0,EDUCATION,7200,12.69,0,2021-05-27 15:44:17.748000+00:00,2021-05-27 15:44:17.748000+00:00 +23828,19840927_3367,54889,25,144996,MORTGAGE,9.0,DEBTCONSOLIDATION,17600,14.84,1,2021-03-02 14:37:15.986000+00:00,2021-03-02 14:37:15.986000+00:00 +30197,19890607_9666,46311,31,37681,RENT,16.0,DEBTCONSOLIDATION,8000,10.99,0,2020-12-11 10:21:25.104000+00:00,2020-12-11 10:21:25.104000+00:00 +22543,19940220_4202,29129,24,70000,RENT,5.0,HOMEIMPROVEMENT,14400,12.23,0,2021-03-18 23:41:59.968000+00:00,2021-03-18 23:41:59.968000+00:00 +28798,19861023_4485,72089,31,30000,RENT,1.0,DEBTCONSOLIDATION,5600,7.74,0,2020-12-29 06:18:29.611000+00:00,2020-12-29 06:18:29.611000+00:00 +17195,19710412_8079,19545,22,25000,RENT,0.0,PERSONAL,7500,7.51,0,2021-05-26 03:38:32.293000+00:00,2021-05-26 03:38:32.293000+00:00 +13615,19791213_6708,30341,25,40000,MORTGAGE,9.0,DEBTCONSOLIDATION,3500,13.49,0,2021-07-10 18:45:25.255000+00:00,2021-07-10 18:45:25.255000+00:00 +26278,19510824_6848,76107,29,14400,RENT,3.0,EDUCATION,1000,16.32,1,2021-01-30 09:10:15.942000+00:00,2021-01-30 09:10:15.942000+00:00 +20708,20010723_8521,53929,23,80000,MORTGAGE,6.0,EDUCATION,9000,7.49,0,2021-04-11 09:01:21.920000+00:00,2021-04-11 09:01:21.920000+00:00 +16799,19990822_3741,4761,24,54996,MORTGAGE,8.0,VENTURE,5500,5.99,0,2021-05-31 04:46:40.431000+00:00,2021-05-31 04:46:40.431000+00:00 +15596,19620322_7692,22315,26,49995,MORTGAGE,10.0,EDUCATION,10000,11.71,0,2021-06-15 12:46:23.334000+00:00,2021-06-15 12:46:23.334000+00:00 +31149,19891102_5641,83332,27,69830,OWN,3.0,EDUCATION,15000,16.45,0,2020-11-29 07:08:31.602000+00:00,2020-11-29 07:08:31.602000+00:00 +12385,20000924_1583,98445,24,53000,RENT,6.0,VENTURE,12000,11.11,0,2021-07-26 11:00:41.441000+00:00,2021-07-26 11:00:41.441000+00:00 +31249,19680402_2654,91320,33,43337,RENT,17.0,PERSONAL,10000,6.92,0,2020-11-28 00:33:08.335000+00:00,2020-11-28 00:33:08.335000+00:00 +20340,19590528_8241,32837,23,83000,RENT,3.0,MEDICAL,10000,6.54,0,2021-04-16 01:35:35.543000+00:00,2021-04-16 01:35:35.543000+00:00 +24679,19700814_6341,80034,24,30000,RENT,8.0,MEDICAL,8000,9.25,0,2021-02-19 18:18:06.983000+00:00,2021-02-19 18:18:06.983000+00:00 +22753,19820623_5294,36343,23,37000,RENT,2.0,PERSONAL,2000,11.14,0,2021-03-16 07:27:41.108000+00:00,2021-03-16 07:27:41.108000+00:00 +36934,19910319_8730,15131,40,60000,MORTGAGE,1.0,VENTURE,4800,14.59,0,2020-09-16 13:31:20.600000+00:00,2020-09-16 13:31:20.600000+00:00 +25389,19680426_8272,24077,25,70000,MORTGAGE,6.0,VENTURE,14000,5.42,0,2021-02-10 17:06:51.787000+00:00,2021-02-10 17:06:51.787000+00:00 +27590,19560401_5451,55943,27,70000,RENT,9.0,MEDICAL,3600,14.79,0,2021-01-13 15:49:58.678000+00:00,2021-01-13 15:49:58.678000+00:00 +27477,19830129_6638,96141,27,83604,RENT,2.0,MEDICAL,11000,9.76,0,2021-01-15 02:23:57.970000+00:00,2021-01-15 02:23:57.970000+00:00 +10826,19500916_9213,79529,25,46000,RENT,8.0,DEBTCONSOLIDATION,18250,14.26,1,2021-08-15 07:54:23.175000+00:00,2021-08-15 07:54:23.175000+00:00 +34675,19640826_2701,10010,29,99000,RENT,3.0,PERSONAL,8000,12.99,0,2020-10-15 08:32:45.204000+00:00,2020-10-15 08:32:45.204000+00:00 +31617,19950614_8318,28722,27,75000,MORTGAGE,6.0,PERSONAL,3500,6.03,0,2020-11-23 07:58:54.712000+00:00,2020-11-23 07:58:54.712000+00:00 +28620,19760924_6012,67561,31,39000,MORTGAGE,0.0,HOMEIMPROVEMENT,12000,13.3,1,2020-12-31 12:45:29.027000+00:00,2020-12-31 12:45:29.027000+00:00 +34631,19580401_1779,66724,28,64900,MORTGAGE,12.0,DEBTCONSOLIDATION,25000,15.37,1,2020-10-15 22:00:19.441000+00:00,2020-10-15 22:00:19.441000+00:00 +28909,19620801_1015,59487,31,24000,RENT,3.0,VENTURE,6000,8.49,0,2020-12-27 20:21:12.785000+00:00,2020-12-27 20:21:12.785000+00:00 +23168,19730420_2738,89049,26,50004,RENT,3.0,VENTURE,15000,13.72,0,2021-03-11 00:30:49.549000+00:00,2021-03-11 00:30:49.549000+00:00 +17383,19810519_4844,17403,25,74004,RENT,2.0,DEBTCONSOLIDATION,7500,12.61,1,2021-05-23 18:08:00.551000+00:00,2021-05-23 18:08:00.551000+00:00 +30021,19970825_2224,13338,32,155000,RENT,3.0,PERSONAL,7500,11.59,0,2020-12-13 16:11:42.055000+00:00,2020-12-13 16:11:42.055000+00:00 +37117,19850316_6074,60959,37,60000,RENT,0.0,VENTURE,9700,13.61,0,2020-09-14 05:32:35.021000+00:00,2020-09-14 05:32:35.021000+00:00 +19770,19951029_6112,27563,24,72000,MORTGAGE,2.0,EDUCATION,6000,16.77,0,2021-04-23 07:57:18.165000+00:00,2021-04-23 07:57:18.165000+00:00 +24257,19511002_4158,29150,25,74000,OWN,1.0,MEDICAL,16000,8.49,0,2021-02-25 03:23:27.170000+00:00,2021-02-25 03:23:27.170000+00:00 +35711,19560406_9865,89053,37,175000,RENT,2.0,HOMEIMPROVEMENT,15000,9.76,0,2020-10-02 03:38:08.156000+00:00,2020-10-02 03:38:08.156000+00:00 +36382,19850307_1167,69156,47,43200,MORTGAGE,8.0,HOMEIMPROVEMENT,13750,14.84,0,2020-09-23 14:22:41.034000+00:00,2020-09-23 14:22:41.034000+00:00 +19011,19480901_2295,33677,23,66000,MORTGAGE,7.0,PERSONAL,10000,9.63,0,2021-05-03 00:07:53.762000+00:00,2021-05-03 00:07:53.762000+00:00 +28146,19561029_3031,7848,31,20800,RENT,3.0,MEDICAL,9750,17.19,1,2021-01-06 13:45:13.313000+00:00,2021-01-06 13:45:13.313000+00:00 +18191,19840122_6705,51054,26,65000,RENT,4.0,PERSONAL,8000,6.92,0,2021-05-13 10:58:04.553000+00:00,2021-05-13 10:58:04.553000+00:00 +34020,19851126_2947,51201,27,61584,RENT,3.0,VENTURE,15000,15.21,0,2020-10-23 16:54:32.603000+00:00,2020-10-23 16:54:32.603000+00:00 +32390,19680828_7648,93243,27,85000,MORTGAGE,11.0,PERSONAL,10000,7.49,0,2020-11-13 11:31:21.857000+00:00,2020-11-13 11:31:21.857000+00:00 +12464,19640720_7331,95367,24,57000,RENT,1.0,MEDICAL,3000,7.88,0,2021-07-25 10:50:44.060000+00:00,2021-07-25 10:50:44.060000+00:00 +24996,19800923_7230,75283,24,85000,MORTGAGE,2.0,MEDICAL,7000,12.69,0,2021-02-15 17:19:56.226000+00:00,2021-02-15 17:19:56.226000+00:00 +24185,19500730_9268,13406,23,30000,RENT,0.0,DEBTCONSOLIDATION,5000,11.86,0,2021-02-26 01:24:55.923000+00:00,2021-02-26 01:24:55.923000+00:00 +18171,19760127_6663,46142,26,55000,MORTGAGE,4.0,DEBTCONSOLIDATION,10000,7.51,1,2021-05-13 17:05:09.206000+00:00,2021-05-13 17:05:09.206000+00:00 +11160,19780524_1657,83847,23,26000,MORTGAGE,3.0,DEBTCONSOLIDATION,7800,10.59,0,2021-08-11 01:44:11.463000+00:00,2021-08-11 01:44:11.463000+00:00 +20892,19921003_2244,1451,22,80340,OWN,2.0,EDUCATION,7000,7.14,0,2021-04-09 00:44:15.108000+00:00,2021-04-09 00:44:15.108000+00:00 +18815,19720629_8145,8010,22,65000,MORTGAGE,2.0,PERSONAL,13000,14.35,0,2021-05-05 12:05:15.366000+00:00,2021-05-05 12:05:15.366000+00:00 +27338,19570408_3315,25512,27,22800,RENT,5.0,PERSONAL,3500,13.99,1,2021-01-16 20:55:09.311000+00:00,2021-01-16 20:55:09.311000+00:00 +21058,19681202_9762,12095,26,65450,MORTGAGE,3.0,MEDICAL,10800,12.21,1,2021-04-06 21:57:30.485000+00:00,2021-04-06 21:57:30.485000+00:00 +31687,19541126_4345,72701,27,70000,RENT,11.0,MEDICAL,10000,10.65,0,2020-11-22 10:34:08.425000+00:00,2020-11-22 10:34:08.425000+00:00 +36001,19580204_4513,16121,39,62692,RENT,9.0,VENTURE,13200,9.88,0,2020-09-28 10:55:30.682000+00:00,2020-09-28 10:55:30.682000+00:00 +10929,19771126_8304,96779,22,125000,RENT,3.0,MEDICAL,18000,14.79,0,2021-08-14 00:23:56.210000+00:00,2021-08-14 00:23:56.210000+00:00 +32036,19641126_8587,92832,27,80000,MORTGAGE,6.0,MEDICAL,23750,10.99,0,2020-11-17 23:48:38.222000+00:00,2020-11-17 23:48:38.222000+00:00 +25819,19781222_8337,10280,27,204000,MORTGAGE,3.0,HOMEIMPROVEMENT,25000,15.31,0,2021-02-05 05:34:41.738000+00:00,2021-02-05 05:34:41.738000+00:00 +35762,19961013_4086,27894,43,72000,RENT,11.0,EDUCATION,22000,10.62,1,2020-10-01 12:02:05.290000+00:00,2020-10-01 12:02:05.290000+00:00 +36975,19580926_5424,35186,45,61000,OWN,7.0,MEDICAL,20000,13.22,0,2020-09-16 00:58:50.060000+00:00,2020-09-16 00:58:50.060000+00:00 +19621,19990918_8053,56258,22,70000,MORTGAGE,3.0,EDUCATION,18000,14.42,0,2021-04-25 05:32:01.833000+00:00,2021-04-25 05:32:01.833000+00:00 +34073,19980721_1321,91016,29,135000,MORTGAGE,14.0,MEDICAL,24000,5.99,0,2020-10-23 00:41:47.272000+00:00,2020-10-23 00:41:47.272000+00:00 +34677,19701025_7628,14513,35,85000,RENT,1.0,VENTURE,3600,7.51,0,2020-10-15 07:56:02.738000+00:00,2020-10-15 07:56:02.738000+00:00 +16697,19760414_2750,84056,24,54000,MORTGAGE,9.0,MEDICAL,15600,13.61,0,2021-06-01 11:58:46.163000+00:00,2021-06-01 11:58:46.163000+00:00 +31990,19900924_2879,90014,29,79894,MORTGAGE,7.0,VENTURE,20000,14.96,0,2020-11-18 13:52:54.925000+00:00,2020-11-18 13:52:54.925000+00:00 +21842,19580604_5865,29417,22,92000,OTHER,2.0,MEDICAL,6000,12.22,0,2021-03-27 22:08:04.071000+00:00,2021-03-27 22:08:04.071000+00:00 +10281,19641127_9743,18327,25,134300,RENT,3.0,MEDICAL,5000,16.49,1,2021-08-22 06:37:14.980000+00:00,2021-08-22 06:37:14.980000+00:00 +32754,19900704_3938,25652,32,67150,MORTGAGE,4.0,MEDICAL,13000,16.0,1,2020-11-08 20:10:33.165000+00:00,2020-11-08 20:10:33.165000+00:00 +13435,19690305_6002,23432,25,39600,MORTGAGE,5.0,HOMEIMPROVEMENT,4800,12.42,0,2021-07-13 01:49:07.136000+00:00,2021-07-13 01:49:07.136000+00:00 +12092,20001029_5071,95310,26,64000,RENT,3.0,MEDICAL,2500,10.99,0,2021-07-30 04:38:22.613000+00:00,2021-07-30 04:38:22.613000+00:00 +29332,19960918_6100,27906,33,45000,MORTGAGE,3.0,HOMEIMPROVEMENT,8000,16.49,1,2020-12-22 10:57:31.365000+00:00,2020-12-22 10:57:31.365000+00:00 +35584,19620909_9491,38943,27,140987,MORTGAGE,5.0,VENTURE,6450,5.99,0,2020-10-03 18:29:04.706000+00:00,2020-10-03 18:29:04.706000+00:00 +13314,19660520_4478,8608,24,38400,MORTGAGE,7.0,EDUCATION,10000,14.72,0,2021-07-14 14:49:56.289000+00:00,2021-07-14 14:49:56.289000+00:00 +32831,19930923_3827,74957,30,94000,MORTGAGE,13.0,EDUCATION,10000,14.27,0,2020-11-07 20:37:18.249000+00:00,2020-11-07 20:37:18.249000+00:00 +26075,19910121_9862,49861,29,46000,RENT,1.0,DEBTCONSOLIDATION,22750,14.46,1,2021-02-01 23:16:06.174000+00:00,2021-02-01 23:16:06.174000+00:00 +37894,19500625_4818,11731,38,130000,MORTGAGE,1.0,HOMEIMPROVEMENT,30000,9.91,0,2020-09-04 07:51:37.236000+00:00,2020-09-04 07:51:37.236000+00:00 +11818,19561030_3762,43006,25,22800,RENT,1.0,MEDICAL,2400,10.36,0,2021-08-02 16:27:20.365000+00:00,2021-08-02 16:27:20.365000+00:00 +13906,19450828_7909,24260,23,52000,RENT,3.0,EDUCATION,4800,9.88,0,2021-07-07 01:44:26.548000+00:00,2021-07-07 01:44:26.548000+00:00 +14336,19620824_6416,96733,22,43200,RENT,6.0,EDUCATION,5000,12.69,0,2021-07-01 14:12:16.500000+00:00,2021-07-01 14:12:16.500000+00:00 +34300,19690121_9375,73062,28,92000,RENT,4.0,DEBTCONSOLIDATION,15000,7.9,0,2020-10-20 03:15:27.455000+00:00,2020-10-20 03:15:27.455000+00:00 +24229,19460328_3544,16407,24,54996,RENT,0.0,DEBTCONSOLIDATION,12500,12.87,0,2021-02-25 11:57:21.685000+00:00,2021-02-25 11:57:21.685000+00:00 +17674,19800608_3306,7070,26,36903,RENT,3.0,DEBTCONSOLIDATION,8000,12.21,0,2021-05-20 01:07:01.844000+00:00,2021-05-20 01:07:01.844000+00:00 +21305,19501016_9440,39365,24,36708,RENT,2.0,HOMEIMPROVEMENT,3000,15.33,1,2021-04-03 18:24:06.015000+00:00,2021-04-03 18:24:06.015000+00:00 +17884,20010404_9879,64024,24,52000,RENT,1.0,EDUCATION,8000,11.78,0,2021-05-17 08:52:42.983000+00:00,2021-05-17 08:52:42.983000+00:00 +13945,19630320_8557,58622,24,103641,RENT,8.0,VENTURE,4800,10.74,0,2021-07-06 13:48:38.474000+00:00,2021-07-06 13:48:38.474000+00:00 +16694,19540401_1520,91748,23,54000,MORTGAGE,0.0,EDUCATION,10000,11.49,0,2021-06-01 12:53:49.861000+00:00,2021-06-01 12:53:49.861000+00:00 +37450,20001128_1271,31643,36,81000,MORTGAGE,9.0,HOMEIMPROVEMENT,6000,12.99,0,2020-09-09 23:40:44.542000+00:00,2020-09-09 23:40:44.542000+00:00 +16586,19900729_5815,74728,25,29120,RENT,0.0,HOMEIMPROVEMENT,6400,16.29,1,2021-06-02 21:56:02.990000+00:00,2021-06-02 21:56:02.990000+00:00 +14980,19940130_5797,29572,23,23340,RENT,8.0,EDUCATION,5300,7.9,0,2021-06-23 09:12:22.659000+00:00,2021-06-23 09:12:22.659000+00:00 +38564,19460921_2514,45773,63,1782000,RENT,13.0,EDUCATION,12025,14.27,0,2020-08-26 18:54:31.346000+00:00,2020-08-26 18:54:31.346000+00:00 +18974,19680723_9170,70807,24,66000,MORTGAGE,8.0,PERSONAL,15000,18.25,0,2021-05-03 11:26:59.371000+00:00,2021-05-03 11:26:59.371000+00:00 +15354,20010711_5288,29730,24,24000,RENT,1.0,MEDICAL,6000,11.99,0,2021-06-18 14:48:01.640000+00:00,2021-06-18 14:48:01.640000+00:00 +16186,19820319_5187,64136,22,60000,RENT,5.0,MEDICAL,7000,9.99,0,2021-06-08 00:17:36.058000+00:00,2021-06-08 00:17:36.058000+00:00 +36937,19640424_1652,18254,38,60000,OWN,2.0,VENTURE,6000,14.96,0,2020-09-16 12:36:16.902000+00:00,2020-09-16 12:36:16.902000+00:00 +29577,19941130_4884,50845,34,54000,MORTGAGE,5.0,HOMEIMPROVEMENT,27000,7.9,0,2020-12-19 08:00:49.360000+00:00,2020-12-19 08:00:49.360000+00:00 +38091,19840917_3681,70606,40,38000,RENT,4.0,DEBTCONSOLIDATION,7000,15.99,1,2020-09-01 19:35:54.399000+00:00,2020-09-01 19:35:54.399000+00:00 +32227,19790328_6095,73506,30,60000,RENT,0.0,PERSONAL,12000,11.71,0,2020-11-15 13:23:02.782000+00:00,2020-11-15 13:23:02.782000+00:00 +18763,19460130_9199,72768,26,45000,RENT,2.0,DEBTCONSOLIDATION,9050,7.29,0,2021-05-06 03:59:39.465000+00:00,2021-05-06 03:59:39.465000+00:00 +34734,19680928_2397,98685,34,84000,RENT,3.0,EDUCATION,9000,5.79,0,2020-10-14 14:29:52.476000+00:00,2020-10-14 14:29:52.476000+00:00 +34647,19590306_7046,30276,32,122004,MORTGAGE,13.0,MEDICAL,10000,8.59,0,2020-10-15 17:06:39.718000+00:00,2020-10-15 17:06:39.718000+00:00 +35691,19980402_5345,77831,36,69000,RENT,0.0,HOMEIMPROVEMENT,25000,14.59,1,2020-10-02 09:45:12.810000+00:00,2020-10-02 09:45:12.810000+00:00 +30795,19791014_9418,32204,31,65000,MORTGAGE,6.0,VENTURE,12000,7.49,0,2020-12-03 19:25:47.967000+00:00,2020-12-03 19:25:47.967000+00:00 +37027,19730922_2834,31052,36,63599,MORTGAGE,10.0,HOMEIMPROVEMENT,5200,7.91,0,2020-09-15 09:04:25.961000+00:00,2020-09-15 09:04:25.961000+00:00 +28062,19730909_3354,53716,34,96900,RENT,1.0,DEBTCONSOLIDATION,4800,5.42,0,2021-01-07 15:26:56.857000+00:00,2021-01-07 15:26:56.857000+00:00 +22232,19640601_3524,32192,25,86000,MORTGAGE,9.0,HOMEIMPROVEMENT,5000,10.36,1,2021-03-22 22:50:03.329000+00:00,2021-03-22 22:50:03.329000+00:00 +34199,19490125_2907,40228,34,143150,MORTGAGE,0.0,VENTURE,12000,9.32,0,2020-10-21 10:09:11.955000+00:00,2020-10-21 10:09:11.955000+00:00 +11548,19551210_7764,34674,23,19200,RENT,2.0,EDUCATION,2000,10.59,0,2021-08-06 03:02:53.186000+00:00,2021-08-06 03:02:53.186000+00:00 +22706,19971219_3037,14504,25,107000,MORTGAGE,4.0,DEBTCONSOLIDATION,24000,5.99,0,2021-03-16 21:50:19.043000+00:00,2021-03-16 21:50:19.043000+00:00 +20153,19610902_5287,50854,24,67600,RENT,7.0,HOMEIMPROVEMENT,10000,16.02,0,2021-04-18 10:47:46.052000+00:00,2021-04-18 10:47:46.052000+00:00 +30856,20000221_8382,30274,27,65000,MORTGAGE,3.0,DEBTCONSOLIDATION,15000,10.75,0,2020-12-03 00:46:12.774000+00:00,2020-12-03 00:46:12.774000+00:00 +38054,19881228_5956,97339,45,54000,RENT,1.0,DEBTCONSOLIDATION,19425,11.99,1,2020-09-02 06:55:00.008000+00:00,2020-09-02 06:55:00.008000+00:00 +22588,19621020_7458,36702,26,130000,RENT,3.0,VENTURE,14400,14.46,0,2021-03-18 09:56:04.498000+00:00,2021-03-18 09:56:04.498000+00:00 +33510,19970312_2783,16674,34,35000,RENT,2.0,PERSONAL,15000,10.99,1,2020-10-30 04:55:01.265000+00:00,2020-10-30 04:55:01.265000+00:00 +34970,19911022_6935,34609,28,68000,MORTGAGE,7.0,HOMEIMPROVEMENT,2500,11.71,0,2020-10-11 14:18:21.566000+00:00,2020-10-11 14:18:21.566000+00:00 +17411,19520303_2944,54968,25,58000,MORTGAGE,7.0,DEBTCONSOLIDATION,7200,11.71,0,2021-05-23 09:34:06.036000+00:00,2021-05-23 09:34:06.036000+00:00 +17958,19840127_8710,70127,22,60000,RENT,6.0,MEDICAL,8000,7.88,0,2021-05-16 10:14:31.765000+00:00,2021-05-16 10:14:31.765000+00:00 +36569,19510521_1606,89301,44,49510,MORTGAGE,5.0,HOMEIMPROVEMENT,4000,10.62,0,2020-09-21 05:10:30.525000+00:00,2020-09-21 05:10:30.525000+00:00 +20030,19541127_6618,30218,23,75000,MORTGAGE,7.0,VENTURE,5400,12.69,0,2021-04-20 00:25:17.671000+00:00,2021-04-20 00:25:17.671000+00:00 +14113,19990513_2356,48174,23,29730,RENT,2.0,DEBTCONSOLIDATION,5000,7.66,0,2021-07-04 10:25:11.385000+00:00,2021-07-04 10:25:11.385000+00:00 +12175,19710310_3389,68757,24,18000,RENT,5.0,PERSONAL,3000,15.27,1,2021-07-29 03:15:00.302000+00:00,2021-07-29 03:15:00.302000+00:00 +12515,19970330_2150,5733,24,35000,MORTGAGE,7.0,EDUCATION,15000,7.49,0,2021-07-24 19:14:41.193000+00:00,2021-07-24 19:14:41.193000+00:00 +25074,19501111_8936,42202,21,37000,OWN,3.0,MEDICAL,7200,13.61,0,2021-02-14 17:28:20.078000+00:00,2021-02-14 17:28:20.078000+00:00 +30844,19970519_8461,14819,28,62000,RENT,3.0,MEDICAL,9200,10.0,0,2020-12-03 04:26:27.566000+00:00,2020-12-03 04:26:27.566000+00:00 +15071,19690708_2092,18347,26,47000,MORTGAGE,5.0,MEDICAL,6600,7.9,0,2021-06-22 05:22:10.486000+00:00,2021-06-22 05:22:10.486000+00:00 +23509,19690211_8042,12580,26,22440,OWN,10.0,VENTURE,4750,11.86,0,2021-03-06 16:12:09.208000+00:00,2021-03-06 16:12:09.208000+00:00 +30221,19891006_8318,54937,32,40000,RENT,3.0,DEBTCONSOLIDATION,8000,9.62,0,2020-12-11 03:00:55.520000+00:00,2020-12-11 03:00:55.520000+00:00 +31898,19830519_7021,94531,29,34900,RENT,2.0,MEDICAL,11200,9.99,1,2020-11-19 18:01:28.331000+00:00,2020-11-19 18:01:28.331000+00:00 +36886,19810426_2329,27405,42,60000,MORTGAGE,1.0,MEDICAL,8000,5.42,0,2020-09-17 04:12:19.768000+00:00,2020-09-17 04:12:19.768000+00:00 +19948,19700530_6338,7078,23,73500,MORTGAGE,7.0,VENTURE,10000,6.92,0,2021-04-21 01:30:18.750000+00:00,2021-04-21 01:30:18.750000+00:00 +22172,19491204_9518,17748,26,96300,MORTGAGE,10.0,PERSONAL,15000,6.17,0,2021-03-23 17:11:17.289000+00:00,2021-03-23 17:11:17.289000+00:00 +12299,19471214_6602,25245,25,45000,RENT,4.0,MEDICAL,3000,7.9,0,2021-07-27 13:19:07.450000+00:00,2021-07-27 13:19:07.450000+00:00 +16569,19791009_5686,63944,24,53184,MORTGAGE,8.0,PERSONAL,13500,10.99,0,2021-06-03 03:08:03.945000+00:00,2021-06-03 03:08:03.945000+00:00 +32960,19580205_5390,60622,31,96000,OWN,3.0,PERSONAL,10000,9.99,0,2020-11-06 05:09:39.234000+00:00,2020-11-06 05:09:39.234000+00:00 +17130,19861204_8812,70068,23,55812,MORTGAGE,4.0,MEDICAL,21825,11.36,0,2021-05-26 23:31:32.417000+00:00,2021-05-26 23:31:32.417000+00:00 +23012,19931106_1555,29831,25,115000,MORTGAGE,1.0,EDUCATION,20000,15.65,0,2021-03-13 00:14:01.846000+00:00,2021-03-13 00:14:01.846000+00:00 +36979,19970524_1853,24245,38,61450,OWN,6.0,VENTURE,12500,7.49,0,2020-09-15 23:45:25.130000+00:00,2020-09-15 23:45:25.130000+00:00 +10829,19600930_7223,70083,23,50000,RENT,4.0,VENTURE,18225,10.74,1,2021-08-15 06:59:19.477000+00:00,2021-08-15 06:59:19.477000+00:00 +18660,19630414_5802,46982,21,65000,MORTGAGE,5.0,DEBTCONSOLIDATION,2200,12.42,0,2021-05-07 11:30:06.430000+00:00,2021-05-07 11:30:06.430000+00:00 +11012,19620615_1391,70359,25,114000,RENT,3.0,EDUCATION,17000,10.37,0,2021-08-12 23:00:33.898000+00:00,2021-08-12 23:00:33.898000+00:00 +19777,20000201_4113,39342,22,72000,OWN,6.0,VENTURE,16000,10.37,0,2021-04-23 05:48:49.536000+00:00,2021-04-23 05:48:49.536000+00:00 +21903,19641112_9044,61241,24,93000,MORTGAGE,3.0,VENTURE,18000,11.78,0,2021-03-27 03:28:28.878000+00:00,2021-03-27 03:28:28.878000+00:00 +25469,19590417_6870,23112,22,50000,MORTGAGE,6.0,VENTURE,10000,9.88,0,2021-02-09 16:38:33.173000+00:00,2021-02-09 16:38:33.173000+00:00 +28331,19940903_5969,60617,32,48000,RENT,8.0,DEBTCONSOLIDATION,5000,11.97,0,2021-01-04 05:09:45.269000+00:00,2021-01-04 05:09:45.269000+00:00 +22520,19961221_8878,49306,26,102000,MORTGAGE,5.0,PERSONAL,13000,5.42,0,2021-03-19 06:44:08.320000+00:00,2021-03-19 06:44:08.320000+00:00 +19265,19550315_6667,53048,23,33000,RENT,4.0,EDUCATION,10000,11.99,0,2021-04-29 18:26:00.664000+00:00,2021-04-29 18:26:00.664000+00:00 +16846,19940916_8629,21226,24,55000,MORTGAGE,8.0,MEDICAL,15000,9.91,0,2021-05-30 14:24:02.495000+00:00,2021-05-30 14:24:02.495000+00:00 +14911,19621018_6161,14428,22,90000,RENT,4.0,EDUCATION,5000,14.96,0,2021-06-24 06:18:47.714000+00:00,2021-06-24 06:18:47.714000+00:00 +14954,19461205_4101,71016,23,150000,RENT,3.0,VENTURE,5000,10.65,0,2021-06-23 17:09:34.709000+00:00,2021-06-23 17:09:34.709000+00:00 +19014,19560428_7329,92312,24,65450,RENT,7.0,DEBTCONSOLIDATION,9600,8.49,0,2021-05-02 23:12:50.064000+00:00,2021-05-02 23:12:50.064000+00:00 +11896,19600821_6571,44129,22,43000,RENT,6.0,PERSONAL,13500,10.95,1,2021-08-01 16:35:44.217000+00:00,2021-08-01 16:35:44.217000+00:00 +24340,19600119_4523,71740,26,165000,MORTGAGE,10.0,EDUCATION,20000,13.22,0,2021-02-24 02:00:04.859000+00:00,2021-02-24 02:00:04.859000+00:00 +20458,19760306_8686,18053,22,90000,RENT,6.0,MEDICAL,10200,11.71,0,2021-04-14 13:29:50.088000+00:00,2021-04-14 13:29:50.088000+00:00 +37561,20000210_6704,10543,41,90000,MORTGAGE,23.0,VENTURE,13200,6.62,0,2020-09-08 13:43:27.715000+00:00,2020-09-08 13:43:27.715000+00:00 +32150,19930916_9118,10579,28,80500,MORTGAGE,4.0,DEBTCONSOLIDATION,6000,7.74,0,2020-11-16 12:56:17.698000+00:00,2020-11-16 12:56:17.698000+00:00 +18313,20000205_6515,85622,24,62000,MORTGAGE,8.0,VENTURE,20000,16.7,0,2021-05-11 21:38:54.167000+00:00,2021-05-11 21:38:54.167000+00:00 +10474,19850915_7842,61555,25,47052,RENT,5.0,VENTURE,21250,10.99,1,2021-08-19 19:34:57.075000+00:00,2021-08-19 19:34:57.075000+00:00 +25101,19510123_1444,3821,25,75000,MORTGAGE,7.0,PERSONAL,15000,9.99,0,2021-02-14 09:12:46.796000+00:00,2021-02-14 09:12:46.796000+00:00 +25383,19870911_8554,23187,23,92004,MORTGAGE,7.0,EDUCATION,24250,11.12,0,2021-02-10 18:56:59.183000+00:00,2021-02-10 18:56:59.183000+00:00 +22595,19910502_4545,80470,25,92085,MORTGAGE,4.0,HOMEIMPROVEMENT,2500,15.27,1,2021-03-18 07:47:35.870000+00:00,2021-03-18 07:47:35.870000+00:00 +16364,19871213_7309,32254,24,24000,RENT,0.0,EDUCATION,6500,11.36,0,2021-06-05 17:50:36.643000+00:00,2021-06-05 17:50:36.643000+00:00 +13914,19640724_8897,98229,21,41000,MORTGAGE,4.0,DEBTCONSOLIDATION,7000,6.03,0,2021-07-06 23:17:36.687000+00:00,2021-07-06 23:17:36.687000+00:00 +34989,19630927_9393,98053,28,33600,MORTGAGE,12.0,MEDICAL,3000,5.42,0,2020-10-11 08:29:38.145000+00:00,2020-10-11 08:29:38.145000+00:00 +31359,19520603_8534,65014,27,53550,RENT,3.0,MEDICAL,4200,11.99,1,2020-11-26 14:54:12.741000+00:00,2020-11-26 14:54:12.741000+00:00 +38289,19520827_2880,34982,36,98240,MORTGAGE,4.0,VENTURE,20000,16.35,0,2020-08-30 07:01:50.331000+00:00,2020-08-30 07:01:50.331000+00:00 +31365,19740420_1544,24440,28,71007,MORTGAGE,4.0,EDUCATION,25000,18.62,0,2020-11-26 13:04:05.345000+00:00,2020-11-26 13:04:05.345000+00:00 +28349,19800518_5656,77354,29,59520,RENT,13.0,HOMEIMPROVEMENT,9000,5.42,0,2021-01-03 23:39:23.081000+00:00,2021-01-03 23:39:23.081000+00:00 +15891,19540924_4310,25839,25,50000,MORTGAGE,9.0,DEBTCONSOLIDATION,18000,7.88,0,2021-06-11 18:31:59.696000+00:00,2021-06-11 18:31:59.696000+00:00 +17069,20010130_4641,43907,24,50000,RENT,0.0,VENTURE,7200,11.71,0,2021-05-27 18:11:07.610000+00:00,2021-05-27 18:11:07.610000+00:00 +36103,20011007_8293,27712,40,35820,RENT,0.0,MEDICAL,3275,8.88,0,2020-09-27 03:43:24.949000+00:00,2020-09-27 03:43:24.949000+00:00 +15534,19571023_2396,41049,24,49000,MORTGAGE,2.0,VENTURE,20000,15.57,0,2021-06-16 07:44:19.760000+00:00,2021-06-16 07:44:19.760000+00:00 +27256,19971016_3322,78250,31,30892,RENT,3.0,MEDICAL,3100,10.59,1,2021-01-17 22:00:10.390000+00:00,2021-01-17 22:00:10.390000+00:00 +26362,19671107_2852,30002,27,132000,RENT,4.0,DEBTCONSOLIDATION,18000,8.49,0,2021-01-29 07:28:32.398000+00:00,2021-01-29 07:28:32.398000+00:00 +25530,19480802_9190,5872,24,70000,MORTGAGE,8.0,DEBTCONSOLIDATION,25000,9.62,0,2021-02-08 21:58:57.980000+00:00,2021-02-08 21:58:57.980000+00:00 +32122,19840324_9938,89049,28,80000,OWN,2.0,HOMEIMPROVEMENT,16000,11.66,0,2020-11-16 21:30:12.213000+00:00,2020-11-16 21:30:12.213000+00:00 +13278,19510702_6043,8641,23,28000,RENT,0.0,EDUCATION,4000,8.9,0,2021-07-15 01:50:40.665000+00:00,2021-07-15 01:50:40.665000+00:00 +26690,19701118_2971,76706,27,122000,RENT,3.0,PERSONAL,15000,12.73,0,2021-01-25 03:08:28.082000+00:00,2021-01-25 03:08:28.082000+00:00 +22411,19540321_1149,94141,25,100000,MORTGAGE,3.0,PERSONAL,13750,15.95,0,2021-03-20 16:04:42.681000+00:00,2021-03-20 16:04:42.681000+00:00 +19563,19810210_2392,92651,22,70000,MORTGAGE,6.0,EDUCATION,6000,7.14,0,2021-04-25 23:16:33.328000+00:00,2021-04-25 23:16:33.328000+00:00 +15385,19560627_2936,57103,25,48000,OWN,0.0,VENTURE,7500,7.05,0,2021-06-18 05:19:03.428000+00:00,2021-06-18 05:19:03.428000+00:00 +33540,19470923_2558,16827,33,38016,RENT,10.0,EDUCATION,15000,6.17,1,2020-10-29 19:44:24.285000+00:00,2020-10-29 19:44:24.285000+00:00 +34957,19670622_4084,20166,30,105000,OWN,14.0,HOMEIMPROVEMENT,15400,11.36,0,2020-10-11 18:16:57.590000+00:00,2020-10-11 18:16:57.590000+00:00 +17927,19890216_4733,1032,22,60000,MORTGAGE,7.0,VENTURE,6000,10.38,0,2021-05-16 19:43:29.978000+00:00,2021-05-16 19:43:29.978000+00:00 +17593,19631223_7957,97843,23,60000,MORTGAGE,5.0,DEBTCONSOLIDATION,10000,11.71,0,2021-05-21 01:53:41.690000+00:00,2021-05-21 01:53:41.690000+00:00 +19450,19540609_5340,40176,23,34000,RENT,7.0,EDUCATION,10000,10.36,1,2021-04-27 09:50:32.620000+00:00,2021-04-27 09:50:32.620000+00:00 +26661,19570511_6902,90036,30,28800,RENT,9.0,MEDICAL,2000,11.48,0,2021-01-25 12:00:43.829000+00:00,2021-01-25 12:00:43.829000+00:00 +25143,19880522_3824,14464,25,59004,RENT,1.0,HOMEIMPROVEMENT,20000,14.84,1,2021-02-13 20:21:55.024000+00:00,2021-02-13 20:21:55.024000+00:00 +10264,19530118_8263,65274,25,174708,RENT,9.0,VENTURE,9000,10.59,0,2021-08-22 11:49:15.936000+00:00,2021-08-22 11:49:15.936000+00:00 +18416,19920607_2455,44053,21,50000,RENT,5.0,DEBTCONSOLIDATION,8300,8.9,0,2021-05-10 14:08:27.202000+00:00,2021-05-10 14:08:27.202000+00:00 +29421,19810912_2316,68418,28,112200,RENT,11.0,MEDICAL,7000,11.66,0,2020-12-21 07:44:01.657000+00:00,2020-12-21 07:44:01.657000+00:00 +30504,19881006_7148,70665,31,65000,RENT,2.0,MEDICAL,8000,6.99,0,2020-12-07 12:26:46.674000+00:00,2020-12-07 12:26:46.674000+00:00 +35206,19810303_4939,98346,33,612000,RENT,3.0,MEDICAL,5950,12.73,0,2020-10-08 14:06:50.655000+00:00,2020-10-08 14:06:50.655000+00:00 +36827,19991105_1560,3431,41,58000,RENT,16.0,PERSONAL,7500,11.03,0,2020-09-17 22:15:12.496000+00:00,2020-09-17 22:15:12.496000+00:00 +32065,19470628_6149,48021,33,80000,MORTGAGE,9.0,VENTURE,6000,11.11,0,2020-11-17 14:56:22.475000+00:00,2020-11-17 14:56:22.475000+00:00 +37454,19610704_2084,92075,40,81120,MORTGAGE,1.0,EDUCATION,24000,9.25,0,2020-09-09 22:27:19.611000+00:00,2020-09-09 22:27:19.611000+00:00 +33790,19520918_7032,50323,29,120000,MORTGAGE,10.0,PERSONAL,4700,7.14,0,2020-10-26 15:15:56.117000+00:00,2020-10-26 15:15:56.117000+00:00 +35227,19970426_2963,75150,27,48000,RENT,0.0,DEBTCONSOLIDATION,10000,10.62,0,2020-10-08 07:41:24.769000+00:00,2020-10-08 07:41:24.769000+00:00 +21869,19711122_4217,47968,22,34800,OWN,4.0,MEDICAL,7350,14.22,0,2021-03-27 13:52:30.789000+00:00,2021-03-27 13:52:30.789000+00:00 +14492,20010903_2877,20707,25,72500,RENT,2.0,HOMEIMPROVEMENT,9000,10.59,0,2021-06-29 14:29:04.203000+00:00,2021-06-29 14:29:04.203000+00:00 +13001,19780720_4827,26374,26,42000,RENT,2.0,PERSONAL,10800,13.99,1,2021-07-18 14:34:42.115000+00:00,2021-07-18 14:34:42.115000+00:00 +35508,19510724_2105,93024,33,75000,MORTGAGE,6.0,VENTURE,6000,7.51,0,2020-10-04 17:43:58.389000+00:00,2020-10-04 17:43:58.389000+00:00 +15873,19530912_2142,55446,21,62000,RENT,2.0,EDUCATION,6000,10.25,0,2021-06-12 00:02:21.884000+00:00,2021-06-12 00:02:21.884000+00:00 +23320,19890608_1101,62037,23,24000,OWN,2.0,VENTURE,6000,15.23,0,2021-03-09 02:01:02.183000+00:00,2021-03-09 02:01:02.183000+00:00 +31614,19930124_4664,84660,29,75000,OWN,5.0,VENTURE,6000,12.69,0,2020-11-23 08:53:58.410000+00:00,2020-11-23 08:53:58.410000+00:00 +33814,19620907_5395,64644,28,91800,MORTGAGE,1.0,MEDICAL,15000,15.37,1,2020-10-26 07:55:26.533000+00:00,2020-10-26 07:55:26.533000+00:00 +32421,19961218_1873,24589,28,42996,RENT,4.0,EDUCATION,3000,7.68,0,2020-11-13 02:02:23.644000+00:00,2020-11-13 02:02:23.644000+00:00 +15675,19510112_4032,6776,23,45000,RENT,7.0,VENTURE,6000,11.49,0,2021-06-14 12:36:25.953000+00:00,2021-06-14 12:36:25.953000+00:00 +19966,19730912_9973,79081,21,74000,MORTGAGE,5.0,VENTURE,25000,12.69,0,2021-04-20 19:59:56.562000+00:00,2021-04-20 19:59:56.562000+00:00 +27749,19910605_2864,90210,29,33996,RENT,11.0,EDUCATION,4000,13.47,1,2021-01-11 15:11:42.683000+00:00,2021-01-11 15:11:42.683000+00:00 +33593,19930430_3770,60042,33,115000,MORTGAGE,3.0,PERSONAL,14000,6.03,0,2020-10-29 03:31:38.954000+00:00,2020-10-29 03:31:38.954000+00:00 +19437,19620203_9560,27331,26,40000,RENT,10.0,VENTURE,10000,16.89,0,2021-04-27 13:49:08.645000+00:00,2021-04-27 13:49:08.645000+00:00 +28307,19661124_5462,62410,33,45360,RENT,3.0,PERSONAL,5000,15.99,0,2021-01-04 12:30:14.853000+00:00,2021-01-04 12:30:14.853000+00:00 +11689,19660219_4269,19943,26,65000,RENT,3.0,MEDICAL,2000,7.51,0,2021-08-04 07:54:59.380000+00:00,2021-08-04 07:54:59.380000+00:00 +36040,19870230_1132,85063,37,40000,RENT,1.0,VENTURE,3000,11.71,0,2020-09-27 22:59:42.608000+00:00,2020-09-27 22:59:42.608000+00:00 +32299,20001012_3230,77561,29,84000,MORTGAGE,9.0,HOMEIMPROVEMENT,5900,7.66,0,2020-11-14 15:21:34.030000+00:00,2020-11-14 15:21:34.030000+00:00 +28398,19950526_7823,5850,27,73004,RENT,5.0,EDUCATION,9000,9.63,1,2021-01-03 08:40:02.680000+00:00,2021-01-03 08:40:02.680000+00:00 +25591,19920127_9712,62355,22,26400,RENT,1.0,PERSONAL,3500,15.27,0,2021-02-08 03:19:22.787000+00:00,2021-02-08 03:19:22.787000+00:00 +11647,19900712_8240,31808,22,33996,RENT,1.0,EDUCATION,14900,15.37,1,2021-08-04 20:45:51.152000+00:00,2021-08-04 20:45:51.152000+00:00 +26358,19740823_1239,19154,33,103000,RENT,17.0,PERSONAL,18000,16.82,0,2021-01-29 08:41:57.329000+00:00,2021-01-29 08:41:57.329000+00:00 +15364,19670430_8377,30439,23,25000,RENT,7.0,VENTURE,6000,7.51,0,2021-06-18 11:44:29.314000+00:00,2021-06-18 11:44:29.314000+00:00 +23675,19950102_1276,34208,23,73000,RENT,7.0,EDUCATION,15000,7.51,1,2021-03-04 13:25:24.585000+00:00,2021-03-04 13:25:24.585000+00:00 +28617,19670601_7686,78004,32,75000,RENT,4.0,MEDICAL,5000,9.99,0,2020-12-31 13:40:32.725000+00:00,2020-12-31 13:40:32.725000+00:00 +31585,19690530_8292,76621,32,74346,MORTGAGE,16.0,MEDICAL,7000,7.9,0,2020-11-23 17:46:14.157000+00:00,2020-11-23 17:46:14.157000+00:00 +15679,19950805_9294,77205,22,39000,RENT,6.0,HOMEIMPROVEMENT,6000,13.22,1,2021-06-14 11:23:01.022000+00:00,2021-06-14 11:23:01.022000+00:00 +23098,19611207_1373,7311,26,119000,MORTGAGE,6.0,VENTURE,15000,14.42,0,2021-03-11 21:55:35.836000+00:00,2021-03-11 21:55:35.836000+00:00 +25845,19831123_9073,99119,27,200000,MORTGAGE,7.0,PERSONAL,15000,9.88,0,2021-02-04 21:37:29.689000+00:00,2021-02-04 21:37:29.689000+00:00 +19378,19770808_9735,95690,22,69996,OWN,2.0,MEDICAL,8000,12.84,0,2021-04-28 07:52:01.372000+00:00,2021-04-28 07:52:01.372000+00:00 +28408,19910630_9243,11516,32,44400,MORTGAGE,5.0,HOMEIMPROVEMENT,6500,14.84,0,2021-01-03 05:36:30.353000+00:00,2021-01-03 05:36:30.353000+00:00 +18997,19870308_7912,49331,26,66000,MORTGAGE,7.0,PERSONAL,4000,11.99,0,2021-05-03 04:24:51.020000+00:00,2021-05-03 04:24:51.020000+00:00 +36539,19571122_6912,44632,39,20400,RENT,3.0,MEDICAL,6000,15.27,0,2020-09-21 14:21:07.505000+00:00,2020-09-21 14:21:07.505000+00:00 +19326,19920109_3054,76311,23,36000,RENT,5.0,MEDICAL,10000,9.99,0,2021-04-28 23:46:25.471000+00:00,2021-04-28 23:46:25.471000+00:00 +18114,19510725_6343,96104,23,24000,RENT,4.0,DEBTCONSOLIDATION,5000,10.62,0,2021-05-14 10:31:19.468000+00:00,2021-05-14 10:31:19.468000+00:00 +27879,19550715_9996,55342,28,40000,MORTGAGE,12.0,HOMEIMPROVEMENT,15000,5.99,0,2021-01-09 23:25:42.436000+00:00,2021-01-09 23:25:42.436000+00:00 +38227,19600710_1107,24134,42,30000,RENT,5.0,VENTURE,8000,14.96,0,2020-08-31 01:59:46.756000+00:00,2020-08-31 01:59:46.756000+00:00 +29627,19920415_9040,94111,32,43000,RENT,2.0,MEDICAL,6950,9.91,0,2020-12-18 16:43:07.727000+00:00,2020-12-18 16:43:07.727000+00:00 +20649,19681216_5909,88044,24,80000,MORTGAGE,8.0,EDUCATION,10000,8.9,0,2021-04-12 03:04:14.647000+00:00,2021-04-12 03:04:14.647000+00:00 +29235,19490301_7917,79608,33,50000,OWN,1.0,VENTURE,12000,13.99,0,2020-12-23 16:37:50.934000+00:00,2020-12-23 16:37:50.934000+00:00 +20281,19520125_8596,42204,23,75000,RENT,0.0,PERSONAL,10000,13.47,0,2021-04-16 19:38:28.270000+00:00,2021-04-16 19:38:28.270000+00:00 +14229,19690925_6673,96820,22,36996,RENT,0.0,MEDICAL,5000,5.42,0,2021-07-02 22:56:08.395000+00:00,2021-07-02 22:56:08.395000+00:00 diff --git a/ui/feature_repo/data/training_dataset_sample.parquet b/ui/feature_repo/data/training_dataset_sample.parquet new file mode 100644 index 00000000000..e9622aaf230 Binary files /dev/null and b/ui/feature_repo/data/training_dataset_sample.parquet differ diff --git a/ui/feature_repo/data/zipcode_table.parquet b/ui/feature_repo/data/zipcode_table.parquet new file mode 100644 index 00000000000..87b67e13e15 Binary files /dev/null and b/ui/feature_repo/data/zipcode_table.parquet differ diff --git a/ui/feature_repo/data/zipcode_table_sample.csv b/ui/feature_repo/data/zipcode_table_sample.csv new file mode 100644 index 00000000000..5690d7ffd32 --- /dev/null +++ b/ui/feature_repo/data/zipcode_table_sample.csv @@ -0,0 +1,2885 @@ +zipcode,city,state,location_type,tax_returns_filed,population,total_wages,event_timestamp,created_timestamp +1463,PEPPERELL,MA,PRIMARY,5549,10100,310246738,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80477,STEAMBOAT SPRINGS,CO,PRIMARY,4376,6952,196199680,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19401,NORRISTOWN,PA,PRIMARY,17975,29398,593090218,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31028,CENTERVILLE,GA,PRIMARY,2791,5013,103348211,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65802,SPRINGFIELD,MO,PRIMARY,18096,30388,484432932,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45101,ABERDEEN,OH,PRIMARY,1001,1826,29504355,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39356,ROSE HILL,MS,PRIMARY,319,583,9854530,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79019,CLAUDE,TX,PRIMARY,790,1486,25573842,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2322,AVON,MA,PRIMARY,2294,3831,98754584,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74355,MIAMI,OK,PRIMARY,352,618,11028437,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95658,NEWCASTLE,CA,PRIMARY,3092,5562,136983650,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47036,OLDENBURG,IN,PRIMARY,558,984,21447674,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65580,VICHY,MO,PRIMARY,365,665,9315944,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8234,EGG HARBOR TOWNSHIP,NJ,PRIMARY,21001,37623,919724508,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62671,NEW HOLLAND,IL,PRIMARY,280,498,8845843,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77831,BEDIAS,TX,PRIMARY,1178,2191,34547649,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77518,BACLIFF,TX,PRIMARY,3754,6825,123827585,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84783,DAMMERON VALLEY,UT,PRIMARY,330,644,10937901,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13090,LIVERPOOL,NY,PRIMARY,15076,26337,669746981,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35674,TUSCUMBIA,AL,PRIMARY,7779,14316,238664103,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51012,CHEROKEE,IA,PRIMARY,3217,5529,90168643,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71935,CADDO GAP,AR,PRIMARY,271,527,5072844,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18829,LE RAYSVILLE,PA,PRIMARY,370,673,10542911,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54512,BOULDER JUNCTION,WI,PRIMARY,641,1080,12456566,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46037,FISHERS,IN,PRIMARY,14420,29121,1109574040,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31301,ALLENHURST,GA,PRIMARY,1617,3025,43253409,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23441,TASLEY,VA,PRIMARY,282,484,5249223,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53532,DE FOREST,WI,PRIMARY,6637,12095,308509381,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71007,BETHANY,LA,PRIMARY,521,909,16527337,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31216,MACON,GA,PRIMARY,6918,12714,251849778,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65264,MARTINSBURG,MO,PRIMARY,404,710,10992871,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68781,TILDEN,NE,PRIMARY,678,1239,17490571,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32780,TITUSVILLE,FL,PRIMARY,16101,27299,530363329,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5905,GUILDHALL,VT,PRIMARY,325,584,9251932,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38348,LAVINIA,TN,PRIMARY,410,757,11777928,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78505,MCALLEN,TX,PRIMARY,902,1682,22515793,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3894,WOLFEBORO,NH,PRIMARY,3113,5312,114608359,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15363,STRABANE,PA,PRIMARY,433,709,10185876,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39474,PRENTISS,MS,PRIMARY,2695,4780,63767399,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14220,BUFFALO,NY,PRIMARY,11783,19047,369097924,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56678,SOLWAY,MN,PRIMARY,541,1010,17871305,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11726,COPIAGUE,NY,PRIMARY,10282,17101,360442098,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60472,ROBBINS,IL,PRIMARY,2193,3628,42695628,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40111,CLOVERPORT,KY,PRIMARY,588,1104,15394648,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1801,WOBURN,MA,PRIMARY,20667,33608,978759571,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15332,FINLEYVILLE,PA,PRIMARY,4295,7209,144526193,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91309,CANOGA PARK,CA,PRIMARY,379,590,12803555,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32362,WOODVILLE,FL,PRIMARY,563,951,15487000,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55763,MAKINEN,MN,PRIMARY,272,469,8786552,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97438,FALL CREEK,OR,PRIMARY,584,1032,20705230,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6786,TERRYVILLE,CT,PRIMARY,4856,8443,210651428,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95333,LE GRAND,CA,PRIMARY,1118,2167,29961304,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29525,CLIO,SC,PRIMARY,966,1747,20933523,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6105,HARTFORD,CT,PRIMARY,8233,12164,294308268,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85658,MARANA,AZ,PRIMARY,2913,5442,143076605,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48505,FLINT,MI,PRIMARY,9440,15571,121379263,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51638,ESSEX,IA,PRIMARY,607,1118,18363054,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51243,LITTLE ROCK,IA,PRIMARY,332,622,8558473,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1061,NORTHAMPTON,MA,PRIMARY,331,423,10230348,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70434,COVINGTON,LA,PRIMARY,1197,2050,35322862,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7836,FLANDERS,NJ,PRIMARY,5629,10541,436195117,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56132,GARVIN,MN,PRIMARY,259,477,7914548,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11972,SPEONK,NY,PRIMARY,486,834,19114157,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28480,WRIGHTSVILLE BEACH,NC,PRIMARY,1502,2209,67485629,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10459,BRONX,NY,PRIMARY,17977,30434,414021653,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27055,YADKINVILLE,NC,PRIMARY,6120,11454,195133931,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35802,HUNTSVILLE,AL,PRIMARY,10852,18463,521820459,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83217,BANCROFT,ID,PRIMARY,327,641,9211460,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68649,NORTH BEND,NE,PRIMARY,830,1508,24530635,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60004,ARLINGTON HEIGHTS,IL,PRIMARY,26586,46798,1560430403,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97233,PORTLAND,OR,PRIMARY,14465,26032,388691435,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58254,MCVILLE,ND,PRIMARY,271,447,5976092,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6242,EASTFORD,CT,PRIMARY,773,1360,34542738,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56576,RICHVILLE,MN,PRIMARY,428,764,9247938,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5340,BONDVILLE,VT,PRIMARY,436,720,14859739,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98241,DARRINGTON,WA,PRIMARY,1041,1835,33476575,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95164,SAN JOSE,CA,PRIMARY,577,819,29710183,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71222,BERNICE,LA,PRIMARY,1298,2432,35843765,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33126,MIAMI,FL,PRIMARY,22630,36254,540253154,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55118,SAINT PAUL,MN,PRIMARY,14389,23819,672233974,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28376,RAEFORD,NC,PRIMARY,14162,27467,456241205,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7751,MORGANVILLE,NJ,PRIMARY,9056,18058,854320255,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96821,HONOLULU,HI,PRIMARY,9986,16918,585034532,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92502,RIVERSIDE,CA,PRIMARY,468,714,16543594,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73086,SULPHUR,OK,PRIMARY,3309,6006,97286402,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65707,MILLER,MO,PRIMARY,954,1770,25170637,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28329,CLINTON,NC,PRIMARY,1353,2505,35505191,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31805,CUSSETA,GA,PRIMARY,1217,2263,29402457,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55127,SAINT PAUL,MN,PRIMARY,9099,15796,673842538,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49744,HERRON,MI,PRIMARY,409,745,11054272,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +81419,HOTCHKISS,CO,PRIMARY,1645,3028,49313392,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91789,WALNUT,CA,PRIMARY,20233,37363,1007412826,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2790,WESTPORT,MA,PRIMARY,7817,13765,336390312,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64790,WALKER,MO,PRIMARY,353,651,6840515,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44814,BERLIN HEIGHTS,OH,PRIMARY,1435,2551,47949650,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60043,KENILWORTH,IL,PRIMARY,1285,2371,287126507,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16731,ELDRED,PA,PRIMARY,1348,2396,39293086,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1867,READING,MA,PRIMARY,11926,21499,808066167,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6460,MILFORD,CT,PRIMARY,20773,34070,1088354615,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91108,SAN MARINO,CA,PRIMARY,6783,12520,720791687,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5079,VERSHIRE,VT,PRIMARY,315,538,8801718,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49405,CUSTER,MI,PRIMARY,732,1304,19421246,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79007,BORGER,TX,PRIMARY,5878,11067,222350247,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26753,RIDGELEY,WV,PRIMARY,2881,5251,101358267,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19079,SHARON HILL,PA,PRIMARY,4444,7196,129870560,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17545,MANHEIM,PA,PRIMARY,10663,18860,390865308,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55384,SPRING PARK,MN,PRIMARY,879,1265,35767491,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97910,JORDAN VALLEY,OR,PRIMARY,297,526,5005716,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58433,EDGELEY,ND,PRIMARY,551,957,13317429,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59468,POWER,MT,PRIMARY,277,500,7159255,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38674,TIPLERSVILLE,MS,PRIMARY,389,741,10667663,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96003,REDDING,CA,PRIMARY,17737,30950,552655890,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77516,ANGLETON,TX,PRIMARY,1202,2127,43951334,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4330,AUGUSTA,ME,PRIMARY,11840,19658,369684475,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33957,SANIBEL,FL,PRIMARY,3247,5478,171898751,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75429,COMMERCE,TX,PRIMARY,459,737,13080280,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32949,GRANT,FL,PRIMARY,996,1761,41362053,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16033,EVANS CITY,PA,PRIMARY,3101,5421,120748627,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4074,SCARBOROUGH,ME,PRIMARY,8902,15910,465173618,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46703,ANGOLA,IN,PRIMARY,8147,14245,252694968,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38345,HURON,TN,PRIMARY,771,1489,25579967,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13616,CALCIUM,NY,PRIMARY,740,1340,21326989,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79336,LEVELLAND,TX,PRIMARY,6896,12753,236728752,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44643,MAGNOLIA,OH,PRIMARY,1532,2693,45076025,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5142,CAVENDISH,VT,PRIMARY,351,601,9548506,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85214,MESA,AZ,PRIMARY,481,806,16020989,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49759,MILLERSBURG,MI,PRIMARY,726,1296,13380152,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54665,VIROQUA,WI,PRIMARY,3873,6813,105279780,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87715,CLEVELAND,NM,PRIMARY,251,429,4435153,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59930,REXFORD,MT,PRIMARY,294,533,4300907,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14174,YOUNGSTOWN,NY,PRIMARY,2925,5187,121049602,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +88049,MIMBRES,NM,PRIMARY,412,715,7855276,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41804,BLACKEY,KY,PRIMARY,332,657,11316849,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +81041,GRANADA,CO,PRIMARY,282,553,6707537,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43964,TORONTO,OH,PRIMARY,4632,8006,138654280,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99827,HAINES,AK,PRIMARY,1331,2152,33427226,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95696,VACAVILLE,CA,PRIMARY,1201,2007,45919613,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2663,SOUTH WELLFLEET,MA,PRIMARY,344,539,6973313,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66865,OLPE,KS,PRIMARY,530,991,18127412,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47512,BICKNELL,IN,PRIMARY,1645,2942,43810253,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95948,GRIDLEY,CA,PRIMARY,4244,8183,123636608,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21524,CORRIGANVILLE,MD,PRIMARY,263,461,7257542,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31795,TY TY,GA,PRIMARY,910,1673,23810078,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96818,HONOLULU,HI,PRIMARY,21125,40131,828284548,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20751,DEALE,MD,PRIMARY,1171,1944,58633820,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94903,SAN RAFAEL,CA,PRIMARY,14328,23974,794700161,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63939,FAIRDEALING,MO,PRIMARY,567,1090,13109575,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70546,JENNINGS,LA,PRIMARY,6766,12538,229974408,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92658,NEWPORT BEACH,CA,PRIMARY,1360,2015,85396822,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61334,LOSTANT,IL,PRIMARY,369,647,11198469,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47017,CROSS PLAINS,IN,PRIMARY,297,531,9102921,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32455,PONCE DE LEON,FL,PRIMARY,1719,3181,43532543,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96818,HONOLULU,HI,PRIMARY,21125,40131,828284548,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71469,ROBELINE,LA,PRIMARY,1023,2019,35930399,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17876,SHAMOKIN DAM,PA,PRIMARY,819,1381,23144279,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12525,GARDINER,NY,PRIMARY,1784,3067,82457095,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59038,HYSHAM,MT,PRIMARY,306,544,7853090,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91394,GRANADA HILLS,CA,PRIMARY,317,493,10565696,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98257,LA CONNER,WA,PRIMARY,2127,3632,64153805,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43110,CANAL WINCHESTER,OH,PRIMARY,15631,27043,647524954,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79936,EL PASO,TX,PRIMARY,46203,88503,1519147089,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91214,LA CRESCENTA,CA,PRIMARY,13591,25651,742668478,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58027,ENDERLIN,ND,PRIMARY,656,1158,20030392,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36088,TUSKEGEE INSTITUTE,AL,PRIMARY,1208,1889,22206967,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70071,LUTCHER,LA,PRIMARY,1624,2934,58133715,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91401,VAN NUYS,CA,PRIMARY,17251,28864,626351718,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53590,SUN PRAIRIE,WI,PRIMARY,17475,31182,840767256,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95666,PIONEER,CA,PRIMARY,2400,4179,65818845,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66736,FREDONIA,KS,PRIMARY,1822,3298,48165696,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42464,WHITE PLAINS,KY,PRIMARY,728,1433,21907471,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92211,PALM DESERT,CA,PRIMARY,11167,18234,294398455,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97532,MERLIN,OR,PRIMARY,1564,2777,35301586,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20117,MIDDLEBURG,VA,PRIMARY,681,1131,49083280,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10464,BRONX,NY,PRIMARY,2131,3381,108256016,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46960,MONTEREY,IN,PRIMARY,539,978,13921870,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36205,ANNISTON,AL,PRIMARY,290,482,10716010,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46301,BEVERLY SHORES,IN,PRIMARY,346,565,16263261,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47124,GREENVILLE,IN,PRIMARY,2034,3856,95933773,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73717,ALVA,OK,PRIMARY,2747,4738,73136986,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7071,LYNDHURST,NJ,PRIMARY,10509,17397,493255803,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23181,WEST POINT,VA,PRIMARY,2653,4776,102638627,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31523,BRUNSWICK,GA,PRIMARY,5667,10672,226099291,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78739,AUSTIN,TX,PRIMARY,6676,14154,565514937,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8829,HIGH BRIDGE,NJ,PRIMARY,1857,3328,115616477,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13440,ROME,NY,PRIMARY,18712,31499,589434231,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48173,ROCKWOOD,MI,PRIMARY,6080,11095,268466610,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96755,KAPAAU,HI,PRIMARY,1827,3148,54341976,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37144,PETERSBURG,TN,PRIMARY,1408,2674,41962060,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72634,FLIPPIN,AR,PRIMARY,2001,3636,45678269,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45225,CINCINNATI,OH,PRIMARY,3049,5039,47671786,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50849,GREENFIELD,IA,PRIMARY,1347,2386,39405946,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8202,AVALON,NJ,PRIMARY,938,1508,53452847,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48173,ROCKWOOD,MI,PRIMARY,6080,11095,268466610,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4015,CASCO,ME,PRIMARY,1508,2620,51686158,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43764,NEW LEXINGTON,OH,PRIMARY,3485,6156,98763597,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76241,GAINESVILLE,TX,PRIMARY,1033,1786,30991572,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77293,HOUSTON,TX,PRIMARY,350,567,8069094,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17093,SUMMERDALE,PA,PRIMARY,375,612,11420268,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10527,GRANITE SPRINGS,NY,PRIMARY,473,901,48392560,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +69024,CULBERTSON,NE,PRIMARY,560,1020,14927250,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41064,MOUNT OLIVET,KY,PRIMARY,806,1505,21730258,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60481,WILMINGTON,IL,PRIMARY,5926,10277,234769230,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14853,ITHACA,NY,PRIMARY,302,342,5064499,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2876,SLATERSVILLE,RI,PRIMARY,765,1211,29798698,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4769,PRESQUE ISLE,ME,PRIMARY,4645,7779,140950065,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7055,PASSAIC,NJ,PRIMARY,28463,51244,778397023,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92570,PERRIS,CA,PRIMARY,16762,33297,488394932,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77865,MARQUEZ,TX,PRIMARY,702,1311,21332997,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87420,SHIPROCK,NM,PRIMARY,3099,5236,93508324,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50648,JESUP,IA,PRIMARY,1883,3476,69459329,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99710,FAIRBANKS,AK,PRIMARY,875,1451,40361564,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29378,UNA,SC,PRIMARY,528,975,9403657,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48730,EAST TAWAS,MI,PRIMARY,2295,3876,51005023,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36373,SHORTERVILLE,AL,PRIMARY,258,472,5785190,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31789,SUMNER,GA,PRIMARY,626,1189,18145167,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39752,MATHISTON,MS,PRIMARY,955,1857,28716799,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38337,GADSDEN,TN,PRIMARY,617,1139,17603973,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28746,LAKE LURE,NC,PRIMARY,1071,1864,23427879,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83334,HANSEN,ID,PRIMARY,781,1501,20265526,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12561,NEW PALTZ,NY,PRIMARY,6999,11547,302822801,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39202,JACKSON,MS,PRIMARY,3284,5162,103618280,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23663,HAMPTON,VA,PRIMARY,6269,10559,173186203,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77531,CLUTE,TX,PRIMARY,6417,11888,239538094,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6382,UNCASVILLE,CT,PRIMARY,5357,8952,204331395,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94064,REDWOOD CITY,CA,PRIMARY,775,1200,35609802,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25301,CHARLESTON,WV,PRIMARY,1341,1800,34568020,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77639,ORANGEFIELD,TX,PRIMARY,327,583,11019630,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21220,MIDDLE RIVER,MD,PRIMARY,18828,31809,727543155,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75146,LANCASTER,TX,PRIMARY,8347,14595,287543216,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80480,WALDEN,CO,PRIMARY,578,985,14818961,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24073,CHRISTIANSBURG,VA,PRIMARY,13101,23032,479491366,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94519,CONCORD,CA,PRIMARY,8562,14804,379103572,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75103,CANTON,TX,PRIMARY,5479,10257,179207421,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60827,RIVERDALE,IL,PRIMARY,11337,19042,279694388,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28905,MARBLE,NC,PRIMARY,1260,2318,29569881,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92115,SAN DIEGO,CA,PRIMARY,22503,36221,751378269,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68957,LAWRENCE,NE,PRIMARY,308,573,6934357,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18101,ALLENTOWN,PA,PRIMARY,1347,2150,20693943,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30066,MARIETTA,GA,PRIMARY,25212,46080,1357866092,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31410,SAVANNAH,GA,PRIMARY,11344,19812,566547068,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97391,TOLEDO,OR,PRIMARY,2247,4019,69303687,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87823,LEMITAR,NM,PRIMARY,300,538,6855610,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64856,PINEVILLE,MO,PRIMARY,1609,2929,45969820,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77227,HOUSTON,TX,PRIMARY,653,1169,148401980,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18931,LAHASKA,PA,PRIMARY,261,400,10852299,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93618,DINUBA,CA,PRIMARY,9673,19322,254938092,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49040,COLON,MI,PRIMARY,1484,2644,38842291,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50050,CHURDAN,IA,PRIMARY,330,592,7540289,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31022,DUDLEY,GA,PRIMARY,675,1271,23032195,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93004,VENTURA,CA,PRIMARY,12882,23167,609355820,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33921,BOCA GRANDE,FL,PRIMARY,846,1392,124128680,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33327,FORT LAUDERDALE,FL,PRIMARY,8150,17177,724191841,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84315,HOOPER,UT,PRIMARY,2989,5926,136607626,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49130,UNION,MI,PRIMARY,904,1590,33750696,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +89135,LAS VEGAS,NV,PRIMARY,10996,19020,768482880,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95605,WEST SACRAMENTO,CA,PRIMARY,5155,9280,153053927,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77388,SPRING,TX,PRIMARY,17956,33840,1035769149,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92393,VICTORVILLE,CA,PRIMARY,1503,2612,51957551,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29518,CADES,SC,PRIMARY,627,1145,15357461,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25529,JULIAN,WV,PRIMARY,330,640,10754869,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92114,SAN DIEGO,CA,PRIMARY,27373,50254,875844144,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30413,BARTOW,GA,PRIMARY,727,1344,19137594,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44129,CLEVELAND,OH,PRIMARY,15246,24474,474355918,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31082,SANDERSVILLE,GA,PRIMARY,4625,8384,137036852,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48652,RHODES,MI,PRIMARY,791,1437,23753720,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24527,BLAIRS,VA,PRIMARY,1448,2606,43651777,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21783,SMITHSBURG,MD,PRIMARY,4105,7642,186231945,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55419,MINNEAPOLIS,MN,PRIMARY,13238,22317,900807593,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27878,SHARPSBURG,NC,PRIMARY,1103,1977,25901168,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46989,UPLAND,IN,PRIMARY,1685,3128,56729502,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10107,NEW YORK,NY,PRIMARY,474,598,102139661,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55109,SAINT PAUL,MN,PRIMARY,16070,26675,609894829,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2809,BRISTOL,RI,PRIMARY,9965,16829,456496819,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50650,LAMONT,IA,PRIMARY,340,602,8241625,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27959,NAGS HEAD,NC,PRIMARY,1523,2496,44156270,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60033,HARVARD,IL,PRIMARY,6498,11934,219079842,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77830,ANDERSON,TX,PRIMARY,1216,2140,40569745,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65737,REEDS SPRING,MO,PRIMARY,3708,6567,85648448,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23005,ASHLAND,VA,PRIMARY,7206,12231,311338934,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30003,NORCROSS,GA,PRIMARY,323,525,7721994,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50541,GILMORE CITY,IA,PRIMARY,401,723,10641243,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91367,WOODLAND HILLS,CA,PRIMARY,18718,31168,1030182882,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33913,FORT MYERS,FL,PRIMARY,6646,12218,341174549,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31757,THOMASVILLE,GA,PRIMARY,4025,7537,140595679,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64748,GOLDEN CITY,MO,PRIMARY,659,1169,14676481,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72112,NEWPORT,AR,PRIMARY,3774,6715,93621747,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84651,PAYSON,UT,PRIMARY,8458,17332,315168222,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73505,LAWTON,OK,PRIMARY,20404,37053,623591583,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27705,DURHAM,NC,PRIMARY,18938,31340,804835237,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20914,SILVER SPRING,MD,PRIMARY,354,541,13866212,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37036,CHARLOTTE,TN,PRIMARY,2459,4605,79487171,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11428,QUEENS VILLAGE,NY,PRIMARY,9216,16017,341921071,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80728,FLEMING,CO,PRIMARY,389,711,10649677,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22920,AFTON,VA,PRIMARY,1903,3352,75656244,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77381,SPRING,TX,PRIMARY,16411,31122,1672426589,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85911,CIBECUE,AZ,PRIMARY,428,849,7184367,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44035,ELYRIA,OH,PRIMARY,30760,50414,913037894,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87499,FARMINGTON,NM,PRIMARY,13305,24735,341621613,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22201,ARLINGTON,VA,PRIMARY,20312,26353,1570573667,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93626,FRIANT,CA,PRIMARY,667,1202,39735058,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61931,HUMBOLDT,IL,PRIMARY,524,968,14578315,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63939,FAIRDEALING,MO,PRIMARY,567,1090,13109575,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34270,TALLEVAST,FL,PRIMARY,427,666,12690881,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80524,FORT COLLINS,CO,PRIMARY,14641,24832,555037289,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20636,HOLLYWOOD,MD,PRIMARY,4560,8431,254490988,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29451,ISLE OF PALMS,SC,PRIMARY,2203,3790,133836057,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47994,WINGATE,IN,PRIMARY,290,524,9709726,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91763,MONTCLAIR,CA,PRIMARY,14454,27063,453244725,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14810,BATH,NY,PRIMARY,5367,9174,151990420,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77990,TIVOLI,TX,PRIMARY,332,613,9543106,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61281,SHERRARD,IL,PRIMARY,1230,2317,56932197,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33177,MIAMI,FL,PRIMARY,23647,41930,693480552,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33173,MIAMI,FL,PRIMARY,16018,26714,628049188,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75937,CHIRENO,TX,PRIMARY,472,891,12580055,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78711,AUSTIN,TX,PRIMARY,266,396,12410388,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78702,AUSTIN,TX,PRIMARY,9463,14748,243264352,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98206,EVERETT,WA,PRIMARY,1288,1947,49607523,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64483,ROSENDALE,MO,PRIMARY,279,558,9784501,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47108,CAMPBELLSBURG,IN,PRIMARY,1006,1885,26784300,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62573,WARRENSBURG,IL,PRIMARY,746,1374,27530398,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26679,MOUNT NEBO,WV,PRIMARY,797,1518,27096101,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70033,METAIRIE,LA,PRIMARY,254,391,6492783,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12464,PHOENICIA,NY,PRIMARY,520,816,13164275,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96148,TAHOE VISTA,CA,PRIMARY,387,632,10908505,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4106,SOUTH PORTLAND,ME,PRIMARY,12850,20593,475989261,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38450,COLLINWOOD,TN,PRIMARY,1069,2055,28218645,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62292,TILDEN,IL,PRIMARY,407,703,9172253,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61546,MANITO,IL,PRIMARY,2038,3744,68886153,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22734,REMINGTON,VA,PRIMARY,1402,2573,60250049,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49913,CALUMET,MI,PRIMARY,3231,5571,78206758,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97526,GRANTS PASS,OR,PRIMARY,13798,24106,339304233,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1001,AGAWAM,MA,PRIMARY,8596,14021,337735143,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39122,NATCHEZ,MS,PRIMARY,354,597,10888991,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98241,DARRINGTON,WA,PRIMARY,1041,1835,33476575,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18621,HUNLOCK CREEK,PA,PRIMARY,2431,4390,82057175,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28618,DEEP GAP,NC,PRIMARY,1010,1837,29327282,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19053,FEASTERVILLE TREVOSE,PA,PRIMARY,14193,24238,649468583,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79110,AMARILLO,TX,PRIMARY,8483,15253,283911288,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36740,FORKLAND,AL,PRIMARY,526,943,12631738,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15083,SUTERSVILLE,PA,PRIMARY,494,844,14378082,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68739,HARTINGTON,NE,PRIMARY,1410,2596,37707057,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45619,CHESAPEAKE,OH,PRIMARY,3547,6472,110189433,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14219,BUFFALO,NY,PRIMARY,6011,9751,183028157,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99523,ANCHORAGE,AK,PRIMARY,1199,1856,51216649,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8067,PEDRICKTOWN,NJ,PRIMARY,821,1451,35607626,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79351,ODONNELL,TX,PRIMARY,573,1076,13006690,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58107,FARGO,ND,PRIMARY,279,401,8551964,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92865,ORANGE,CA,PRIMARY,8810,15604,408519540,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80482,WINTER PARK,CO,PRIMARY,1186,1767,42662858,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85006,PHOENIX,AZ,PRIMARY,8660,15463,231696954,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92116,SAN DIEGO,CA,PRIMARY,17446,24400,719960889,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46766,LIBERTY CENTER,IN,PRIMARY,261,473,8706611,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95487,VINEBURG,CA,PRIMARY,276,470,8891097,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23234,RICHMOND,VA,PRIMARY,18687,31921,562632911,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75778,MURCHISON,TX,PRIMARY,1254,2311,34676291,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96726,HONAUNAU,HI,PRIMARY,640,1088,14513183,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68862,ORD,NE,PRIMARY,1390,2496,36990100,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +81226,FLORENCE,CO,PRIMARY,2396,4384,69073349,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75224,DALLAS,TX,PRIMARY,12840,23717,327341629,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13808,MORRIS,NY,PRIMARY,790,1411,23193396,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40068,SMITHFIELD,KY,PRIMARY,1050,1973,42721880,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60443,MATTESON,IL,PRIMARY,10013,16892,398674460,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76630,BRUCEVILLE,TX,PRIMARY,742,1397,29530450,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37410,CHATTANOOGA,TN,PRIMARY,1387,2314,21960081,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1035,HADLEY,MA,PRIMARY,2617,4327,97134728,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67954,ROLLA,KS,PRIMARY,339,638,9587901,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53202,MILWAUKEE,WI,PRIMARY,13057,15593,651034663,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93223,FARMERSVILLE,CA,PRIMARY,3332,6716,79055086,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35149,SYCAMORE,AL,PRIMARY,307,576,7263074,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44643,MAGNOLIA,OH,PRIMARY,1532,2693,45076025,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15148,WILMERDING,PA,PRIMARY,1248,1898,26440710,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53518,BLUE RIVER,WI,PRIMARY,639,1134,16364196,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35544,BEAVERTON,AL,PRIMARY,281,532,7195412,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48509,BURTON,MI,PRIMARY,4853,8434,137064063,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17845,MILLMONT,PA,PRIMARY,959,1790,21610107,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51025,HOLSTEIN,IA,PRIMARY,979,1759,27681993,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60952,MELVIN,IL,PRIMARY,301,574,8869339,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12871,SCHUYLERVILLE,NY,PRIMARY,1912,3391,70321403,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25507,CEREDO,WV,PRIMARY,660,1074,16947203,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17872,SHAMOKIN,PA,PRIMARY,4540,7558,110316191,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56115,BALATON,MN,PRIMARY,671,1176,19547722,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56560,MOORHEAD,MN,PRIMARY,16801,28610,578340681,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30417,CLAXTON,GA,PRIMARY,3746,6867,102717818,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68361,GENEVA,NE,PRIMARY,1224,2206,35898742,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60619,CHICAGO,IL,PRIMARY,30282,48410,780108829,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76627,BLUM,TX,PRIMARY,659,1261,22306849,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64446,FAIRFAX,MO,PRIMARY,532,968,13707849,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35565,HALEYVILLE,AL,PRIMARY,5214,9940,139423643,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85637,SONOITA,AZ,PRIMARY,687,1225,26050942,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27622,RALEIGH,NC,PRIMARY,322,505,11320081,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47038,PATRIOT,IN,PRIMARY,508,923,14597846,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24569,LONG ISLAND,VA,PRIMARY,420,782,12002292,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4949,LIBERTY,ME,PRIMARY,450,824,11317144,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17024,ELLIOTTSBURG,PA,PRIMARY,897,1648,32568610,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35453,COTTONDALE,AL,PRIMARY,4575,8490,158892811,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64016,BUCKNER,MO,PRIMARY,2047,3796,77052694,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48081,SAINT CLAIR SHORES,MI,PRIMARY,11042,18281,405089294,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61334,LOSTANT,IL,PRIMARY,369,647,11198469,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15436,FAIRCHANCE,PA,PRIMARY,1267,2180,33272489,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60507,AURORA,IL,PRIMARY,878,1505,22654746,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45629,FRANKLIN FURNACE,OH,PRIMARY,1270,2369,42009646,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52064,MILES,IA,PRIMARY,386,738,12309161,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92254,MECCA,CA,PRIMARY,5189,11107,96913687,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5836,EAST HARDWICK,VT,PRIMARY,486,880,13556320,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33156,MIAMI,FL,PRIMARY,14785,26260,1409543303,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39326,DALEVILLE,MS,PRIMARY,322,571,8463548,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60074,PALATINE,IL,PRIMARY,18681,33175,815369950,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83832,GENESEE,ID,PRIMARY,688,1314,25534920,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53144,KENOSHA,WI,PRIMARY,11933,20705,477473327,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61550,MORTON,IL,PRIMARY,8765,15680,439743630,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49322,CORAL,MI,PRIMARY,467,889,13648922,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36863,LANETT,AL,PRIMARY,5246,9401,131928321,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +89407,FALLON,NV,PRIMARY,966,1609,28995773,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61014,CHADWICK,IL,PRIMARY,600,1081,17994066,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5069,SOUTH RYEGATE,VT,PRIMARY,335,581,9218551,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32332,GRETNA,FL,PRIMARY,954,1735,19600826,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11432,JAMAICA,NY,PRIMARY,24626,41968,815001669,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38650,MYRTLE,MS,PRIMARY,1498,2838,39922440,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70596,LAFAYETTE,LA,PRIMARY,554,893,21752695,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94305,STANFORD,CA,PRIMARY,3657,5084,258000176,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63349,HAWK POINT,MO,PRIMARY,869,1642,30398195,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41080,PETERSBURG,KY,PRIMARY,866,1565,33353316,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23417,ONANCOCK,VA,PRIMARY,1730,2899,46157669,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74864,PRAGUE,OK,PRIMARY,2049,3896,62764134,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +69169,WALLACE,NE,PRIMARY,268,517,7566728,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44651,MECHANICSTOWN,OH,PRIMARY,361,664,8956470,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60403,CREST HILL,IL,PRIMARY,8302,13949,284179527,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12946,LAKE PLACID,NY,PRIMARY,2893,4566,92540183,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46166,PARAGON,IN,PRIMARY,1042,1961,31695699,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63544,GREEN CASTLE,MO,PRIMARY,339,640,7140159,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46733,DECATUR,IN,PRIMARY,8894,15973,274309636,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39342,MARION,MS,PRIMARY,751,1300,23864412,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29108,NEWBERRY,SC,PRIMARY,8671,15490,229507254,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92315,BIG BEAR LAKE,CA,PRIMARY,3747,6550,101626614,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98015,BELLEVUE,WA,PRIMARY,571,868,33095427,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17967,RINGTOWN,PA,PRIMARY,1214,2146,39500842,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84774,TOQUERVILLE,UT,PRIMARY,537,1053,16028044,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96094,WEED,CA,PRIMARY,2674,4766,72748977,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73738,GARBER,OK,PRIMARY,531,967,15313682,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48074,SMITHS CREEK,MI,PRIMARY,4322,7771,147486251,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19475,SPRING CITY,PA,PRIMARY,5109,8983,273158219,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78801,UVALDE,TX,PRIMARY,7898,14841,195993185,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45150,MILFORD,OH,PRIMARY,15545,27012,646795539,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61378,WEST BROOKLYN,IL,PRIMARY,259,466,7152076,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28392,TAR HEEL,NC,PRIMARY,762,1422,21138637,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15957,STRONGSTOWN,PA,PRIMARY,258,455,7607813,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85756,TUCSON,AZ,PRIMARY,7604,14665,238131456,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53065,OAKFIELD,WI,PRIMARY,1049,1933,40506986,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57709,RAPID CITY,SD,PRIMARY,1679,2528,47339015,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68716,BEEMER,NE,PRIMARY,455,815,11540833,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85086,PHOENIX,AZ,PRIMARY,14825,29056,850418427,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95518,ARCATA,CA,PRIMARY,965,1402,21280014,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73932,BEAVER,OK,PRIMARY,940,1800,31409085,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39564,OCEAN SPRINGS,MS,PRIMARY,15851,28673,644589818,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37148,PORTLAND,TN,PRIMARY,9620,18152,316659098,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40903,ARTEMUS,KY,PRIMARY,340,665,7398555,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83830,FERNWOOD,ID,PRIMARY,280,526,6637168,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7620,ALPINE,NJ,PRIMARY,970,1696,193066840,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38483,SUMMERTOWN,TN,PRIMARY,2111,4137,61501726,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97867,NORTH POWDER,OR,PRIMARY,325,613,7302914,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28504,KINSTON,NC,PRIMARY,9070,16316,287556016,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41146,HITCHINS,KY,PRIMARY,274,513,6709382,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19341,EXTON,PA,PRIMARY,8813,15505,611500552,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15676,PLEASANT UNITY,PA,PRIMARY,286,506,9873123,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42367,POWDERLY,KY,PRIMARY,439,826,9949922,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54481,STEVENS POINT,WI,PRIMARY,16425,27473,563847441,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11717,BRENTWOOD,NY,PRIMARY,28265,48090,850200013,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1037,HARDWICK,MA,PRIMARY,388,714,17327614,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43447,MILLBURY,OH,PRIMARY,1819,3111,68923846,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99803,JUNEAU,AK,PRIMARY,2223,3545,94757025,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79235,FLOYDADA,TX,PRIMARY,1646,3085,36797398,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74501,MCALESTER,OK,PRIMARY,10505,18926,346429620,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11724,COLD SPRING HARBOR,NY,PRIMARY,1803,3232,271529797,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23221,RICHMOND,VA,PRIMARY,7764,10957,456885469,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20905,SILVER SPRING,MD,PRIMARY,9042,16516,592923713,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29464,MOUNT PLEASANT,SC,PRIMARY,22010,36456,1094083177,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61764,PONTIAC,IL,PRIMARY,6262,10677,201511259,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49426,HUDSONVILLE,MI,PRIMARY,14860,28748,657602868,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20710,BLADENSBURG,MD,PRIMARY,4030,6493,122820042,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17961,ORWIGSBURG,PA,PRIMARY,3430,5985,147532725,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40157,PAYNEVILLE,KY,PRIMARY,445,825,13008680,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32937,SATELLITE BEACH,FL,PRIMARY,12963,21943,573425547,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80833,RUSH,CO,PRIMARY,275,521,6971785,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37724,CUMBERLAND GAP,TN,PRIMARY,863,1614,24587713,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14820,CAMERON MILLS,NY,PRIMARY,294,543,9261359,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49202,JACKSON,MI,PRIMARY,8750,14274,207103338,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97324,ALSEA,OR,PRIMARY,481,844,13463500,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76302,WICHITA FALLS,TX,PRIMARY,5102,8940,163036221,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34233,SARASOTA,FL,PRIMARY,8728,14328,274182890,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76645,HILLSBORO,TX,PRIMARY,4547,8425,122502546,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11730,EAST ISLIP,NY,PRIMARY,7031,12627,416491794,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57471,ROSCOE,SD,PRIMARY,320,573,6051349,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14477,KENT,NY,PRIMARY,803,1443,25182121,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36027,EUFAULA,AL,PRIMARY,6494,11678,178675618,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15486,VANDERBILT,PA,PRIMARY,1125,2027,34013004,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35810,HUNTSVILLE,AL,PRIMARY,14235,23653,372751691,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80030,WESTMINSTER,CO,PRIMARY,6660,11249,205713219,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80615,EATON,CO,PRIMARY,3196,6149,131390991,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1901,LYNN,MA,PRIMARY,830,1155,22363981,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11802,HICKSVILLE,NY,PRIMARY,411,620,16176164,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48877,RIVERDALE,MI,PRIMARY,994,1862,26716044,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21224,BALTIMORE,MD,PRIMARY,22061,33150,876200844,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42140,GAMALIEL,KY,PRIMARY,505,948,10871559,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67101,MAIZE,KS,PRIMARY,1555,2961,66297614,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38011,BRIGHTON,TN,PRIMARY,4069,7861,151924852,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37934,KNOXVILLE,TN,PRIMARY,11134,21174,681700579,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71749,JUNCTION CITY,AR,PRIMARY,1152,2213,36329410,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79424,LUBBOCK,TX,PRIMARY,17537,32403,917331139,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28401,WILMINGTON,NC,PRIMARY,9214,14224,221277005,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59018,CLYDE PARK,MT,PRIMARY,296,524,7916287,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42160,PARK CITY,KY,PRIMARY,825,1574,21279315,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39564,OCEAN SPRINGS,MS,PRIMARY,15851,28673,644589818,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93062,SIMI VALLEY,CA,PRIMARY,615,962,26928183,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29728,PAGELAND,SC,PRIMARY,3823,7007,93366796,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65284,STURGEON,MO,PRIMARY,1020,1882,35803834,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54859,MINONG,WI,PRIMARY,943,1706,23769015,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18832,MONROETON,PA,PRIMARY,817,1411,20753238,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68106,OMAHA,NE,PRIMARY,10521,15966,353634802,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3741,CANAAN,NH,PRIMARY,2056,3514,78885778,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31783,REBECCA,GA,PRIMARY,445,841,12182704,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32302,TALLAHASSEE,FL,PRIMARY,584,899,28539963,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64493,TURNEY,MO,PRIMARY,254,472,8658158,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2808,BRADFORD,RI,PRIMARY,1153,2043,41610566,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55325,DASSEL,MN,PRIMARY,2019,3752,74636255,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26201,BUCKHANNON,WV,PRIMARY,7871,14223,238611381,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54213,FORESTVILLE,WI,PRIMARY,660,1230,21581543,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62926,DONGOLA,IL,PRIMARY,952,1748,24532517,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20851,ROCKVILLE,MD,PRIMARY,7019,11459,287309289,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80047,AURORA,CO,PRIMARY,876,1362,29554617,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79248,PADUCAH,TX,PRIMARY,657,1199,14323236,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3254,MOULTONBOROUGH,NH,PRIMARY,1816,3190,66627549,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97361,MONMOUTH,OR,PRIMARY,4168,7320,133670416,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47948,GOODLAND,IN,PRIMARY,674,1164,17962691,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4281,SOUTH PARIS,ME,PRIMARY,2174,3737,62067583,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61614,PEORIA,IL,PRIMARY,14848,24235,663839867,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13037,CHITTENANGO,NY,PRIMARY,4286,7640,165223974,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28213,CHARLOTTE,NC,PRIMARY,15011,25793,481719203,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17538,LANDISVILLE,PA,PRIMARY,3271,5913,153033333,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50641,HAZLETON,IA,PRIMARY,637,1245,15331941,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85204,MESA,AZ,PRIMARY,23251,42421,728526805,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40771,WOODBINE,KY,PRIMARY,615,1160,11736119,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98579,ROCHESTER,WA,PRIMARY,5410,9937,202874004,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48122,MELVINDALE,MI,PRIMARY,4831,8081,127084375,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95630,FOLSOM,CA,PRIMARY,28672,53688,1899333607,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27501,ANGIER,NC,PRIMARY,7058,13444,246564481,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48348,CLARKSTON,MI,PRIMARY,10702,20501,735123611,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10012,NEW YORK,NY,PRIMARY,13415,17738,1529644615,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63146,SAINT LOUIS,MO,PRIMARY,15396,24912,689003338,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54205,CASCO,WI,PRIMARY,1035,1910,36998005,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21009,ABINGDON,MD,PRIMARY,14151,25308,779581367,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2643,EAST ORLEANS,MA,PRIMARY,661,1081,26076809,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40010,BUCKNER,KY,PRIMARY,297,607,16781891,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61080,SOUTH BELOIT,IL,PRIMARY,4857,8878,193089401,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43837,PORT WASHINGTON,OH,PRIMARY,842,1506,23766200,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1850,LOWELL,MA,PRIMARY,6713,11001,222920009,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4976,SKOWHEGAN,ME,PRIMARY,4356,7550,135684772,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95641,ISLETON,CA,PRIMARY,879,1486,23897009,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45205,CINCINNATI,OH,PRIMARY,7065,11782,161986979,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30711,CRANDALL,GA,PRIMARY,1404,2690,39044255,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47142,MAUCKPORT,IN,PRIMARY,423,749,11610685,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91913,CHULA VISTA,CA,PRIMARY,15720,31558,850730380,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24599,WINGINA,VA,PRIMARY,252,437,7197428,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50830,AFTON,IA,PRIMARY,751,1402,21968576,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54562,THREE LAKES,WI,PRIMARY,1067,1804,25919880,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51542,HONEY CREEK,IA,PRIMARY,466,874,22186723,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24085,EAGLE ROCK,VA,PRIMARY,903,1648,30684275,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16510,ERIE,PA,PRIMARY,12020,21150,404957360,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56320,COLD SPRING,MN,PRIMARY,3770,6910,147883240,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17540,LEOLA,PA,PRIMARY,4693,8322,153303595,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12956,MINEVILLE,NY,PRIMARY,529,913,15438631,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12076,GILBOA,NY,PRIMARY,579,1012,16755100,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59011,BIG TIMBER,MT,PRIMARY,1540,2695,40805157,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2863,CENTRAL FALLS,RI,PRIMARY,7451,12807,155524266,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29030,CAMERON,SC,PRIMARY,869,1521,26674338,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +89128,LAS VEGAS,NV,PRIMARY,17206,28310,691134906,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27540,HOLLY SPRINGS,NC,PRIMARY,11397,23508,741818553,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23059,GLEN ALLEN,VA,PRIMARY,13278,25802,1059404731,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7304,JERSEY CITY,NJ,PRIMARY,18986,31180,608970277,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65325,COLE CAMP,MO,PRIMARY,1383,2531,34221073,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84782,VEYO,UT,PRIMARY,313,584,8745723,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75225,DALLAS,TX,PRIMARY,10943,19408,1646556171,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96027,ETNA,CA,PRIMARY,904,1656,23105894,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76017,ARLINGTON,TX,PRIMARY,20979,37503,982754586,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13090,LIVERPOOL,NY,PRIMARY,15076,26337,669746981,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5669,ROXBURY,VT,PRIMARY,268,462,6659703,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30528,CLEVELAND,GA,PRIMARY,8912,16648,256094867,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72940,HUNTINGTON,AR,PRIMARY,958,1848,29321227,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61204,ROCK ISLAND,IL,PRIMARY,291,410,7912628,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7303,JERSEY CITY,NJ,PRIMARY,1115,1707,37296479,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98650,TROUT LAKE,WA,PRIMARY,443,796,14616106,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62901,CARBONDALE,IL,PRIMARY,8676,13025,215833434,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95562,RIO DELL,CA,PRIMARY,1202,2147,28716384,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14616,ROCHESTER,NY,PRIMARY,14962,24464,446717959,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64421,AMAZONIA,MO,PRIMARY,424,779,13151840,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78522,BROWNSVILLE,TX,PRIMARY,437,780,8320614,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55337,BURNSVILLE,MN,PRIMARY,22600,38193,997781459,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27939,GRANDY,NC,PRIMARY,1167,2059,30526226,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92423,SAN BERNARDINO,CA,PRIMARY,615,1021,25765924,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79907,EL PASO,TX,PRIMARY,23443,43435,476840996,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94708,BERKELEY,CA,PRIMARY,6100,10062,456099830,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62314,BAYLIS,IL,PRIMARY,278,514,7225452,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45323,ENON,OH,PRIMARY,2734,4727,94452916,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95008,CAMPBELL,CA,PRIMARY,21629,36168,1394476952,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21557,RAWLINGS,MD,PRIMARY,842,1524,25768478,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11746,HUNTINGTON STATION,NY,PRIMARY,32197,56971,1986757091,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36032,FORT DEPOSIT,AL,PRIMARY,1206,2230,27095732,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20108,MANASSAS,VA,PRIMARY,973,1594,38004138,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74435,GORE,OK,PRIMARY,1297,2448,36616210,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72766,SPRINGDALE,AR,PRIMARY,674,1201,23452182,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65810,SPRINGFIELD,MO,PRIMARY,9759,17974,458849836,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93725,FRESNO,CA,PRIMARY,8415,16278,213137120,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12155,SCHENEVUS,NY,PRIMARY,782,1378,22636112,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54984,WILD ROSE,WI,PRIMARY,1579,2719,40442597,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29565,LATTA,SC,PRIMARY,2861,5245,70550097,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83655,NEW PLYMOUTH,ID,PRIMARY,1778,3448,51204695,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78003,BANDERA,TX,PRIMARY,4052,7180,113119211,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95490,WILLITS,CA,PRIMARY,5400,9434,145592603,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14550,SILVER SPRINGS,NY,PRIMARY,794,1369,25310025,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25063,DUCK,WV,PRIMARY,533,1010,13857726,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70033,METAIRIE,LA,PRIMARY,254,391,6492783,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66063,OLATHE,KS,PRIMARY,333,552,11467971,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47142,MAUCKPORT,IN,PRIMARY,423,749,11610685,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49544,GRAND RAPIDS,MI,PRIMARY,4518,7557,148235773,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53583,SAUK CITY,WI,PRIMARY,2906,5021,111960066,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15214,PITTSBURGH,PA,PRIMARY,6767,10700,203171183,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37656,FALL BRANCH,TN,PRIMARY,1672,3062,51649956,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34142,IMMOKALEE,FL,PRIMARY,5475,10418,112722244,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39563,MOSS POINT,MS,PRIMARY,5897,10216,162668146,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60661,CHICAGO,IL,PRIMARY,4459,5726,369568564,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52003,DUBUQUE,IA,PRIMARY,6880,12170,313811358,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44890,WILLARD,OH,PRIMARY,5298,9165,153785787,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22546,RUTHER GLEN,VA,PRIMARY,6997,12545,292216115,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92823,BREA,CA,PRIMARY,1557,3045,105550592,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71021,CULLEN,LA,PRIMARY,432,755,8115762,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56026,ELLENDALE,MN,PRIMARY,959,1719,31827756,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2126,MATTAPAN,MA,PRIMARY,12276,19266,399176436,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33308,FORT LAUDERDALE,FL,PRIMARY,16094,23333,787866464,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14548,SHORTSVILLE,NY,PRIMARY,1925,3340,64636212,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17097,WICONISCO,PA,PRIMARY,395,689,11037517,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17864,PORT TREVORTON,PA,PRIMARY,992,1809,23000164,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +69152,MULLEN,NE,PRIMARY,412,749,8961104,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7503,PATERSON,NJ,PRIMARY,8454,14649,213985183,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56368,RICHMOND,MN,PRIMARY,2010,3685,71040061,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56728,HALLOCK,MN,PRIMARY,723,1247,18369573,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7723,DEAL,NJ,PRIMARY,535,875,38425444,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51250,SIOUX CENTER,IA,PRIMARY,3078,5875,118901813,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6379,PAWCATUCK,CT,PRIMARY,4464,7620,205807466,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25504,BARBOURSVILLE,WV,PRIMARY,5542,9894,202926890,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79029,DUMAS,TX,PRIMARY,6753,12948,231494323,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1756,MENDON,MA,PRIMARY,2753,5234,188037787,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38367,RAMER,TN,PRIMARY,1054,2011,32698860,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24015,ROANOKE,VA,PRIMARY,7911,12643,285429315,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60921,CHATSWORTH,IL,PRIMARY,731,1258,18053181,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70884,BATON ROUGE,LA,PRIMARY,493,805,33251831,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79045,HEREFORD,TX,PRIMARY,7886,15188,206430730,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47850,FARMERSBURG,IN,PRIMARY,1173,2120,37762044,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80653,WELDONA,CO,PRIMARY,340,626,10585279,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20692,VALLEY LEE,MD,PRIMARY,589,1054,28617466,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53039,JUNEAU,WI,PRIMARY,2063,3685,76517600,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45230,CINCINNATI,OH,PRIMARY,14079,23360,674299362,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31629,DIXIE,GA,PRIMARY,370,683,8799045,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27865,PINETOWN,NC,PRIMARY,824,1543,25142734,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66007,BASEHOR,KS,PRIMARY,2704,4989,129081698,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25671,DINGESS,WV,PRIMARY,415,848,12544551,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19344,HONEY BROOK,PA,PRIMARY,5555,9962,212867444,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51640,HAMBURG,IA,PRIMARY,760,1339,22284123,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32925,PATRICK AFB,FL,PRIMARY,524,1019,20001344,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21864,STOCKTON,MD,PRIMARY,293,522,9373767,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33197,MIAMI,FL,PRIMARY,628,1028,15702441,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97032,HUBBARD,OR,PRIMARY,2003,3828,67957870,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90056,LOS ANGELES,CA,PRIMARY,4421,7060,232623389,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30513,BLUE RIDGE,GA,PRIMARY,4412,8079,102776437,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79225,CHILLICOTHE,TX,PRIMARY,424,791,11983029,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21014,BEL AIR,MD,PRIMARY,17433,31074,936065910,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24599,WINGINA,VA,PRIMARY,252,437,7197428,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68812,AMHERST,NE,PRIMARY,388,702,10500665,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2460,NEWTONVILLE,MA,PRIMARY,4687,7764,361543245,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56560,MOORHEAD,MN,PRIMARY,16801,28610,578340681,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55017,DALBO,MN,PRIMARY,319,580,12207218,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8067,PEDRICKTOWN,NJ,PRIMARY,821,1451,35607626,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32413,PANAMA CITY BEACH,FL,PRIMARY,6421,10441,195562587,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49762,NAUBINWAY,MI,PRIMARY,310,543,5863212,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66852,GRIDLEY,KS,PRIMARY,294,557,9551913,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85552,THATCHER,AZ,PRIMARY,2354,4487,90479970,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77640,PORT ARTHUR,TX,PRIMARY,7011,12079,189750941,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28016,BESSEMER CITY,NC,PRIMARY,5559,10243,164642296,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84513,CASTLE DALE,UT,PRIMARY,639,1281,24539679,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32170,NEW SMYRNA BEACH,FL,PRIMARY,805,1221,22539279,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63857,KENNETT,MO,PRIMARY,4915,9013,133612279,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70444,KENTWOOD,LA,PRIMARY,3899,7259,116352404,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23829,CAPRON,VA,PRIMARY,573,1030,17889491,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77238,HOUSTON,TX,PRIMARY,301,479,6557203,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73050,LANGSTON,OK,PRIMARY,290,465,5214735,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28128,NORWOOD,NC,PRIMARY,3235,5964,96140145,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8075,RIVERSIDE,NJ,PRIMARY,14165,24711,642668487,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45209,CINCINNATI,OH,PRIMARY,5543,7341,234157208,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67208,WICHITA,KS,PRIMARY,8799,14041,286314548,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6511,NEW HAVEN,CT,PRIMARY,21024,31415,762115986,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71327,COTTONPORT,LA,PRIMARY,1549,2922,45276535,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79325,FARWELL,TX,PRIMARY,927,1790,26169992,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22604,WINCHESTER,VA,PRIMARY,958,1534,34379854,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24557,GRETNA,VA,PRIMARY,3367,6054,91103640,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83014,WILSON,WY,PRIMARY,1496,2334,96854336,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10025,NEW YORK,NY,PRIMARY,47778,70190,1675737238,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83655,NEW PLYMOUTH,ID,PRIMARY,1778,3448,51204695,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14231,BUFFALO,NY,PRIMARY,267,399,9522851,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28451,LELAND,NC,PRIMARY,11397,20410,404692253,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52653,WAPELLO,IA,PRIMARY,1594,2893,51701946,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32148,INTERLACHEN,FL,PRIMARY,4019,7169,92768490,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53190,WHITEWATER,WI,PRIMARY,6267,10569,201835644,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98232,BOW,WA,PRIMARY,1955,3469,77454557,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22728,MIDLAND,VA,PRIMARY,1389,2546,68995450,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63965,VAN BUREN,MO,PRIMARY,1195,2132,26119506,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74126,TULSA,OK,PRIMARY,3985,6893,81627990,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91909,CHULA VISTA,CA,PRIMARY,474,841,11782141,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59829,DARBY,MT,PRIMARY,1130,1938,24292384,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60103,BARTLETT,IL,PRIMARY,20134,37918,1252379138,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48894,WESTPHALIA,MI,PRIMARY,1053,2033,39758498,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75486,SUMNER,TX,PRIMARY,1017,2011,33670660,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20773,UPPER MARLBORO,MD,PRIMARY,344,513,17558570,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20195,RESTON,VA,PRIMARY,287,438,20790433,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77517,SANTA FE,TX,PRIMARY,2612,4944,131423741,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56014,BRICELYN,MN,PRIMARY,395,697,8518763,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15690,VANDERGRIFT,PA,PRIMARY,4358,7442,116409170,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3282,WENTWORTH,NH,PRIMARY,462,806,13482596,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73165,OKLAHOMA CITY,OK,PRIMARY,2598,5059,120394853,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33777,SEMINOLE,FL,PRIMARY,8280,14037,335188768,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79096,WHEELER,TX,PRIMARY,906,1776,33320288,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54738,ELEVA,WI,PRIMARY,1598,3015,71309354,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2673,WEST YARMOUTH,MA,PRIMARY,4460,6986,125350712,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58104,FARGO,ND,PRIMARY,12906,22549,708573115,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49441,MUSKEGON,MI,PRIMARY,17321,29547,565270175,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47527,DUBOIS,IN,PRIMARY,975,1745,32164989,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71921,AMITY,AR,PRIMARY,1162,2241,27039702,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80218,DENVER,CO,PRIMARY,10809,13313,525937276,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5254,MANCHESTER,VT,PRIMARY,499,845,19826468,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32183,OCKLAWAHA,FL,PRIMARY,560,951,12547019,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28480,WRIGHTSVILLE BEACH,NC,PRIMARY,1502,2209,67485629,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30188,WOODSTOCK,GA,PRIMARY,24012,43717,1173642244,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18237,MCADOO,PA,PRIMARY,1634,2684,42689012,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90221,COMPTON,CA,PRIMARY,18585,36005,462648300,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13655,HOGANSBURG,NY,PRIMARY,1086,2150,32842598,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39057,CONEHATTA,MS,PRIMARY,888,1630,21110771,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33076,POMPANO BEACH,FL,PRIMARY,12888,25322,947666207,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72959,WINSLOW,AR,PRIMARY,1050,1990,27749155,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73079,POCASSET,OK,PRIMARY,264,531,9620964,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7750,MONMOUTH BEACH,NJ,PRIMARY,1827,3013,156890532,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33027,HOLLYWOOD,FL,PRIMARY,25047,45429,1196502485,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54409,ANTIGO,WI,PRIMARY,6388,11005,182534975,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56331,FREEPORT,MN,PRIMARY,1002,1816,30541680,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64110,KANSAS CITY,MO,PRIMARY,6528,9801,205182278,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45362,ROSSBURG,OH,PRIMARY,538,941,16658552,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92276,THOUSAND PALMS,CA,PRIMARY,3064,5380,70593564,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62010,BETHALTO,IL,PRIMARY,5429,9675,207613949,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62611,ARENZVILLE,IL,PRIMARY,504,927,18239642,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95903,BEALE AFB,CA,PRIMARY,846,1623,25497108,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33762,CLEARWATER,FL,PRIMARY,3351,5211,178625482,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55753,KEEWATIN,MN,PRIMARY,497,830,13125293,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72128,POYEN,AR,PRIMARY,343,687,10260487,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48413,BAD AXE,MI,PRIMARY,3736,6417,100458067,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42204,ALLENSVILLE,KY,PRIMARY,299,548,7749892,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35802,HUNTSVILLE,AL,PRIMARY,10852,18463,521820459,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27619,RALEIGH,NC,PRIMARY,414,630,16204724,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72207,LITTLE ROCK,AR,PRIMARY,5627,9222,436797031,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48075,SOUTHFIELD,MI,PRIMARY,10626,16960,375465460,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62351,MENDON,IL,PRIMARY,879,1613,28403364,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70582,SAINT MARTINVILLE,LA,PRIMARY,8569,15665,285085506,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80205,DENVER,CO,PRIMARY,13419,20189,456593085,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60450,MORRIS,IL,PRIMARY,10340,18207,444554365,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85119,APACHE JUNCTION,AZ,PRIMARY,689,1207,20656687,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87514,ARROYO SECO,NM,PRIMARY,613,970,12634735,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75125,FERRIS,TX,PRIMARY,2732,5213,85432345,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22728,MIDLAND,VA,PRIMARY,1389,2546,68995450,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45828,COLDWATER,OH,PRIMARY,3084,5327,105167744,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +89002,HENDERSON,NV,PRIMARY,13583,24976,723953476,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85547,PAYSON,AZ,PRIMARY,1006,1729,24055404,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75030,ROWLETT,TX,PRIMARY,476,849,23056349,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4493,WEST ENFIELD,ME,PRIMARY,775,1455,23720499,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84341,LOGAN,UT,PRIMARY,7668,14269,264368076,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77803,BRYAN,TX,PRIMARY,11115,20368,263041853,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97396,WILLAMINA,OR,PRIMARY,1404,2516,40441721,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52733,CLINTON,IA,PRIMARY,361,548,6668997,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53214,MILWAUKEE,WI,PRIMARY,17812,27867,566023689,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10524,GARRISON,NY,PRIMARY,2076,3723,159699797,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94039,MOUNTAIN VIEW,CA,PRIMARY,471,688,32743775,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21639,GREENSBORO,MD,PRIMARY,2035,3629,69195085,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53716,MADISON,WI,PRIMARY,10288,16904,400293102,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92254,MECCA,CA,PRIMARY,5189,11107,96913687,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68319,BRADSHAW,NE,PRIMARY,262,488,7042064,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65653,FORSYTH,MO,PRIMARY,2529,4465,54047876,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36456,MC KENZIE,AL,PRIMARY,794,1465,21806318,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30107,BALL GROUND,GA,PRIMARY,5458,10682,240554192,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1810,ANDOVER,MA,PRIMARY,16462,30346,1580077483,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28376,RAEFORD,NC,PRIMARY,14162,27467,456241205,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30566,OAKWOOD,GA,PRIMARY,3720,6624,119917038,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50864,VILLISCA,IA,PRIMARY,933,1681,24850601,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27288,EDEN,NC,PRIMARY,9808,17582,269043217,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51461,SCHLESWIG,IA,PRIMARY,580,1032,16056173,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72023,CABOT,AR,PRIMARY,14585,28306,594957681,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74455,PORUM,OK,PRIMARY,1106,2075,29370040,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19320,COATESVILLE,PA,PRIMARY,23309,41003,1070387587,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50056,COLO,IA,PRIMARY,659,1191,22964118,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74852,MACOMB,OK,PRIMARY,595,1127,16583731,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61844,FITHIAN,IL,PRIMARY,516,930,17564785,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20187,WARRENTON,VA,PRIMARY,6817,13112,459401358,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50441,HAMPTON,IA,PRIMARY,2591,4742,75598555,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49887,STEPHENSON,MI,PRIMARY,1065,1891,26108281,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87045,PREWITT,NM,PRIMARY,553,1003,10997054,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28521,CHINQUAPIN,NC,PRIMARY,845,1578,23750994,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43209,COLUMBUS,OH,PRIMARY,13327,21668,682621181,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62425,DUNDAS,IL,PRIMARY,307,550,7950991,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32164,PALM COAST,FL,PRIMARY,17242,31048,451633982,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2370,ROCKLAND,MA,PRIMARY,8794,14690,372071550,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30076,ROSWELL,GA,PRIMARY,19161,34455,1087537165,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49779,ROGERS CITY,MI,PRIMARY,2261,3945,52424806,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64725,ARCHIE,MO,PRIMARY,987,1894,36226313,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38139,GERMANTOWN,TN,PRIMARY,7629,15172,864017202,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98009,BELLEVUE,WA,PRIMARY,926,1433,73539686,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49779,ROGERS CITY,MI,PRIMARY,2261,3945,52424806,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28644,LAUREL SPRINGS,NC,PRIMARY,605,1115,13849064,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90808,LONG BEACH,CA,PRIMARY,18909,33131,1062835453,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16374,KENNERDELL,PA,PRIMARY,853,1523,23284895,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95759,ELK GROVE,CA,PRIMARY,768,1325,28631213,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21733,FAIRPLAY,MD,PRIMARY,573,1070,26855409,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80741,MERINO,CO,PRIMARY,396,759,11923247,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31798,WRAY,GA,PRIMARY,432,827,11634929,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91906,CAMPO,CA,PRIMARY,1282,2441,49118662,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76126,FORT WORTH,TX,PRIMARY,9571,17198,506360212,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56181,WELCOME,MN,PRIMARY,566,1015,15963154,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72466,SMITHVILLE,AR,PRIMARY,459,915,11592459,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97913,NYSSA,OR,PRIMARY,2007,3893,47994364,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11209,BROOKLYN,NY,PRIMARY,32762,51567,1567801401,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29301,SPARTANBURG,SC,PRIMARY,13226,23385,451629488,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37088,LEBANON,TN,PRIMARY,725,1157,20940138,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1903,LYNN,MA,PRIMARY,531,851,13606118,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92248,LA QUINTA,CA,PRIMARY,548,966,20372887,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22193,WOODBRIDGE,VA,PRIMARY,32955,60216,1665525403,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20177,LEESBURG,VA,PRIMARY,515,820,26736081,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74565,SAVANNA,OK,PRIMARY,392,701,13384620,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57022,DELL RAPIDS,SD,PRIMARY,2427,4446,97342309,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76932,BIG LAKE,TX,PRIMARY,1383,2780,60231796,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21158,WESTMINSTER,MD,PRIMARY,9983,18082,485160426,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23833,CHURCH ROAD,VA,PRIMARY,991,1846,39171958,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44053,LORAIN,OH,PRIMARY,8702,14680,285228163,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78580,RAYMONDVILLE,TX,PRIMARY,4414,8338,100258071,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48822,EAGLE,MI,PRIMARY,1409,2555,57687648,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +81067,ROCKY FORD,CO,PRIMARY,2201,4033,52837830,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33549,LUTZ,FL,PRIMARY,7730,13920,369893330,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49262,NORTH ADAMS,MI,PRIMARY,564,1018,14010802,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74152,TULSA,OK,PRIMARY,282,434,13351387,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23665,HAMPTON,VA,PRIMARY,1935,3830,66821348,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70420,ABITA SPRINGS,LA,PRIMARY,3511,6539,136634569,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30008,MARIETTA,GA,PRIMARY,11686,20427,367217309,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59016,BUSBY,MT,PRIMARY,271,519,6754987,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39657,OSYKA,MS,PRIMARY,971,1819,27772258,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15376,WEST ALEXANDER,PA,PRIMARY,796,1474,26936690,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98585,SILVER CREEK,WA,PRIMARY,311,561,8499284,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18436,LAKE ARIEL,PA,PRIMARY,6183,10997,195734197,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94920,BELVEDERE TIBURON,CA,PRIMARY,6348,10900,869131648,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33548,LUTZ,FL,PRIMARY,3078,5601,172146924,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46126,FAIRLAND,IN,PRIMARY,2306,4262,86190260,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97006,BEAVERTON,OR,PRIMARY,28732,50291,1294732226,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83444,ROBERTS,ID,PRIMARY,500,992,13955008,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48081,SAINT CLAIR SHORES,MI,PRIMARY,11042,18281,405089294,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77026,HOUSTON,TX,PRIMARY,9436,16377,191123201,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35771,SECTION,AL,PRIMARY,1465,2819,42174753,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32837,ORLANDO,FL,PRIMARY,23738,41755,859684130,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51537,HARLAN,IA,PRIMARY,3282,5729,98638674,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77365,PORTER,TX,PRIMARY,10291,19604,460822437,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33706,SAINT PETERSBURG,FL,PRIMARY,8231,12575,332946452,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10034,NEW YORK,NY,PRIMARY,20855,32614,604187876,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72365,MARKED TREE,AR,PRIMARY,1217,2179,27825131,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43402,BOWLING GREEN,OH,PRIMARY,13379,21455,484123577,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56524,CLITHERALL,MN,PRIMARY,356,640,8219349,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17366,WINDSOR,PA,PRIMARY,2675,4740,97297953,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17851,MOUNT CARMEL,PA,PRIMARY,3593,5842,89656801,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31642,PEARSON,GA,PRIMARY,1802,3525,40432353,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78070,SPRING BRANCH,TX,PRIMARY,6323,12245,336004817,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57471,ROSCOE,SD,PRIMARY,320,573,6051349,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40160,RADCLIFF,KY,PRIMARY,9749,17547,265254732,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14715,BOLIVAR,NY,PRIMARY,1206,2139,34342047,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52747,DURANT,IA,PRIMARY,1094,1983,41187754,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41230,LOUISA,KY,PRIMARY,4374,8613,140741418,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90230,CULVER CITY,CA,PRIMARY,15572,25528,765127473,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4419,CARMEL,ME,PRIMARY,1269,2343,43979594,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44305,AKRON,OH,PRIMARY,10399,16710,271067506,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58402,JAMESTOWN,ND,PRIMARY,463,706,14607507,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49757,MACKINAC ISLAND,MI,PRIMARY,502,709,15195247,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67202,WICHITA,KS,PRIMARY,820,1056,25391594,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92177,SAN DIEGO,CA,PRIMARY,526,766,17444998,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68465,WILBER,NE,PRIMARY,1075,1951,35088609,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84053,NEOLA,UT,PRIMARY,310,638,14758583,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65452,CROCKER,MO,PRIMARY,1352,2524,36433514,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74084,WYNONA,OK,PRIMARY,252,457,7964992,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1222,ASHLEY FALLS,MA,PRIMARY,392,681,11545093,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66605,TOPEKA,KS,PRIMARY,8976,15815,267162620,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70065,KENNER,LA,PRIMARY,22698,39430,898759433,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92703,SANTA ANA,CA,PRIMARY,24634,48715,640236193,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23407,MAPPSVILLE,VA,PRIMARY,310,536,7083474,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72774,WEST FORK,AR,PRIMARY,2710,5051,89189078,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +89021,LOGANDALE,NV,PRIMARY,1303,2624,67641125,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71857,PRESCOTT,AR,PRIMARY,2449,4526,63666889,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +81025,BOONE,CO,PRIMARY,404,708,9587699,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13159,TULLY,NY,PRIMARY,2516,4590,110806140,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6483,SEYMOUR,CT,PRIMARY,8152,14118,397890142,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99710,FAIRBANKS,AK,PRIMARY,875,1451,40361564,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95210,STOCKTON,CA,PRIMARY,13868,25741,378633657,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27521,COATS,NC,PRIMARY,2478,4701,77262958,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98177,SEATTLE,WA,PRIMARY,10329,17778,621883188,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98231,BLAINE,WA,PRIMARY,776,1290,29343828,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12417,CONNELLY,NY,PRIMARY,260,432,7600316,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48051,NEW BALTIMORE,MI,PRIMARY,7586,13716,319553500,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45365,SIDNEY,OH,PRIMARY,14848,25141,478046749,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71264,OAK RIDGE,LA,PRIMARY,400,743,12612818,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35961,COLLINSVILLE,AL,PRIMARY,2218,4299,55782841,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78669,SPICEWOOD,TX,PRIMARY,3910,7063,228739962,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92530,LAKE ELSINORE,CA,PRIMARY,17339,33145,621516645,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21041,ELLICOTT CITY,MD,PRIMARY,266,423,12028370,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93591,PALMDALE,CA,PRIMARY,2227,4371,65159544,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29138,SALUDA,SC,PRIMARY,4300,8004,112078768,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6793,WASHINGTON,CT,PRIMARY,604,998,37584199,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92056,OCEANSIDE,CA,PRIMARY,24430,42843,944700547,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48465,PALMS,MI,PRIMARY,286,525,6057365,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40588,LEXINGTON,KY,PRIMARY,335,476,10120217,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72623,CLARKRIDGE,AR,PRIMARY,275,522,7514330,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45344,NEW CARLISLE,OH,PRIMARY,8206,14497,272182896,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27298,LIBERTY,NC,PRIMARY,4501,8345,147055675,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31811,HAMILTON,GA,PRIMARY,1891,3585,84378596,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72702,FAYETTEVILLE,AR,PRIMARY,989,1544,33042042,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61242,CORDOVA,IL,PRIMARY,608,1057,24052592,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31211,MACON,GA,PRIMARY,7113,12269,205730150,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38316,BRADFORD,TN,PRIMARY,1250,2322,33223350,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78040,LAREDO,TX,PRIMARY,15169,28418,290900892,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51653,TABOR,IA,PRIMARY,586,1082,20565304,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50448,KENSETT,IA,PRIMARY,333,581,8527006,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +88029,COLUMBUS,NM,PRIMARY,1014,1991,13218650,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85902,SHOW LOW,AZ,PRIMARY,1964,3587,57252215,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36035,GOSHEN,AL,PRIMARY,811,1462,22676119,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52039,DURANGO,IA,PRIMARY,568,1079,20100697,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47030,METAMORA,IN,PRIMARY,720,1325,18410058,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11746,HUNTINGTON STATION,NY,PRIMARY,32197,56971,1986757091,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87023,JARALES,NM,PRIMARY,423,791,12183131,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58631,GLEN ULLIN,ND,PRIMARY,553,956,14346824,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42303,OWENSBORO,KY,PRIMARY,16887,30036,591296979,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47952,KINGMAN,IN,PRIMARY,1251,2261,32821481,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92423,SAN BERNARDINO,CA,PRIMARY,615,1021,25765924,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95982,SUTTER,CA,PRIMARY,1447,2736,58659895,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79745,KERMIT,TX,PRIMARY,2442,4819,95996386,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45813,ANTWERP,OH,PRIMARY,1747,3085,53919033,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48105,ANN ARBOR,MI,PRIMARY,15149,25072,901733416,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18419,FACTORYVILLE,PA,PRIMARY,2179,3759,69764541,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30445,MOUNT VERNON,GA,PRIMARY,1037,1883,26299516,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11412,SAINT ALBANS,NY,PRIMARY,16657,26508,564187781,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21617,CENTREVILLE,MD,PRIMARY,4412,8123,220131860,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33826,AVON PARK,FL,PRIMARY,809,1397,19035497,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41647,MC DOWELL,KY,PRIMARY,639,1224,16876193,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21773,MYERSVILLE,MD,PRIMARY,2544,4697,137859875,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27824,ENGELHARD,NC,PRIMARY,566,1011,12694135,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72395,WILSON,AR,PRIMARY,458,818,14062448,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32526,PENSACOLA,FL,PRIMARY,17116,30239,526613084,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14210,BUFFALO,NY,PRIMARY,6453,10360,160177015,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7920,BASKING RIDGE,NJ,PRIMARY,13210,24379,1761489724,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60172,ROSELLE,IL,PRIMARY,12831,22378,643440914,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49507,GRAND RAPIDS,MI,PRIMARY,13511,23888,343792530,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54856,MASON,WI,PRIMARY,734,1336,19961550,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40601,FRANKFORT,KY,PRIMARY,22938,39539,721803780,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1237,LANESBORO,MA,PRIMARY,1513,2606,57730107,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93032,OXNARD,CA,PRIMARY,616,1199,14946777,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28787,WEAVERVILLE,NC,PRIMARY,9202,16686,300749647,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83541,LENORE,ID,PRIMARY,414,752,9734937,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14001,AKRON,NY,PRIMARY,4753,8276,167959982,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68847,KEARNEY,NE,PRIMARY,7703,13199,267124051,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34604,BROOKSVILLE,FL,PRIMARY,3918,7120,122276944,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29039,CORDOVA,SC,PRIMARY,1774,3167,42818757,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18214,BARNESVILLE,PA,PRIMARY,1105,1939,37504004,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96741,KALAHEO,HI,PRIMARY,2229,3885,88740520,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14094,LOCKPORT,NY,PRIMARY,24378,41705,834465018,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38175,MEMPHIS,TN,PRIMARY,775,1274,22673894,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15683,SCOTTDALE,PA,PRIMARY,4072,7090,128711405,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24569,LONG ISLAND,VA,PRIMARY,420,782,12002292,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60941,HERSCHER,IL,PRIMARY,998,1810,37625072,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32681,ORANGE LAKE,FL,PRIMARY,412,699,9598261,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49689,WELLSTON,MI,PRIMARY,674,1176,13161694,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53012,CEDARBURG,WI,PRIMARY,9303,16791,510434872,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30722,DALTON,GA,PRIMARY,1045,1873,33156912,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71030,GLOSTER,LA,PRIMARY,642,1204,19792512,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51529,DUNLAP,IA,PRIMARY,793,1409,24448432,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38452,CYPRESS INN,TN,PRIMARY,397,763,10933408,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48749,OMER,MI,PRIMARY,549,952,13287085,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12985,SCHUYLER FALLS,NY,PRIMARY,529,931,16204574,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30710,COHUTTA,GA,PRIMARY,2575,5041,99678926,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80547,TIMNATH,CO,PRIMARY,314,601,20268910,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45695,WILKESVILLE,OH,PRIMARY,304,525,7896798,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33483,DELRAY BEACH,FL,PRIMARY,7376,10800,442724945,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36530,ELBERTA,AL,PRIMARY,3014,5453,82269151,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19043,HOLMES,PA,PRIMARY,1428,2430,56451132,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21851,POCOMOKE CITY,MD,PRIMARY,3441,5977,105001707,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27958,MOYOCK,NC,PRIMARY,4133,8123,177994696,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30327,ATLANTA,GA,PRIMARY,16627,24665,1565488324,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10462,BRONX,NY,PRIMARY,35620,57854,1197519842,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8861,PERTH AMBOY,NJ,PRIMARY,24814,41825,689264920,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4217,BETHEL,ME,PRIMARY,1595,2781,45001237,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64801,JOPLIN,MO,PRIMARY,13998,23939,396766346,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43952,STEUBENVILLE,OH,PRIMARY,7755,12725,202735860,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77223,HOUSTON,TX,PRIMARY,267,466,7000057,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6825,FAIRFIELD,CT,PRIMARY,9355,16768,638307823,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37708,BEAN STATION,TN,PRIMARY,2661,4967,67890037,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13165,WATERLOO,NY,PRIMARY,5168,8844,147657152,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46710,AVILLA,IN,PRIMARY,2173,4010,77137244,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49404,COOPERSVILLE,MI,PRIMARY,3812,7010,131629549,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65337,LA MONTE,MO,PRIMARY,847,1642,22626986,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15436,FAIRCHANCE,PA,PRIMARY,1267,2180,33272489,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2116,BOSTON,MA,PRIMARY,10214,13687,1351420353,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16877,WARRIORS MARK,PA,PRIMARY,802,1474,33638459,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96701,AIEA,HI,PRIMARY,21530,35697,861344249,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +82223,LINGLE,WY,PRIMARY,462,857,13324885,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16671,RAMEY,PA,PRIMARY,266,466,7259127,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42040,FARMINGTON,KY,PRIMARY,465,896,11562973,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36010,BRUNDIDGE,AL,PRIMARY,2159,3931,55475515,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12185,VALLEY FALLS,NY,PRIMARY,964,1709,38659386,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12873,SHUSHAN,NY,PRIMARY,376,639,10792237,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98520,ABERDEEN,WA,PRIMARY,9023,15882,281981527,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53537,FOOTVILLE,WI,PRIMARY,332,582,10085158,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62548,MOUNT PULASKI,IL,PRIMARY,1108,1967,37112435,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12066,ESPERANCE,NY,PRIMARY,1010,1819,40371993,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39288,PEARL,MS,PRIMARY,412,688,11426134,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76127,NAVAL AIR STATION/ JRB,TX,PRIMARY,262,405,9208585,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63469,SHELBYVILLE,MO,PRIMARY,576,1032,12751737,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15870,WILCOX,PA,PRIMARY,685,1150,22281572,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80904,COLORADO SPRINGS,CO,PRIMARY,9987,15460,300137463,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27510,CARRBORO,NC,PRIMARY,7200,10912,250212722,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21090,LINTHICUM HEIGHTS,MD,PRIMARY,5033,8675,243858620,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65759,TANEYVILLE,MO,PRIMARY,500,918,11018545,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97216,PORTLAND,OR,PRIMARY,7125,11628,197896621,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19545,NEW BERLINVILLE,PA,PRIMARY,305,497,9384985,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85329,CASHION,AZ,PRIMARY,1256,2530,31843702,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75902,LUFKIN,TX,PRIMARY,587,988,17370778,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22645,MIDDLETOWN,VA,PRIMARY,1744,3154,75454601,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31636,LAKE PARK,GA,PRIMARY,3811,7161,128630584,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67156,WINFIELD,KS,PRIMARY,6794,11851,210044044,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37337,GRANDVIEW,TN,PRIMARY,591,1097,14924501,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38345,HURON,TN,PRIMARY,771,1489,25579967,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34489,SILVER SPRINGS,FL,PRIMARY,649,1089,15507565,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57078,YANKTON,SD,PRIMARY,8799,15005,286326125,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57259,REVILLO,SD,PRIMARY,250,447,5406567,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49010,ALLEGAN,MI,PRIMARY,7887,14231,255543875,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39647,MC CALL CREEK,MS,PRIMARY,437,871,14290330,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93121,SANTA BARBARA,CA,PRIMARY,631,901,21837923,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8750,SEA GIRT,NJ,PRIMARY,2054,3480,175134188,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59911,BIGFORK,MT,PRIMARY,3770,6546,93872021,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95378,TRACY,CA,PRIMARY,576,1002,18653694,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38326,COUNCE,TN,PRIMARY,1036,1859,33972097,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24068,CHRISTIANSBURG,VA,PRIMARY,538,875,15781170,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76060,KENNEDALE,TX,PRIMARY,3234,5925,152428234,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83217,BANCROFT,ID,PRIMARY,327,641,9211460,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25309,CHARLESTON,WV,PRIMARY,5798,9969,208657138,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50441,HAMPTON,IA,PRIMARY,2591,4742,75598555,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33731,SAINT PETERSBURG,FL,PRIMARY,503,684,10738465,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75439,ECTOR,TX,PRIMARY,387,712,11703480,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93555,RIDGECREST,CA,PRIMARY,13159,24004,537637961,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61368,TISKILWA,IL,PRIMARY,706,1283,19637024,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58573,STRASBURG,ND,PRIMARY,277,486,5403975,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34289,NORTH PORT,FL,PRIMARY,784,1436,21534354,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24128,NEWPORT,VA,PRIMARY,892,1597,31754246,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +89030,NORTH LAS VEGAS,NV,PRIMARY,19128,37689,483264421,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76543,KILLEEN,TX,PRIMARY,12391,22469,329515990,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13442,ROME,NY,PRIMARY,627,936,18582419,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46933,GAS CITY,IN,PRIMARY,3142,5559,88969193,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61114,ROCKFORD,IL,PRIMARY,8040,14122,393482620,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10930,HIGHLAND MILLS,NY,PRIMARY,4153,7893,283230231,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97528,GRANTS PASS,OR,PRIMARY,1105,1806,25912381,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38174,MEMPHIS,TN,PRIMARY,342,486,10914282,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60416,COAL CITY,IL,PRIMARY,4486,8082,194706304,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92867,ORANGE,CA,PRIMARY,18747,34563,998345482,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62202,EAST SAINT LOUIS,IL,PRIMARY,317,497,6182150,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60712,LINCOLNWOOD,IL,PRIMARY,6255,10969,286950954,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51652,SIDNEY,IA,PRIMARY,827,1496,24856756,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97477,SPRINGFIELD,OR,PRIMARY,15926,26525,431535808,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37320,CLEVELAND,TN,PRIMARY,1203,1970,38764839,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61238,CAMBRIDGE,IL,PRIMARY,1480,2714,45977626,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48754,OWENDALE,MI,PRIMARY,456,820,11784555,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74930,BOKOSHE,OK,PRIMARY,673,1291,18690536,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67441,ENTERPRISE,KS,PRIMARY,497,912,14533810,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31629,DIXIE,GA,PRIMARY,370,683,8799045,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61856,MONTICELLO,IL,PRIMARY,3755,6850,171499127,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72047,ENOLA,AR,PRIMARY,396,787,14174112,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60930,DANFORTH,IL,PRIMARY,396,708,13032029,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48220,FERNDALE,MI,PRIMARY,11871,17626,420915748,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99102,ALBION,WA,PRIMARY,290,504,9291544,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92061,PAUMA VALLEY,CA,PRIMARY,1337,2444,40982223,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83128,ALPINE,WY,PRIMARY,764,1355,29296840,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28763,OTTO,NC,PRIMARY,1136,2070,25903242,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11420,SOUTH OZONE PARK,NY,PRIMARY,19959,34717,644033694,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32766,OVIEDO,FL,PRIMARY,6170,12531,392771982,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2038,FRANKLIN,MA,PRIMARY,14611,27220,1034537207,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55117,SAINT PAUL,MN,PRIMARY,18640,30600,646795138,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57334,ETHAN,SD,PRIMARY,396,734,10825971,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38141,MEMPHIS,TN,PRIMARY,10815,18497,327860921,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37130,MURFREESBORO,TN,PRIMARY,20872,34702,680894938,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78582,RIO GRANDE CITY,TX,PRIMARY,11976,24672,299540066,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +86505,GANADO,AZ,PRIMARY,1444,2610,40221537,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58545,HAZEN,ND,PRIMARY,1750,3178,72840362,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14872,PINE VALLEY,NY,PRIMARY,286,506,7136468,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70538,FRANKLIN,LA,PRIMARY,5787,10497,166874065,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55709,BOVEY,MN,PRIMARY,1764,3212,56893247,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49445,MUSKEGON,MI,PRIMARY,10135,18427,372164205,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33414,WELLINGTON,FL,PRIMARY,23608,43745,1290177589,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71061,OIL CITY,LA,PRIMARY,707,1302,22014531,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47665,OWENSVILLE,IN,PRIMARY,1639,3093,61388965,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77080,HOUSTON,TX,PRIMARY,16177,29608,482815586,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20773,UPPER MARLBORO,MD,PRIMARY,344,513,17558570,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93030,OXNARD,CA,PRIMARY,23624,45834,782668499,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61816,BROADLANDS,IL,PRIMARY,254,456,8235627,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16117,ELLWOOD CITY,PA,PRIMARY,8495,14648,268573628,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58237,GRAFTON,ND,PRIMARY,2657,4532,74575194,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92174,SAN DIEGO,CA,PRIMARY,518,868,14406180,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60651,CHICAGO,IL,PRIMARY,27734,47832,634299811,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38310,ADAMSVILLE,TN,PRIMARY,2385,4536,64717478,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93271,THREE RIVERS,CA,PRIMARY,1086,1879,37368070,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15958,SUMMERHILL,PA,PRIMARY,1077,1906,33870823,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87930,ARREY,NM,PRIMARY,289,551,5016012,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39826,BRONWOOD,GA,PRIMARY,313,583,7549480,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68801,GRAND ISLAND,NE,PRIMARY,12518,22157,382091286,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49256,MORENCI,MI,PRIMARY,1737,3219,50500729,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70345,CUT OFF,LA,PRIMARY,4528,8375,196394021,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64138,KANSAS CITY,MO,PRIMARY,12147,20286,384747364,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26030,BEECH BOTTOM,WV,PRIMARY,275,471,6643775,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75148,MALAKOFF,TX,PRIMARY,2343,4306,64709148,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44721,CANTON,OH,PRIMARY,6709,11678,271063176,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21662,ROYAL OAK,MD,PRIMARY,415,722,23020481,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67480,SOLOMON,KS,PRIMARY,854,1560,29373470,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79313,ANTON,TX,PRIMARY,719,1332,19098172,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63039,GRAY SUMMIT,MO,PRIMARY,454,790,15359648,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4976,SKOWHEGAN,ME,PRIMARY,4356,7550,135684772,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28209,CHARLOTTE,NC,PRIMARY,10330,15675,592214123,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19043,HOLMES,PA,PRIMARY,1428,2430,56451132,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36474,RED LEVEL,AL,PRIMARY,1169,2154,32034399,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52746,DONAHUE,IA,PRIMARY,449,843,18427282,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21209,BALTIMORE,MD,PRIMARY,12434,20922,678390490,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56438,BROWERVILLE,MN,PRIMARY,1361,2416,40252970,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73012,EDMOND,OK,PRIMARY,9146,18114,608520099,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75758,CHANDLER,TX,PRIMARY,4113,7626,136403326,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66616,TOPEKA,KS,PRIMARY,2959,4783,72406615,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49010,ALLEGAN,MI,PRIMARY,7887,14231,255543875,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41183,WORTHINGTON,KY,PRIMARY,724,1368,23088847,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10305,STATEN ISLAND,NY,PRIMARY,18275,31760,828916882,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57235,FLORENCE,SD,PRIMARY,396,726,10740439,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33082,PEMBROKE PINES,FL,PRIMARY,560,981,27177584,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23050,DUTTON,VA,PRIMARY,346,640,13112053,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33169,MIAMI,FL,PRIMARY,19270,32158,552245685,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62817,BROUGHTON,IL,PRIMARY,253,472,5538551,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36081,TROY,AL,PRIMARY,5891,10180,166027036,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67017,BENTON,KS,PRIMARY,1026,1909,51249220,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54977,SCANDINAVIA,WI,PRIMARY,658,1175,20343179,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19382,WEST CHESTER,PA,PRIMARY,24193,41450,1687695566,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46135,GREENCASTLE,IN,PRIMARY,7528,13457,238968366,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22959,NORTH GARDEN,VA,PRIMARY,828,1457,31845926,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28757,MONTREAT,NC,PRIMARY,290,481,7421358,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29672,SENECA,SC,PRIMARY,5106,9293,224341019,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4001,ACTON,ME,PRIMARY,1090,1934,35436412,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55355,LITCHFIELD,MN,PRIMARY,4532,8039,150533896,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41144,GREENUP,KY,PRIMARY,4023,7836,129737364,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63626,BLACKWELL,MO,PRIMARY,375,729,11866843,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29680,SIMPSONVILLE,SC,PRIMARY,11384,21575,517070798,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3885,STRATHAM,NH,PRIMARY,3831,6872,251004191,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59868,SEELEY LAKE,MT,PRIMARY,1000,1732,21663660,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98923,COWICHE,WA,PRIMARY,711,1380,20766657,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15767,PUNXSUTAWNEY,PA,PRIMARY,6626,11583,181481699,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99587,GIRDWOOD,AK,PRIMARY,1306,1911,51471481,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47850,FARMERSBURG,IN,PRIMARY,1173,2120,37762044,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23921,BUCKINGHAM,VA,PRIMARY,840,1472,23037440,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13491,WEST WINFIELD,NY,PRIMARY,1664,2989,52730992,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76579,TROY,TX,PRIMARY,1819,3427,64436696,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93513,BIG PINE,CA,PRIMARY,817,1370,26299862,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67119,OXFORD,KS,PRIMARY,679,1255,23959099,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27243,EFLAND,NC,PRIMARY,2040,3745,94542197,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73568,TEMPLE,OK,PRIMARY,462,849,12171506,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97055,SANDY,OR,PRIMARY,7530,13811,296096266,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78417,CORPUS CHRISTI,TX,PRIMARY,1777,3233,45661931,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +81006,PUEBLO,CO,PRIMARY,5219,9410,168254244,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45502,SPRINGFIELD,OH,PRIMARY,8389,14878,325037911,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75760,CUSHING,TX,PRIMARY,1048,1897,29312959,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83323,DECLO,ID,PRIMARY,683,1394,20220582,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68801,GRAND ISLAND,NE,PRIMARY,12518,22157,382091286,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94002,BELMONT,CA,PRIMARY,13324,23092,1076478920,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72471,SWIFTON,AR,PRIMARY,394,736,9639917,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66109,KANSAS CITY,KS,PRIMARY,9730,17446,433460543,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80814,DIVIDE,CO,PRIMARY,1832,3423,76203537,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20120,CENTREVILLE,VA,PRIMARY,19282,35432,1368248118,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98840,OKANOGAN,WA,PRIMARY,1887,3339,53770984,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24224,CASTLEWOOD,VA,PRIMARY,2164,4093,64660388,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8855,PISCATAWAY,NJ,PRIMARY,286,428,12193710,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45323,ENON,OH,PRIMARY,2734,4727,94452916,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48386,WHITE LAKE,MI,PRIMARY,8392,14995,390237839,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94403,SAN MATEO,CA,PRIMARY,19779,33305,1237433782,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30522,CHERRY LOG,GA,PRIMARY,500,889,12505343,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56374,SAINT JOSEPH,MN,PRIMARY,3769,6660,148662630,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99011,FAIRCHILD AIR FORCE BASE,WA,PRIMARY,1127,2244,34707491,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71941,DONALDSON,AR,PRIMARY,766,1479,21580809,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98027,ISSAQUAH,WA,PRIMARY,13620,24023,1002486654,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35175,UNION GROVE,AL,PRIMARY,2205,4185,81231083,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26705,AURORA,WV,PRIMARY,488,880,13031295,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35094,LEEDS,AL,PRIMARY,6371,11438,235783525,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43314,CALEDONIA,OH,PRIMARY,1475,2603,47618321,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48889,SUMNER,MI,PRIMARY,620,1188,17974622,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97361,MONMOUTH,OR,PRIMARY,4168,7320,133670416,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49233,CEMENT CITY,MI,PRIMARY,1257,2256,42359689,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23460,VIRGINIA BEACH,VA,PRIMARY,512,563,9266008,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62638,FRANKLIN,IL,PRIMARY,699,1239,21986983,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23921,BUCKINGHAM,VA,PRIMARY,840,1472,23037440,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68045,OAKLAND,NE,PRIMARY,830,1533,25052945,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +81005,PUEBLO,CO,PRIMARY,13878,24381,443382936,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65713,NIANGUA,MO,PRIMARY,972,1808,23584811,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32777,TANGERINE,FL,PRIMARY,281,509,8962046,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95688,VACAVILLE,CA,PRIMARY,15268,28085,764285035,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1474,WEST TOWNSEND,MA,PRIMARY,1035,1866,50583574,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70729,ERWINVILLE,LA,PRIMARY,543,997,21106540,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61233,ANDOVER,IL,PRIMARY,269,501,9481373,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43515,DELTA,OH,PRIMARY,3880,6891,125377974,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14132,SANBORN,NY,PRIMARY,2861,5028,97045301,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19601,READING,PA,PRIMARY,13371,22537,277797320,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38666,SARDIS,MS,PRIMARY,2812,5090,64598376,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71913,HOT SPRINGS NATIONAL PARK,AR,PRIMARY,18793,32485,515123605,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38577,PALL MALL,TN,PRIMARY,436,821,11063705,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43136,LITHOPOLIS,OH,PRIMARY,570,1015,22252944,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7460,STOCKHOLM,NJ,PRIMARY,1747,3178,99498648,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15019,BULGER,PA,PRIMARY,830,1386,26038890,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97760,TERREBONNE,OR,PRIMARY,3089,5621,84167568,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68070,WESTON,NE,PRIMARY,391,718,11761161,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57339,FORT THOMPSON,SD,PRIMARY,518,969,9643572,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19122,PHILADELPHIA,PA,PRIMARY,6297,9856,136619959,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29451,ISLE OF PALMS,SC,PRIMARY,2203,3790,133836057,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29696,WEST UNION,SC,PRIMARY,1953,3582,65851508,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49455,SHELBY,MI,PRIMARY,2227,4142,58487281,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83839,KINGSTON,ID,PRIMARY,550,1005,16892199,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22313,ALEXANDRIA,VA,PRIMARY,364,478,16842666,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56385,VILLARD,MN,PRIMARY,460,820,12949042,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58077,WALCOTT,ND,PRIMARY,362,685,14291418,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96779,PAIA,HI,PRIMARY,2087,3245,56268426,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94506,DANVILLE,CA,PRIMARY,10418,20743,1408422912,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84511,BLANDING,UT,PRIMARY,1476,2906,48325188,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14853,ITHACA,NY,PRIMARY,302,342,5064499,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66015,COLONY,KS,PRIMARY,374,670,9028170,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13676,POTSDAM,NY,PRIMARY,5068,8585,171680430,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68978,SUPERIOR,NE,PRIMARY,1155,1993,25405139,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66103,KANSAS CITY,KS,PRIMARY,5915,9428,158348574,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59070,ROBERTS,MT,PRIMARY,481,863,14303335,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18405,BEACH LAKE,PA,PRIMARY,1130,1980,31230308,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98051,RAVENSDALE,WA,PRIMARY,1734,3087,97853859,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49072,MENDON,MI,PRIMARY,1467,2691,47565379,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30153,ROCKMART,GA,PRIMARY,7295,13703,235743491,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21146,SEVERNA PARK,MD,PRIMARY,12624,23707,902644194,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12168,STEPHENTOWN,NY,PRIMARY,958,1639,32261983,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28683,THURMOND,NC,PRIMARY,691,1294,17446767,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +82190,YELLOWSTONE NATIONAL PARK,WY,PRIMARY,358,515,14677047,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35130,QUINTON,AL,PRIMARY,1280,2403,41987238,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40068,SMITHFIELD,KY,PRIMARY,1050,1973,42721880,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1982,SOUTH HAMILTON,MA,PRIMARY,3513,6501,296420268,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85625,PEARCE,AZ,PRIMARY,852,1462,16435242,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55025,FOREST LAKE,MN,PRIMARY,11050,19742,513278711,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95926,CHICO,CA,PRIMARY,14130,22651,418715754,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94938,LAGUNITAS,CA,PRIMARY,302,479,8857201,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87375,YATAHEY,NM,PRIMARY,635,1082,14540511,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29691,WALHALLA,SC,PRIMARY,4416,8224,120258867,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +89803,ELKO,NV,PRIMARY,968,1627,47860883,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78659,PAIGE,TX,PRIMARY,1191,2142,40635886,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55130,SAINT PAUL,MN,PRIMARY,5969,10092,144491142,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33673,TAMPA,FL,PRIMARY,276,429,6481567,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76470,RANGER,TX,PRIMARY,1212,2140,27806648,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4684,SURRY,ME,PRIMARY,736,1252,21803755,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54138,LAKEWOOD,WI,PRIMARY,507,866,10298781,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92395,VICTORVILLE,CA,PRIMARY,14227,26559,440358531,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67449,HERINGTON,KS,PRIMARY,1465,2585,40048600,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33493,SOUTH BAY,FL,PRIMARY,1267,2306,31364205,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67466,MILTONVALE,KS,PRIMARY,333,601,6826313,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68020,DECATUR,NE,PRIMARY,363,618,9241891,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78339,BANQUETE,TX,PRIMARY,466,894,14211551,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85396,BUCKEYE,AZ,PRIMARY,4286,8428,214489002,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14572,WAYLAND,NY,PRIMARY,2356,4137,72787411,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29250,COLUMBIA,SC,PRIMARY,285,418,11366477,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17059,MIFFLINTOWN,PA,PRIMARY,3379,6026,100090251,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24330,FRIES,VA,PRIMARY,1378,2514,31753875,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36542,GULF SHORES,AL,PRIMARY,4773,8103,126030692,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15357,RICES LANDING,PA,PRIMARY,765,1350,25078384,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39667,TYLERTOWN,MS,PRIMARY,4995,9415,132768382,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35953,ASHVILLE,AL,PRIMARY,3038,5784,98716002,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4780,SMYRNA MILLS,ME,PRIMARY,302,573,6894049,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60626,CHICAGO,IL,PRIMARY,21612,32581,763896673,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42078,SALEM,KY,PRIMARY,763,1447,21640714,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48457,MONTROSE,MI,PRIMARY,3791,6924,106989146,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4982,STRATTON,ME,PRIMARY,302,509,7559592,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32221,JACKSONVILLE,FL,PRIMARY,12119,22388,457633744,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14042,DELEVAN,NY,PRIMARY,1718,3060,50164400,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46759,KEYSTONE,IN,PRIMARY,269,506,7290814,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27116,WINSTON SALEM,NC,PRIMARY,275,425,6511545,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90022,LOS ANGELES,CA,PRIMARY,24562,46198,622984671,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35045,CLANTON,AL,PRIMARY,5398,10205,170447908,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6117,WEST HARTFORD,CT,PRIMARY,7295,13211,599591815,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11977,WESTHAMPTON,NY,PRIMARY,1221,2110,73879423,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96142,TAHOMA,CA,PRIMARY,359,590,10865121,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29388,WOODRUFF,SC,PRIMARY,5829,11048,196764372,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53158,PLEASANT PRAIRIE,WI,PRIMARY,7465,13763,416865360,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7057,WALLINGTON,NJ,PRIMARY,5850,9893,215940992,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8873,SOMERSET,NJ,PRIMARY,24909,42921,1399665021,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90059,LOS ANGELES,CA,PRIMARY,13711,25507,310497390,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44410,CORTLAND,OH,PRIMARY,9291,15757,317805586,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62225,SCOTT AIR FORCE BASE,IL,PRIMARY,1845,4091,77592935,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80743,OTIS,CO,PRIMARY,474,874,12580454,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62920,COBDEN,IL,PRIMARY,1431,2573,40916944,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90702,ARTESIA,CA,PRIMARY,341,540,13296043,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40906,BARBOURVILLE,KY,PRIMARY,3781,7188,100928544,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37366,PELHAM,TN,PRIMARY,372,687,9833180,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19115,PHILADELPHIA,PA,PRIMARY,15881,26806,584521712,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52756,LONG GROVE,IA,PRIMARY,1059,2008,49143103,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12053,DELANSON,NY,PRIMARY,2093,3842,99351136,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56425,BAXTER,MN,PRIMARY,3510,6468,139021777,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77856,FRANKLIN,TX,PRIMARY,1882,3468,60191662,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3576,COLEBROOK,NH,PRIMARY,1644,2776,45479318,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29681,SIMPSONVILLE,SC,PRIMARY,20606,40234,1200442556,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11368,CORONA,NY,PRIMARY,39840,67717,892353230,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49747,HUBBARD LAKE,MI,PRIMARY,872,1525,16331551,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96822,HONOLULU,HI,PRIMARY,21430,32666,843183964,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25638,OMAR,WV,PRIMARY,397,777,11724824,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5462,HUNTINGTON,VT,PRIMARY,958,1733,41923754,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25506,BRANCHLAND,WV,PRIMARY,1526,2987,42199436,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16828,CENTRE HALL,PA,PRIMARY,2204,3930,72939133,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64130,KANSAS CITY,MO,PRIMARY,8872,14296,181743514,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25557,RANGER,WV,PRIMARY,494,971,13222684,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3076,PELHAM,NH,PRIMARY,6433,11839,366493993,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10475,BRONX,NY,PRIMARY,21124,31659,740068715,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4488,STETSON,ME,PRIMARY,519,944,16712172,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71430,FOREST HILL,LA,PRIMARY,968,1848,30126708,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36580,SUMMERDALE,AL,PRIMARY,2263,4095,61493346,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44040,GATES MILLS,OH,PRIMARY,1859,3144,220009031,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20748,TEMPLE HILLS,MD,PRIMARY,19163,30423,735793244,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56551,HENNING,MN,PRIMARY,957,1748,22376564,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46173,RUSHVILLE,IN,PRIMARY,5133,9157,145188539,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79110,AMARILLO,TX,PRIMARY,8483,15253,283911288,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29727,MOUNT CROGHAN,SC,PRIMARY,569,1078,13728394,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83332,HAGERMAN,ID,PRIMARY,1018,1848,24093449,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14043,DEPEW,NY,PRIMARY,13172,21518,430002941,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62223,BELLEVILLE,IL,PRIMARY,9236,15546,369657037,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98320,BRINNON,WA,PRIMARY,551,924,10262619,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50022,ATLANTIC,IA,PRIMARY,4087,7112,113076453,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72455,POCAHONTAS,AR,PRIMARY,5000,9253,121599670,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59875,VICTOR,MT,PRIMARY,1663,2927,38412853,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3784,WEST LEBANON,NH,PRIMARY,2089,3344,82514482,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3079,SALEM,NH,PRIMARY,15171,26049,714089826,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98586,SOUTH BEND,WA,PRIMARY,929,1730,24773724,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23707,PORTSMOUTH,VA,PRIMARY,6615,11025,202037015,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79606,ABILENE,TX,PRIMARY,10401,18819,415666682,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98251,GOLD BAR,WA,PRIMARY,2081,3652,81231650,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47567,PETERSBURG,IN,PRIMARY,2719,4936,90076257,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61469,OQUAWKA,IL,PRIMARY,1048,1798,27841747,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8346,NEWTONVILLE,NJ,PRIMARY,419,717,13139452,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8009,BERLIN,NJ,PRIMARY,6593,11467,308358424,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98360,ORTING,WA,PRIMARY,5584,10462,262496781,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62420,CASEY,IL,PRIMARY,2295,4031,59695180,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91763,MONTCLAIR,CA,PRIMARY,14454,27063,453244725,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48173,ROCKWOOD,MI,PRIMARY,6080,11095,268466610,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36035,GOSHEN,AL,PRIMARY,811,1462,22676119,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41425,EZEL,KY,PRIMARY,390,801,10204009,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16210,ADRIAN,PA,PRIMARY,455,843,13678147,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18913,CARVERSVILLE,PA,PRIMARY,253,421,32900007,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43528,HOLLAND,OH,PRIMARY,8008,13829,385634634,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31551,MERSHON,GA,PRIMARY,352,697,10201883,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30156,KENNESAW,GA,PRIMARY,503,763,15618680,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71405,BALL,LA,PRIMARY,2433,4354,76939911,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64834,CARL JUNCTION,MO,PRIMARY,3951,7698,159219087,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38858,NETTLETON,MS,PRIMARY,2783,5263,72541372,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17365,WELLSVILLE,PA,PRIMARY,1311,2344,52832508,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73080,PURCELL,OK,PRIMARY,3789,7043,127744932,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18030,BOWMANSTOWN,PA,PRIMARY,315,535,9387111,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37143,PEGRAM,TN,PRIMARY,1851,3423,73157985,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41071,NEWPORT,KY,PRIMARY,9108,14293,295339416,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63532,BEVIER,MO,PRIMARY,607,1082,14533303,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11763,MEDFORD,NY,PRIMARY,13590,23711,649126962,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97870,RICHLAND,OR,PRIMARY,269,457,3872036,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67467,MINNEAPOLIS,KS,PRIMARY,1410,2491,42323337,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80235,DENVER,CO,PRIMARY,3720,6000,149636214,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11954,MONTAUK,NY,PRIMARY,2507,3976,83023570,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2910,CRANSTON,RI,PRIMARY,11193,18350,395506404,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99581,EMMONAK,AK,PRIMARY,322,545,6049925,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6269,STORRS MANSFIELD,CT,PRIMARY,375,384,5069622,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17212,BIG COVE TANNERY,PA,PRIMARY,281,538,9425445,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41139,FLATWOODS,KY,PRIMARY,3692,6748,121902277,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95307,CERES,CA,PRIMARY,15983,30984,503604712,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92656,ALISO VIEJO,CA,PRIMARY,22348,39419,1542655701,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5494,WESTFORD,VT,PRIMARY,870,1555,41720931,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95549,KNEELAND,CA,PRIMARY,350,635,10673232,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26178,SMITHVILLE,WV,PRIMARY,271,487,5849046,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14621,ROCHESTER,NY,PRIMARY,12188,20021,235030215,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97457,MYRTLE CREEK,OR,PRIMARY,3951,7128,100415178,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46237,INDIANAPOLIS,IN,PRIMARY,18892,33325,807583985,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92261,PALM DESERT,CA,PRIMARY,1163,1814,30976723,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7102,NEWARK,NJ,PRIMARY,3651,5503,135280553,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33015,HIALEAH,FL,PRIMARY,27904,48677,913467912,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34112,NAPLES,FL,PRIMARY,11854,19197,289148450,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32040,GLEN SAINT MARY,FL,PRIMARY,3297,6294,115147099,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54937,FOND DU LAC,WI,PRIMARY,7718,13861,341453239,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72443,MARMADUKE,AR,PRIMARY,1105,2148,28994684,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11230,BROOKLYN,NY,PRIMARY,32295,56454,1182130112,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13132,PENNELLVILLE,NY,PRIMARY,1968,3516,72968697,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98232,BOW,WA,PRIMARY,1955,3469,77454557,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11933,CALVERTON,NY,PRIMARY,3242,5527,138189454,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75455,MOUNT PLEASANT,TX,PRIMARY,10164,19644,316107076,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28815,ASHEVILLE,NC,PRIMARY,557,836,14421870,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14167,VARYSBURG,NY,PRIMARY,795,1383,27640706,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55012,CENTER CITY,MN,PRIMARY,937,1720,40798861,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38650,MYRTLE,MS,PRIMARY,1498,2838,39922440,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74883,WETUMKA,OK,PRIMARY,987,1789,25388758,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76801,BROWNWOOD,TX,PRIMARY,9898,17792,279370637,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63437,CLARENCE,MO,PRIMARY,706,1261,15178971,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33323,FORT LAUDERDALE,FL,PRIMARY,9140,16261,456414551,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47991,WEST LEBANON,IN,PRIMARY,487,901,15316403,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92706,SANTA ANA,CA,PRIMARY,14635,27773,521280485,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26855,CABINS,WV,PRIMARY,319,590,8662344,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15928,DAVIDSVILLE,PA,PRIMARY,990,1745,29637638,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20876,GERMANTOWN,MD,PRIMARY,11707,20992,662408800,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57276,WHITE,SD,PRIMARY,531,955,16098630,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48453,MARLETTE,MI,PRIMARY,2295,4196,57824700,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95677,ROCKLIN,CA,PRIMARY,11381,20132,536083455,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36560,MOUNT VERNON,AL,PRIMARY,1377,2564,33969230,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47932,COVINGTON,IN,PRIMARY,2535,4661,84945611,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84039,LAPOINT,UT,PRIMARY,391,772,17768323,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8536,PLAINSBORO,NJ,PRIMARY,9397,17344,753685514,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33165,MIAMI,FL,PRIMARY,26643,44352,771792330,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38039,GRAND JUNCTION,TN,PRIMARY,906,1629,21642549,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27874,SCOTLAND NECK,NC,PRIMARY,1980,3455,42200986,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95361,OAKDALE,CA,PRIMARY,13130,24557,550548895,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47523,DALE,IN,PRIMARY,1542,2768,49588107,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24603,BIG ROCK,VA,PRIMARY,446,851,13562279,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84011,BOUNTIFUL,UT,PRIMARY,441,746,14631744,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30563,MOUNT AIRY,GA,PRIMARY,2198,4196,72676015,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75652,HENDERSON,TX,PRIMARY,5285,9772,174907560,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5089,WINDSOR,VT,PRIMARY,2134,3525,71543063,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3444,DUBLIN,NH,PRIMARY,781,1417,32765403,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98903,YAKIMA,WA,PRIMARY,6345,11510,198636282,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90632,LA HABRA,CA,PRIMARY,404,673,15915967,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46076,WINDFALL,IN,PRIMARY,781,1447,25002028,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64056,INDEPENDENCE,MO,PRIMARY,7307,13063,252906377,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39296,JACKSON,MS,PRIMARY,251,378,9875015,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36756,MARION,AL,PRIMARY,2407,4346,53117958,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75091,SHERMAN,TX,PRIMARY,992,1675,36634282,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21742,HAGERSTOWN,MD,PRIMARY,14688,25720,651749820,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48374,NOVI,MI,PRIMARY,6185,12379,572559561,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20147,ASHBURN,VA,PRIMARY,23767,45259,2005708619,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16130,HADLEY,PA,PRIMARY,992,1726,25303235,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41042,FLORENCE,KY,PRIMARY,23212,40441,919294532,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3234,EPSOM,NH,PRIMARY,2357,4174,96794392,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95357,MODESTO,CA,PRIMARY,5474,10140,215924416,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66510,MELVERN,KS,PRIMARY,357,661,11195502,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75644,GILMER,TX,PRIMARY,4953,9164,145792063,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72419,CARAWAY,AR,PRIMARY,701,1332,17355451,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35587,TOWNLEY,AL,PRIMARY,361,693,10770532,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30172,SHANNON,GA,PRIMARY,496,878,11388468,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14006,ANGOLA,NY,PRIMARY,4925,8348,161988353,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15342,HOUSTON,PA,PRIMARY,2513,4211,87932376,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37727,DEL RIO,TN,PRIMARY,824,1541,18971575,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83522,COTTONWOOD,ID,PRIMARY,835,1502,22103548,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87522,CHIMAYO,NM,PRIMARY,1335,2265,37296044,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49643,INTERLOCHEN,MI,PRIMARY,2969,5269,90518408,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54653,ROCKLAND,WI,PRIMARY,484,883,16064109,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40175,VINE GROVE,KY,PRIMARY,5645,10700,187414483,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75790,VAN,TX,PRIMARY,1920,3609,63811063,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63033,FLORISSANT,MO,PRIMARY,21268,35384,682026273,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92277,TWENTYNINE PALMS,CA,PRIMARY,8483,16226,254665955,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55072,SANDSTONE,MN,PRIMARY,1500,2569,38252125,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3580,FRANCONIA,NH,PRIMARY,830,1362,28818933,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72047,ENOLA,AR,PRIMARY,396,787,14174112,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18439,LAKEWOOD,PA,PRIMARY,250,433,7347310,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64790,WALKER,MO,PRIMARY,353,651,6840515,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45654,NEW PLYMOUTH,OH,PRIMARY,364,679,9368509,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45505,SPRINGFIELD,OH,PRIMARY,8745,14526,208180984,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4259,MONMOUTH,ME,PRIMARY,1488,2764,54751262,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75839,ELKHART,TX,PRIMARY,2145,3985,70107398,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78130,NEW BRAUNFELS,TX,PRIMARY,26382,47380,915619654,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58482,STEELE,ND,PRIMARY,471,834,11805631,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33414,WELLINGTON,FL,PRIMARY,23608,43745,1290177589,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83352,SHOSHONE,ID,PRIMARY,1247,2411,38485858,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79916,FORT BLISS,TX,PRIMARY,1668,1803,35153258,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38138,GERMANTOWN,TN,PRIMARY,12287,22137,867998325,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27712,DURHAM,NC,PRIMARY,9696,17922,509535483,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17065,MOUNT HOLLY SPRINGS,PA,PRIMARY,2146,3792,77562605,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49930,HANCOCK,MI,PRIMARY,2867,4781,84280969,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90061,LOS ANGELES,CA,PRIMARY,10076,18477,238903309,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45843,FOREST,OH,PRIMARY,1752,3140,55481075,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49841,GWINN,MI,PRIMARY,2866,5127,75735495,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78755,AUSTIN,TX,PRIMARY,475,706,20473711,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92192,SAN DIEGO,CA,PRIMARY,695,1002,40979982,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28503,KINSTON,NC,PRIMARY,381,644,11064754,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5846,ISLAND POND,VT,PRIMARY,636,1053,13151508,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10473,BRONX,NY,PRIMARY,26122,42812,817850845,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90071,LOS ANGELES,CA,PRIMARY,639,964,75762361,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84414,OGDEN,UT,PRIMARY,11433,21986,509315593,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25506,BRANCHLAND,WV,PRIMARY,1526,2987,42199436,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1969,ROWLEY,MA,PRIMARY,2926,5259,182610213,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61039,GERMAN VALLEY,IL,PRIMARY,397,756,15061557,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60480,WILLOW SPRINGS,IL,PRIMARY,2859,4851,162192650,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46767,LIGONIER,IN,PRIMARY,3517,6961,100798989,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +81410,AUSTIN,CO,PRIMARY,681,1247,19461749,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87317,GAMERCO,NM,PRIMARY,577,988,12731045,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61752,LE ROY,IL,PRIMARY,2078,3813,85876769,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72366,MARVELL,AR,PRIMARY,918,1629,18975872,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12737,GLEN SPEY,NY,PRIMARY,852,1516,32340091,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6109,WETHERSFIELD,CT,PRIMARY,14144,23881,681976153,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92593,TEMECULA,CA,PRIMARY,895,1600,32274104,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +69045,WAUNETA,NE,PRIMARY,461,821,7947200,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77805,BRYAN,TX,PRIMARY,1151,1910,37628002,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96705,ELEELE,HI,PRIMARY,1205,2101,45346330,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74079,STROUD,OK,PRIMARY,1814,3345,55561714,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92552,MORENO VALLEY,CA,PRIMARY,1274,2209,40390418,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18701,WILKES BARRE,PA,PRIMARY,676,890,11338812,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21663,SAINT MICHAELS,MD,PRIMARY,1687,2855,76085334,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48616,CHESANING,MI,PRIMARY,3538,6441,105758829,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27045,RURAL HALL,NC,PRIMARY,3955,7167,132984201,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95019,FREEDOM,CA,PRIMARY,3535,7068,101582066,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62853,KELL,IL,PRIMARY,444,816,13040519,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61242,CORDOVA,IL,PRIMARY,608,1057,24052592,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85539,MIAMI,AZ,PRIMARY,1130,1998,34779837,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98660,VANCOUVER,WA,PRIMARY,4977,7929,171919527,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54896,WINTER,WI,PRIMARY,767,1313,15481838,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23523,NORFOLK,VA,PRIMARY,3188,5360,62395602,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44887,TIRO,OH,PRIMARY,501,898,15340626,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70509,LAFAYETTE,LA,PRIMARY,843,1423,25328687,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16915,COUDERSPORT,PA,PRIMARY,2671,4741,84422963,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60565,NAPERVILLE,IL,PRIMARY,19741,37904,1591174879,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52540,BRIGHTON,IA,PRIMARY,673,1190,17573415,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7718,BELFORD,NJ,PRIMARY,3101,5572,170026421,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4920,BINGHAM,ME,PRIMARY,705,1204,14763726,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55335,GIBBON,MN,PRIMARY,789,1395,19522927,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5874,WESTFIELD,VT,PRIMARY,257,464,6554608,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24553,GLADSTONE,VA,PRIMARY,788,1456,23455656,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +88045,LORDSBURG,NM,PRIMARY,1577,2798,43110519,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33607,TAMPA,FL,PRIMARY,12780,19120,295349939,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49046,DELTON,MI,PRIMARY,3282,5973,109608648,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94949,NOVATO,CA,PRIMARY,8237,14246,477070476,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44028,COLUMBIA STATION,OH,PRIMARY,4607,7817,183755201,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44011,AVON,OH,PRIMARY,9615,17564,572075157,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28434,COUNCIL,NC,PRIMARY,516,927,13483314,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37690,TELFORD,TN,PRIMARY,1775,3331,53372385,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78565,LOS EBANOS,TX,PRIMARY,504,1017,9101957,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78574,MISSION,TX,PRIMARY,14582,30029,369076600,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94564,PINOLE,CA,PRIMARY,9214,15898,410951647,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57570,ROSEBUD,SD,PRIMARY,741,1399,17240936,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20158,HAMILTON,VA,PRIMARY,1644,3203,141237456,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97030,GRESHAM,OR,PRIMARY,16314,28011,517481587,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37809,MIDWAY,TN,PRIMARY,834,1580,24600102,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92801,ANAHEIM,CA,PRIMARY,24755,45683,790993358,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49230,BROOKLYN,MI,PRIMARY,5214,9108,177009246,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59855,PABLO,MT,PRIMARY,596,1075,12586416,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18510,SCRANTON,PA,PRIMARY,4764,7607,129145124,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26159,PADEN CITY,WV,PRIMARY,1207,2162,31629367,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34737,HOWEY IN THE HILLS,FL,PRIMARY,1271,2305,55806159,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40050,NEW CASTLE,KY,PRIMARY,710,1297,19819131,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68847,KEARNEY,NE,PRIMARY,7703,13199,267124051,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8619,TRENTON,NJ,PRIMARY,11573,19382,565510328,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62326,COLCHESTER,IL,PRIMARY,1216,2079,34352762,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27708,DURHAM,NC,PRIMARY,289,345,6548220,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45663,WEST PORTSMOUTH,OH,PRIMARY,2661,4988,75946276,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80911,COLORADO SPRINGS,CO,PRIMARY,13584,25331,458792855,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92160,SAN DIEGO,CA,PRIMARY,340,501,11148512,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36376,WEBB,AL,PRIMARY,980,1828,27107825,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60604,CHICAGO,IL,PRIMARY,922,1192,42414664,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46637,SOUTH BEND,IN,PRIMARY,6980,11644,238693177,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38460,GOODSPRING,TN,PRIMARY,596,1118,17892699,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28584,SWANSBORO,NC,PRIMARY,5375,9654,173005896,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27574,ROXBORO,NC,PRIMARY,6056,11151,204771737,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60118,DUNDEE,IL,PRIMARY,8129,14431,462291903,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61723,ATLANTA,IL,PRIMARY,1214,2146,43417857,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41216,EAST POINT,KY,PRIMARY,381,742,13145694,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95001,APTOS,CA,PRIMARY,1003,1526,42277293,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71935,CADDO GAP,AR,PRIMARY,271,527,5072844,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68526,LINCOLN,NE,PRIMARY,2024,4025,148597860,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85037,PHOENIX,AZ,PRIMARY,16110,30898,525204717,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37079,INDIAN MOUND,TN,PRIMARY,1078,2081,32422409,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8848,MILFORD,NJ,PRIMARY,4036,7470,261146410,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84054,NORTH SALT LAKE,UT,PRIMARY,6555,12482,336772173,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24925,CALDWELL,WV,PRIMARY,475,897,15081072,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73534,DUNCAN,OK,PRIMARY,662,1144,21117935,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32577,MOLINO,FL,PRIMARY,2177,4057,73645693,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14851,ITHACA,NY,PRIMARY,356,469,9456698,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63019,CRYSTAL CITY,MO,PRIMARY,2086,3688,68962638,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16636,DYSART,PA,PRIMARY,377,675,12187008,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56360,OSAKIS,MN,PRIMARY,1787,3196,44391725,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17777,WATSONTOWN,PA,PRIMARY,3225,5704,99411335,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99163,PULLMAN,WA,PRIMARY,9718,15193,329628503,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80117,KIOWA,CO,PRIMARY,1136,2139,54976626,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71064,PLAIN DEALING,LA,PRIMARY,1557,2783,41316889,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76630,BRUCEVILLE,TX,PRIMARY,742,1397,29530450,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13204,SYRACUSE,NY,PRIMARY,7788,12137,180571623,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96057,MCCLOUD,CA,PRIMARY,623,1037,12502847,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27325,ROBBINS,NC,PRIMARY,2719,5174,74882494,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46368,PORTAGE,IN,PRIMARY,18487,32445,713943132,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33609,TAMPA,FL,PRIMARY,8358,12817,502464700,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49076,OLIVET,MI,PRIMARY,1766,3277,58184953,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62919,CAVE IN ROCK,IL,PRIMARY,365,697,10712302,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45224,CINCINNATI,OH,PRIMARY,10218,16213,307385578,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17061,MILLERSBURG,PA,PRIMARY,3383,5854,110365357,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1119,SPRINGFIELD,MA,PRIMARY,5978,9915,191005823,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80163,LITTLETON,CO,PRIMARY,283,443,16062338,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98101,SEATTLE,WA,PRIMARY,6245,7771,321726983,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13032,CANASTOTA,NY,PRIMARY,5950,10386,199644445,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74852,MACOMB,OK,PRIMARY,595,1127,16583731,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73038,FORT COBB,OK,PRIMARY,763,1410,20184763,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44634,HOMEWORTH,OH,PRIMARY,1038,1868,34751769,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87823,LEMITAR,NM,PRIMARY,300,538,6855610,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11955,MORICHES,NY,PRIMARY,1698,2780,70767286,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8691,TRENTON,NJ,PRIMARY,7101,13091,573048878,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84537,ORANGEVILLE,UT,PRIMARY,537,1108,25866959,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75754,BEN WHEELER,TX,PRIMARY,2428,4452,76850949,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84601,PROVO,UT,PRIMARY,11603,22642,343200226,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76059,KEENE,TX,PRIMARY,1918,3540,56418169,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10603,WHITE PLAINS,NY,PRIMARY,9301,14937,530196836,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50464,PLYMOUTH,IA,PRIMARY,307,560,9575651,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43116,COMMERCIAL POINT,OH,PRIMARY,622,1210,27850157,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71913,HOT SPRINGS NATIONAL PARK,AR,PRIMARY,18793,32485,515123605,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12192,WEST COXSACKIE,NY,PRIMARY,731,1254,26391056,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44133,NORTH ROYALTON,OH,PRIMARY,17057,27776,735697398,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99161,PALOUSE,WA,PRIMARY,685,1243,23759533,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97862,MILTON FREEWATER,OR,PRIMARY,4570,8481,122656785,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84043,LEHI,UT,PRIMARY,16368,34837,805922225,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1026,CUMMINGTON,MA,PRIMARY,520,865,15391058,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39211,JACKSON,MS,PRIMARY,11198,18806,521231524,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90255,HUNTINGTON PARK,CA,PRIMARY,28269,54716,708223920,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93387,BAKERSFIELD,CA,PRIMARY,455,874,10952866,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31410,SAVANNAH,GA,PRIMARY,11344,19812,566547068,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1007,BELCHERTOWN,MA,PRIMARY,7097,12895,342529324,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +69358,MORRILL,NE,PRIMARY,908,1617,27166691,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68856,MERNA,NE,PRIMARY,295,545,7090931,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57770,PINE RIDGE,SD,PRIMARY,1650,3139,41093990,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41553,PHELPS,KY,PRIMARY,793,1556,22683216,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8555,ROOSEVELT,NJ,PRIMARY,444,796,22653514,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53095,WEST BEND,WI,PRIMARY,13758,24005,596800992,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74728,BROKEN BOW,OK,PRIMARY,4373,8178,112950201,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36010,BRUNDIDGE,AL,PRIMARY,2159,3931,55475515,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36504,ATMORE,AL,PRIMARY,624,1096,16284788,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41822,HINDMAN,KY,PRIMARY,1155,2175,41339584,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15469,NORMALVILLE,PA,PRIMARY,972,1752,25874806,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17086,RICHFIELD,PA,PRIMARY,1070,1974,29545687,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47345,GREENS FORK,IN,PRIMARY,626,1190,19050091,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62817,BROUGHTON,IL,PRIMARY,253,472,5538551,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5774,WELLS,VT,PRIMARY,623,1047,15825719,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27943,HATTERAS,NC,PRIMARY,398,648,9853980,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78151,RUNGE,TX,PRIMARY,572,1060,13996473,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16877,WARRIORS MARK,PA,PRIMARY,802,1474,33638459,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17845,MILLMONT,PA,PRIMARY,959,1790,21610107,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20187,WARRENTON,VA,PRIMARY,6817,13112,459401358,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22313,ALEXANDRIA,VA,PRIMARY,364,478,16842666,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28470,SHALLOTTE,NC,PRIMARY,3530,6333,88595330,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17740,JERSEY SHORE,PA,PRIMARY,6054,10809,184817065,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33145,MIAMI,FL,PRIMARY,13944,22151,424788779,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23432,SUFFOLK,VA,PRIMARY,704,1276,34393045,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84622,CENTERFIELD,UT,PRIMARY,514,1032,15810366,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76127,NAVAL AIR STATION/ JRB,TX,PRIMARY,262,405,9208585,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98848,QUINCY,WA,PRIMARY,4255,8293,119200919,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17058,MIFFLIN,PA,PRIMARY,854,1462,20907837,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64728,BRONAUGH,MO,PRIMARY,263,497,6383599,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78599,WESLACO,TX,PRIMARY,1716,3313,44704752,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12857,OLMSTEDVILLE,NY,PRIMARY,299,512,7057434,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26505,MORGANTOWN,WV,PRIMARY,11086,16568,381211913,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48236,GROSSE POINTE,MI,PRIMARY,15705,27762,1114680733,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87197,ALBUQUERQUE,NM,PRIMARY,389,593,12565091,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28092,LINCOLNTON,NC,PRIMARY,15221,28399,495711965,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46952,MARION,IN,PRIMARY,9773,16978,294968479,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6824,FAIRFIELD,CT,PRIMARY,14839,26855,1714239972,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92654,LAGUNA HILLS,CA,PRIMARY,577,846,18974739,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14065,FREEDOM,NY,PRIMARY,791,1467,24554282,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79245,MEMPHIS,TX,PRIMARY,992,1853,22094630,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93036,OXNARD,CA,PRIMARY,15745,29528,584645007,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97348,HALSEY,OR,PRIMARY,653,1231,20100572,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93011,CAMARILLO,CA,PRIMARY,1178,1879,47507052,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14212,BUFFALO,NY,PRIMARY,4060,6607,89392718,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54638,KENDALL,WI,PRIMARY,689,1269,20506162,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74871,STONEWALL,OK,PRIMARY,972,1773,27850167,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79772,PECOS,TX,PRIMARY,3962,7403,123068574,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32314,TALLAHASSEE,FL,PRIMARY,986,1510,24537352,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93275,TULARE,CA,PRIMARY,811,1471,22331244,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65629,CHADWICK,MO,PRIMARY,256,497,6112241,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48176,SALINE,MI,PRIMARY,9991,18549,597069121,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6234,BROOKLYN,CT,PRIMARY,3671,6516,157308809,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13104,MANLIUS,NY,PRIMARY,7629,14081,532753376,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36006,BILLINGSLEY,AL,PRIMARY,564,1117,19042671,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35218,BIRMINGHAM,AL,PRIMARY,3046,5263,63831130,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75243,DALLAS,TX,PRIMARY,24145,40571,824539368,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71234,DOWNSVILLE,LA,PRIMARY,1778,3359,64091099,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28306,FAYETTEVILLE,NC,PRIMARY,16125,30542,559414772,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47043,VEVAY,IN,PRIMARY,2340,4158,66898429,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20143,CATHARPIN,VA,PRIMARY,577,1029,40476976,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67430,CAWKER CITY,KS,PRIMARY,348,587,7166001,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2032,EAST WALPOLE,MA,PRIMARY,2082,3705,133930220,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30309,ATLANTA,GA,PRIMARY,12336,15857,923521797,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14111,NORTH COLLINS,NY,PRIMARY,1577,2725,52890844,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66285,LENEXA,KS,PRIMARY,257,396,10337807,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29438,EDISTO ISLAND,SC,PRIMARY,1193,1976,31652508,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61125,ROCKFORD,IL,PRIMARY,270,408,8427726,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85007,PHOENIX,AZ,PRIMARY,4675,7993,154328707,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52223,DELHI,IA,PRIMARY,669,1184,20926327,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10583,SCARSDALE,NY,PRIMARY,19793,36163,528333370,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65582,VIENNA,MO,PRIMARY,938,1725,25775009,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96091,TRINITY CENTER,CA,PRIMARY,293,501,3841609,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42078,SALEM,KY,PRIMARY,763,1447,21640714,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50841,CORNING,IA,PRIMARY,1374,2411,34696804,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13224,SYRACUSE,NY,PRIMARY,4167,6872,162086803,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53153,NORTH PRAIRIE,WI,PRIMARY,1231,2302,68430870,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36540,GAINESTOWN,AL,PRIMARY,379,735,9178197,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33936,LEHIGH ACRES,FL,PRIMARY,8583,14941,214227701,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68015,CEDAR BLUFFS,NE,PRIMARY,503,910,15234873,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73061,MORRISON,OK,PRIMARY,647,1261,23624297,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79313,ANTON,TX,PRIMARY,719,1332,19098172,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63548,LANCASTER,MO,PRIMARY,575,1036,12854714,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92101,SAN DIEGO,CA,PRIMARY,16788,21606,941833907,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19055,LEVITTOWN,PA,PRIMARY,6888,11766,258651472,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61853,MAHOMET,IL,PRIMARY,5916,11293,298336301,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66524,OVERBROOK,KS,PRIMARY,1209,2211,43794745,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28411,WILMINGTON,NC,PRIMARY,14204,25564,625581389,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47858,LEWIS,IN,PRIMARY,304,575,10038558,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52801,DAVENPORT,IA,PRIMARY,327,400,7177890,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35055,CULLMAN,AL,PRIMARY,7814,14351,246815105,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62629,CHATHAM,IL,PRIMARY,6169,11461,292298197,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37391,TURTLETOWN,TN,PRIMARY,534,1026,12386548,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56484,WALKER,MN,PRIMARY,1918,3282,48746056,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50597,WEST BEND,IA,PRIMARY,683,1186,15999293,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60169,HOFFMAN ESTATES,IL,PRIMARY,15505,27194,658665469,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43571,WHITEHOUSE,OH,PRIMARY,3392,6054,176743842,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28368,OLIVIA,NC,PRIMARY,379,660,10336533,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67056,HALSTEAD,KS,PRIMARY,1385,2539,47720990,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66012,BONNER SPRINGS,KS,PRIMARY,5190,9439,228149876,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58621,BEACH,ND,PRIMARY,673,1119,17569061,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24266,LEBANON,VA,PRIMARY,4042,7466,135873255,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78234,SAN ANTONIO,TX,PRIMARY,1673,3432,69135921,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70116,NEW ORLEANS,LA,PRIMARY,4612,6580,129465605,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63071,RICHWOODS,MO,PRIMARY,425,805,11093285,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98359,OLALLA,WA,PRIMARY,2273,4171,94563736,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48108,ANN ARBOR,MI,PRIMARY,12492,21112,666763111,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45761,MILLFIELD,OH,PRIMARY,703,1225,16837663,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54891,WASHBURN,WI,PRIMARY,1646,2834,52026716,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49920,CRYSTAL FALLS,MI,PRIMARY,1921,3287,46237483,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90755,SIGNAL HILL,CA,PRIMARY,5205,8468,258295992,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7013,CLIFTON,NJ,PRIMARY,14153,23975,704167193,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10517,CROMPOND,NY,PRIMARY,454,809,25296212,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3854,NEW CASTLE,NH,PRIMARY,590,959,45088962,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68959,MINDEN,NE,PRIMARY,1813,3260,52873387,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33918,NORTH FORT MYERS,FL,PRIMARY,631,979,13641891,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1522,JEFFERSON,MA,PRIMARY,1672,2984,93338120,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29449,HOLLYWOOD,SC,PRIMARY,3509,6131,112055204,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31824,PRESTON,GA,PRIMARY,704,1335,18183190,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72211,LITTLE ROCK,AR,PRIMARY,10054,17089,502041111,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32327,CRAWFORDVILLE,FL,PRIMARY,9839,17961,351500595,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13691,THERESA,NY,PRIMARY,1300,2395,40555190,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26534,GRANVILLE,WV,PRIMARY,466,770,10349617,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +86047,WINSLOW,AZ,PRIMARY,4897,9122,144717338,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55430,MINNEAPOLIS,MN,PRIMARY,9978,16574,312911213,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36526,DAPHNE,AL,PRIMARY,12122,22153,564796697,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92504,RIVERSIDE,CA,PRIMARY,20774,37665,723697102,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90295,MARINA DEL REY,CA,PRIMARY,875,1166,40862193,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59104,BILLINGS,MT,PRIMARY,562,872,19440224,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28612,CONNELLYS SPRINGS,NC,PRIMARY,4354,8122,125108281,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78550,HARLINGEN,TX,PRIMARY,19279,35476,552425626,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49233,CEMENT CITY,MI,PRIMARY,1257,2256,42359689,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42729,CUB RUN,KY,PRIMARY,507,991,10849515,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32771,SANFORD,FL,PRIMARY,21728,38014,858548338,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65640,DUNNEGAN,MO,PRIMARY,322,600,6277740,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45389,CHRISTIANSBURG,OH,PRIMARY,282,481,7842436,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44609,BELOIT,OH,PRIMARY,1779,3143,56381065,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49047,DOWAGIAC,MI,PRIMARY,6530,11320,175759009,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61101,ROCKFORD,IL,PRIMARY,9028,15650,216110837,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78553,HARLINGEN,TX,PRIMARY,1157,2013,30328230,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98932,GRANGER,WA,PRIMARY,1834,3725,46775377,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67853,INGALLS,KS,PRIMARY,385,724,11320016,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4428,EDDINGTON,ME,PRIMARY,1426,2514,47557054,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99521,ANCHORAGE,AK,PRIMARY,902,1389,35257804,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16827,BOALSBURG,PA,PRIMARY,2269,3952,103160487,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56349,LOWRY,MN,PRIMARY,362,664,11998989,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63461,PALMYRA,MO,PRIMARY,2678,4885,83359101,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3842,HAMPTON,NH,PRIMARY,7982,13085,395486874,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73773,WAUKOMIS,OK,PRIMARY,771,1414,23811775,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34607,SPRING HILL,FL,PRIMARY,3580,6196,108320693,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47260,MEDORA,IN,PRIMARY,886,1612,24079158,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62629,CHATHAM,IL,PRIMARY,6169,11461,292298197,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31909,COLUMBUS,GA,PRIMARY,15634,27967,596204109,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76104,FORT WORTH,TX,PRIMARY,6058,10534,142325465,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71069,RODESSA,LA,PRIMARY,271,509,7284560,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25181,SETH,WV,PRIMARY,587,1152,20917456,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91763,MONTCLAIR,CA,PRIMARY,14454,27063,453244725,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99740,FORT YUKON,AK,PRIMARY,278,420,6385108,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16040,HILLIARDS,PA,PRIMARY,438,781,11862271,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83350,RUPERT,ID,PRIMARY,4962,9622,134737047,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60505,AURORA,IL,PRIMARY,23662,44855,636961078,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76903,SAN ANGELO,TX,PRIMARY,13472,23126,320563090,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29583,PAMPLICO,SC,PRIMARY,2208,4058,59088838,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95472,SEBASTOPOL,CA,PRIMARY,13081,21680,493650051,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29506,FLORENCE,SC,PRIMARY,7824,13667,190085130,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71462,NOBLE,LA,PRIMARY,541,1049,17675682,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28341,FAISON,NC,PRIMARY,1756,3329,45375995,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38114,MEMPHIS,TN,PRIMARY,12739,21150,233344846,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46184,WHITELAND,IN,PRIMARY,5418,10100,215147469,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90633,LA HABRA,CA,PRIMARY,301,508,8864607,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63051,HOUSE SPRINGS,MO,PRIMARY,6579,11892,245384916,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35034,BRENT,AL,PRIMARY,1689,3090,43472736,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98021,BOTHELL,WA,PRIMARY,12362,22499,747557806,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96837,HONOLULU,HI,PRIMARY,506,772,15103378,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66010,BLUE MOUND,KS,PRIMARY,275,489,6519930,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62881,SALEM,IL,PRIMARY,5311,9380,156322898,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26187,WILLIAMSTOWN,WV,PRIMARY,2791,5122,106783094,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75972,SAN AUGUSTINE,TX,PRIMARY,2694,4840,65068750,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79029,DUMAS,TX,PRIMARY,6753,12948,231494323,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17737,HUGHESVILLE,PA,PRIMARY,3052,5359,95918965,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95306,CATHEYS VALLEY,CA,PRIMARY,414,781,14170835,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38034,FRIENDSHIP,TN,PRIMARY,1132,2142,31157716,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49454,SCOTTVILLE,MI,PRIMARY,2108,3847,56437606,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67428,CANTON,KS,PRIMARY,706,1317,24683170,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20817,BETHESDA,MD,PRIMARY,17115,31025,1785078706,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32176,ORMOND BEACH,FL,PRIMARY,7350,11627,220641577,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30152,KENNESAW,GA,PRIMARY,17602,33285,1107231532,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32720,DELAND,FL,PRIMARY,12134,21124,353565495,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5487,STARKSBORO,VT,PRIMARY,763,1323,25310357,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21787,TANEYTOWN,MD,PRIMARY,5024,9033,195175957,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98908,YAKIMA,WA,PRIMARY,16300,29357,648522174,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72858,POTTSVILLE,AR,PRIMARY,1374,2692,43381017,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77670,VIDOR,TX,PRIMARY,867,1518,26748294,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49635,FRANKFORT,MI,PRIMARY,1747,2913,34972330,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68517,LINCOLN,NE,PRIMARY,251,476,11422901,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38326,COUNCE,TN,PRIMARY,1036,1859,33972097,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71747,HUTTIG,AR,PRIMARY,399,742,11230738,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76471,RISING STAR,TX,PRIMARY,673,1221,15839607,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83832,GENESEE,ID,PRIMARY,688,1314,25534920,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43767,NORWICH,OH,PRIMARY,705,1296,24740458,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43545,NAPOLEON,OH,PRIMARY,7261,12429,231187111,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42452,ROBARDS,KY,PRIMARY,1047,2032,41156077,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53594,WATERLOO,WI,PRIMARY,2660,4736,97656259,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35078,HARPERSVILLE,AL,PRIMARY,958,1768,30258698,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13034,CAYUGA,NY,PRIMARY,834,1505,30953085,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54812,BARRON,WI,PRIMARY,2764,4756,73105539,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75054,GRAND PRAIRIE,TX,PRIMARY,3197,6470,223864571,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56304,SAINT CLOUD,MN,PRIMARY,6772,10660,209766787,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43023,GRANVILLE,OH,PRIMARY,5481,10048,331579502,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33685,TAMPA,FL,PRIMARY,698,1095,17808652,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71424,ELMER,LA,PRIMARY,502,984,18205660,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25621,GILBERT,WV,PRIMARY,1036,2049,38283828,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77856,FRANKLIN,TX,PRIMARY,1882,3468,60191662,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38618,COLDWATER,MS,PRIMARY,5009,9294,153034488,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13652,HERMON,NY,PRIMARY,740,1353,20921242,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55612,LUTSEN,MN,PRIMARY,282,455,6161213,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45882,ROCKFORD,OH,PRIMARY,1517,2589,43053646,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30452,REGISTER,GA,PRIMARY,674,1255,18664920,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47401,BLOOMINGTON,IN,PRIMARY,16842,27740,731808245,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32346,PANACEA,FL,PRIMARY,821,1408,20696358,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47620,MOUNT VERNON,IN,PRIMARY,6328,11552,248647326,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23234,RICHMOND,VA,PRIMARY,18687,31921,562632911,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79604,ABILENE,TX,PRIMARY,727,1206,22681587,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13116,MINOA,NY,PRIMARY,1711,2992,65411187,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63945,HARVIELL,MO,PRIMARY,492,934,12523376,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32714,ALTAMONTE SPRINGS,FL,PRIMARY,17149,27758,602956990,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66724,CHEROKEE,KS,PRIMARY,485,882,12946467,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18214,BARNESVILLE,PA,PRIMARY,1105,1939,37504004,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +81401,MONTROSE,CO,PRIMARY,11102,19993,329361407,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27883,STANTONSBURG,NC,PRIMARY,1494,2693,40520695,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38174,MEMPHIS,TN,PRIMARY,342,486,10914282,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53968,WONEWOC,WI,PRIMARY,1081,1895,28801628,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65063,NEW BLOOMFIELD,MO,PRIMARY,1543,2892,56761511,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55373,ROCKFORD,MN,PRIMARY,2702,4831,130223746,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62952,JONESBORO,IL,PRIMARY,1513,2746,42934076,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60516,DOWNERS GROVE,IL,PRIMARY,15386,26828,848619357,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62547,MOUNT AUBURN,IL,PRIMARY,379,687,12554192,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18414,DALTON,PA,PRIMARY,2787,4924,125431491,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54006,CUSHING,WI,PRIMARY,397,695,12805598,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7605,LEONIA,NJ,PRIMARY,4156,7589,259754085,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22971,SHIPMAN,VA,PRIMARY,732,1291,22138662,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58207,GRAND FORKS,ND,PRIMARY,273,285,4275788,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47620,MOUNT VERNON,IN,PRIMARY,6328,11552,248647326,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73084,SPENCER,OK,PRIMARY,2887,4808,63783363,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33074,POMPANO BEACH,FL,PRIMARY,385,596,10290584,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67002,ANDOVER,KS,PRIMARY,5786,11299,363402717,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49272,PLEASANT LAKE,MI,PRIMARY,1197,2196,44714765,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11947,JAMESPORT,NY,PRIMARY,741,1261,37830806,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70441,GREENSBURG,LA,PRIMARY,2122,3865,53481936,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79915,EL PASO,TX,PRIMARY,16044,29001,316247822,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2462,NEWTON LOWER FALLS,MA,PRIMARY,689,1184,50636755,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48244,DETROIT,MI,PRIMARY,336,504,10093547,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74641,KAW CITY,OK,PRIMARY,319,563,9379117,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21054,GAMBRILLS,MD,PRIMARY,5092,9367,354966758,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33335,FORT LAUDERDALE,FL,PRIMARY,351,504,13145133,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54742,FALL CREEK,WI,PRIMARY,2196,4070,85292045,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92607,LAGUNA NIGUEL,CA,PRIMARY,510,795,21622264,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98065,SNOQUALMIE,WA,PRIMARY,5184,10415,442377417,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80514,DACONO,CO,PRIMARY,1762,3217,67359626,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85935,PINETOP,AZ,PRIMARY,2142,3965,67863773,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52233,HIAWATHA,IA,PRIMARY,3417,5715,133754293,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12833,GREENFIELD CENTER,NY,PRIMARY,2173,3878,97388018,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10459,BRONX,NY,PRIMARY,17977,30434,414021653,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92607,LAGUNA NIGUEL,CA,PRIMARY,510,795,21622264,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36854,VALLEY,AL,PRIMARY,6440,11676,184575673,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11765,MILL NECK,NY,PRIMARY,371,609,53923307,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3455,MARLBOROUGH,NH,PRIMARY,1140,1895,42897804,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57314,ARTESIAN,SD,PRIMARY,320,545,6148004,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39074,FOREST,MS,PRIMARY,5837,10722,147109672,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41174,SOUTH PORTSMOUTH,KY,PRIMARY,380,733,11769032,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70126,NEW ORLEANS,LA,PRIMARY,8133,14185,198343652,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33076,POMPANO BEACH,FL,PRIMARY,12888,25322,947666207,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58602,DICKINSON,ND,PRIMARY,415,663,15083214,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1902,LYNN,MA,PRIMARY,18627,30268,565476884,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62351,MENDON,IL,PRIMARY,879,1613,28403364,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20036,WASHINGTON,DC,PRIMARY,3854,4479,276290738,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95645,KNIGHTS LANDING,CA,PRIMARY,662,1285,20033406,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95524,BAYSIDE,CA,PRIMARY,1038,1740,32200527,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71264,OAK RIDGE,LA,PRIMARY,400,743,12612818,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4429,HOLDEN,ME,PRIMARY,2427,4302,104362764,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46507,BRISTOL,IN,PRIMARY,4426,8126,185424431,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90012,LOS ANGELES,CA,PRIMARY,8834,13839,288859252,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23093,LOUISA,VA,PRIMARY,5577,9999,208591582,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46268,INDIANAPOLIS,IN,PRIMARY,12562,20516,460320675,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16866,PHILIPSBURG,PA,PRIMARY,3822,6561,115339961,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80653,WELDONA,CO,PRIMARY,340,626,10585279,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97333,CORVALLIS,OR,PRIMARY,8497,13876,300513923,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61841,FAIRMOUNT,IL,PRIMARY,663,1218,22931130,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77836,CALDWELL,TX,PRIMARY,4813,8783,156682163,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63748,FROHNA,MO,PRIMARY,450,811,13386812,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29368,MAYO,SC,PRIMARY,413,708,10844329,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6119,WEST HARTFORD,CT,PRIMARY,7507,12133,401473695,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61480,STRONGHURST,IL,PRIMARY,641,1149,18219366,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35473,NORTHPORT,AL,PRIMARY,6354,11384,243262138,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37873,SURGOINSVILLE,TN,PRIMARY,1736,3242,46289333,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78538,EDCOUCH,TX,PRIMARY,3415,6689,70887559,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70514,BALDWIN,LA,PRIMARY,1255,2287,37233044,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +89113,LAS VEGAS,NV,PRIMARY,11226,18126,578215900,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91767,POMONA,CA,PRIMARY,18442,33720,578550841,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26590,WANA,WV,PRIMARY,297,574,10443151,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36867,PHENIX CITY,AL,PRIMARY,8405,14901,255624855,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54733,DALLAS,WI,PRIMARY,623,1149,18162095,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48210,DETROIT,MI,PRIMARY,9780,18392,173358285,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6420,SALEM,CT,PRIMARY,2052,3806,128811331,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93505,CALIFORNIA CITY,CA,PRIMARY,3792,7123,143873013,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52157,MC GREGOR,IA,PRIMARY,856,1458,24791324,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46217,INDIANAPOLIS,IN,PRIMARY,14727,25860,617589207,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3284,SPRINGFIELD,NH,PRIMARY,377,676,12629305,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96740,KAILUA KONA,HI,PRIMARY,11334,18960,383807736,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56169,RUSSELL,MN,PRIMARY,335,611,11094716,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57528,COLOME,SD,PRIMARY,341,644,6658527,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17584,WILLOW STREET,PA,PRIMARY,4628,8112,153995957,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37409,CHATTANOOGA,TN,PRIMARY,1415,2336,39471123,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75432,COOPER,TX,PRIMARY,1357,2477,40152215,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96001,REDDING,CA,PRIMARY,13491,23744,469950362,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44851,NEW LONDON,OH,PRIMARY,2564,4542,77557285,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94130,SAN FRANCISCO,CA,PRIMARY,966,1387,33246327,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95367,RIVERBANK,CA,PRIMARY,9078,17864,348987321,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94546,CASTRO VALLEY,CA,PRIMARY,20616,35351,987939047,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36575,SEMMES,AL,PRIMARY,7673,14723,277891064,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61420,BLANDINSVILLE,IL,PRIMARY,537,961,14340835,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77423,BROOKSHIRE,TX,PRIMARY,3400,6299,114609605,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6450,MERIDEN,CT,PRIMARY,17977,29435,718014481,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64640,GALLATIN,MO,PRIMARY,1374,2538,37555781,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61778,WAYNESVILLE,IL,PRIMARY,330,607,10800525,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71111,BOSSIER CITY,LA,PRIMARY,15934,28820,640130529,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77578,MANVEL,TX,PRIMARY,5615,10680,355621459,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38847,GOLDEN,MS,PRIMARY,1326,2592,37582287,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26624,GASSAWAY,WV,PRIMARY,1199,2151,36421050,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53034,HUSTISFORD,WI,PRIMARY,964,1653,35215160,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96091,TRINITY CENTER,CA,PRIMARY,293,501,3841609,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42345,GREENVILLE,KY,PRIMARY,4432,8336,140443503,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80234,DENVER,CO,PRIMARY,12131,20539,574285443,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64117,KANSAS CITY,MO,PRIMARY,6677,11001,198354416,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33538,LAKE PANASOFFKEE,FL,PRIMARY,1828,3199,41467056,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96055,LOS MOLINOS,CA,PRIMARY,1466,2732,40104959,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50471,RUDD,IA,PRIMARY,345,614,9547507,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3218,BARNSTEAD,NH,PRIMARY,592,1040,22542745,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40855,LYNCH,KY,PRIMARY,343,644,9364593,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +82054,CARPENTER,WY,PRIMARY,351,668,12280782,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33852,LAKE PLACID,FL,PRIMARY,7633,13363,156977577,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23225,RICHMOND,VA,PRIMARY,18633,29120,655538330,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16501,ERIE,PA,PRIMARY,614,778,6263221,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95036,MILPITAS,CA,PRIMARY,824,1343,40689789,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62684,SHERMAN,IL,PRIMARY,2387,4514,115618522,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33410,PALM BEACH GARDENS,FL,PRIMARY,19757,29752,824014973,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68376,HUMBOLDT,NE,PRIMARY,681,1199,15668981,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48105,ANN ARBOR,MI,PRIMARY,15149,25072,901733416,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27217,BURLINGTON,NC,PRIMARY,14999,27330,403486230,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44117,EUCLID,OH,PRIMARY,4773,7440,134687685,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97114,DAYTON,OR,PRIMARY,2052,3869,68317318,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14813,BELMONT,NY,PRIMARY,1046,1857,30299947,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50130,JEWELL,IA,PRIMARY,786,1482,29802717,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23050,DUTTON,VA,PRIMARY,346,640,13112053,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19035,GLADWYNE,PA,PRIMARY,2151,3761,353254555,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1902,LYNN,MA,PRIMARY,18627,30268,565476884,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97202,PORTLAND,OR,PRIMARY,19428,29321,782621168,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30271,NEWNAN,GA,PRIMARY,497,834,17503903,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95311,COULTERVILLE,CA,PRIMARY,781,1402,19322366,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39096,LORMAN,MS,PRIMARY,860,1507,20656446,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2767,RAYNHAM,MA,PRIMARY,6595,11607,343769637,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8021,CLEMENTON,NJ,PRIMARY,22635,37348,819258817,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54205,CASCO,WI,PRIMARY,1035,1910,36998005,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +89179,LAS VEGAS,NV,PRIMARY,1300,2329,72009836,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34433,DUNNELLON,FL,PRIMARY,2798,5014,69415228,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96049,REDDING,CA,PRIMARY,1324,2172,39128730,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55373,ROCKFORD,MN,PRIMARY,2702,4831,130223746,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77433,CYPRESS,TX,PRIMARY,18562,37962,1278558250,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62014,BUNKER HILL,IL,PRIMARY,1823,3375,62651385,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95374,STEVINSON,CA,PRIMARY,685,1329,19206707,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8724,BRICK,NJ,PRIMARY,21871,37268,994471914,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50402,MASON CITY,IA,PRIMARY,315,455,8193863,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77020,HOUSTON,TX,PRIMARY,9757,17899,242110745,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27809,BATTLEBORO,NC,PRIMARY,2203,4020,74212407,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45760,MIDDLEPORT,OH,PRIMARY,1344,2438,35409296,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92678,TRABUCO CANYON,CA,PRIMARY,330,561,16470274,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23150,SANDSTON,VA,PRIMARY,6194,10558,234960055,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97361,MONMOUTH,OR,PRIMARY,4168,7320,133670416,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40209,LOUISVILLE,KY,PRIMARY,297,475,6930788,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2047,HUMAROCK,MA,PRIMARY,377,595,13510944,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12009,ALTAMONT,NY,PRIMARY,3502,6187,170041565,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54135,KESHENA,WI,PRIMARY,1234,2191,27631487,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4543,DAMARISCOTTA,ME,PRIMARY,1234,1996,28687557,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42755,LEITCHFIELD,KY,PRIMARY,311,563,8955080,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45018,FAIRFIELD,OH,PRIMARY,280,434,8702766,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27818,COMO,NC,PRIMARY,573,1024,16188667,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64096,WAVERLY,MO,PRIMARY,485,894,14868497,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14204,BUFFALO,NY,PRIMARY,3294,5302,73479105,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49046,DELTON,MI,PRIMARY,3282,5973,109608648,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61535,GROVELAND,IL,PRIMARY,801,1536,44292423,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74002,BARNSDALL,OK,PRIMARY,915,1708,28091450,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72854,OZONE,AR,PRIMARY,259,488,5550503,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13159,TULLY,NY,PRIMARY,2516,4590,110806140,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79313,ANTON,TX,PRIMARY,719,1332,19098172,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84663,SPRINGVILLE,UT,PRIMARY,10892,22010,417211220,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41005,BURLINGTON,KY,PRIMARY,9904,18294,445749587,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98374,PUYALLUP,WA,PRIMARY,16053,29998,774870786,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66604,TOPEKA,KS,PRIMARY,11875,18933,358938885,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30293,WOODBURY,GA,PRIMARY,1289,2377,32501976,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33243,MIAMI,FL,PRIMARY,318,461,8904012,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41073,BELLEVUE,KY,PRIMARY,2990,4685,100072674,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38948,OAKLAND,MS,PRIMARY,877,1576,20403335,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77650,PORT BOLIVAR,TX,PRIMARY,674,1139,17505164,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29856,WINDSOR,SC,PRIMARY,1075,2051,28668479,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64114,KANSAS CITY,MO,PRIMARY,13330,19663,509733149,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76238,ERA,TX,PRIMARY,252,474,9302032,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14466,HEMLOCK,NY,PRIMARY,873,1557,29993583,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18431,HONESDALE,PA,PRIMARY,6306,10706,185241782,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15027,CONWAY,PA,PRIMARY,1121,1918,34815855,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1370,SHELBURNE FALLS,MA,PRIMARY,2105,3439,65890148,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46204,INDIANAPOLIS,IN,PRIMARY,2151,2623,126173588,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37771,LENOIR CITY,TN,PRIMARY,6751,12281,209398463,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12431,FREEHOLD,NY,PRIMARY,683,1188,23087267,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53214,MILWAUKEE,WI,PRIMARY,17812,27867,566023689,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46072,TIPTON,IN,PRIMARY,4541,7955,144866056,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30634,DEWY ROSE,GA,PRIMARY,1016,1904,25586062,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95977,SMARTSVILLE,CA,PRIMARY,619,1146,21308751,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29596,WALLACE,SC,PRIMARY,1015,1860,26227201,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35981,IDER,AL,PRIMARY,854,1689,24829511,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42086,WEST PADUCAH,KY,PRIMARY,1863,3509,69783114,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93730,FRESNO,CA,PRIMARY,3993,7681,311497250,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4653,BASS HARBOR,ME,PRIMARY,288,473,7116735,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53021,FREDONIA,WI,PRIMARY,2311,4219,109776583,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95073,SOQUEL,CA,PRIMARY,5537,9169,259513233,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3605,LEMPSTER,NH,PRIMARY,486,837,15816778,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65655,GAINESVILLE,MO,PRIMARY,1265,2279,27307412,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56262,MILAN,MN,PRIMARY,341,605,9198202,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61528,EDWARDS,IL,PRIMARY,1220,2369,85914917,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16218,COWANSVILLE,PA,PRIMARY,529,936,16726545,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8310,BUENA,NJ,PRIMARY,927,1546,30173830,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94963,SAN GERONIMO,CA,PRIMARY,294,485,14591953,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13209,SYRACUSE,NY,PRIMARY,6817,11191,214056205,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60005,ARLINGTON HEIGHTS,IL,PRIMARY,15155,25773,797251202,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7764,WEST LONG BRANCH,NJ,PRIMARY,3343,5838,175716375,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62061,MARINE,IL,PRIMARY,864,1517,34372344,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30175,TALKING ROCK,GA,PRIMARY,2311,4487,74264784,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44807,ATTICA,OH,PRIMARY,1170,2044,34240317,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97089,DAMASCUS,OR,PRIMARY,4882,9159,225703744,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72205,LITTLE ROCK,AR,PRIMARY,11104,17073,414729310,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6351,JEWETT CITY,CT,PRIMARY,7952,13771,339228486,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56671,REDLAKE,MN,PRIMARY,1204,2214,25934497,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74446,OKAY,OK,PRIMARY,465,848,12840162,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8558,SKILLMAN,NJ,PRIMARY,3140,6048,468109768,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38859,NEW SITE,MS,PRIMARY,267,523,6792114,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92546,HEMET,CA,PRIMARY,675,1153,17248817,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21851,POCOMOKE CITY,MD,PRIMARY,3441,5977,105001707,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32572,MILTON,FL,PRIMARY,498,845,15077019,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17935,GIRARDVILLE,PA,PRIMARY,793,1285,20377016,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30677,WATKINSVILLE,GA,PRIMARY,7320,14161,339000189,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12578,SALT POINT,NY,PRIMARY,1137,2043,60259098,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96729,HOOLEHUA,HI,PRIMARY,380,737,10614688,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70112,NEW ORLEANS,LA,PRIMARY,1543,2310,46228230,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53705,MADISON,WI,PRIMARY,12878,20296,613364030,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72315,BLYTHEVILLE,AR,PRIMARY,9088,16578,276679318,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49009,KALAMAZOO,MI,PRIMARY,18841,32845,898833232,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20119,CATLETT,VA,PRIMARY,1725,3067,83160072,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6093,WEST SUFFIELD,CT,PRIMARY,1757,3130,98172513,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62479,WHEELER,IL,PRIMARY,428,762,10944585,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26711,CAPON BRIDGE,WV,PRIMARY,1191,2192,42904971,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45616,BLUE CREEK,OH,PRIMARY,518,967,12386710,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39402,HATTIESBURG,MS,PRIMARY,15516,27793,678391743,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92661,NEWPORT BEACH,CA,PRIMARY,2023,2915,131354093,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7649,ORADELL,NJ,PRIMARY,3914,7355,369791979,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66614,TOPEKA,KS,PRIMARY,15992,27021,597331998,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84083,WENDOVER,UT,PRIMARY,669,1265,16789224,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47577,SAINT MEINRAD,IN,PRIMARY,509,871,15383942,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87901,TRUTH OR CONSEQUENCES,NM,PRIMARY,3001,4730,49361750,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78130,NEW BRAUNFELS,TX,PRIMARY,26382,47380,915619654,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61019,DAVIS,IL,PRIMARY,1668,3112,55956024,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44878,SHILOH,OH,PRIMARY,1270,2326,32591722,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50216,PANORA,IA,PRIMARY,1306,2424,55330227,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41055,MAYSLICK,KY,PRIMARY,761,1454,22078452,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46914,BUNKER HILL,IN,PRIMARY,1037,1787,29361166,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10024,NEW YORK,NY,PRIMARY,31925,47261,1108944328,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5669,ROXBURY,VT,PRIMARY,268,462,6659703,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71325,CHENEYVILLE,LA,PRIMARY,490,905,11902789,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27804,ROCKY MOUNT,NC,PRIMARY,12981,22882,457893619,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43432,GRAYTOWN,OH,PRIMARY,743,1313,29499460,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30360,ATLANTA,GA,PRIMARY,6046,10858,263685354,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19956,LAUREL,DE,PRIMARY,6858,12111,200021101,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27537,HENDERSON,NC,PRIMARY,9009,16584,260448570,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67074,LEON,KS,PRIMARY,802,1463,30617862,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67672,WAKEENEY,KS,PRIMARY,1260,2142,32841547,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56623,BAUDETTE,MN,PRIMARY,1395,2425,37453913,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43901,ADENA,OH,PRIMARY,971,1712,31350149,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98855,TONASKET,WA,PRIMARY,2361,4299,55454229,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99921,CRAIG,AK,PRIMARY,824,1367,25062656,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71676,WILMOT,AR,PRIMARY,305,549,5734747,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94571,RIO VISTA,CA,PRIMARY,3913,6699,129395123,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68638,FULLERTON,NE,PRIMARY,788,1437,19517537,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87745,SAPELLO,NM,PRIMARY,264,484,6068769,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71107,SHREVEPORT,LA,PRIMARY,13265,23793,393082419,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67004,ARGONIA,KS,PRIMARY,381,705,11071808,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12009,ALTAMONT,NY,PRIMARY,3502,6187,170041565,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41002,AUGUSTA,KY,PRIMARY,1023,1898,30704824,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71474,SIMPSON,LA,PRIMARY,323,600,12646353,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40977,PINEVILLE,KY,PRIMARY,3058,5825,84322345,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64865,SENECA,MO,PRIMARY,2468,4624,70179487,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68450,TECUMSEH,NE,PRIMARY,1133,2029,31652377,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62803,HOYLETON,IL,PRIMARY,528,927,14921593,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55971,RUSHFORD,MN,PRIMARY,1418,2598,44984750,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62037,GRAFTON,IL,PRIMARY,929,1699,37991685,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46565,SHIPSHEWANA,IN,PRIMARY,3171,5947,86771510,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10969,PINE ISLAND,NY,PRIMARY,623,1106,27734147,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6712,PROSPECT,CT,PRIMARY,4689,8427,245168855,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6354,MOOSUP,CT,PRIMARY,2619,4561,101944212,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36467,OPP,AL,PRIMARY,4126,7660,110214704,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35808,HUNTSVILLE,AL,PRIMARY,388,896,17497561,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47449,NEWBERRY,IN,PRIMARY,273,491,8371430,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61764,PONTIAC,IL,PRIMARY,6262,10677,201511259,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54151,NIAGARA,WI,PRIMARY,1778,3100,56375967,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83840,KOOTENAI,ID,PRIMARY,300,537,7759110,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71854,TEXARKANA,AR,PRIMARY,14812,26511,456447690,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13668,NORWOOD,NY,PRIMARY,1467,2591,47386113,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59018,CLYDE PARK,MT,PRIMARY,296,524,7916287,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49738,GRAYLING,MI,PRIMARY,4550,7941,107679728,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55368,NORWOOD YOUNG AMERICA,MN,PRIMARY,1115,1961,40306149,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30566,OAKWOOD,GA,PRIMARY,3720,6624,119917038,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17101,HARRISBURG,PA,PRIMARY,1053,1215,26229154,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11434,JAMAICA,NY,PRIMARY,28175,44414,922046847,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77426,CHAPPELL HILL,TX,PRIMARY,933,1654,41947435,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70005,METAIRIE,LA,PRIMARY,12020,19374,634099734,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1560,SOUTH GRAFTON,MA,PRIMARY,2022,3675,123503278,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66748,HUMBOLDT,KS,PRIMARY,1274,2288,37506705,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26501,MORGANTOWN,WV,PRIMARY,8042,13220,266869676,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7073,EAST RUTHERFORD,NJ,PRIMARY,4707,7669,217842919,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77498,SUGAR LAND,TX,PRIMARY,13340,26061,686997827,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21875,DELMAR,MD,PRIMARY,2981,5235,105266691,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21719,CASCADE,MD,PRIMARY,757,1331,26938345,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60302,OAK PARK,IL,PRIMARY,16180,27186,1137923677,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95448,HEALDSBURG,CA,PRIMARY,8593,14838,343340891,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85260,SCOTTSDALE,AZ,PRIMARY,18493,29865,1084111228,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51241,LARCHWOOD,IA,PRIMARY,754,1436,25743107,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22841,MOUNT CRAWFORD,VA,PRIMARY,1360,2419,51697444,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72633,EVERTON,AR,PRIMARY,571,1126,15165496,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38504,ALLARDT,TN,PRIMARY,599,1138,14846343,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93955,SEASIDE,CA,PRIMARY,13223,24162,450948197,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25827,CRAB ORCHARD,WV,PRIMARY,1386,2554,50613288,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90404,SANTA MONICA,CA,PRIMARY,11003,16220,754476822,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12090,HOOSICK FALLS,NY,PRIMARY,2688,4771,92694191,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6085,UNIONVILLE,CT,PRIMARY,3456,6187,209701987,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31566,WAYNESVILLE,GA,PRIMARY,1380,2610,35740098,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55722,COLERAINE,MN,PRIMARY,550,1002,17985299,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2163,BOSTON,MA,PRIMARY,630,723,46464955,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +89318,MC GILL,NV,PRIMARY,516,896,17746290,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29353,JONESVILLE,SC,PRIMARY,1818,3229,48951710,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64423,BARNARD,MO,PRIMARY,345,639,11174112,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19468,ROYERSFORD,PA,PRIMARY,12835,22357,704775892,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72902,FORT SMITH,AR,PRIMARY,574,937,16107173,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1731,HANSCOM AFB,MA,PRIMARY,596,1343,28379331,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3302,CONCORD,NH,PRIMARY,764,1096,28178610,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45885,SAINT MARYS,OH,PRIMARY,6389,10830,202765355,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5680,WOLCOTT,VT,PRIMARY,941,1662,28332837,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32115,DAYTONA BEACH,FL,PRIMARY,387,542,9855865,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56264,MINNEOTA,MN,PRIMARY,1020,1825,29359630,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38462,HOHENWALD,TN,PRIMARY,4129,7770,103755133,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78231,SAN ANTONIO,TX,PRIMARY,4066,7193,232799653,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84157,SALT LAKE CITY,UT,PRIMARY,588,938,20472974,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67480,SOLOMON,KS,PRIMARY,854,1560,29373470,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39211,JACKSON,MS,PRIMARY,11198,18806,521231524,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92887,YORBA LINDA,CA,PRIMARY,9669,18153,823004537,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76651,ITALY,TX,PRIMARY,1276,2328,43869221,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62889,TEXICO,IL,PRIMARY,399,759,11264705,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78630,CEDAR PARK,TX,PRIMARY,804,1331,28792042,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43977,FLUSHING,OH,PRIMARY,973,1675,26181628,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47018,DILLSBORO,IN,PRIMARY,2085,3733,68085639,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51551,MALVERN,IA,PRIMARY,816,1493,28969463,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8530,LAMBERTVILLE,NJ,PRIMARY,3931,6511,257879296,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10988,UNIONVILLE,NY,PRIMARY,363,629,13783721,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2903,PROVIDENCE,RI,PRIMARY,3952,5160,156882227,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +81643,MESA,CO,PRIMARY,383,689,14428107,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15541,FRIEDENS,PA,PRIMARY,1780,3264,56922657,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34134,BONITA SPRINGS,FL,PRIMARY,6923,11428,570760748,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38460,GOODSPRING,TN,PRIMARY,596,1118,17892699,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29620,ABBEVILLE,SC,PRIMARY,5554,10139,154549847,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28310,FORT BRAGG,NC,PRIMARY,3260,3863,65016523,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64163,KANSAS CITY,MO,PRIMARY,360,564,12326442,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74940,HOWE,OK,PRIMARY,864,1680,26304688,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75232,DALLAS,TX,PRIMARY,12851,22153,333730368,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91203,GLENDALE,CA,PRIMARY,6453,10833,219540443,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62613,ATHENS,IL,PRIMARY,1877,3489,73003434,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6762,MIDDLEBURY,CT,PRIMARY,3760,6856,242736491,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47987,VEEDERSBURG,IN,PRIMARY,1899,3447,56917481,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92198,SAN DIEGO,CA,PRIMARY,629,1033,33996926,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63956,PATTERSON,MO,PRIMARY,386,740,7950037,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85246,CHANDLER,AZ,PRIMARY,630,1016,26596817,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8098,WOODSTOWN,NJ,PRIMARY,4297,7744,208318084,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70451,NATALBANY,LA,PRIMARY,1123,2105,28543239,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49224,ALBION,MI,PRIMARY,5300,9318,142870046,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23027,CARTERSVILLE,VA,PRIMARY,586,1070,18181935,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72004,ALTHEIMER,AR,PRIMARY,657,1114,12143994,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62545,MECHANICSBURG,IL,PRIMARY,619,1115,22566283,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46356,LOWELL,IN,PRIMARY,8090,14904,346309874,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66951,KENSINGTON,KS,PRIMARY,364,650,7320184,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61125,ROCKFORD,IL,PRIMARY,270,408,8427726,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20777,HIGHLAND,MD,PRIMARY,1595,3036,142205219,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78270,SAN ANTONIO,TX,PRIMARY,409,650,13395100,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84534,MONTEZUMA CREEK,UT,PRIMARY,385,711,12790009,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62627,CHANDLERVILLE,IL,PRIMARY,474,855,13679882,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47978,RENSSELAER,IN,PRIMARY,5236,9430,167397542,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32038,FORT WHITE,FL,PRIMARY,3740,6648,106072477,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55428,MINNEAPOLIS,MN,PRIMARY,14155,23451,491549095,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44004,ASHTABULA,OH,PRIMARY,14605,24745,405089505,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43065,POWELL,OH,PRIMARY,17969,33749,1406747373,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15762,NICKTOWN,PA,PRIMARY,454,835,15653513,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32550,MIRAMAR BEACH,FL,PRIMARY,3548,5708,170514509,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35044,CHILDERSBURG,AL,PRIMARY,3134,5729,93021157,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37016,AUBURNTOWN,TN,PRIMARY,392,714,12192821,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74332,BIG CABIN,OK,PRIMARY,765,1478,23230395,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62441,MARSHALL,IL,PRIMARY,3465,6204,110639963,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90274,PALOS VERDES PENINSULA,CA,PRIMARY,13159,24008,1404879976,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60550,SHABBONA,IL,PRIMARY,670,1179,22598110,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65452,CROCKER,MO,PRIMARY,1352,2524,36433514,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +81521,FRUITA,CO,PRIMARY,6740,12464,276339638,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78578,PORT ISABEL,TX,PRIMARY,4126,7482,96921761,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56701,THIEF RIVER FALLS,MN,PRIMARY,6163,10548,210359029,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14042,DELEVAN,NY,PRIMARY,1718,3060,50164400,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6807,COS COB,CT,PRIMARY,3444,6107,444794403,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43115,CLARKSBURG,OH,PRIMARY,567,1035,17613890,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46016,ANDERSON,IN,PRIMARY,7658,12898,138099333,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80513,BERTHOUD,CO,PRIMARY,5057,9316,244197618,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35401,TUSCALOOSA,AL,PRIMARY,10214,16255,215081021,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35452,COKER,AL,PRIMARY,1586,3077,57684991,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31532,DENTON,GA,PRIMARY,297,573,8045990,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1876,TEWKSBURY,MA,PRIMARY,14632,25645,790024913,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92308,APPLE VALLEY,CA,PRIMARY,14023,26211,459646224,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40340,NICHOLASVILLE,KY,PRIMARY,423,726,10599725,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45414,DAYTON,OH,PRIMARY,10415,17442,337111812,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11238,BROOKLYN,NY,PRIMARY,26156,37151,1236922826,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49424,HOLLAND,MI,PRIMARY,20517,37715,817216179,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67740,HOXIE,KS,PRIMARY,903,1606,24887087,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11693,FAR ROCKAWAY,NY,PRIMARY,5423,8984,209039482,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52574,MYSTIC,IA,PRIMARY,367,664,9625712,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27943,HATTERAS,NC,PRIMARY,398,648,9853980,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62448,NEWTON,IL,PRIMARY,2903,5182,84135218,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95052,SANTA CLARA,CA,PRIMARY,389,580,20793149,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44413,EAST PALESTINE,OH,PRIMARY,3479,5943,100730827,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28344,GODWIN,NC,PRIMARY,1197,2305,35479609,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38017,COLLIERVILLE,TN,PRIMARY,21449,42115,1560357984,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74362,PRYOR,OK,PRIMARY,663,1197,25116058,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95367,RIVERBANK,CA,PRIMARY,9078,17864,348987321,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5763,PITTSFORD,VT,PRIMARY,1415,2481,55269375,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28739,HENDERSONVILLE,NC,PRIMARY,8327,14540,238609610,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13069,FULTON,NY,PRIMARY,11158,19739,357501522,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28515,BAYBORO,NC,PRIMARY,885,1543,20752574,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49410,FOUNTAIN,MI,PRIMARY,777,1366,17997965,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2667,WELLFLEET,MA,PRIMARY,1406,2145,34818321,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38614,CLARKSDALE,MS,PRIMARY,7768,14062,188124583,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78935,ALLEYTON,TX,PRIMARY,368,689,15589470,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29547,HAMER,SC,PRIMARY,1137,2092,29450259,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +88048,MESQUITE,NM,PRIMARY,1742,3476,36761875,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90640,MONTEBELLO,CA,PRIMARY,26228,46577,863251749,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70639,EVANS,LA,PRIMARY,251,479,8164089,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54209,EGG HARBOR,WI,PRIMARY,748,1270,17683706,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60434,JOLIET,IL,PRIMARY,771,1213,22151646,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48653,ROSCOMMON,MI,PRIMARY,4473,7846,103814357,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8091,WEST BERLIN,NJ,PRIMARY,2694,4550,102854475,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7960,MORRISTOWN,NJ,PRIMARY,20272,33647,1862771371,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80134,PARKER,CO,PRIMARY,24453,47361,1779414950,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13202,SYRACUSE,NY,PRIMARY,1676,2520,41928158,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31126,ATLANTA,GA,PRIMARY,494,563,7143345,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38083,MILLINGTON,TN,PRIMARY,324,539,11173852,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17316,EAST BERLIN,PA,PRIMARY,4009,7396,166843100,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70057,HAHNVILLE,LA,PRIMARY,1862,3323,71163076,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43611,TOLEDO,OH,PRIMARY,9019,14938,275006057,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26801,BAKER,WV,PRIMARY,520,933,16143223,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33957,SANIBEL,FL,PRIMARY,3247,5478,171898751,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46156,MILROY,IN,PRIMARY,642,1208,18163354,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72101,MC CRORY,AR,PRIMARY,1356,2552,35363360,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24541,DANVILLE,VA,PRIMARY,12241,21053,352550953,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38135,MEMPHIS,TN,PRIMARY,13502,24884,624309598,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13655,HOGANSBURG,NY,PRIMARY,1086,2150,32842598,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54456,NEILLSVILLE,WI,PRIMARY,2925,5071,82826559,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23847,EMPORIA,VA,PRIMARY,5915,10290,161830570,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80477,STEAMBOAT SPRINGS,CO,PRIMARY,4376,6952,196199680,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48237,OAK PARK,MI,PRIMARY,14384,23430,432020412,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28111,MONROE,NC,PRIMARY,829,1460,26365462,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24087,ELLISTON,VA,PRIMARY,1733,3135,54778025,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48335,FARMINGTON,MI,PRIMARY,11621,19642,591500096,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37301,ALTAMONT,TN,PRIMARY,615,1213,11973497,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56542,FOSSTON,MN,PRIMARY,1322,2314,36056167,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7021,ESSEX FELLS,NJ,PRIMARY,1091,2007,166956457,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74017,CLAREMORE,OK,PRIMARY,10981,20237,395208643,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51234,BOYDEN,IA,PRIMARY,561,1112,18543957,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48112,BELLEVILLE,MI,PRIMARY,387,607,13600635,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4463,MILO,ME,PRIMARY,1146,2019,27029236,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5047,HARTFORD,VT,PRIMARY,445,698,14200608,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74833,CASTLE,OK,PRIMARY,274,525,7439989,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80517,ESTES PARK,CO,PRIMARY,5115,8636,146219457,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18854,WYSOX,PA,PRIMARY,766,1298,20466138,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36551,LOXLEY,AL,PRIMARY,3314,6160,111072944,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97429,DAYS CREEK,OR,PRIMARY,317,575,7345532,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27011,BOONVILLE,NC,PRIMARY,2237,4153,63701740,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76226,ARGYLE,TX,PRIMARY,7253,14869,655673789,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16509,ERIE,PA,PRIMARY,13751,23284,496141340,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52809,DAVENPORT,IA,PRIMARY,284,433,6242496,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44444,NEWTON FALLS,OH,PRIMARY,5199,8868,150414836,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30038,LITHONIA,GA,PRIMARY,16132,27454,560542732,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50247,STATE CENTER,IA,PRIMARY,1063,1995,38420148,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77662,VIDOR,TX,PRIMARY,10480,19641,375640152,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64688,WHEELING,MO,PRIMARY,251,465,5613218,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87004,BERNALILLO,NM,PRIMARY,4742,8129,129793741,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3844,HAMPTON FALLS,NH,PRIMARY,1188,2143,81832537,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66748,HUMBOLDT,KS,PRIMARY,1274,2288,37506705,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19442,KIMBERTON,PA,PRIMARY,585,1001,33030996,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23227,RICHMOND,VA,PRIMARY,12451,19421,412004706,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7726,ENGLISHTOWN,NJ,PRIMARY,21395,39570,1469011742,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27051,WALKERTOWN,NC,PRIMARY,3465,6248,106779805,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71357,NEWELLTON,LA,PRIMARY,816,1496,20967676,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15224,PITTSBURGH,PA,PRIMARY,5114,7053,129720383,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51529,DUNLAP,IA,PRIMARY,793,1409,24448432,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45769,POMEROY,OH,PRIMARY,2613,4757,72556319,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11232,BROOKLYN,NY,PRIMARY,10584,17338,294496128,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25502,APPLE GROVE,WV,PRIMARY,412,800,12391414,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77836,CALDWELL,TX,PRIMARY,4813,8783,156682163,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37853,ROCKFORD,TN,PRIMARY,1737,3124,54004743,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33875,SEBRING,FL,PRIMARY,4697,8331,126159569,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93927,GREENFIELD,CA,PRIMARY,6092,12788,184526450,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3833,EXETER,NH,PRIMARY,10490,18286,571105228,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97623,BONANZA,OR,PRIMARY,904,1736,20678294,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79789,WINK,TX,PRIMARY,428,791,17749920,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16843,HYDE,PA,PRIMARY,418,673,8637578,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92866,ORANGE,CA,PRIMARY,6759,11381,275673039,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25064,DUNBAR,WV,PRIMARY,4644,7497,132687650,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18966,SOUTHAMPTON,PA,PRIMARY,20813,36515,1110748379,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28052,GASTONIA,NC,PRIMARY,13289,24059,353456373,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54868,RICE LAKE,WI,PRIMARY,7526,12887,236583824,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21084,JARRETTSVILLE,MD,PRIMARY,3804,6986,204002723,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19952,HARRINGTON,DE,PRIMARY,4655,8258,141512863,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61454,LOMAX,IL,PRIMARY,328,605,8724588,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32059,LEE,FL,PRIMARY,984,1817,27174190,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70516,BRANCH,LA,PRIMARY,577,1094,19605048,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2839,MAPLEVILLE,RI,PRIMARY,906,1601,41396175,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87015,EDGEWOOD,NM,PRIMARY,6008,10942,235758194,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37374,SEQUATCHIE,TN,PRIMARY,684,1297,18542038,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58042,HARWOOD,ND,PRIMARY,625,1237,32477395,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62338,FOWLER,IL,PRIMARY,735,1341,27415548,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43344,RICHWOOD,OH,PRIMARY,2634,4746,94272492,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2812,CAROLINA,RI,PRIMARY,749,1368,37503525,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29402,CHARLESTON,SC,PRIMARY,349,531,15751160,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28391,STEDMAN,NC,PRIMARY,2401,4502,84097929,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23069,HANOVER,VA,PRIMARY,1452,2561,57841342,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46218,INDIANAPOLIS,IN,PRIMARY,12732,20903,241512037,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +83110,AFTON,WY,PRIMARY,1822,3543,65872797,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70003,METAIRIE,LA,PRIMARY,18927,32396,679783342,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27046,SANDY RIDGE,NC,PRIMARY,917,1709,27985887,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72761,SILOAM SPRINGS,AR,PRIMARY,8095,15283,259389835,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2659,SOUTH CHATHAM,MA,PRIMARY,594,985,16124247,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97208,PORTLAND,OR,PRIMARY,1160,1533,31521968,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85626,PIRTLEVILLE,AZ,PRIMARY,419,834,8196655,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20136,BRISTOW,VA,PRIMARY,10619,22107,845849788,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +89015,HENDERSON,NV,PRIMARY,17849,30967,735729333,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43779,SARAHSVILLE,OH,PRIMARY,481,835,13164372,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96863,M C B H KANEOHE BAY,HI,PRIMARY,2310,2556,39469202,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41601,ALLEN,KY,PRIMARY,514,957,17423017,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40390,WILMORE,KY,PRIMARY,2483,4629,72942488,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28431,CHADBOURN,NC,PRIMARY,2786,5116,70942390,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25514,FORT GAY,WV,PRIMARY,1373,2774,42518481,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13732,APALACHIN,NY,PRIMARY,3966,7253,167062976,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33433,BOCA RATON,FL,PRIMARY,21240,34128,828003054,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99009,ELK,WA,PRIMARY,1617,2991,51925836,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5658,MARSHFIELD,VT,PRIMARY,697,1228,19008014,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48749,OMER,MI,PRIMARY,549,952,13287085,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34949,FORT PIERCE,FL,PRIMARY,3242,5198,90134616,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76092,SOUTHLAKE,TX,PRIMARY,11594,24319,1906589831,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5738,CUTTINGSVILLE,VT,PRIMARY,615,1058,20967960,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18351,PORTLAND,PA,PRIMARY,347,559,11051612,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55127,SAINT PAUL,MN,PRIMARY,9099,15796,673842538,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74832,CARNEY,OK,PRIMARY,378,702,10362996,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44224,STOW,OH,PRIMARY,20030,33898,875868822,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37381,SPRING CITY,TN,PRIMARY,3749,6875,104001316,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48327,WATERFORD,MI,PRIMARY,10732,18206,413035396,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36783,THOMASTON,AL,PRIMARY,348,661,9995867,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38486,WESTPOINT,TN,PRIMARY,425,811,11391714,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56514,BARNESVILLE,MN,PRIMARY,1683,3111,62499955,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45841,JENERA,OH,PRIMARY,483,865,15970273,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54451,MEDFORD,WI,PRIMARY,5445,9722,176858106,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24631,OAKWOOD,VA,PRIMARY,522,968,15688367,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56589,WAUBUN,MN,PRIMARY,801,1423,19265259,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +63434,BETHEL,MO,PRIMARY,262,479,5759705,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72330,DYESS,AR,PRIMARY,276,548,6954655,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40210,LOUISVILLE,KY,PRIMARY,5918,9539,108705958,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33197,MIAMI,FL,PRIMARY,628,1028,15702441,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +88032,DONA ANA,NM,PRIMARY,983,1789,21136525,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30132,DALLAS,GA,PRIMARY,13113,25321,569160215,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11563,LYNBROOK,NY,PRIMARY,11104,19016,606418035,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91733,SOUTH EL MONTE,CA,PRIMARY,16472,31052,430750015,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14559,SPENCERPORT,NY,PRIMARY,8942,15998,365362043,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95436,FORESTVILLE,CA,PRIMARY,2855,4585,107428617,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13752,DELANCEY,NY,PRIMARY,361,616,9364710,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77586,SEABROOK,TX,PRIMARY,9752,17586,657995710,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97054,DEER ISLAND,OR,PRIMARY,556,1020,22216491,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13203,SYRACUSE,NY,PRIMARY,6280,9714,171340485,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95246,MOUNTAIN RANCH,CA,PRIMARY,832,1401,22405016,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27828,FARMVILLE,NC,PRIMARY,3759,6921,114599842,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87412,BLANCO,NM,PRIMARY,315,579,11722260,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71941,DONALDSON,AR,PRIMARY,766,1479,21580809,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55106,SAINT PAUL,MN,PRIMARY,21868,36448,635661245,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41719,BONNYMAN,KY,PRIMARY,645,1242,18487449,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15666,MOUNT PLEASANT,PA,PRIMARY,7663,13112,237676324,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48321,AUBURN HILLS,MI,PRIMARY,287,445,9772270,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64622,BOGARD,MO,PRIMARY,277,501,7234999,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13438,REMSEN,NY,PRIMARY,1665,2899,57511036,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27965,POPLAR BRANCH,NC,PRIMARY,253,424,6252364,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65441,BOURBON,MO,PRIMARY,2297,4205,64970980,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60154,WESTCHESTER,IL,PRIMARY,8905,15100,385973046,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25039,CEDAR GROVE,WV,PRIMARY,485,890,14469525,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66509,MAYETTA,KS,PRIMARY,1211,2120,34821740,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15022,CHARLEROI,PA,PRIMARY,5124,8570,150473679,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97131,NEHALEM,OR,PRIMARY,982,1652,19921931,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51503,COUNCIL BLUFFS,IA,PRIMARY,16612,29102,683574290,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17235,MARION,PA,PRIMARY,349,596,10153044,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28127,NEW LONDON,NC,PRIMARY,2697,4990,102116917,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32503,PENSACOLA,FL,PRIMARY,14501,23321,471846283,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50263,WAUKEE,IA,PRIMARY,6423,12093,412354771,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48045,HARRISON TOWNSHIP,MI,PRIMARY,12646,20828,518189512,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32189,SATSUMA,FL,PRIMARY,2102,3641,43126165,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76119,FORT WORTH,TX,PRIMARY,15694,28696,349381901,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62633,EASTON,IL,PRIMARY,337,597,10032671,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3220,BELMONT,NH,PRIMARY,3554,6141,129018031,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +94955,PETALUMA,CA,PRIMARY,349,564,15086176,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42633,MONTICELLO,KY,PRIMARY,7479,14080,174728326,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64744,EL DORADO SPRINGS,MO,PRIMARY,3177,5807,68789500,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5488,SWANTON,VT,PRIMARY,3644,6347,130712847,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56093,WASECA,MN,PRIMARY,5904,10276,198193116,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30467,SYLVANIA,GA,PRIMARY,5232,9444,137885942,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1254,RICHMOND,MA,PRIMARY,632,1068,39209955,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37303,ATHENS,TN,PRIMARY,9889,18135,299186543,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61752,LE ROY,IL,PRIMARY,2078,3813,85876769,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95969,PARADISE,CA,PRIMARY,11201,19114,297576409,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14468,HILTON,NY,PRIMARY,8994,16219,349425027,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52591,SIGOURNEY,IA,PRIMARY,1382,2444,38544938,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68701,NORFOLK,NE,PRIMARY,13671,24172,482863129,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44837,GREENWICH,OH,PRIMARY,1891,3472,51515139,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98948,TOPPENISH,WA,PRIMARY,4949,9422,121897135,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95122,SAN JOSE,CA,PRIMARY,22062,41936,701153563,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6897,WILTON,CT,PRIMARY,8651,16501,1556090212,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52405,CEDAR RAPIDS,IA,PRIMARY,11605,20107,452457222,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91739,RANCHO CUCAMONGA,CA,PRIMARY,13201,25587,840812511,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95113,SAN JOSE,CA,PRIMARY,781,1049,37924110,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36527,SPANISH FORT,AL,PRIMARY,4841,9416,271939844,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44662,NAVARRE,OH,PRIMARY,4586,7868,139038676,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25033,BUFFALO,WV,PRIMARY,939,1817,34788657,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71232,DELHI,LA,PRIMARY,2746,5067,80564652,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43734,DUNCAN FALLS,OH,PRIMARY,568,1038,18828277,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12985,SCHUYLER FALLS,NY,PRIMARY,529,931,16204574,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28776,SKYLAND,NC,PRIMARY,535,876,17091498,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92562,MURRIETA,CA,PRIMARY,23762,45927,1191210837,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37080,JOELTON,TN,PRIMARY,3557,6307,129951131,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30427,GLENNVILLE,GA,PRIMARY,4135,7747,111936916,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90232,CULVER CITY,CA,PRIMARY,8201,13073,465313191,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53934,FRIENDSHIP,WI,PRIMARY,2025,3431,45525291,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56222,CLARA CITY,MN,PRIMARY,967,1724,25418961,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26519,ALBRIGHT,WV,PRIMARY,705,1311,22142722,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55388,WATERTOWN,MN,PRIMARY,2495,4556,109001030,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +66044,LAWRENCE,KS,PRIMARY,10860,16052,310085286,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29909,OKATIE,SC,PRIMARY,7881,13658,195389288,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48041,MEMPHIS,MI,PRIMARY,2099,3901,83506554,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90061,LOS ANGELES,CA,PRIMARY,10076,18477,238903309,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74137,TULSA,OK,PRIMARY,12450,22445,1042828497,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7876,SUCCASUNNA,NJ,PRIMARY,5329,9849,354128006,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12180,TROY,NY,PRIMARY,22753,36062,781174813,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46507,BRISTOL,IN,PRIMARY,4426,8126,185424431,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16033,EVANS CITY,PA,PRIMARY,3101,5421,120748627,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13642,GOUVERNEUR,NY,PRIMARY,3638,6605,110043459,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56352,MELROSE,MN,PRIMARY,2572,4670,79530423,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77272,HOUSTON,TX,PRIMARY,574,952,17871728,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +96753,KIHEI,HI,PRIMARY,12196,19553,425439028,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77563,HITCHCOCK,TX,PRIMARY,4006,6870,145494518,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47303,MUNCIE,IN,PRIMARY,9663,15957,246705803,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49740,HARBOR SPRINGS,MI,PRIMARY,3741,6424,118544746,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13073,GROTON,NY,PRIMARY,2990,5355,110391836,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48809,BELDING,MI,PRIMARY,4799,8802,152588977,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27713,DURHAM,NC,PRIMARY,22527,37767,1145303534,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39452,LUCEDALE,MS,PRIMARY,9858,19596,363756494,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77531,CLUTE,TX,PRIMARY,6417,11888,239538094,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30241,LAGRANGE,GA,PRIMARY,9927,18185,282897258,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36536,FOLEY,AL,PRIMARY,1029,1785,27615352,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60079,WAUKEGAN,IL,PRIMARY,569,931,14368629,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44882,SYCAMORE,OH,PRIMARY,1427,2512,42929151,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93667,TOLLHOUSE,CA,PRIMARY,982,1864,38484975,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1852,LOWELL,MA,PRIMARY,15022,23950,573609990,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16928,KNOXVILLE,PA,PRIMARY,602,1100,13995939,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58638,HEBRON,ND,PRIMARY,461,844,11962712,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65020,CAMDENTON,MO,PRIMARY,6388,11399,165682464,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29608,GREENVILLE,SC,PRIMARY,381,637,10473673,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +68037,LOUISVILLE,NE,PRIMARY,1065,1908,43614107,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37650,ERWIN,TN,PRIMARY,5270,9419,149030757,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44680,STRASBURG,OH,PRIMARY,1999,3492,63067186,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52069,PRESTON,IA,PRIMARY,752,1356,23630672,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35474,MOUNDVILLE,AL,PRIMARY,2712,5149,92262755,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18092,ZIONSVILLE,PA,PRIMARY,1559,2807,83296501,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40143,HARDINSBURG,KY,PRIMARY,2322,4268,68638106,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38104,MEMPHIS,TN,PRIMARY,10387,15241,435448708,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93666,SULTANA,CA,PRIMARY,407,842,8590796,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79521,HASKELL,TX,PRIMARY,1520,2731,36788484,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15639,HUNKER,PA,PRIMARY,978,1723,35257131,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44507,YOUNGSTOWN,OH,PRIMARY,2012,3357,29382008,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39120,NATCHEZ,MS,PRIMARY,11745,20822,310840632,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31624,AXSON,GA,PRIMARY,459,908,11809567,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92372,PINON HILLS,CA,PRIMARY,1972,3747,75581667,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32245,JACKSONVILLE,FL,PRIMARY,616,954,19787441,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8901,NEW BRUNSWICK,NJ,PRIMARY,16776,28187,495595423,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28001,ALBEMARLE,NC,PRIMARY,10376,18787,314253696,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8840,METUCHEN,NJ,PRIMARY,8479,15163,598124729,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98513,OLYMPIA,WA,PRIMARY,14094,25697,596758047,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60042,ISLAND LAKE,IL,PRIMARY,4229,7500,196089463,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93930,KING CITY,CA,PRIMARY,6008,12376,192372786,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65470,FALCON,MO,PRIMARY,405,793,9531033,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59433,DUTTON,MT,PRIMARY,302,522,7419720,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61850,INDIANOLA,IL,PRIMARY,264,493,7541580,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43952,STEUBENVILLE,OH,PRIMARY,7755,12725,202735860,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11786,SHOREHAM,NY,PRIMARY,2963,5684,199871422,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45849,GROVER HILL,OH,PRIMARY,558,993,14985287,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92075,SOLANA BEACH,CA,PRIMARY,6695,10911,481295872,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56159,MOUNTAIN LAKE,MN,PRIMARY,1239,2247,32183747,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32562,GULF BREEZE,FL,PRIMARY,419,684,19907223,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55975,SPRING VALLEY,MN,PRIMARY,2088,3746,73572794,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27826,FAIRFIELD,NC,PRIMARY,264,491,6260077,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48475,UBLY,MI,PRIMARY,1402,2465,36328566,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27617,RALEIGH,NC,PRIMARY,7515,12300,484966226,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91344,GRANADA HILLS,CA,PRIMARY,23384,41602,1102040461,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4352,MOUNT VERNON,ME,PRIMARY,753,1307,25438393,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5402,BURLINGTON,VT,PRIMARY,556,728,16805420,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1506,BROOKFIELD,MA,PRIMARY,1665,2920,68732705,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30647,ILA,GA,PRIMARY,272,498,8140291,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59323,COLSTRIP,MT,PRIMARY,1082,2035,58024076,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70125,NEW ORLEANS,LA,PRIMARY,5234,8350,178284259,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48184,WAYNE,MI,PRIMARY,8255,13869,242363273,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32818,ORLANDO,FL,PRIMARY,20019,34498,546764528,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47443,LYONS,IN,PRIMARY,517,942,14494654,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73036,EL RENO,OK,PRIMARY,7193,12754,213297307,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +86043,SECOND MESA,AZ,PRIMARY,590,1121,12271709,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54494,WISCONSIN RAPIDS,WI,PRIMARY,13663,23860,458696321,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64097,WELLINGTON,MO,PRIMARY,637,1175,21678040,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60089,BUFFALO GROVE,IL,PRIMARY,21901,39466,1356499180,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95117,SAN JOSE,CA,PRIMARY,12721,22030,666191379,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39202,JACKSON,MS,PRIMARY,3284,5162,103618280,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42048,HARDIN,KY,PRIMARY,950,1767,21529327,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75845,GROVETON,TX,PRIMARY,1089,2052,30798298,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78716,AUSTIN,TX,PRIMARY,511,811,25638980,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37891,WHITESBURG,TN,PRIMARY,1523,2848,41515006,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48607,SAGINAW,MI,PRIMARY,584,871,7579846,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10602,WHITE PLAINS,NY,PRIMARY,541,826,19730717,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24095,GOODVIEW,VA,PRIMARY,2083,3782,71992357,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3458,PETERBOROUGH,NH,PRIMARY,3405,5705,135735376,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22821,DAYTON,VA,PRIMARY,2618,4830,74790158,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46368,PORTAGE,IN,PRIMARY,18487,32445,713943132,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98568,OAKVILLE,WA,PRIMARY,1128,1966,32040078,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39096,LORMAN,MS,PRIMARY,860,1507,20656446,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12472,ROSENDALE,NY,PRIMARY,896,1409,30585447,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3462,SPOFFORD,NH,PRIMARY,877,1539,46464738,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98296,SNOHOMISH,WA,PRIMARY,11048,21459,736882094,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42718,CAMPBELLSVILLE,KY,PRIMARY,9728,17818,264063372,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98635,LYLE,WA,PRIMARY,733,1308,22438525,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4220,BUCKFIELD,ME,PRIMARY,1400,2457,43905680,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28020,CASAR,NC,PRIMARY,1069,2024,29408223,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48464,OTTER LAKE,MI,PRIMARY,985,1821,28884205,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64735,CLINTON,MO,PRIMARY,5994,10581,167771555,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27882,SPRING HOPE,NC,PRIMARY,3256,5961,94047347,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15920,ARMAGH,PA,PRIMARY,506,872,16182812,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98377,RANDLE,WA,PRIMARY,844,1440,23690039,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6907,STAMFORD,CT,PRIMARY,4783,8014,324883757,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3812,BARTLETT,NH,PRIMARY,323,518,7199051,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52625,DONNELLSON,IA,PRIMARY,1270,2301,39773462,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54104,ATHELSTANE,WI,PRIMARY,487,842,9615288,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30152,KENNESAW,GA,PRIMARY,17602,33285,1107231532,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37891,WHITESBURG,TN,PRIMARY,1523,2848,41515006,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26456,WEST UNION,WV,PRIMARY,1451,2708,38198185,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98038,MAPLE VALLEY,WA,PRIMARY,13596,26284,868946579,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14755,LITTLE VALLEY,NY,PRIMARY,1225,2136,36477187,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76548,HARKER HEIGHTS,TX,PRIMARY,10661,20541,422227386,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80962,COLORADO SPRINGS,CO,PRIMARY,483,827,21714643,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18840,SAYRE,PA,PRIMARY,5014,8644,174076971,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19903,DOVER,DE,PRIMARY,516,804,14735224,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34142,IMMOKALEE,FL,PRIMARY,5475,10418,112722244,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64077,ORRICK,MO,PRIMARY,878,1617,30004694,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2125,DORCHESTER,MA,PRIMARY,14981,22994,501492850,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71660,NEW EDINBURG,AR,PRIMARY,384,724,11289280,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8052,MAPLE SHADE,NJ,PRIMARY,9877,15607,376208480,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36608,MOBILE,AL,PRIMARY,15750,27204,656498067,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98606,BRUSH PRAIRIE,WA,PRIMARY,4142,8043,211769233,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5872,WEST CHARLESTON,VT,PRIMARY,339,583,7858471,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +49287,TIPTON,MI,PRIMARY,1034,1917,40179950,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12468,PRATTSVILLE,NY,PRIMARY,513,881,14590558,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10474,BRONX,NY,PRIMARY,4369,7377,97578251,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57366,PARKSTON,SD,PRIMARY,1129,2005,31558453,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99741,GALENA,AK,PRIMARY,269,441,8949655,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21224,BALTIMORE,MD,PRIMARY,22061,33150,876200844,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55316,CHAMPLIN,MN,PRIMARY,11573,20946,614760299,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7407,ELMWOOD PARK,NJ,PRIMARY,9934,17030,405823236,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37217,NASHVILLE,TN,PRIMARY,14205,23166,409496387,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39440,LAUREL,MS,PRIMARY,7730,13723,208360016,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70835,BATON ROUGE,LA,PRIMARY,370,604,10424012,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14534,PITTSFORD,NY,PRIMARY,16194,30109,1195986419,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6902,STAMFORD,CT,PRIMARY,29001,47130,1753889885,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2830,HARRISVILLE,RI,PRIMARY,3056,5420,146989186,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54412,AUBURNDALE,WI,PRIMARY,1034,1887,36383977,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29401,CHARLESTON,SC,PRIMARY,4007,5783,242908839,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43105,BALTIMORE,OH,PRIMARY,3984,7064,159708382,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7424,LITTLE FALLS,NJ,PRIMARY,12172,20128,585762325,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44444,NEWTON FALLS,OH,PRIMARY,5199,8868,150414836,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11105,ASTORIA,NY,PRIMARY,19011,28457,722693754,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2108,BOSTON,MA,PRIMARY,2348,3312,388783474,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91394,GRANADA HILLS,CA,PRIMARY,317,493,10565696,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98947,TIETON,WA,PRIMARY,1081,2111,32403858,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39341,MACON,MS,PRIMARY,3192,5664,62245351,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38337,GADSDEN,TN,PRIMARY,617,1139,17603973,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74048,NOWATA,OK,PRIMARY,2447,4533,72150270,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13605,ADAMS,NY,PRIMARY,1990,3684,66542359,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65247,EXCELLO,MO,PRIMARY,255,465,7506334,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +75960,MOSCOW,TX,PRIMARY,382,717,11714217,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41003,BERRY,KY,PRIMARY,1064,2054,32740893,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54534,HURLEY,WI,PRIMARY,1213,1996,30144904,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +55969,ROLLINGSTONE,MN,PRIMARY,526,968,18179186,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +26257,COALTON,WV,PRIMARY,312,617,10235062,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30123,CASSVILLE,GA,PRIMARY,400,728,10254856,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61024,DURAND,IL,PRIMARY,1298,2360,49407398,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52748,ELDRIDGE,IA,PRIMARY,4082,7608,199334547,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5733,BRANDON,VT,PRIMARY,2818,4770,87545419,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65043,HOLTS SUMMIT,MO,PRIMARY,4532,8226,155701367,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45387,YELLOW SPRINGS,OH,PRIMARY,2812,4576,102001851,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5866,SHEFFIELD,VT,PRIMARY,323,573,8362085,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12564,PAWLING,NY,PRIMARY,3344,5933,185634365,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +51449,LAKE CITY,IA,PRIMARY,964,1711,26237453,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17002,ALLENSVILLE,PA,PRIMARY,270,513,5518469,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99517,ANCHORAGE,AK,PRIMARY,8337,12984,368564168,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5068,SOUTH ROYALTON,VT,PRIMARY,1524,2458,45320281,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77320,HUNTSVILLE,TX,PRIMARY,8454,14906,254326480,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12764,NARROWSBURG,NY,PRIMARY,773,1300,22315129,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61081,STERLING,IL,PRIMARY,10835,18732,348525244,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35011,ALEXANDER CITY,AL,PRIMARY,763,1334,24855050,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33419,WEST PALM BEACH,FL,PRIMARY,567,915,14880762,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28072,GRANITE QUARRY,NC,PRIMARY,685,1182,20002156,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95825,SACRAMENTO,CA,PRIMARY,13577,20027,413966183,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32241,JACKSONVILLE,FL,PRIMARY,704,1113,25647121,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31038,HILLSBORO,GA,PRIMARY,381,697,10703049,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1730,BEDFORD,MA,PRIMARY,6588,11940,472027119,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31018,DAVISBORO,GA,PRIMARY,535,978,13778028,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6902,STAMFORD,CT,PRIMARY,29001,47130,1753889885,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5734,BRIDPORT,VT,PRIMARY,636,1087,17995407,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77009,HOUSTON,TX,PRIMARY,16263,27460,620494819,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12809,ARGYLE,NY,PRIMARY,1685,2994,55154197,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15948,REVLOC,PA,PRIMARY,284,523,8316497,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14801,ADDISON,NY,PRIMARY,2212,4062,65839037,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2135,BRIGHTON,MA,PRIMARY,21268,27370,855471186,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7110,NUTLEY,NJ,PRIMARY,14513,25001,882251300,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31054,MC INTYRE,GA,PRIMARY,750,1365,19033239,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85302,GLENDALE,AZ,PRIMARY,15451,26533,504502805,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92868,ORANGE,CA,PRIMARY,9575,16174,369443577,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +58533,ELGIN,ND,PRIMARY,463,772,8081153,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +64850,NEOSHO,MO,PRIMARY,9846,18271,270357486,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76028,BURLESON,TX,PRIMARY,25425,48315,1206427469,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13839,SIDNEY CENTER,NY,PRIMARY,608,1088,18102112,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37602,JOHNSON CITY,TN,PRIMARY,586,898,23142996,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10704,YONKERS,NY,PRIMARY,15745,25409,706145477,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +42721,CANEYVILLE,KY,PRIMARY,1403,2761,35343402,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37082,KINGSTON SPRINGS,TN,PRIMARY,2977,5512,132663068,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13320,CHERRY VALLEY,NY,PRIMARY,934,1642,24912132,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13464,SMYRNA,NY,PRIMARY,478,851,12885849,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18325,CANADENSIS,PA,PRIMARY,1188,2012,37934925,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +34145,MARCO ISLAND,FL,PRIMARY,7444,12812,367150533,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27284,KERNERSVILLE,NC,PRIMARY,22754,42019,997453411,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31625,BARNEY,GA,PRIMARY,468,857,12142370,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71237,EPPS,LA,PRIMARY,517,975,14290608,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37082,KINGSTON SPRINGS,TN,PRIMARY,2977,5512,132663068,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99655,QUINHAGAK,AK,PRIMARY,263,470,3903253,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43442,LINDSEY,OH,PRIMARY,511,883,16798678,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33133,MIAMI,FL,PRIMARY,15579,24458,1042707180,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16501,ERIE,PA,PRIMARY,614,778,6263221,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29130,RIDGEWAY,SC,PRIMARY,2806,4927,93677948,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12428,ELLENVILLE,NY,PRIMARY,2601,4494,76147839,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92625,CORONA DEL MAR,CA,PRIMARY,6986,10985,697736150,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78467,CORPUS CHRISTI,TX,PRIMARY,479,799,11633418,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +86003,FLAGSTAFF,AZ,PRIMARY,1417,2352,46059771,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60564,NAPERVILLE,IL,PRIMARY,17498,36024,1772224608,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95012,CASTROVILLE,CA,PRIMARY,4326,8542,126955739,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +19606,READING,PA,PRIMARY,17255,29985,723273693,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45849,GROVER HILL,OH,PRIMARY,558,993,14985287,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37939,KNOXVILLE,TN,PRIMARY,310,480,13270687,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27920,BUXTON,NC,PRIMARY,814,1379,19072639,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56545,GARY,MN,PRIMARY,352,614,7464491,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31031,GORDON,GA,PRIMARY,2649,4822,74535288,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30907,AUGUSTA,GA,PRIMARY,22313,40607,1003729909,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32341,MADISON,FL,PRIMARY,529,911,13438499,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8869,RARITAN,NJ,PRIMARY,3424,5803,175605743,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12464,PHOENICIA,NY,PRIMARY,520,816,13164275,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56044,HENDERSON,MN,PRIMARY,995,1755,37014136,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +86043,SECOND MESA,AZ,PRIMARY,590,1121,12271709,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37029,BURNS,TN,PRIMARY,2424,4593,105799260,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67837,COPELAND,KS,PRIMARY,357,703,7189382,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8051,MANTUA,NJ,PRIMARY,5474,9204,262368742,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50436,FOREST CITY,IA,PRIMARY,2723,4832,86047944,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59443,FORT SHAW,MT,PRIMARY,305,545,8399557,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70361,HOUMA,LA,PRIMARY,1036,1700,40922277,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37752,HARROGATE,TN,PRIMARY,2616,4847,77573429,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60632,CHICAGO,IL,PRIMARY,32858,63860,877276155,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +79508,BUFFALO GAP,TX,PRIMARY,609,1070,19949804,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95363,PATTERSON,CA,PRIMARY,9127,18121,354778180,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +69043,STRATTON,NE,PRIMARY,264,468,5130200,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61722,ARROWSMITH,IL,PRIMARY,267,492,8659985,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14032,CLARENCE CENTER,NY,PRIMARY,3566,6906,217101920,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41092,VERONA,KY,PRIMARY,1572,2977,65833618,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36451,GROVE HILL,AL,PRIMARY,2098,4014,64887195,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7640,HARRINGTON PARK,NJ,PRIMARY,2279,4361,194366466,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27842,HENRICO,NC,PRIMARY,656,1123,15629016,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +90807,LONG BEACH,CA,PRIMARY,15959,26420,795362567,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61755,MACKINAW,IL,PRIMARY,2116,4031,93516788,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37082,KINGSTON SPRINGS,TN,PRIMARY,2977,5512,132663068,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30436,LYONS,GA,PRIMARY,4355,8258,112095015,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2631,BREWSTER,MA,PRIMARY,5179,8575,167998522,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85754,TUCSON,AZ,PRIMARY,852,1399,33845636,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +87103,ALBUQUERQUE,NM,PRIMARY,425,611,15513655,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56232,DAWSON,MN,PRIMARY,1111,1970,30294887,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +36401,EVERGREEN,AL,PRIMARY,3190,5813,78778511,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +72769,SUMMERS,AR,PRIMARY,370,707,10302981,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38663,RIPLEY,MS,PRIMARY,5106,9444,132042313,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48301,BLOOMFIELD HILLS,MI,PRIMARY,7143,12890,669214343,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +93103,SANTA BARBARA,CA,PRIMARY,8204,13621,343916881,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15146,MONROEVILLE,PA,PRIMARY,15256,25238,584154297,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32757,MOUNT DORA,FL,PRIMARY,9353,16168,318130210,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +85702,TUCSON,AZ,PRIMARY,643,959,17479478,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32091,STARKE,FL,PRIMARY,6234,11250,178806243,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29250,COLUMBIA,SC,PRIMARY,285,418,11366477,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31058,MAUK,GA,PRIMARY,607,1172,16528710,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54902,OSHKOSH,WI,PRIMARY,11496,18650,363524314,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +77878,SNOOK,TX,PRIMARY,451,813,13287452,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30144,KENNESAW,GA,PRIMARY,21815,38067,948599536,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10520,CROTON ON HUDSON,NY,PRIMARY,6109,10857,524242389,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95337,MANTECA,CA,PRIMARY,11853,22663,529597186,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4292,SUMNER,ME,PRIMARY,371,678,10918039,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97118,GARIBALDI,OR,PRIMARY,457,738,9728423,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15541,FRIEDENS,PA,PRIMARY,1780,3264,56922657,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +76518,BUCKHOLTS,TX,PRIMARY,537,993,14450698,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8270,WOODBINE,NJ,PRIMARY,3431,6102,138499266,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15955,SIDMAN,PA,PRIMARY,959,1699,30975871,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +30302,ATLANTA,GA,PRIMARY,420,564,11777761,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35172,TRAFFORD,AL,PRIMARY,1195,2333,40016483,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46635,SOUTH BEND,IN,PRIMARY,3068,5336,108187588,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45217,CINCINNATI,OH,PRIMARY,3209,5071,89786871,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +16929,LAWRENCEVILLE,PA,PRIMARY,1039,1840,28415690,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +21040,EDGEWOOD,MD,PRIMARY,11222,19332,409405527,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +65753,SPARTA,MO,PRIMARY,1970,3764,55164289,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37097,LOBELVILLE,TN,PRIMARY,867,1559,21940184,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +43004,BLACKLICK,OH,PRIMARY,11181,19234,606984386,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46068,SHARPSVILLE,IN,PRIMARY,1371,2586,52184597,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70395,SCHRIEVER,LA,PRIMARY,2213,4127,95205934,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84402,OGDEN,UT,PRIMARY,348,571,7832354,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78016,DEVINE,TX,PRIMARY,3911,7256,122646677,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17850,MONTANDON,PA,PRIMARY,364,608,9183139,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29162,TURBEVILLE,SC,PRIMARY,1048,1982,28902485,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52544,CENTERVILLE,IA,PRIMARY,3476,6109,91864298,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54628,FERRYVILLE,WI,PRIMARY,550,957,12863442,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80935,COLORADO SPRINGS,CO,PRIMARY,800,1434,23216043,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53140,KENOSHA,WI,PRIMARY,12669,21042,374038255,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13438,REMSEN,NY,PRIMARY,1665,2899,57511036,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53926,DALTON,WI,PRIMARY,599,1107,15104474,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57720,BUFFALO,SD,PRIMARY,338,591,8671219,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99678,TOGIAK,AK,PRIMARY,296,512,4084359,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +70653,MERRYVILLE,LA,PRIMARY,1199,2288,43277924,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +31089,TENNILLE,GA,PRIMARY,1908,3535,51591757,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +2130,JAMAICA PLAIN,MA,PRIMARY,19207,27060,930225860,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28371,PARKTON,NC,PRIMARY,2572,4854,74419550,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +50157,MALCOM,IA,PRIMARY,369,675,10747101,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +40011,CAMPBELLSBURG,KY,PRIMARY,1084,1999,34946469,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44092,WICKLIFFE,OH,PRIMARY,9141,14390,298733108,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +97741,MADRAS,OR,PRIMARY,4516,8373,125936176,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84032,HEBER CITY,UT,PRIMARY,6696,13213,266389121,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60076,SKOKIE,IL,PRIMARY,16726,29619,714881611,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +5769,SALISBURY,VT,PRIMARY,548,951,16611396,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13690,STAR LAKE,NY,PRIMARY,403,726,11668199,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78164,YORKTOWN,TX,PRIMARY,1682,3046,50870658,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +33924,CAPTIVA,FL,PRIMARY,288,426,18292113,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +4932,DIXMONT,ME,PRIMARY,556,994,19170243,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37388,TULLAHOMA,TN,PRIMARY,11254,20304,368318377,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54729,CHIPPEWA FALLS,WI,PRIMARY,15301,26758,531748675,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29804,AIKEN,SC,PRIMARY,332,560,13380367,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +1041,HOLYOKE,MA,PRIMARY,606,997,14650215,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +41063,MORNING VIEW,KY,PRIMARY,1400,2575,50252821,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20634,GREAT MILLS,MD,PRIMARY,3347,5941,173165833,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73160,OKLAHOMA CITY,OK,PRIMARY,23174,41857,855349080,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +28532,HAVELOCK,NC,PRIMARY,9805,18917,306741464,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +3777,ORFORD,NH,PRIMARY,626,1064,24973577,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60954,MOMENCE,IL,PRIMARY,3086,5430,94239294,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27603,RALEIGH,NC,PRIMARY,19277,33789,836671525,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95045,SAN JUAN BAUTISTA,CA,PRIMARY,1829,3345,85440444,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62869,NORRIS CITY,IL,PRIMARY,1225,2312,40131325,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +86015,BELLEMONT,AZ,PRIMARY,352,688,18796038,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44611,BIG PRAIRIE,OH,PRIMARY,860,1510,24298782,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39176,VAIDEN,MS,PRIMARY,820,1530,21377104,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +67735,GOODLAND,KS,PRIMARY,2618,4491,67588640,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +7438,OAK RIDGE,NJ,PRIMARY,5566,10328,344235177,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +12787,WHITE SULPHUR SPRINGS,NY,PRIMARY,284,493,9763246,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13123,NORTH BAY,NY,PRIMARY,258,451,5933714,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +47141,MARYSVILLE,IN,PRIMARY,701,1328,25990664,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +95991,YUBA CITY,CA,PRIMARY,14875,27881,477345135,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56449,FORT RIPLEY,MN,PRIMARY,728,1375,25150046,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +14437,DANSVILLE,NY,PRIMARY,4419,7679,139677842,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53015,CLEVELAND,WI,PRIMARY,1299,2344,50719141,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +15665,MANOR,PA,PRIMARY,817,1403,28953012,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32202,JACKSONVILLE,FL,PRIMARY,1536,2088,54046102,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +44460,SALEM,OH,PRIMARY,12335,21189,378339845,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +18087,TREXLERTOWN,PA,PRIMARY,481,765,16246858,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52722,BETTENDORF,IA,PRIMARY,17207,30958,948502308,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +84110,SALT LAKE CITY,UT,PRIMARY,709,1023,22241202,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +98550,HOQUIAM,WA,PRIMARY,4611,8013,137902954,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +59865,SAINT IGNATIUS,MT,PRIMARY,1271,2321,29946515,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +74159,TULSA,OK,PRIMARY,312,457,12805173,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +37416,CHATTANOOGA,TN,PRIMARY,7022,11829,220714255,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +25168,RED HOUSE,WV,PRIMARY,1136,2170,39931250,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +45238,CINCINNATI,OH,PRIMARY,23159,38407,772285806,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35143,SHELBY,AL,PRIMARY,1234,2292,40345152,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27371,TROY,NC,PRIMARY,3033,5604,88266631,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +57004,BERESFORD,SD,PRIMARY,1641,3001,53161015,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +86340,SEDONA,AZ,PRIMARY,538,840,12913321,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22405,FREDERICKSBURG,VA,PRIMARY,12910,24120,703269692,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +29729,RICHBURG,SC,PRIMARY,1019,1893,31572323,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +52632,KEOKUK,IA,PRIMARY,5782,10097,163052856,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10505,BALDWIN PLACE,NY,PRIMARY,563,1113,45340262,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8558,SKILLMAN,NJ,PRIMARY,3140,6048,468109768,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +73017,CEMENT,OK,PRIMARY,675,1294,19274076,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +80016,AURORA,CO,PRIMARY,17090,33336,1273315330,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +53051,MENOMONEE FALLS,WI,PRIMARY,18327,32430,952639265,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10950,MONROE,NY,PRIMARY,15249,31099,794108919,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62272,PERCY,IL,PRIMARY,692,1258,18053957,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +60022,GLENCOE,IL,PRIMARY,4281,7975,780571641,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32081,PONTE VEDRA,FL,PRIMARY,1587,3200,102959037,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +78384,SAN DIEGO,TX,PRIMARY,2344,4355,66674520,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +89041,PAHRUMP,NV,PRIMARY,2780,4623,71850383,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +10471,BRONX,NY,PRIMARY,9876,15606,623827705,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99587,GIRDWOOD,AK,PRIMARY,1306,1911,51471481,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +27205,ASHEBORO,NC,PRIMARY,13470,25331,464012531,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +61260,JOY,IL,PRIMARY,400,712,11099004,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +92261,PALM DESERT,CA,PRIMARY,1163,1814,30976723,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +82933,FORT BRIDGER,WY,PRIMARY,376,706,16480206,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +22150,SPRINGFIELD,VA,PRIMARY,13628,22990,565927238,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +71929,BISMARCK,AR,PRIMARY,1820,3420,52794110,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +8060,MOUNT HOLLY,NJ,PRIMARY,12422,21570,576915574,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +48202,DETROIT,MI,PRIMARY,5928,8794,130581093,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +35243,BIRMINGHAM,AL,PRIMARY,9194,15569,637548845,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +91711,CLAREMONT,CA,PRIMARY,15562,27155,842885054,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +62883,SCHELLER,IL,PRIMARY,294,551,9711667,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +20749,FORT WASHINGTON,MD,PRIMARY,304,487,15665381,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +32811,ORLANDO,FL,PRIMARY,16556,26038,375095638,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +39404,HATTIESBURG,MS,PRIMARY,1015,1685,32266631,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +54441,HEWITT,WI,PRIMARY,397,767,19498575,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +6811,DANBURY,CT,PRIMARY,14312,24956,817156060,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +38310,ADAMSVILLE,TN,PRIMARY,2385,4536,64717478,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +23231,HENRICO,VA,PRIMARY,16492,28091,606831085,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +17240,NEWBURG,PA,PRIMARY,1543,2880,47589961,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +99218,SPOKANE,WA,PRIMARY,5973,10594,210817301,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +11206,BROOKLYN,NY,PRIMARY,30896,50200,755431690,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +46989,UPLAND,IN,PRIMARY,1685,3128,56729502,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +13027,BALDWINSVILLE,NY,PRIMARY,15658,27650,728067119,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +56501,DETROIT LAKES,MN,PRIMARY,7471,12936,236814606,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 +24053,ARARAT,VA,PRIMARY,981,1837,23500829,2017-01-01 12:00:00+00:00,2017-01-01 12:00:00+00:00 diff --git a/ui/feature_repo/feature_store.yaml b/ui/feature_repo/feature_store.yaml new file mode 100644 index 00000000000..31b27e23857 --- /dev/null +++ b/ui/feature_repo/feature_store.yaml @@ -0,0 +1,10 @@ +registry: registry.db +project: credit_scoring_aws +provider: local +online_store: + type: sqlite +offline_store: + type: file +flags: + alpha_features: true + on_demand_transforms: true diff --git a/ui/feature_repo/features.py b/ui/feature_repo/features.py new file mode 100644 index 00000000000..8d9f5c66f14 --- /dev/null +++ b/ui/feature_repo/features.py @@ -0,0 +1,198 @@ +from datetime import timedelta + +from feast import ( + Entity, + Feature, + FeatureService, + FeatureView, + FileSource, + ValueType, +) +from feast.data_source import RequestDataSource +from feast.request_feature_view import RequestFeatureView +from feast.on_demand_feature_view import on_demand_feature_view +import pandas as pd + +zipcode = Entity( + name="zipcode", + value_type=ValueType.INT64, + description="A zipcode", + labels={"owner": "danny@tecton.ai", "team": "hack week",}, +) + +zipcode_source = FileSource( + name="zipcode", + path="data/zipcode_table.parquet", + event_timestamp_column="event_timestamp", + created_timestamp_column="created_timestamp", +) + +zipcode_features = FeatureView( + name="zipcode_features", + entities=["zipcode"], + ttl=timedelta(days=3650), + features=[ + Feature(name="city", dtype=ValueType.STRING), + Feature(name="state", dtype=ValueType.STRING), + Feature(name="location_type", dtype=ValueType.STRING), + Feature(name="tax_returns_filed", dtype=ValueType.INT64), + Feature(name="population", dtype=ValueType.INT64), + Feature(name="total_wages", dtype=ValueType.INT64), + ], + batch_source=zipcode_source, + tags={ + "date_added": "2022-02-7", + "experiments": "experiment-A,experiment-B,experiment-C", + "access_group": "feast-team@tecton.ai", + }, + online=True, +) + +zipcode_features = FeatureView( + name="zipcode_features", + entities=["zipcode"], + ttl=timedelta(days=3650), + features=[ + Feature(name="city", dtype=ValueType.STRING), + Feature(name="state", dtype=ValueType.STRING), + Feature(name="location_type", dtype=ValueType.STRING), + Feature(name="tax_returns_filed", dtype=ValueType.INT64), + Feature(name="population", dtype=ValueType.INT64), + Feature(name="total_wages", dtype=ValueType.INT64), + ], + batch_source=zipcode_source, + tags={ + "date_added": "2022-02-7", + "experiments": "experiment-A,experiment-B,experiment-C", + "access_group": "feast-team@tecton.ai", + }, + online=True, +) + +zipcode_money_features = FeatureView( + name="zipcode_money_features", + entities=["zipcode"], + ttl=timedelta(days=3650), + features=[ + Feature(name="tax_returns_filed", dtype=ValueType.INT64), + Feature(name="total_wages", dtype=ValueType.INT64), + ], + batch_source=zipcode_source, + tags={ + "date_added": "2022-02-7", + "experiments": "experiment-A,experiment-B,experiment-C", + "access_group": "feast-team@tecton.ai", + }, + online=True, +) + +dob_ssn = Entity( + name="dob_ssn", + value_type=ValueType.STRING, + description="Date of birth and last four digits of social security number", + labels={"owner": "tony@tecton.ai", "team": "hack week",}, +) + +credit_history_source = FileSource( + name="credit_history", + path="data/credit_history.parquet", + event_timestamp_column="event_timestamp", + created_timestamp_column="created_timestamp", +) + +credit_history = FeatureView( + name="credit_history", + entities=["dob_ssn"], + ttl=timedelta(days=9000), + features=[ + Feature(name="credit_card_due", dtype=ValueType.INT64), + Feature(name="mortgage_due", dtype=ValueType.INT64), + Feature(name="student_loan_due", dtype=ValueType.INT64), + Feature(name="vehicle_loan_due", dtype=ValueType.INT64), + Feature(name="hard_pulls", dtype=ValueType.INT64), + Feature(name="missed_payments_2y", dtype=ValueType.INT64), + Feature(name="missed_payments_1y", dtype=ValueType.INT64), + Feature(name="missed_payments_6m", dtype=ValueType.INT64), + Feature(name="bankruptcies", dtype=ValueType.INT64), + ], + batch_source=credit_history_source, + tags={ + "date_added": "2022-02-6", + "experiments": "experiment-A", + "access_group": "feast-team@tecton.ai", + }, + online=True, +) + +# Define a request data source which encodes features / information only +# available at request time (e.g. part of the user initiated HTTP request) +input_request = RequestDataSource( + name="transaction", schema={"transaction_amt": ValueType.INT64}, +) + +# Define an on demand feature view which can generate new features based on +# existing feature views and RequestDataSource features +@on_demand_feature_view( + inputs={"credit_history": credit_history, "transaction": input_request,}, + features=[ + Feature(name="transaction_gt_last_credit_card_due", dtype=ValueType.BOOL), + ], +) +def transaction_gt_last_credit_card_due(inputs: pd.DataFrame) -> pd.DataFrame: + df = pd.DataFrame() + df["transaction_gt_last_credit_card_due"] = ( + inputs["transaction_amt"] > inputs["credit_card_due"] + ) + return df + + +# Define request feature view +transaction_request_fv = RequestFeatureView( + name="transaction_request_fv", request_data_source=input_request, +) + +model_v1 = FeatureService( + name="credit_score_v1", + features=[ + credit_history[["mortgage_due", "credit_card_due", "missed_payments_1y"]], + zipcode_features, + ], + tags={"owner": "tony@tecton.ai", "stage": "staging"}, + description="Credit scoring model", +) + +model_v2 = FeatureService( + name="credit_score_v2", + features=[ + credit_history[["mortgage_due", "credit_card_due", "missed_payments_1y"]], + zipcode_features, + transaction_request_fv, + ], + tags={"owner": "tony@tecton.ai", "stage": "prod"}, + description="Credit scoring model", +) + +model_v3 = FeatureService( + name="credit_score_v3", + features=[ + credit_history[["mortgage_due", "credit_card_due", "missed_payments_1y"]], + zipcode_features, + transaction_gt_last_credit_card_due, + ], + tags={"owner": "tony@tecton.ai", "stage": "dev"}, + description="Credit scoring model", +) + +zipcode_model = FeatureService( + name="zipcode_model", + features=[zipcode_features,], + tags={"owner": "amanda@tecton.ai", "stage": "dev"}, + description="Location model", +) + +zipcode_model_v2 = FeatureService( + name="zipcode_model_v2", + features=[zipcode_money_features,], + tags={"owner": "amanda@tecton.ai", "stage": "dev"}, + description="Location model", +) diff --git a/ui/feature_repo/materialize.sh b/ui/feature_repo/materialize.sh new file mode 100644 index 00000000000..5702895cba7 --- /dev/null +++ b/ui/feature_repo/materialize.sh @@ -0,0 +1,4 @@ +THREE_YEAR_AGO=$(date -v-3y -u +"%Y-%m-%dT%H:%M:%S") +feast materialize-incremental $THREE_YEAR_AGO +CURRENT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%S") +feast materialize-incremental $CURRENT_TIME \ No newline at end of file diff --git a/ui/feature_repo/my_training_ds.parquet b/ui/feature_repo/my_training_ds.parquet new file mode 100644 index 00000000000..614bb424d9a Binary files /dev/null and b/ui/feature_repo/my_training_ds.parquet differ diff --git a/ui/feature_repo/test_get_features.py b/ui/feature_repo/test_get_features.py new file mode 100644 index 00000000000..42af53e94b8 --- /dev/null +++ b/ui/feature_repo/test_get_features.py @@ -0,0 +1,87 @@ +import pandas as pd +from feast import FeatureStore +from feast.infra.offline_stores.file import SavedDatasetFileStorage + +from feast.dqm.profilers.ge_profiler import ge_profiler + +from great_expectations.core.expectation_suite import ExpectationSuite +from great_expectations.dataset import PandasDataset + +DELTA = 0.1 # controlling allowed window in fraction of the value on scale [0, 1] +# Note: the GE integration allows asserting differences between datasets. The "ds" below is the reference dataset to check and this generates the expectation suite which can be used against future datasets. +# It's used via ge.validate(new_dataset, ExpectationSuite) +# For this demo though, we ignore this and + + +@ge_profiler +def credit_profiler(ds: PandasDataset) -> ExpectationSuite: + # simple checks on data consistency + ds.expect_column_values_to_be_between( + "credit_card_due", min_value=0, mostly=0.99, # allow some outliers + ) + + ds.expect_column_values_to_be_between( + "missed_payments_1y", + min_value=0, + max_value=5, + mostly=0.99, # allow some outliers + ) + + return ds.get_expectation_suite() + + +def generate_saved_dataset(): + store = FeatureStore(repo_path=".") + entity_df = pd.read_parquet(path="data/loan_table.parquet") + + fs = store.get_feature_service("credit_score_v1") + job = store.get_historical_features(entity_df=entity_df, features=fs,) + store.create_saved_dataset( + from_=job, + name="my_training_ds", + storage=SavedDatasetFileStorage(path="my_training_ds.parquet"), + feature_service=fs, + profiler=credit_profiler, + ) + + +def get_latest_timestamps(): + store = FeatureStore(repo_path=".") + feature_views = store.list_feature_views() + for fv in feature_views: + print( + f"Data source latest event for {fv.name} is {fv.batch_source._meta.latest_event_timestamp}" + ) + + +def test_ge(): + store = FeatureStore(repo_path=".") + + print("--- Historical features (from saved dataset) ---") + ds = store.get_saved_dataset("my_training_ds") + print(ds._profile) + + +def run_demo(): + store = FeatureStore(repo_path=".") + + print("--- Historical features (from saved dataset) ---") + ds = store.get_saved_dataset("my_training_ds") + print(ds.to_df()) + + print("\n--- Online features ---") + features = store.get_online_features( + features=store.get_feature_service("credit_score_v3"), + entity_rows=[ + {"zipcode": 30721, "dob_ssn": "19530219_5179", "transaction_amt": 1023} + ], + ).to_dict() + for key, value in sorted(features.items()): + print(key, " : ", value) + + +if __name__ == "__main__": + generate_saved_dataset() + get_latest_timestamps() + # test_ge() + run_demo() diff --git a/ui/package.json b/ui/package.json new file mode 100644 index 00000000000..f53ea7ce6df --- /dev/null +++ b/ui/package.json @@ -0,0 +1,64 @@ +{ + "name": "feast-ui", + "version": "0.1.0", + "private": true, + "dependencies": { + "@elastic/datemath": "^5.0.3", + "@elastic/eui": "^50.0.0", + "@emotion/react": "^11.8.1", + "@testing-library/jest-dom": "^5.16.2", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^13.5.0", + "@types/d3": "^7.1.0", + "@types/jest": "^27.4.1", + "@types/node": "^17.0.21", + "@types/react": "^17.0.39", + "@types/react-dom": "^17.0.13", + "d3": "^7.3.0", + "inter-ui": "^3.19.3", + "moment": "^2.29.1", + "prop-types": "^15.8.1", + "query-string": "^7.1.1", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-query": "^3.34.16", + "react-router-dom": "6", + "react-scripts": "5.0.0", + "typescript": "^4.6.2", + "use-query-params": "^1.2.3", + "web-vitals": "^2.1.4", + "zod": "^3.13.4" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "jest": { + "moduleNameMapper": { + "d3": "/node_modules/d3/dist/d3.min.js" + } + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "msw": "^0.38.2" + } +} diff --git a/ui/public/data.json b/ui/public/data.json new file mode 100644 index 00000000000..3fd16300221 --- /dev/null +++ b/ui/public/data.json @@ -0,0 +1,6 @@ +[ + { "name": "basketball", "league": "NBA" }, + { "name": "hockey", "league": "NHL" }, + { "name": "football", "league": "UEFA" }, + { "name": "baseball", "league": "MLB" } +] diff --git a/ui/public/demo-custom-tabs/demo.json b/ui/public/demo-custom-tabs/demo.json new file mode 100644 index 00000000000..5b0162a496b --- /dev/null +++ b/ui/public/demo-custom-tabs/demo.json @@ -0,0 +1,4 @@ +{ + "hello": "world", + "name": "Feast" +} diff --git a/ui/public/empty_registry.json b/ui/public/empty_registry.json new file mode 100644 index 00000000000..2ac5ef3eab1 --- /dev/null +++ b/ui/public/empty_registry.json @@ -0,0 +1,3 @@ +{ + "project": "empty_registry" +} diff --git a/ui/public/favicon.ico b/ui/public/favicon.ico new file mode 100644 index 00000000000..a11777cc471 Binary files /dev/null and b/ui/public/favicon.ico differ diff --git a/ui/public/feast-favicon-300x300.png b/ui/public/feast-favicon-300x300.png new file mode 100644 index 00000000000..e9f43491f6b Binary files /dev/null and b/ui/public/feast-favicon-300x300.png differ diff --git a/ui/public/feast-favicon-36x36.png b/ui/public/feast-favicon-36x36.png new file mode 100644 index 00000000000..ed39c60c1bf Binary files /dev/null and b/ui/public/feast-favicon-36x36.png differ diff --git a/ui/public/index.html b/ui/public/index.html new file mode 100644 index 00000000000..59d14d1959e --- /dev/null +++ b/ui/public/index.html @@ -0,0 +1,46 @@ + + + + + + + + + + + + + Feast Feature Store + + + +
+ + + diff --git a/ui/public/logo192.png b/ui/public/logo192.png new file mode 100644 index 00000000000..fc44b0a3796 Binary files /dev/null and b/ui/public/logo192.png differ diff --git a/ui/public/logo512.png b/ui/public/logo512.png new file mode 100644 index 00000000000..a4e47a6545b Binary files /dev/null and b/ui/public/logo512.png differ diff --git a/ui/public/manifest.json b/ui/public/manifest.json new file mode 100644 index 00000000000..080d6c77ac2 --- /dev/null +++ b/ui/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/ui/public/metadata/credit_score_project/featureView/credit_history.json b/ui/public/metadata/credit_score_project/featureView/credit_history.json new file mode 100644 index 00000000000..7e88efd80a4 --- /dev/null +++ b/ui/public/metadata/credit_score_project/featureView/credit_history.json @@ -0,0 +1,185 @@ +{ + "columnsSummaryStatistics": { + "credit_card_due": { + "name": "credit_card_due", + "valueType": "INT64", + "sampleValues": [1, 2, 3], + "histogram": [ + { "x0": 0, "x1": 0.1, "count": 35 }, + { "x0": 0.1, "x1": 0.2, "count": 8 }, + { "x0": 0.2, "x1": 0.3, "count": 5 }, + { "x0": 0.3, "x1": 0.4, "count": 3 }, + { "x0": 0.4, "x1": 0.5, "count": 2 }, + { "x0": 0.5, "x1": 0.6, "count": 1 }, + { "x0": 0.6, "x1": 0.7, "count": 0 }, + { "x0": 0.7, "x1": 0.8, "count": 1 }, + { "x0": 0.8, "x1": 0.9, "count": 2 }, + { "x0": 0.9, "x1": 1, "count": 1 } + ], + "proportionOfZeros": 0.01, + "proportionMissing": 0.01, + "min": 0, + "max": 12 + }, + "mortgage_due": { + "name": "mortgage_due", + "valueType": "INT64", + "sampleValues": [4, 6, 8], + "histogram": [ + { "x0": 0, "x1": 0.1, "count": 35 }, + { "x0": 0.1, "x1": 0.2, "count": 8 }, + { "x0": 0.2, "x1": 0.3, "count": 5 }, + { "x0": 0.3, "x1": 0.4, "count": 3 }, + { "x0": 0.4, "x1": 0.5, "count": 2 }, + { "x0": 0.5, "x1": 0.6, "count": 1 }, + { "x0": 0.6, "x1": 0.7, "count": 0 }, + { "x0": 0.7, "x1": 0.8, "count": 1 }, + { "x0": 0.8, "x1": 0.9, "count": 2 }, + { "x0": 0.9, "x1": 1, "count": 1 } + ], + "proportionOfZeros": 0.01, + "proportionMissing": 0.01, + "min": 0, + "max": 12 + }, + "student_loan_due": { + "name": "student_loan_due", + "valueType": "INT64", + "sampleValues": [0, 1, 3], + "histogram": [ + { "x0": 0, "x1": 0.1, "count": 35 }, + { "x0": 0.1, "x1": 0.2, "count": 8 }, + { "x0": 0.2, "x1": 0.3, "count": 5 }, + { "x0": 0.3, "x1": 0.4, "count": 3 }, + { "x0": 0.4, "x1": 0.5, "count": 2 }, + { "x0": 0.5, "x1": 0.6, "count": 1 }, + { "x0": 0.6, "x1": 0.7, "count": 0 }, + { "x0": 0.7, "x1": 0.8, "count": 1 }, + { "x0": 0.8, "x1": 0.9, "count": 2 }, + { "x0": 0.9, "x1": 1, "count": 1 } + ], + "proportionOfZeros": 0.01, + "proportionMissing": 0.01, + "min": 0, + "max": 12 + }, + "vehicle_loan_due": { + "name": "vehicle_loan_due", + "valueType": "INT64", + "sampleValues": [2, 1, 0], + "histogram": [ + { "x0": 0, "x1": 0.1, "count": 35 }, + { "x0": 0.1, "x1": 0.2, "count": 8 }, + { "x0": 0.2, "x1": 0.3, "count": 5 }, + { "x0": 0.3, "x1": 0.4, "count": 3 }, + { "x0": 0.4, "x1": 0.5, "count": 2 }, + { "x0": 0.5, "x1": 0.6, "count": 1 }, + { "x0": 0.6, "x1": 0.7, "count": 0 }, + { "x0": 0.7, "x1": 0.8, "count": 1 }, + { "x0": 0.8, "x1": 0.9, "count": 2 }, + { "x0": 0.9, "x1": 1, "count": 1 } + ] + }, + "hard_pulls": { + "name": "hard_pulls", + "valueType": "INT64", + "sampleValues": [0, 9, 12], + "histogram": [ + { "x0": 0, "x1": 0.1, "count": 35 }, + { "x0": 0.1, "x1": 0.2, "count": 8 }, + { "x0": 0.2, "x1": 0.3, "count": 5 }, + { "x0": 0.3, "x1": 0.4, "count": 3 }, + { "x0": 0.4, "x1": 0.5, "count": 2 }, + { "x0": 0.5, "x1": 0.6, "count": 1 }, + { "x0": 0.6, "x1": 0.7, "count": 0 }, + { "x0": 0.7, "x1": 0.8, "count": 1 }, + { "x0": 0.8, "x1": 0.9, "count": 2 }, + { "x0": 0.9, "x1": 1, "count": 1 } + ], + "proportionOfZeros": 0.01, + "proportionMissing": 0.01, + "min": 0, + "max": 12 + }, + "missed_payments_2y": { + "name": "missed_payments_2y", + "valueType": "INT64", + "sampleValues": [0, 1, 3], + "histogram": [ + { "x0": 0, "x1": 0.1, "count": 35 }, + { "x0": 0.1, "x1": 0.2, "count": 8 }, + { "x0": 0.2, "x1": 0.3, "count": 5 }, + { "x0": 0.3, "x1": 0.4, "count": 3 }, + { "x0": 0.4, "x1": 0.5, "count": 2 }, + { "x0": 0.5, "x1": 0.6, "count": 1 }, + { "x0": 0.6, "x1": 0.7, "count": 0 }, + { "x0": 0.7, "x1": 0.8, "count": 1 }, + { "x0": 0.8, "x1": 0.9, "count": 2 }, + { "x0": 0.9, "x1": 1, "count": 1 } + ], + "proportionOfZeros": 0.01, + "proportionMissing": 0.01, + "min": 0, + "max": 12 + }, + "missed_payments_1y": { + "name": "missed_payments_1y", + "valueType": "INT64", + "sampleValues": [0, 1, 3], + "histogram": [ + { "x0": 0, "x1": 0.1, "count": 35 }, + { "x0": 0.1, "x1": 0.2, "count": 8 }, + { "x0": 0.2, "x1": 0.3, "count": 5 }, + { "x0": 0.3, "x1": 0.4, "count": 3 }, + { "x0": 0.4, "x1": 0.5, "count": 2 }, + { "x0": 0.5, "x1": 0.6, "count": 1 }, + { "x0": 0.6, "x1": 0.7, "count": 0 }, + { "x0": 0.7, "x1": 0.8, "count": 1 }, + { "x0": 0.8, "x1": 0.9, "count": 2 }, + { "x0": 0.9, "x1": 1, "count": 1 } + ], + "proportionOfZeros": 0.01, + "proportionMissing": 0.01, + "min": 0, + "max": 12 + }, + "missed_payments_6m": { + "name": "missed_payments_6m", + "valueType": "INT64", + "sampleValues": [0, 1, 3], + "histogram": [ + { "x0": 0, "x1": 0.1, "count": 35 }, + { "x0": 0.1, "x1": 0.2, "count": 8 }, + { "x0": 0.2, "x1": 0.3, "count": 5 }, + { "x0": 0.3, "x1": 0.4, "count": 3 }, + { "x0": 0.4, "x1": 0.5, "count": 2 }, + { "x0": 0.5, "x1": 0.6, "count": 1 }, + { "x0": 0.6, "x1": 0.7, "count": 0 }, + { "x0": 0.7, "x1": 0.8, "count": 1 }, + { "x0": 0.8, "x1": 0.9, "count": 2 }, + { "x0": 0.9, "x1": 1, "count": 1 } + ] + }, + "bankruptcies": { + "name": "bankruptcies", + "valueType": "INT64", + "sampleValues": [0, 1, 3], + "histogram": [ + { "x0": 0, "x1": 0.1, "count": 35 }, + { "x0": 0.1, "x1": 0.2, "count": 8 }, + { "x0": 0.2, "x1": 0.3, "count": 5 }, + { "x0": 0.3, "x1": 0.4, "count": 3 }, + { "x0": 0.4, "x1": 0.5, "count": 2 }, + { "x0": 0.5, "x1": 0.6, "count": 1 }, + { "x0": 0.6, "x1": 0.7, "count": 0 }, + { "x0": 0.7, "x1": 0.8, "count": 1 }, + { "x0": 0.8, "x1": 0.9, "count": 2 }, + { "x0": 0.9, "x1": 1, "count": 1 } + ], + "proportionOfZeros": 0.01, + "proportionMissing": 0.01, + "min": 0, + "max": 12 + } + } +} diff --git a/ui/public/projects-list.json b/ui/public/projects-list.json new file mode 100644 index 00000000000..d3d7c3b7d91 --- /dev/null +++ b/ui/public/projects-list.json @@ -0,0 +1,16 @@ +{ + "projects": [ + { + "name": "Credit Score Project", + "description": "Project for credit scoring team and associated models.", + "id": "credit_score_project", + "registryPath": "/registry.json" + }, + { + "name": "Empty Registry", + "description": "Testing how things look when the registry is empty", + "id": "empty_registry", + "registryPath": "/empty_registry.json" + } + ] +} diff --git a/ui/public/registry.json b/ui/public/registry.json new file mode 100644 index 00000000000..024fb1ac194 --- /dev/null +++ b/ui/public/registry.json @@ -0,0 +1,789 @@ +{ + "project": "credit_scoring_aws", + "dataSources": [ + { + "type": "BATCH_FILE", + "eventTimestampColumn": "event_timestamp", + "createdTimestampColumn": "created_timestamp", + "fileOptions": { + "fileUrl": "data/credit_history.parquet" + }, + "name": "credit_history", + "meta": { + "latestEventTimestamp": "2021-08-29T22:01:04.746575Z", + "earliestEventTimestamp": "2020-04-26T22:01:04.746575Z" + } + }, + { + "type": "REQUEST_SOURCE", + "requestDataOptions": { + "schema": { + "transaction_amt": "INT64" + } + }, + "name": "transaction" + }, + { + "type": "BATCH_FILE", + "eventTimestampColumn": "event_timestamp", + "createdTimestampColumn": "created_timestamp", + "fileOptions": { + "fileUrl": "data/zipcode_table.parquet" + }, + "name": "zipcode", + "meta": { + "latestEventTimestamp": "2017-01-01T12:00:00Z", + "earliestEventTimestamp": "2017-01-01T12:00:00Z" + } + } + ], + "entities": [ + { + "spec": { + "name": "__dummy", + "valueType": "STRING", + "joinKey": "__dummy_id" + }, + "meta": { + "createdTimestamp": "2022-02-09T20:40:53.101387Z", + "lastUpdatedTimestamp": "2022-02-09T20:40:53.101387Z" + } + }, + { + "spec": { + "name": "dob_ssn", + "valueType": "STRING", + "description": "Date of birth and last four digits of social security number", + "joinKey": "dob_ssn", + "labels": { + "team": "hack week", + "owner": "tony@tecton.ai" + } + }, + "meta": { + "createdTimestamp": "2022-02-09T20:40:53.101256Z", + "lastUpdatedTimestamp": "2022-02-09T20:40:53.101256Z" + } + }, + { + "spec": { + "name": "zipcode", + "valueType": "INT64", + "description": "A zipcode", + "joinKey": "zipcode", + "labels": { + "owner": "danny@tecton.ai", + "team": "hack week" + } + }, + "meta": { + "createdTimestamp": "2022-02-09T20:40:53.101335Z", + "lastUpdatedTimestamp": "2022-02-09T20:40:53.101335Z" + } + } + ], + "featureViews": [ + { + "spec": { + "name": "credit_history", + "entities": ["dob_ssn"], + "features": [ + { + "name": "credit_card_due", + "valueType": "INT64" + }, + { + "name": "mortgage_due", + "valueType": "INT64" + }, + { + "name": "student_loan_due", + "valueType": "INT64" + }, + { + "name": "vehicle_loan_due", + "valueType": "INT64" + }, + { + "name": "hard_pulls", + "valueType": "INT64" + }, + { + "name": "missed_payments_2y", + "valueType": "INT64" + }, + { + "name": "missed_payments_1y", + "valueType": "INT64" + }, + { + "name": "missed_payments_6m", + "valueType": "INT64" + }, + { + "name": "bankruptcies", + "valueType": "INT64" + } + ], + "tags": { + "access_group": "feast-team@tecton.ai", + "experiments": "experiment-A", + "date_added": "2022-02-6" + }, + "ttl": "777600000s", + "batchSource": { + "type": "BATCH_FILE", + "eventTimestampColumn": "event_timestamp", + "createdTimestampColumn": "created_timestamp", + "fileOptions": { + "fileUrl": "data/credit_history.parquet" + }, + "dataSourceClassType": "feast.infra.offline_stores.file_source.FileSource", + "name": "credit_history", + "meta": { + "latestEventTimestamp": "2021-08-29T22:01:04.746575Z", + "earliestEventTimestamp": "2020-04-26T22:01:04.746575Z" + } + }, + "online": true + }, + "meta": { + "createdTimestamp": "2022-02-09T20:40:53.101460Z", + "lastUpdatedTimestamp": "2022-02-11T20:15:13.735432Z", + "materializationIntervals": [ + { + "startTime": "1997-06-20T20:41:14.456417Z", + "endTime": "2019-02-09T20:41:11Z" + }, + { + "startTime": "2019-02-09T20:41:11Z", + "endTime": "2022-02-09T20:42:03Z" + }, + { + "startTime": "2022-02-09T20:42:03Z", + "endTime": "2022-02-11T00:18:02Z" + } + ] + } + }, + { + "spec": { + "name": "zipcode_features", + "entities": ["zipcode"], + "features": [ + { + "name": "city", + "valueType": "STRING" + }, + { + "name": "state", + "valueType": "STRING" + }, + { + "name": "location_type", + "valueType": "STRING" + }, + { + "name": "tax_returns_filed", + "valueType": "INT64" + }, + { + "name": "population", + "valueType": "INT64" + }, + { + "name": "total_wages", + "valueType": "INT64" + } + ], + "tags": { + "experiments": "experiment-A,experiment-B,experiment-C", + "date_added": "2022-02-7", + "access_group": "feast-team@tecton.ai" + }, + "ttl": "315360000s", + "batchSource": { + "type": "BATCH_FILE", + "eventTimestampColumn": "event_timestamp", + "createdTimestampColumn": "created_timestamp", + "fileOptions": { + "fileUrl": "data/zipcode_table.parquet" + }, + "dataSourceClassType": "feast.infra.offline_stores.file_source.FileSource", + "name": "zipcode", + "meta": { + "latestEventTimestamp": "2017-01-01T12:00:00Z", + "earliestEventTimestamp": "2017-01-01T12:00:00Z" + } + }, + "online": true + }, + "meta": { + "createdTimestamp": "2022-02-11T20:12:50.182923Z", + "lastUpdatedTimestamp": "2022-02-11T20:15:21.790447Z" + } + }, + { + "spec": { + "name": "zipcode_money_features", + "entities": ["zipcode"], + "features": [ + { + "name": "tax_returns_filed", + "valueType": "INT64" + }, + { + "name": "total_wages", + "valueType": "INT64" + } + ], + "tags": { + "experiments": "experiment-A,experiment-B,experiment-C", + "access_group": "feast-team@tecton.ai", + "date_added": "2022-02-7", + "test_apple": "2022-02-7", + "test_banana": "2022-02-7", + "test_cherry": "2022-02-7", + "test_danish": "2022-02-7", + "test_eggplant": "2022-02-7", + "test_figs": "2022-02-7", + "test_grape": "2022-02-7", + "test_honey": "2022-02-7", + "test_ice": "2022-02-7", + "test_jackfruit": "2022-02-7", + "test_kiwi_fruit": "2022-02-7", + "test_lychee": "2022-02-7", + "test_mango": "2022-02-7", + "test_orange": "2022-02-7", + "test_peach": "2022-02-7", + "test_question": "2022-02-7", + "test_ruby": "2022-02-7", + "test_starfruit": "2022-02-7", + "test_tamarind": "2022-02-7" + }, + "ttl": "315360000s", + "batchSource": { + "type": "BATCH_FILE", + "eventTimestampColumn": "event_timestamp", + "createdTimestampColumn": "created_timestamp", + "fileOptions": { + "fileUrl": "data/zipcode_table.parquet" + }, + "dataSourceClassType": "feast.infra.offline_stores.file_source.FileSource", + "name": "zipcode", + "meta": { + "latestEventTimestamp": "2017-01-01T12:00:00Z", + "earliestEventTimestamp": "2017-01-01T12:00:00Z" + } + }, + "online": true + }, + "meta": { + "createdTimestamp": "2022-02-11T20:10:53.228047Z", + "lastUpdatedTimestamp": "2022-02-11T20:15:15.949101Z" + } + } + ], + "featureServices": [ + { + "spec": { + "name": "credit_score_v1", + "features": [ + { + "featureViewName": "credit_history", + "featureColumns": [ + { + "name": "credit_card_due", + "valueType": "INT64" + }, + { + "name": "mortgage_due", + "valueType": "INT64" + }, + { + "name": "missed_payments_1y", + "valueType": "INT64" + } + ] + }, + { + "featureViewName": "zipcode_features", + "featureColumns": [ + { + "name": "city", + "valueType": "STRING" + }, + { + "name": "state", + "valueType": "STRING" + }, + { + "name": "location_type", + "valueType": "STRING" + }, + { + "name": "tax_returns_filed", + "valueType": "INT64" + }, + { + "name": "population", + "valueType": "INT64" + }, + { + "name": "total_wages", + "valueType": "INT64" + } + ] + } + ], + "tags": { + "owner": "tony@tecton.ai", + "stage": "staging" + }, + "description": "Credit scoring model" + }, + "meta": { + "createdTimestamp": "2022-02-11T20:12:50.186773Z" + } + }, + { + "spec": { + "name": "credit_score_v2", + "features": [ + { + "featureViewName": "credit_history", + "featureColumns": [ + { + "name": "credit_card_due", + "valueType": "INT64" + }, + { + "name": "mortgage_due", + "valueType": "INT64" + }, + { + "name": "missed_payments_1y", + "valueType": "INT64" + } + ] + }, + { + "featureViewName": "zipcode_features", + "featureColumns": [ + { + "name": "city", + "valueType": "STRING" + }, + { + "name": "state", + "valueType": "STRING" + }, + { + "name": "location_type", + "valueType": "STRING" + }, + { + "name": "tax_returns_filed", + "valueType": "INT64" + }, + { + "name": "population", + "valueType": "INT64" + }, + { + "name": "total_wages", + "valueType": "INT64" + } + ] + }, + { + "featureViewName": "transaction_request_fv", + "featureColumns": [ + { + "name": "transaction_amt", + "valueType": "INT64" + } + ] + } + ], + "tags": { + "stage": "prod", + "owner": "tony@tecton.ai" + }, + "description": "Credit scoring model" + }, + "meta": { + "createdTimestamp": "2022-02-11T20:12:50.185785Z" + } + }, + { + "spec": { + "name": "credit_score_v3", + "features": [ + { + "featureViewName": "credit_history", + "featureColumns": [ + { + "name": "credit_card_due", + "valueType": "INT64" + }, + { + "name": "mortgage_due", + "valueType": "INT64" + }, + { + "name": "missed_payments_1y", + "valueType": "INT64" + } + ] + }, + { + "featureViewName": "zipcode_features", + "featureColumns": [ + { + "name": "city", + "valueType": "STRING" + }, + { + "name": "state", + "valueType": "STRING" + }, + { + "name": "location_type", + "valueType": "STRING" + }, + { + "name": "tax_returns_filed", + "valueType": "INT64" + }, + { + "name": "population", + "valueType": "INT64" + }, + { + "name": "total_wages", + "valueType": "INT64" + } + ] + }, + { + "featureViewName": "transaction_gt_last_credit_card_due", + "featureColumns": [ + { + "name": "transaction_gt_last_credit_card_due", + "valueType": "BOOL" + } + ] + } + ], + "tags": { + "stage": "dev", + "owner": "tony@tecton.ai" + }, + "description": "Credit scoring model" + }, + "meta": { + "createdTimestamp": "2022-02-11T20:12:50.186367Z" + } + }, + { + "spec": { + "name": "zipcode_model", + "features": [ + { + "featureViewName": "zipcode_features", + "featureColumns": [ + { + "name": "city", + "valueType": "STRING" + }, + { + "name": "state", + "valueType": "STRING" + }, + { + "name": "location_type", + "valueType": "STRING" + }, + { + "name": "tax_returns_filed", + "valueType": "INT64" + }, + { + "name": "population", + "valueType": "INT64" + }, + { + "name": "total_wages", + "valueType": "INT64" + } + ] + } + ], + "tags": { + "stage": "dev", + "owner": "amanda@tecton.ai" + }, + "description": "Location model" + }, + "meta": { + "createdTimestamp": "2022-02-11T20:12:50.187069Z" + } + }, + { + "spec": { + "name": "zipcode_model_v2", + "features": [ + { + "featureViewName": "zipcode_money_features", + "featureColumns": [ + { + "name": "tax_returns_filed", + "valueType": "INT64" + }, + { + "name": "total_wages", + "valueType": "INT64" + } + ] + } + ], + "tags": { + "owner": "amanda@tecton.ai", + "stage": "dev" + }, + "description": "Location model" + }, + "meta": { + "createdTimestamp": "2022-02-11T20:17:15.582561Z" + } + } + ], + "onDemandFeatureViews": [ + { + "spec": { + "name": "transaction_gt_last_credit_card_due", + "features": [ + { + "name": "transaction_gt_last_credit_card_due", + "valueType": "BOOL" + } + ], + "inputs": { + "transaction": { + "requestDataSource": { + "type": "REQUEST_SOURCE", + "requestDataOptions": { + "schema": { + "transaction_amt": "INT64" + } + }, + "name": "transaction" + } + }, + "credit_history": { + "featureViewProjection": { + "featureViewName": "credit_history", + "featureColumns": [ + { + "name": "credit_card_due", + "valueType": "INT64" + }, + { + "name": "mortgage_due", + "valueType": "INT64" + }, + { + "name": "student_loan_due", + "valueType": "INT64" + }, + { + "name": "vehicle_loan_due", + "valueType": "INT64" + }, + { + "name": "hard_pulls", + "valueType": "INT64" + }, + { + "name": "missed_payments_2y", + "valueType": "INT64" + }, + { + "name": "missed_payments_1y", + "valueType": "INT64" + }, + { + "name": "missed_payments_6m", + "valueType": "INT64" + }, + { + "name": "bankruptcies", + "valueType": "INT64" + } + ] + } + } + }, + "userDefinedFunction": { + "name": "transaction_gt_last_credit_card_due", + "body": "@on_demand_feature_view(\n inputs={\"credit_history\": credit_history, \"transaction\": input_request,},\n features=[\n Feature(name=\"transaction_gt_last_credit_card_due\", dtype=ValueType.BOOL),\n ],\n)\ndef transaction_gt_last_credit_card_due(inputs: pd.DataFrame) -> pd.DataFrame:\n df = pd.DataFrame()\n df[\"transaction_gt_last_credit_card_due\"] = (\n inputs[\"transaction_amt\"] > inputs[\"credit_card_due\"]\n )\n return df\n" + } + }, + "meta": { + "createdTimestamp": "2022-02-11T20:17:15.581514Z", + "lastUpdatedTimestamp": "2022-02-11T20:17:15.581514Z" + } + } + ], + "requestFeatureViews": [ + { + "spec": { + "name": "transaction_request_fv", + "requestDataSource": { + "type": "REQUEST_SOURCE", + "requestDataOptions": { + "schema": { + "transaction_amt": "INT64" + } + }, + "name": "transaction" + } + } + } + ], + "savedDatasets": [ + { + "spec": { + "name": "my_training_ds", + "features": [ + "credit_history:credit_card_due", + "credit_history:mortgage_due", + "credit_history:missed_payments_1y", + "zipcode_features:city", + "zipcode_features:state", + "zipcode_features:location_type", + "zipcode_features:tax_returns_filed", + "zipcode_features:population", + "zipcode_features:total_wages" + ], + "joinKeys": [ + "person_income", + "person_emp_length", + "created_timestamp", + "zipcode", + "person_home_ownership", + "loan_amnt", + "person_age", + "loan_int_rate", + "loan_status", + "loan_id", + "dob_ssn", + "loan_intent" + ], + "storage": { + "fileStorage": { + "fileFormat": { + "parquetFormat": {} + }, + "fileUrl": "my_training_ds.parquet" + } + }, + "featureService": { + "spec": { + "name": "credit_score_v1", + "features": [ + { + "featureViewName": "credit_history", + "featureColumns": [ + { + "name": "credit_card_due", + "valueType": "INT64" + }, + { + "name": "mortgage_due", + "valueType": "INT64" + }, + { + "name": "missed_payments_1y", + "valueType": "INT64" + } + ] + }, + { + "featureViewName": "zipcode_features", + "featureColumns": [ + { + "name": "city", + "valueType": "STRING" + }, + { + "name": "state", + "valueType": "STRING" + }, + { + "name": "location_type", + "valueType": "STRING" + }, + { + "name": "tax_returns_filed", + "valueType": "INT64" + }, + { + "name": "population", + "valueType": "INT64" + }, + { + "name": "total_wages", + "valueType": "INT64" + } + ] + } + ], + "tags": { + "stage": "staging", + "owner": "tony@tecton.ai" + }, + "description": "Credit scoring model" + }, + "meta": { + "createdTimestamp": "2022-02-09T20:40:53.103078Z" + } + }, + "profile": "{\"meta\": {\"great_expectations_version\": \"0.14.4\"}, \"expectations\": [{\"meta\": {}, \"kwargs\": {\"column\": \"credit_card_due\", \"min_value\": 0, \"mostly\": 0.99}, \"expectation_type\": \"expect_column_values_to_be_between\"}, {\"meta\": {}, \"kwargs\": {\"column\": \"missed_payments_1y\", \"min_value\": 0, \"max_value\": 5, \"mostly\": 0.99}, \"expectation_type\": \"expect_column_values_to_be_between\"}], \"data_asset_type\": \"Dataset\", \"expectation_suite_name\": \"default\", \"ge_cloud_id\": null}" + }, + "meta": { + "createdTimestamp": "2022-02-09T20:44:03.377806Z", + "minEventTimestamp": "2020-08-25T20:34:41.361Z", + "maxEventTimestamp": "2021-08-25T20:34:41.361Z" + } + } + ], + "infra": [ + { + "infraObjects": [ + { + "infraObjectClassType": "feast.infra.online_stores.sqlite.SqliteTable", + "sqliteTable": { + "path": "/Users/dannychiao/GitHub/feast-ui/feature_repo/data/online.db", + "name": "credit_scoring_aws_credit_history" + } + }, + { + "infraObjectClassType": "feast.infra.online_stores.sqlite.SqliteTable", + "sqliteTable": { + "path": "/Users/dannychiao/GitHub/feast-ui/feature_repo/data/online.db", + "name": "credit_scoring_aws_zipcode_features" + } + }, + { + "infraObjectClassType": "feast.infra.online_stores.sqlite.SqliteTable", + "sqliteTable": { + "path": "/Users/dannychiao/GitHub/feast-ui/feature_repo/data/online.db", + "name": "credit_scoring_aws_zipcode_money_features" + } + } + ] + } + ] +} diff --git a/ui/public/robots.txt b/ui/public/robots.txt new file mode 100644 index 00000000000..e9e57dc4d41 --- /dev/null +++ b/ui/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/ui/sample.png b/ui/sample.png new file mode 100644 index 00000000000..360d57186d3 Binary files /dev/null and b/ui/sample.png differ diff --git a/ui/src/App.css b/ui/src/App.css new file mode 100644 index 00000000000..47655db950b --- /dev/null +++ b/ui/src/App.css @@ -0,0 +1,4 @@ +html { + background: url("feast-icon-white.svg") no-repeat bottom left; + background-size: 20vh; +} diff --git a/ui/src/App.test.tsx b/ui/src/App.test.tsx new file mode 100644 index 00000000000..fa6df6ebc53 --- /dev/null +++ b/ui/src/App.test.tsx @@ -0,0 +1,96 @@ +import React from "react"; + +import { setupServer } from "msw/node"; +import { render } from "./test-utils"; +import { + waitFor, + screen, + waitForElementToBeRemoved, +} from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; + +import App from "./App"; +import { + projectsListWithDefaultProject, + creditHistoryRegistry, +} from "./mocks/handlers"; + +import registry from "../public/registry.json"; + +// declare which API requests to mock +const server = setupServer( + projectsListWithDefaultProject, + creditHistoryRegistry +); + +// establish API mocking before all tests +beforeAll(() => server.listen()); +// reset any request handlers that are declared as a part of our tests +// (i.e. for testing one-time error scenarios) +afterEach(() => server.resetHandlers()); +// clean up once the tests are done +afterAll(() => server.close()); + +test("full app rendering", async () => { + render(); + + // Rendering the app without any paths should mean + // rendering the + // Therefore we should expect to see + // "Welcome to Feast." + const noProjectSelectedElement = screen.getByText(/Welcome to Feast/i); + + expect(noProjectSelectedElement).toBeInTheDocument(); + + // Wait for the Redirect, and check that it got removed + await waitForElementToBeRemoved(noProjectSelectedElement); + + expect(screen.queryByText(/Welcome to Feast/i)).toBeNull(); + + // Explore Panel Should Appear + expect(screen.getByText(/Explore this Project/i)).toBeInTheDocument(); + + const projectNameRegExp = new RegExp(registry.project, "i"); + + // It should load the default project, which is credit_scoring_aws + await waitFor(() => { + expect(screen.getByText(projectNameRegExp)).toBeInTheDocument(); + }); +}); + +const leftClick = { button: 0 }; + +test("routes are reachable", async () => { + render(); + + // Wait for content to load + await screen.findByText(/Explore this Project/i); + + const mainRoutesNames = [ + "Data Sources", + "Entities", + "Feature Views", + "Feature Services", + "Datasets", + ]; + + for (const routeName of mainRoutesNames) { + // Main heading shouldn't start with the route name + expect( + screen.queryByRole("heading", { name: routeName, level: 1 }) + ).toBeNull(); + + const routeRegExp = new RegExp(routeName, "i"); + + userEvent.click( + screen.getByRole("button", { name: routeRegExp }), + leftClick + ); + + // Should land on a page with the heading + screen.getByRole("heading", { + name: routeName, + level: 1, + }); + } +}); diff --git a/ui/src/App.tsx b/ui/src/App.tsx new file mode 100644 index 00000000000..f93c7c314fe --- /dev/null +++ b/ui/src/App.tsx @@ -0,0 +1,62 @@ +import React from "react"; +import "inter-ui/inter.css"; +import "@elastic/eui/dist/eui_theme_light.css"; + +import { EuiProvider } from "@elastic/eui"; +import ProjectOverviewPage from "./pages/ProjectOverviewPage"; +import { Route, Routes } from "react-router"; +import Layout from "./pages/Layout"; +import NoMatch from "./pages/NoMatch"; +import DatasourceIndex from "./pages/data-sources/Index"; +import DatasetIndex from "./pages/saved-data-sets/Index"; +import EntityIndex from "./pages/entities/Index"; +import EntityInstance from "./pages/entities/EntityInstance"; +import FeatureServiceIndex from "./pages/feature-services/Index"; +import FeatureViewIndex from "./pages/feature-views/Index"; +import FeatureViewInstance from "./pages/feature-views/FeatureViewInstance"; +import FeatureServiceInstance from "./pages/feature-services/FeatureServiceInstance"; +import DataSourceInstance from "./pages/data-sources/DataSourceInstance"; +import RootProjectSelectionPage from "./pages/RootProjectSelectionPage"; +import DatasetInstance from "./pages/saved-data-sets/DatasetInstance"; +import NoProjectGuard from "./components/NoProjectGuard"; + +const App = () => { + return ( + + + }> + } /> + }> + } /> + } /> + } + /> + } /> + } + /> + } /> + } + /> + } /> + } /> + + } /> + } + /> + + + } /> + + + ); +}; + +export default App; diff --git a/ui/src/components/EuiCustomLink.jsx b/ui/src/components/EuiCustomLink.jsx new file mode 100644 index 00000000000..a9c0d625f3a --- /dev/null +++ b/ui/src/components/EuiCustomLink.jsx @@ -0,0 +1,46 @@ +// File name: "EuiCustomLink.js". +import React from "react"; +import { EuiLink } from "@elastic/eui"; +import { useNavigate, useHref } from "react-router"; + +const isModifiedEvent = (event) => + !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); + +const isLeftClickEvent = (event) => event.button === 0; + +const isTargetBlank = (event) => { + const target = event.target.getAttribute("target"); + return target && target !== "_self"; +}; + +export default function EuiCustomLink({ to, ...rest }) { + // This is the key! + const navigate = useNavigate(); + + function onClick(event) { + if (event.defaultPrevented) { + return; + } + + // Let the browser handle links that open new tabs/windows + if ( + isModifiedEvent(event) || + !isLeftClickEvent(event) || + isTargetBlank(event) + ) { + return; + } + + // Prevent regular link behavior, which causes a browser refresh. + event.preventDefault(); + + // Push the route to the history. + navigate(to); + } + + // Generate the correct link href (with basename accounted for) + const href = useHref({ pathname: to }); + + const props = { ...rest, href, onClick }; + return ; +} diff --git a/ui/src/components/ExplorePanel.tsx b/ui/src/components/ExplorePanel.tsx new file mode 100644 index 00000000000..1bcc2e99789 --- /dev/null +++ b/ui/src/components/ExplorePanel.tsx @@ -0,0 +1,62 @@ +import React from "react"; + +import { + EuiHorizontalRule, + EuiPanel, + EuiTitle, + EuiBadge, + EuiLoadingContent, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, +} from "@elastic/eui"; + +import { useNavigate } from "react-router-dom"; +import useFCOExploreSuggestions from "../hooks/useFCOExploreSuggestions"; + +const ExplorePanel = () => { + const { isLoading, isSuccess, data } = useFCOExploreSuggestions(); + + const navigate = useNavigate(); + + return ( + + +

Explore this Project

+
+ + {isLoading && } + {isSuccess && + data && + data.map((suggestionGroup, i) => { + return ( + + +

{suggestionGroup.title}

+
+ + {suggestionGroup.items.map((item, j) => { + return ( + + { + navigate(item.link); + }} + onClickAriaLabel={item.label} + > + {item.name} ({item.count}) + + + ); + })} + + +
+ ); + })} +
+ ); +}; + +export default ExplorePanel; diff --git a/ui/src/components/FeaturesInServiceDisplay.tsx b/ui/src/components/FeaturesInServiceDisplay.tsx new file mode 100644 index 00000000000..39091b81dec --- /dev/null +++ b/ui/src/components/FeaturesInServiceDisplay.tsx @@ -0,0 +1,71 @@ +import React from "react"; +import { z } from "zod"; +import { EuiBasicTable } from "@elastic/eui"; +import { FeastFeatureInServiceType } from "../parsers/feastFeatureServices"; +import EuiCustomLink from "./EuiCustomLink"; +import { FEAST_FEATURE_VALUE_TYPES } from "../parsers/types"; +import { useParams } from "react-router-dom"; + +interface FeatureViewsListInterace { + featureViews: FeastFeatureInServiceType[]; +} + +const FeaturesInServiceList = ({ featureViews }: FeatureViewsListInterace) => { + const { projectName } = useParams(); + + const FeatureInService = z.object({ + featureViewName: z.string(), + featureColumnName: z.string(), + valueType: z.nativeEnum(FEAST_FEATURE_VALUE_TYPES), + }); + type FeatureInServiceType = z.infer; + + var items: FeatureInServiceType[] = []; + featureViews.forEach((featureView) => { + featureView.featureColumns.forEach((featureColumn) => { + const row: FeatureInServiceType = { + featureViewName: featureView.featureViewName, + featureColumnName: featureColumn.name, + valueType: featureColumn.valueType, + }; + items.push(row); + }); + }); + + const columns = [ + { + name: "Feature View", + field: "featureViewName", + render: (name: string) => { + return ( + + {name} + + ); + }, + }, + { + name: "Feature Column", + field: "featureColumnName", + }, + { + name: "Value Type", + field: "valueType", + }, + ]; + + const getRowProps = (item: FeatureInServiceType) => { + return { + "data-test-subj": `row-${item.featureViewName}`, + }; + }; + + return ( + + ); +}; + +export default FeaturesInServiceList; diff --git a/ui/src/components/FeaturesListDisplay.tsx b/ui/src/components/FeaturesListDisplay.tsx new file mode 100644 index 00000000000..2ab17fdbf5b --- /dev/null +++ b/ui/src/components/FeaturesListDisplay.tsx @@ -0,0 +1,79 @@ +import React from "react"; +import { enabledFeatureStatistics } from "../flags"; +import { EuiBasicTable, EuiLoadingSpinner, EuiBadge } from "@elastic/eui"; +import { FeastFeatureColumnType } from "../parsers/feastFeatureViews"; +import useLoadFeatureViewSummaryStatistics from "../queries/useLoadFeatureViewSummaryStatistics"; +import SparklineHistogram from "./SparklineHistogram"; + +interface FeaturesListProps { + featureViewName: string; + features: FeastFeatureColumnType[]; +} + +const FeaturesList = ({ featureViewName, features }: FeaturesListProps) => { + const { isLoading, isError, isSuccess, data } = + useLoadFeatureViewSummaryStatistics(featureViewName); + + let columns: { name: string; render?: any; field: any }[] = [ + { name: "Name", field: "name" }, + { + name: "Value Type", + field: "valueType", + }, + ]; + + if (enabledFeatureStatistics) { + columns.push( + ...[ + { + name: "Sample", + field: "", + render: (item: FeastFeatureColumnType) => { + const statistics = + isSuccess && data && data.columnsSummaryStatistics[item.name]; + + return ( + + {isLoading && } + {isError && ( + error loading samples + )} + {statistics && statistics.sampleValues.join(",")} + + ); + }, + }, + { + name: "Sparklines", + field: "", + render: (item: FeastFeatureColumnType) => { + const statistics = + isSuccess && data && data.columnsSummaryStatistics[item.name]; + + if ( + statistics && + statistics.valueType === "INT64" && + statistics.histogram + ) { + return ; + } else { + return ""; + } + }, + }, + ] + ); + } + + const getRowProps = (item: FeastFeatureColumnType) => { + return { + "data-test-subj": `row-${item.name}`, + }; + }; + + return ( + + ); +}; + +export default FeaturesList; diff --git a/ui/src/components/NoProjectGuard.tsx b/ui/src/components/NoProjectGuard.tsx new file mode 100644 index 00000000000..faa1fd92832 --- /dev/null +++ b/ui/src/components/NoProjectGuard.tsx @@ -0,0 +1,61 @@ +import { EuiEmptyPrompt, EuiLoadingContent } from "@elastic/eui"; +import React from "react"; +import { Outlet, useParams } from "react-router-dom"; +import useLoadProjectsList from "../queries/useLoadProjectsList"; +import ProjectSelector from "./ProjectSelector"; + +const NoProjectGuard = () => { + const { projectName } = useParams(); + + const { isLoading, isError, data } = useLoadProjectsList(); + + if (isLoading && !data) { + return ; + } + + if (isError) { + return ( + Error Loading Project List} + body={ +

+ Unable to find + projects-list.json. Check that you have a project list + file defined. +

+ } + /> + ); + } + + const currentProject = data?.projects.find((project) => { + return project.id === projectName; + }); + + if (currentProject === undefined) { + return ( + Error Loading Project} + body={ + +

+ There is no project with id {projectName} in{" "} + projects-list.json. Check that you have the correct + project id. +

+

You can also select one of the project in the following list:

+ +
+ } + /> + ); + } + + return ; +}; + +export default NoProjectGuard; diff --git a/ui/src/components/NumericFeaturesTable.tsx b/ui/src/components/NumericFeaturesTable.tsx new file mode 100644 index 00000000000..7c55f5ddbae --- /dev/null +++ b/ui/src/components/NumericFeaturesTable.tsx @@ -0,0 +1,60 @@ +import { EuiBasicTable } from "@elastic/eui"; +import React from "react"; +import { NumericColumnSummaryStatisticType } from "../parsers/featureViewSummaryStatistics"; +import SparklineHistogram from "./SparklineHistogram"; + +interface NumericFeaturesTableProps { + data: NumericColumnSummaryStatisticType[]; +} + +const NumericFeaturesTable = ({ data }: NumericFeaturesTableProps) => { + const columns = [ + { name: "Name", field: "name" }, + { + name: "Value Type", + field: "valueType", + }, + { + name: "Sample", + render: (statistics: NumericColumnSummaryStatisticType) => { + return ( + + {statistics && statistics.sampleValues.join(",")} + + ); + }, + }, + { + name: "Min/Max", + render: (statistics: NumericColumnSummaryStatisticType) => { + return statistics.min !== undefined && statistics.max !== undefined + ? `${statistics.min}/${statistics.max}` + : undefined; + }, + }, + { name: "zeros", field: "proportionOfZeros" }, + { name: "missing", field: "proportionMissing" }, + { + name: "Sparklines", + render: (statistics: NumericColumnSummaryStatisticType) => { + if (statistics && statistics.histogram) { + return ; + } else { + return ""; + } + }, + }, + ]; + + const getRowProps = (item: NumericColumnSummaryStatisticType) => { + return { + "data-test-subj": `row-${item.name}`, + }; + }; + + return ( + + ); +}; + +export default NumericFeaturesTable; diff --git a/ui/src/components/ObjectsCountStats.tsx b/ui/src/components/ObjectsCountStats.tsx new file mode 100644 index 00000000000..bf1dd2dc9dd --- /dev/null +++ b/ui/src/components/ObjectsCountStats.tsx @@ -0,0 +1,98 @@ +import React, { useContext } from "react"; +import { + EuiFlexGroup, + EuiFlexItem, + EuiStat, + EuiHorizontalRule, + EuiTitle, + EuiSpacer, +} from "@elastic/eui"; +import useLoadRegistry from "../queries/useLoadRegistry"; +import { useNavigate, useParams } from "react-router-dom"; +import RegistryPathContext from "../contexts/RegistryPathContext"; + +const useLoadObjectStats = () => { + const registryUrl = useContext(RegistryPathContext); + const query = useLoadRegistry(registryUrl); + + const data = + query.isSuccess && query.data + ? { + featureServices: query.data.objects.featureServices?.length || 0, + featureViews: query.data.mergedFVList.length, + entities: query.data.objects.entities?.length || 0, + dataSources: query.data.objects.dataSources?.length || 0, + } + : undefined; + + return { + ...query, + data, + }; +}; + +const statStyle = { cursor: "pointer" }; + +const ObjectsCountStats = () => { + const { isLoading, isSuccess, isError, data } = useLoadObjectStats(); + const { projectName } = useParams(); + + const navigate = useNavigate(); + + return ( + + + + {isLoading &&

Loading

} + {isError &&

There was an error in loading registry information.

} + {isSuccess && data && ( + + +

Registered in this Feast project are …

+
+ + + + navigate(`/p/${projectName}/feature-service`)} + description="Feature Services→" + title={data.featureServices} + reverse + /> + + + navigate(`/p/${projectName}/feature-view`)} + title={data.featureViews} + reverse + /> + + + navigate(`/p/${projectName}/entity`)} + title={data.entities} + reverse + /> + + + navigate(`/p/${projectName}/data-source`)} + title={data.dataSources} + reverse + /> + + +
+ )} +
+ ); +}; + +export default ObjectsCountStats; diff --git a/ui/src/components/ProjectSelector.test.tsx b/ui/src/components/ProjectSelector.test.tsx new file mode 100644 index 00000000000..c5b8d6cba38 --- /dev/null +++ b/ui/src/components/ProjectSelector.test.tsx @@ -0,0 +1,87 @@ +import { setupServer } from "msw/node"; +import { render } from "../test-utils"; +import { screen, within } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; + +import App from "../App"; + +import { + projectsListWithDefaultProject, + creditHistoryRegistry, +} from "../mocks/handlers"; + +// declare which API requests to mock +const server = setupServer( + projectsListWithDefaultProject, + creditHistoryRegistry +); + +// establish API mocking before all tests +beforeAll(() => server.listen()); +// reset any request handlers that are declared as a part of our tests +// (i.e. for testing one-time error scenarios) +afterEach(() => server.resetHandlers()); +// clean up once the tests are done +afterAll(() => server.close()); + +test("in a full App render, it shows the right initial project", async () => { + render(); + + const select = await screen.findByRole("combobox", { + name: "Select a Feast Project", + }); + + // Wait for Project List to Load + const options = await within(select).findAllByRole("option"); + + const topLevelNavigation = await screen.findByRole("navigation", { + name: "Top Level", + }); + + within(topLevelNavigation).getByDisplayValue("Credit Score Project"); + + expect(options.length).toBe(2); + + // Wait for Project Data from Registry to Load + await screen.findAllByRole("heading", { + name: /Project:/i, + }); + + // Before User Event: Heading is the credit scoring project + screen.getByRole("heading", { + name: /credit_scoring_aws/i, + }); + + // ... and Big Query Project is not selected + expect( + within(topLevelNavigation).getByRole("option", { + name: "Big Query Project", + selected: false, + }) + ).toBeInTheDocument(); + + // Do the select option user event + // https://stackoverflow.com/a/69478957 + userEvent.selectOptions( + // Find the select element + within(topLevelNavigation).getByRole("combobox"), + // Find and select the Ireland option + within(topLevelNavigation).getByRole("option", { + name: "Big Query Project", + }) + ); + + // The selection should updated + expect( + within(topLevelNavigation).getByRole("option", { + name: "Big Query Project", + selected: true, + }) + ).toBeInTheDocument(); + + // ... and the new heading should appear + // meaning we successfully navigated + await screen.findByRole("heading", { + name: /dbt_demo/i, + }); +}); diff --git a/ui/src/components/ProjectSelector.tsx b/ui/src/components/ProjectSelector.tsx new file mode 100644 index 00000000000..a1237e3d502 --- /dev/null +++ b/ui/src/components/ProjectSelector.tsx @@ -0,0 +1,42 @@ +import { EuiSelect, useGeneratedHtmlId } from "@elastic/eui"; +import React from "react"; +import { useNavigate, useParams } from "react-router-dom"; +import useLoadProjectsList from "../queries/useLoadProjectsList"; + +const ProjectSelector = () => { + const { projectName } = useParams(); + const navigate = useNavigate(); + + const { isLoading, data } = useLoadProjectsList(); + + const currentProject = data?.projects.find((project) => { + return project.id === projectName; + }); + + const options = data?.projects.map((p) => { + return { + value: p.id, + text: p.name, + }; + }); + + const basicSelectId = useGeneratedHtmlId({ prefix: "basicSelect" }); + const onChange = (e: React.ChangeEvent) => { + navigate(`/p/${e.target.value}`); + }; + + return ( + onChange(e)} + aria-label="Select a Feast Project" + /> + ); +}; + +export default ProjectSelector; diff --git a/ui/src/components/SearchTokensList.tsx b/ui/src/components/SearchTokensList.tsx new file mode 100644 index 00000000000..c382298d5ad --- /dev/null +++ b/ui/src/components/SearchTokensList.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { EuiBadge, EuiFlexGroup, EuiFlexItem } from "@elastic/eui"; + +interface SearchTokensListProps { + tokens: string[]; + removeTokenByPosition: (tokenPosition: number) => void; +} + +const SearchTokensList = ({ + tokens, + removeTokenByPosition, +}: SearchTokensListProps) => { + return ( + + {tokens.map((token, index) => { + const badgeColor = token.indexOf(":") > 0 ? "primary" : "hollow"; + + return ( + + { + removeTokenByPosition(index); + }} + iconOnClickAriaLabel="Example of onClick event for icon within the button" + > + {token} + + + ); + })} + + ); +}; + +export default SearchTokensList; diff --git a/ui/src/components/SparklineHistogram.tsx b/ui/src/components/SparklineHistogram.tsx new file mode 100644 index 00000000000..bd632ec20d1 --- /dev/null +++ b/ui/src/components/SparklineHistogram.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import { HistogramDataType } from "../parsers/featureViewSummaryStatistics"; +import { extent } from "d3-array"; +import { scaleLinear } from "d3"; +import { EuiBadge, useEuiTheme } from "@elastic/eui"; + +interface SparklineHistogramProps { + data: HistogramDataType; +} + +const SparklineHistogram = ({ data }: SparklineHistogramProps) => { + const width = 100; + const height = 24; + + const yMax = height - 2; + + const { euiTheme } = useEuiTheme(); + + if (data.length > 0) { + const x0Extent = extent(data, (d) => d.x0) as [number, number]; + const xScale = scaleLinear() + .domain(x0Extent) + .range([0, width - width / data.length]); + + const yExtent = extent(data, (d) => d.count) as [number, number]; + const yScale = scaleLinear().domain(yExtent).range([0, yMax]); + + return ( + + + {data.map((d) => { + const barHeight = yScale(d.count); + + return ( + + ); + })} + + ); + } else { + return histogram n/a; + } +}; + +export default SparklineHistogram; diff --git a/ui/src/components/TagSearch.tsx b/ui/src/components/TagSearch.tsx new file mode 100644 index 00000000000..e89d4a44ccb --- /dev/null +++ b/ui/src/components/TagSearch.tsx @@ -0,0 +1,221 @@ +import { EuiTitle, EuiInputPopover, EuiSelectable } from "@elastic/eui"; + +import React, { useEffect, useRef, useState } from "react"; +import { + SuggestionModes, + TagSuggestionInstance, +} from "../hooks/useSearchInputWithTags"; + +interface TagSearchInterface { + currentTag: string; + tagsString: string; + setTagsString: (tagsString: string) => void; + acceptSuggestion: (suggestion: TagSuggestionInstance) => void; + tagSuggestions: TagSuggestionInstance[]; + suggestionMode: SuggestionModes; + setCursorPosition: (position: number | undefined) => void; +} + +interface SelectableOption { + label: string; + checked?: "on" | "off" | undefined; + suggestion: TagSuggestionInstance; +} + +// Helper Functions +const suggestionFormatter = (item: TagSuggestionInstance) => { + return { + label: item.suggestion, + suggestion: item, + showIcons: false, + append: {item.description}, + }; +}; + +const getCursorPosition = ( + inputNode: React.MutableRefObject +) => { + return inputNode.current?.selectionStart || undefined; +}; + +const computePlaceholderText = ( + tagSuggestions: TagSuggestionInstance[] | undefined +) => { + return !tagSuggestions + ? "" + : "e.g. " + + tagSuggestions + .slice(0, 2) + .map((s) => `"${s.suggestion}"`) + .join(" or "); +}; + +const generateResultsCount = ( + currentTag: string, + suggestionMode: SuggestionModes, + tagSuggestions: TagSuggestionInstance[] +) => { + let resultsCount = undefined; + + const currentTagIsEmpty = currentTag.length <= 0; + const currentTagHasNoValue = currentTag.split(":")[1] === ""; + const operatingWord = + currentTagIsEmpty || currentTagHasNoValue ? "possible" : "matching"; + const counterWord = suggestionMode === "KEY" ? `key` : `value`; + + if (tagSuggestions.length > 0) { + const isPlural = tagSuggestions.length > 1 ? "s" : ""; + resultsCount = ( + {`${tagSuggestions.length} ${operatingWord} ${counterWord}${isPlural}`} + ); + } + + return resultsCount; +}; + +// Hooks +const useInputHack = ( + setTagsString: (s: string) => void, + setCursorPosition: (n: number | undefined) => void +) => { + // HACK --- route around the lack of onChange + // See: https://github.com/elastic/eui/issues/5651 + const inputNode = useRef(null); + useEffect(() => { + const cb = () => { + const s: string = inputNode.current?.value || ""; + + setTagsString(s); + setCursorPosition(getCursorPosition(inputNode)); + }; + + const copiedNode = inputNode.current; + + if (copiedNode) { + copiedNode.addEventListener("input", cb); + } + + return () => { + if (copiedNode) { + copiedNode.removeEventListener("input", cb); + } + }; + }, [inputNode, setTagsString, setCursorPosition]); + + return inputNode; +}; + +const useSelectableOptions = ( + tagSuggestions: TagSuggestionInstance[], + acceptSuggestion: (suggestion: TagSuggestionInstance) => void +) => { + const [options, setOptions] = useState( + tagSuggestions ? tagSuggestions.map(suggestionFormatter) : [] + ); + + const onSelectableChange = (options: SelectableOption[]) => { + // Get the thing that just got "checked" + const clickedItem = options.find((option) => option.checked === "on"); + + if (clickedItem) { + acceptSuggestion(clickedItem.suggestion); + } + + setOptions(options); + }; + + useEffect(() => { + // Update options when new set of suggestions are passed down + setOptions(tagSuggestions.map(suggestionFormatter)); + }, [tagSuggestions, setOptions]); + + return { + options, + onSelectableChange, + }; +}; + +const TagSearch = ({ + currentTag, + tagsString, + setTagsString, + acceptSuggestion, + tagSuggestions, + suggestionMode, + setCursorPosition, +}: TagSearchInterface) => { + // HACK --- route around the lack of onChange + const inputNode = useInputHack(setTagsString, setCursorPosition); + + // Handling Suggestion Options + const { options, onSelectableChange } = useSelectableOptions( + tagSuggestions, // Gets turned into options + acceptSuggestion // Get triggered when an option is selected + ); + + // Using EuiInputPopover: https://elastic.github.io/eui/#/layout/popover + const [hasFocus, setHasFocus] = useState(false); + + // Props for EuiFieldSearch + const searchProps = { + value: tagsString, + inputRef: (node: HTMLInputElement | null) => { + // HTMLInputElement is hooked into useInputHack + inputNode.current = node; + }, + onfocus: () => { + setHasFocus(true); + }, + fullWidth: true, + placeholder: computePlaceholderText(tagSuggestions), + }; + + const resultsCount = generateResultsCount( + currentTag, + suggestionMode, + tagSuggestions + ); + + return ( + <> + +

Filter by Tags

+
+ { + setHasFocus(true); + }} + onBlur={() => { + setHasFocus(false); + }} + searchable={true} + isPreFiltered={true} + searchProps={searchProps} + aria-label="Filter by " + onChange={onSelectableChange} + options={options} + singleSelection={true} + listProps={{ bordered: true }} + > + {(list, search) => { + return ( + {search}} + isOpen={hasFocus} + closePopover={() => { + setHasFocus(false); + }} + > + {resultsCount} + {list} + + ); + }} + + + ); +}; + +export default TagSearch; diff --git a/ui/src/components/TagsDisplay.tsx b/ui/src/components/TagsDisplay.tsx new file mode 100644 index 00000000000..6f7f23b0072 --- /dev/null +++ b/ui/src/components/TagsDisplay.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import { + EuiDescriptionList, + EuiDescriptionListDescription, + EuiDescriptionListTitle, +} from "@elastic/eui"; +import EuiCustomLink from "./EuiCustomLink"; + +interface TagsDisplayProps { + createLink?: (key: string, value: string) => string; + tags: Record; +} + +const TagsDisplay = ({ tags, createLink }: TagsDisplayProps) => { + return ( + + {Object.entries(tags).map(([key, value]) => { + return ( + + {key} + + {createLink ? ( + + {value} + + ) : ( + value + )} + + + ); + })} + + ); +}; + +export default TagsDisplay; diff --git a/ui/src/contexts/RegistryPathContext.ts b/ui/src/contexts/RegistryPathContext.ts new file mode 100644 index 00000000000..89eac2a7cdc --- /dev/null +++ b/ui/src/contexts/RegistryPathContext.ts @@ -0,0 +1,5 @@ +import React from "react"; + +const RegistryPathContext = React.createContext("/registry.json"); + +export default RegistryPathContext; diff --git a/ui/src/custom-tabs/CustomTabsRegistry.ts b/ui/src/custom-tabs/CustomTabsRegistry.ts new file mode 100644 index 00000000000..aa363beb120 --- /dev/null +++ b/ui/src/custom-tabs/CustomTabsRegistry.ts @@ -0,0 +1,88 @@ +import { + DatasetCustomTabRegistrationInterface, + DataSourceCustomTabRegistrationInterface, + EntityCustomTabRegistrationInterface, + FeatureServiceCustomTabRegistrationInterface, + OnDemandFeatureViewCustomTabRegistrationInterface, + RegularFeatureViewCustomTabRegistrationInterface, +} from "./types"; + +// How to add a Custom Tab +// 1. Pick which object type you want your tab +// to be in. e.g. Feature View, Feature Service, etc. +// +// 2. Write a regular React Component for Tab Content. +// It will be passed props with data about the Feast FCO +// e.g. RegularFeatureViewCustomTabProps, FeatureServiceCustomTabProps +// See: types.ts in this folder +// +// 3. Register the tab in the appropriate array below. Each entry +// is a record with three keys: label, path, and Component. +// Import your component and pass it as Component +import RFVDemoCustomTab from "./reguar-fv-demo-tab/DemoCustomTab"; +import ODFVDemoCustomTab from "./ondemand-fv-demo-tab/DemoCustomTab"; +import FSDemoCustomTab from "./feature-service-demo-tab/DemoCustomTab"; +import DSDemoCustomTab from "./data-source-demo-tab/DemoCustomTab"; +import EntDemoCustomTab from "./entity-demo-tab/DemoCustomTab"; +import DatasetDemoCustomTab from "./dataset-demo-tab/DemoCustomTab"; + +// Registry of Custom Tabs +const RegularFeatureViewCustomTabs: RegularFeatureViewCustomTabRegistrationInterface[] = + [ + { + label: "Custom Tab Demo", // Navigation Label for the tab + path: "demo-tab", // Subpath for the tab + Component: RFVDemoCustomTab, + }, + ]; + +const OnDemandFeatureViewCustomTabs: OnDemandFeatureViewCustomTabRegistrationInterface[] = + [ + { + label: "Custom Tab Demo", + path: "demo-tab", + Component: ODFVDemoCustomTab, + }, + ]; + +const FeatureServiceCustomTabs: FeatureServiceCustomTabRegistrationInterface[] = + [ + { + label: "Custom Tab Demo", + path: "fs-demo-tab", + Component: FSDemoCustomTab, + }, + ]; + +const DataSourceCustomTabs: DataSourceCustomTabRegistrationInterface[] = [ + { + label: "Custom Tab Demo", + path: "fs-demo-tab", + Component: DSDemoCustomTab, + }, +]; + +const EntityCustomTabs: EntityCustomTabRegistrationInterface[] = [ + { + label: "Custom Tab Demo", + path: "demo-tab", + Component: EntDemoCustomTab, + }, +]; + +const DatasetCustomTabs: DatasetCustomTabRegistrationInterface[] = [ + { + label: "Custom Tab Demo", + path: "demo-tab", + Component: DatasetDemoCustomTab, + }, +]; + +export { + RegularFeatureViewCustomTabs, + OnDemandFeatureViewCustomTabs, + FeatureServiceCustomTabs, + DataSourceCustomTabs, + EntityCustomTabs, + DatasetCustomTabs, +}; diff --git a/ui/src/custom-tabs/data-source-demo-tab/DemoCustomTab.tsx b/ui/src/custom-tabs/data-source-demo-tab/DemoCustomTab.tsx new file mode 100644 index 00000000000..79ba01d7aa3 --- /dev/null +++ b/ui/src/custom-tabs/data-source-demo-tab/DemoCustomTab.tsx @@ -0,0 +1,82 @@ +import React from "react"; + +import { + // Feature View Custom Tabs will get these props + DataSourceCustomTabProps, +} from "../types"; + +import { + EuiLoadingContent, + EuiEmptyPrompt, + EuiFlexGroup, + EuiFlexItem, + EuiCode, + EuiSpacer, +} from "@elastic/eui"; + +// Separating out the query is not required, +// but encouraged for code readability +import useDemoQuery from "./useDemoQuery"; + +const DemoCustomTab = ({ id, feastObjectQuery }: DataSourceCustomTabProps) => { + // Use React Query to fetch data + // that is custom to this tab. + // See: https://react-query.tanstack.com/guides/queries + const { isLoading, isError, isSuccess, data } = useDemoQuery({ + featureView: id, + }); + + if (isLoading) { + // Handle Loading State + // https://elastic.github.io/eui/#/display/loading + return ; + } + + if (isError) { + // Handle Data Fetching Error + // https://elastic.github.io/eui/#/display/empty-prompt + return ( + Unable to load your demo page} + body={ +

+ There was an error loading the Dashboard application. Contact your + administrator for help. +

+ } + /> + ); + } + + // Feast UI uses the Elastic UI component system. + // and are particularly + // useful for layouts. + return ( + + + +

Hello World. The following is fetched data.

+ + {isSuccess && data && ( + +
{JSON.stringify(data, null, 2)}
+
+ )} +
+ +

... and this is data from Feast UI’s own query.

+ + {feastObjectQuery.isSuccess && feastObjectQuery.data && ( + +
{JSON.stringify(feastObjectQuery.data, null, 2)}
+
+ )} +
+
+
+ ); +}; + +export default DemoCustomTab; diff --git a/ui/src/custom-tabs/data-source-demo-tab/useDemoQuery.tsx b/ui/src/custom-tabs/data-source-demo-tab/useDemoQuery.tsx new file mode 100644 index 00000000000..b93602dbe3b --- /dev/null +++ b/ui/src/custom-tabs/data-source-demo-tab/useDemoQuery.tsx @@ -0,0 +1,44 @@ +import { useQuery } from "react-query"; +import { z } from "zod"; + +// Use Zod to check the shape of the +// json object being loaded +const demoSchema = z.object({ + hello: z.string(), + name: z.string().optional(), +}); + +// Make the type of the object available +type DemoDataType = z.infer; + +interface DemoQueryInterface { + featureView: string | undefined; +} + +const useDemoQuery = ({ featureView }: DemoQueryInterface) => { + // React Query manages caching for you based on query keys + // See: https://react-query.tanstack.com/guides/query-keys + const queryKey = `demo-tab-namespace:${featureView}`; + + // Pass the type to useQuery + // so that components consuming the + // result gets nice type hints + // on the other side. + return useQuery( + queryKey, + () => { + // Customizing the URL based on your needs + const url = `/demo-custom-tabs/demo.json`; + + return fetch(url) + .then((res) => res.json()) + .then((data) => demoSchema.parse(data)); // Use zod to parse results + }, + { + enabled: !!featureView, // Only start the query when the variable is not undefined + } + ); +}; + +export default useDemoQuery; +export type { DemoDataType }; diff --git a/ui/src/custom-tabs/dataset-demo-tab/DemoCustomTab.tsx b/ui/src/custom-tabs/dataset-demo-tab/DemoCustomTab.tsx new file mode 100644 index 00000000000..37038b84a99 --- /dev/null +++ b/ui/src/custom-tabs/dataset-demo-tab/DemoCustomTab.tsx @@ -0,0 +1,82 @@ +import React from "react"; + +import { + // Feature View Custom Tabs will get these props + DatasetCustomTabProps, +} from "../types"; + +import { + EuiLoadingContent, + EuiEmptyPrompt, + EuiFlexGroup, + EuiFlexItem, + EuiCode, + EuiSpacer, +} from "@elastic/eui"; + +// Separating out the query is not required, +// but encouraged for code readability +import useDemoQuery from "./useDemoQuery"; + +const DemoCustomTab = ({ id, feastObjectQuery }: DatasetCustomTabProps) => { + // Use React Query to fetch data + // that is custom to this tab. + // See: https://react-query.tanstack.com/guides/queries + const { isLoading, isError, isSuccess, data } = useDemoQuery({ + featureView: id, + }); + + if (isLoading) { + // Handle Loading State + // https://elastic.github.io/eui/#/display/loading + return ; + } + + if (isError) { + // Handle Data Fetching Error + // https://elastic.github.io/eui/#/display/empty-prompt + return ( + Unable to load your demo page} + body={ +

+ There was an error loading the Dashboard application. Contact your + administrator for help. +

+ } + /> + ); + } + + // Feast UI uses the Elastic UI component system. + // and are particularly + // useful for layouts. + return ( + + + +

Hello World. The following is fetched data.

+ + {isSuccess && data && ( + +
{JSON.stringify(data, null, 2)}
+
+ )} +
+ +

... and this is data from Feast UI’s own query.

+ + {feastObjectQuery.isSuccess && feastObjectQuery.data && ( + +
{JSON.stringify(feastObjectQuery.data, null, 2)}
+
+ )} +
+
+
+ ); +}; + +export default DemoCustomTab; diff --git a/ui/src/custom-tabs/dataset-demo-tab/useDemoQuery.tsx b/ui/src/custom-tabs/dataset-demo-tab/useDemoQuery.tsx new file mode 100644 index 00000000000..b93602dbe3b --- /dev/null +++ b/ui/src/custom-tabs/dataset-demo-tab/useDemoQuery.tsx @@ -0,0 +1,44 @@ +import { useQuery } from "react-query"; +import { z } from "zod"; + +// Use Zod to check the shape of the +// json object being loaded +const demoSchema = z.object({ + hello: z.string(), + name: z.string().optional(), +}); + +// Make the type of the object available +type DemoDataType = z.infer; + +interface DemoQueryInterface { + featureView: string | undefined; +} + +const useDemoQuery = ({ featureView }: DemoQueryInterface) => { + // React Query manages caching for you based on query keys + // See: https://react-query.tanstack.com/guides/query-keys + const queryKey = `demo-tab-namespace:${featureView}`; + + // Pass the type to useQuery + // so that components consuming the + // result gets nice type hints + // on the other side. + return useQuery( + queryKey, + () => { + // Customizing the URL based on your needs + const url = `/demo-custom-tabs/demo.json`; + + return fetch(url) + .then((res) => res.json()) + .then((data) => demoSchema.parse(data)); // Use zod to parse results + }, + { + enabled: !!featureView, // Only start the query when the variable is not undefined + } + ); +}; + +export default useDemoQuery; +export type { DemoDataType }; diff --git a/ui/src/custom-tabs/entity-demo-tab/DemoCustomTab.tsx b/ui/src/custom-tabs/entity-demo-tab/DemoCustomTab.tsx new file mode 100644 index 00000000000..6e4a87b5704 --- /dev/null +++ b/ui/src/custom-tabs/entity-demo-tab/DemoCustomTab.tsx @@ -0,0 +1,82 @@ +import React from "react"; + +import { + // Feature View Custom Tabs will get these props + EntityCustomTabProps, +} from "../types"; + +import { + EuiLoadingContent, + EuiEmptyPrompt, + EuiFlexGroup, + EuiFlexItem, + EuiCode, + EuiSpacer, +} from "@elastic/eui"; + +// Separating out the query is not required, +// but encouraged for code readability +import useDemoQuery from "./useDemoQuery"; + +const DemoCustomTab = ({ id, feastObjectQuery }: EntityCustomTabProps) => { + // Use React Query to fetch data + // that is custom to this tab. + // See: https://react-query.tanstack.com/guides/queries + const { isLoading, isError, isSuccess, data } = useDemoQuery({ + featureView: id, + }); + + if (isLoading) { + // Handle Loading State + // https://elastic.github.io/eui/#/display/loading + return ; + } + + if (isError) { + // Handle Data Fetching Error + // https://elastic.github.io/eui/#/display/empty-prompt + return ( + Unable to load your demo page} + body={ +

+ There was an error loading the Dashboard application. Contact your + administrator for help. +

+ } + /> + ); + } + + // Feast UI uses the Elastic UI component system. + // and are particularly + // useful for layouts. + return ( + + + +

Hello World. The following is fetched data.

+ + {isSuccess && data && ( + +
{JSON.stringify(data, null, 2)}
+
+ )} +
+ +

... and this is data from Feast UI’s own query.

+ + {feastObjectQuery.isSuccess && feastObjectQuery.data && ( + +
{JSON.stringify(feastObjectQuery.data, null, 2)}
+
+ )} +
+
+
+ ); +}; + +export default DemoCustomTab; diff --git a/ui/src/custom-tabs/entity-demo-tab/useDemoQuery.tsx b/ui/src/custom-tabs/entity-demo-tab/useDemoQuery.tsx new file mode 100644 index 00000000000..b93602dbe3b --- /dev/null +++ b/ui/src/custom-tabs/entity-demo-tab/useDemoQuery.tsx @@ -0,0 +1,44 @@ +import { useQuery } from "react-query"; +import { z } from "zod"; + +// Use Zod to check the shape of the +// json object being loaded +const demoSchema = z.object({ + hello: z.string(), + name: z.string().optional(), +}); + +// Make the type of the object available +type DemoDataType = z.infer; + +interface DemoQueryInterface { + featureView: string | undefined; +} + +const useDemoQuery = ({ featureView }: DemoQueryInterface) => { + // React Query manages caching for you based on query keys + // See: https://react-query.tanstack.com/guides/query-keys + const queryKey = `demo-tab-namespace:${featureView}`; + + // Pass the type to useQuery + // so that components consuming the + // result gets nice type hints + // on the other side. + return useQuery( + queryKey, + () => { + // Customizing the URL based on your needs + const url = `/demo-custom-tabs/demo.json`; + + return fetch(url) + .then((res) => res.json()) + .then((data) => demoSchema.parse(data)); // Use zod to parse results + }, + { + enabled: !!featureView, // Only start the query when the variable is not undefined + } + ); +}; + +export default useDemoQuery; +export type { DemoDataType }; diff --git a/ui/src/custom-tabs/feature-service-demo-tab/DemoCustomTab.tsx b/ui/src/custom-tabs/feature-service-demo-tab/DemoCustomTab.tsx new file mode 100644 index 00000000000..724c2504aa6 --- /dev/null +++ b/ui/src/custom-tabs/feature-service-demo-tab/DemoCustomTab.tsx @@ -0,0 +1,85 @@ +import React from "react"; + +import { + // Feature View Custom Tabs will get these props + FeatureServiceCustomTabProps, +} from "../types"; + +import { + EuiLoadingContent, + EuiEmptyPrompt, + EuiFlexGroup, + EuiFlexItem, + EuiCode, + EuiSpacer, +} from "@elastic/eui"; + +// Separating out the query is not required, +// but encouraged for code readability +import useDemoQuery from "./useDemoQuery"; + +const DemoCustomTab = ({ + id, + feastObjectQuery, +}: FeatureServiceCustomTabProps) => { + // Use React Query to fetch data + // that is custom to this tab. + // See: https://react-query.tanstack.com/guides/queries + const { isLoading, isError, isSuccess, data } = useDemoQuery({ + featureView: id, + }); + + if (isLoading) { + // Handle Loading State + // https://elastic.github.io/eui/#/display/loading + return ; + } + + if (isError) { + // Handle Data Fetching Error + // https://elastic.github.io/eui/#/display/empty-prompt + return ( + Unable to load your demo page} + body={ +

+ There was an error loading the Dashboard application. Contact your + administrator for help. +

+ } + /> + ); + } + + // Feast UI uses the Elastic UI component system. + // and are particularly + // useful for layouts. + return ( + + + +

Hello World. The following is fetched data.

+ + {isSuccess && data && ( + +
{JSON.stringify(data, null, 2)}
+
+ )} +
+ +

... and this is data from Feast UI’s own query.

+ + {feastObjectQuery.isSuccess && feastObjectQuery.data && ( + +
{JSON.stringify(feastObjectQuery.data, null, 2)}
+
+ )} +
+
+
+ ); +}; + +export default DemoCustomTab; diff --git a/ui/src/custom-tabs/feature-service-demo-tab/useDemoQuery.tsx b/ui/src/custom-tabs/feature-service-demo-tab/useDemoQuery.tsx new file mode 100644 index 00000000000..b93602dbe3b --- /dev/null +++ b/ui/src/custom-tabs/feature-service-demo-tab/useDemoQuery.tsx @@ -0,0 +1,44 @@ +import { useQuery } from "react-query"; +import { z } from "zod"; + +// Use Zod to check the shape of the +// json object being loaded +const demoSchema = z.object({ + hello: z.string(), + name: z.string().optional(), +}); + +// Make the type of the object available +type DemoDataType = z.infer; + +interface DemoQueryInterface { + featureView: string | undefined; +} + +const useDemoQuery = ({ featureView }: DemoQueryInterface) => { + // React Query manages caching for you based on query keys + // See: https://react-query.tanstack.com/guides/query-keys + const queryKey = `demo-tab-namespace:${featureView}`; + + // Pass the type to useQuery + // so that components consuming the + // result gets nice type hints + // on the other side. + return useQuery( + queryKey, + () => { + // Customizing the URL based on your needs + const url = `/demo-custom-tabs/demo.json`; + + return fetch(url) + .then((res) => res.json()) + .then((data) => demoSchema.parse(data)); // Use zod to parse results + }, + { + enabled: !!featureView, // Only start the query when the variable is not undefined + } + ); +}; + +export default useDemoQuery; +export type { DemoDataType }; diff --git a/ui/src/custom-tabs/ondemand-fv-demo-tab/DemoCustomTab.tsx b/ui/src/custom-tabs/ondemand-fv-demo-tab/DemoCustomTab.tsx new file mode 100644 index 00000000000..dd6f3ab6549 --- /dev/null +++ b/ui/src/custom-tabs/ondemand-fv-demo-tab/DemoCustomTab.tsx @@ -0,0 +1,85 @@ +import React from "react"; + +import { + // Feature View Custom Tabs will get these props + OnDemandFeatureViewCustomTabProps, +} from "../types"; + +import { + EuiLoadingContent, + EuiEmptyPrompt, + EuiFlexGroup, + EuiFlexItem, + EuiCode, + EuiSpacer, +} from "@elastic/eui"; + +// Separating out the query is not required, +// but encouraged for code readability +import useDemoQuery from "./useDemoQuery"; + +const DemoCustomTab = ({ + id, + feastObjectQuery, +}: OnDemandFeatureViewCustomTabProps) => { + // Use React Query to fetch data + // that is custom to this tab. + // See: https://react-query.tanstack.com/guides/queries + const { isLoading, isError, isSuccess, data } = useDemoQuery({ + featureView: id, + }); + + if (isLoading) { + // Handle Loading State + // https://elastic.github.io/eui/#/display/loading + return ; + } + + if (isError) { + // Handle Data Fetching Error + // https://elastic.github.io/eui/#/display/empty-prompt + return ( + Unable to load your demo page} + body={ +

+ There was an error loading the Dashboard application. Contact your + administrator for help. +

+ } + /> + ); + } + + // Feast UI uses the Elastic UI component system. + // and are particularly + // useful for layouts. + return ( + + + +

Hello World. The following is fetched data.

+ + {isSuccess && data && ( + +
{JSON.stringify(data, null, 2)}
+
+ )} +
+ +

... and this is data from Feast UI’s own query.

+ + {feastObjectQuery.isSuccess && feastObjectQuery.data && ( + +
{JSON.stringify(feastObjectQuery.data, null, 2)}
+
+ )} +
+
+
+ ); +}; + +export default DemoCustomTab; diff --git a/ui/src/custom-tabs/ondemand-fv-demo-tab/useDemoQuery.tsx b/ui/src/custom-tabs/ondemand-fv-demo-tab/useDemoQuery.tsx new file mode 100644 index 00000000000..b93602dbe3b --- /dev/null +++ b/ui/src/custom-tabs/ondemand-fv-demo-tab/useDemoQuery.tsx @@ -0,0 +1,44 @@ +import { useQuery } from "react-query"; +import { z } from "zod"; + +// Use Zod to check the shape of the +// json object being loaded +const demoSchema = z.object({ + hello: z.string(), + name: z.string().optional(), +}); + +// Make the type of the object available +type DemoDataType = z.infer; + +interface DemoQueryInterface { + featureView: string | undefined; +} + +const useDemoQuery = ({ featureView }: DemoQueryInterface) => { + // React Query manages caching for you based on query keys + // See: https://react-query.tanstack.com/guides/query-keys + const queryKey = `demo-tab-namespace:${featureView}`; + + // Pass the type to useQuery + // so that components consuming the + // result gets nice type hints + // on the other side. + return useQuery( + queryKey, + () => { + // Customizing the URL based on your needs + const url = `/demo-custom-tabs/demo.json`; + + return fetch(url) + .then((res) => res.json()) + .then((data) => demoSchema.parse(data)); // Use zod to parse results + }, + { + enabled: !!featureView, // Only start the query when the variable is not undefined + } + ); +}; + +export default useDemoQuery; +export type { DemoDataType }; diff --git a/ui/src/custom-tabs/reguar-fv-demo-tab/DemoCustomTab.tsx b/ui/src/custom-tabs/reguar-fv-demo-tab/DemoCustomTab.tsx new file mode 100644 index 00000000000..2ce1b4e64b6 --- /dev/null +++ b/ui/src/custom-tabs/reguar-fv-demo-tab/DemoCustomTab.tsx @@ -0,0 +1,85 @@ +import React from "react"; + +import { + // Feature View Custom Tabs will get these props + RegularFeatureViewCustomTabProps, +} from "../types"; + +import { + EuiLoadingContent, + EuiEmptyPrompt, + EuiFlexGroup, + EuiFlexItem, + EuiCode, + EuiSpacer, +} from "@elastic/eui"; + +// Separating out the query is not required, +// but encouraged for code readability +import useDemoQuery from "./useDemoQuery"; + +const DemoCustomTab = ({ + id, + feastObjectQuery, +}: RegularFeatureViewCustomTabProps) => { + // Use React Query to fetch data + // that is custom to this tab. + // See: https://react-query.tanstack.com/guides/queries + const { isLoading, isError, isSuccess, data } = useDemoQuery({ + featureView: id, + }); + + if (isLoading) { + // Handle Loading State + // https://elastic.github.io/eui/#/display/loading + return ; + } + + if (isError) { + // Handle Data Fetching Error + // https://elastic.github.io/eui/#/display/empty-prompt + return ( + Unable to load your demo page} + body={ +

+ There was an error loading the Dashboard application. Contact your + administrator for help. +

+ } + /> + ); + } + + // Feast UI uses the Elastic UI component system. + // and are particularly + // useful for layouts. + return ( + + + +

Hello World. The following is fetched data.

+ + {isSuccess && data && ( + +
{JSON.stringify(data, null, 2)}
+
+ )} +
+ +

... and this is data from Feast UI’s own query.

+ + {feastObjectQuery.isSuccess && feastObjectQuery.data && ( + +
{JSON.stringify(feastObjectQuery.data, null, 2)}
+
+ )} +
+
+
+ ); +}; + +export default DemoCustomTab; diff --git a/ui/src/custom-tabs/reguar-fv-demo-tab/useDemoQuery.tsx b/ui/src/custom-tabs/reguar-fv-demo-tab/useDemoQuery.tsx new file mode 100644 index 00000000000..b93602dbe3b --- /dev/null +++ b/ui/src/custom-tabs/reguar-fv-demo-tab/useDemoQuery.tsx @@ -0,0 +1,44 @@ +import { useQuery } from "react-query"; +import { z } from "zod"; + +// Use Zod to check the shape of the +// json object being loaded +const demoSchema = z.object({ + hello: z.string(), + name: z.string().optional(), +}); + +// Make the type of the object available +type DemoDataType = z.infer; + +interface DemoQueryInterface { + featureView: string | undefined; +} + +const useDemoQuery = ({ featureView }: DemoQueryInterface) => { + // React Query manages caching for you based on query keys + // See: https://react-query.tanstack.com/guides/query-keys + const queryKey = `demo-tab-namespace:${featureView}`; + + // Pass the type to useQuery + // so that components consuming the + // result gets nice type hints + // on the other side. + return useQuery( + queryKey, + () => { + // Customizing the URL based on your needs + const url = `/demo-custom-tabs/demo.json`; + + return fetch(url) + .then((res) => res.json()) + .then((data) => demoSchema.parse(data)); // Use zod to parse results + }, + { + enabled: !!featureView, // Only start the query when the variable is not undefined + } + ); +}; + +export default useDemoQuery; +export type { DemoDataType }; diff --git a/ui/src/custom-tabs/types.ts b/ui/src/custom-tabs/types.ts new file mode 100644 index 00000000000..f80c56d0e2d --- /dev/null +++ b/ui/src/custom-tabs/types.ts @@ -0,0 +1,122 @@ +import { + useLoadOnDemandFeatureView, + useLoadRegularFeatureView, +} from "../pages/feature-views/useLoadFeatureView"; +import useLoadFeatureService from "../pages/feature-services/useLoadFeatureService"; +import useLoadDataSource from "../pages/data-sources/useLoadDataSource"; +import useLoadEntity from "../pages/entities/useLoadEntity"; +import useLoadDataset from "../pages/saved-data-sets/useLoadDataset"; + +interface CustomTabRegistrationInterface { + label: string; + path: string; + Component: (...args: any[]) => JSX.Element; +} + +// Type for Regular Feature View Custom Tabs +type RegularFeatureViewQueryReturnType = ReturnType< + typeof useLoadRegularFeatureView +>; +interface RegularFeatureViewCustomTabProps { + id: string | undefined; + feastObjectQuery: RegularFeatureViewQueryReturnType; +} +interface RegularFeatureViewCustomTabRegistrationInterface + extends CustomTabRegistrationInterface { + Component: ({ + id, + feastObjectQuery, + ...args + }: RegularFeatureViewCustomTabProps) => JSX.Element; +} + +// Type for OnDemand Feature View Custom Tabs +type OnDemandFeatureViewQueryReturnType = ReturnType< + typeof useLoadOnDemandFeatureView +>; +interface OnDemandFeatureViewCustomTabProps { + id: string | undefined; + feastObjectQuery: OnDemandFeatureViewQueryReturnType; +} +interface OnDemandFeatureViewCustomTabRegistrationInterface + extends CustomTabRegistrationInterface { + Component: ({ + id, + feastObjectQuery, + ...args + }: OnDemandFeatureViewCustomTabProps) => JSX.Element; +} + +// Type for Feature Service Custom Tabs +interface EntityCustomTabProps { + id: string | undefined; + feastObjectQuery: ReturnType; +} +interface EntityCustomTabRegistrationInterface + extends CustomTabRegistrationInterface { + Component: ({ + id, + feastObjectQuery, + ...args + }: EntityCustomTabProps) => JSX.Element; +} + +// Type for Feature Service Custom Tabs +interface FeatureServiceCustomTabProps { + id: string | undefined; + feastObjectQuery: ReturnType; +} +interface FeatureServiceCustomTabRegistrationInterface + extends CustomTabRegistrationInterface { + Component: ({ + id, + feastObjectQuery, + ...args + }: FeatureServiceCustomTabProps) => JSX.Element; +} + +// Type for Data Source Custom Tabs +interface DataSourceCustomTabProps { + id: string | undefined; + feastObjectQuery: ReturnType; +} +interface DataSourceCustomTabRegistrationInterface + extends CustomTabRegistrationInterface { + Component: ({ + id, + feastObjectQuery, + ...args + }: DataSourceCustomTabProps) => JSX.Element; +} + +// Type for Data Source Custom Tabs +interface DatasetCustomTabProps { + id: string | undefined; + feastObjectQuery: ReturnType; +} +interface DatasetCustomTabRegistrationInterface + extends CustomTabRegistrationInterface { + Component: ({ + id, + feastObjectQuery, + ...args + }: DatasetCustomTabProps) => JSX.Element; +} + +export type { + CustomTabRegistrationInterface, + RegularFeatureViewQueryReturnType, + RegularFeatureViewCustomTabRegistrationInterface, + RegularFeatureViewCustomTabProps, + OnDemandFeatureViewQueryReturnType, + OnDemandFeatureViewCustomTabProps, + OnDemandFeatureViewCustomTabRegistrationInterface, + FeatureServiceCustomTabRegistrationInterface, + FeatureServiceCustomTabProps, + DataSourceCustomTabRegistrationInterface, + DataSourceCustomTabProps, + EntityCustomTabRegistrationInterface, + EntityCustomTabProps, + DatasetCustomTabRegistrationInterface, + DatasetCustomTabProps, +}; diff --git a/ui/src/data-source-icon.svg b/ui/src/data-source-icon.svg new file mode 100644 index 00000000000..51f2f9be9ab --- /dev/null +++ b/ui/src/data-source-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/ui/src/dataset-icon.svg b/ui/src/dataset-icon.svg new file mode 100644 index 00000000000..49bcc990c84 --- /dev/null +++ b/ui/src/dataset-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/ui/src/entity-icon.svg b/ui/src/entity-icon.svg new file mode 100644 index 00000000000..991e1dec758 --- /dev/null +++ b/ui/src/entity-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/ui/src/feast-icon-blue.svg b/ui/src/feast-icon-blue.svg new file mode 100644 index 00000000000..fcb755d99aa --- /dev/null +++ b/ui/src/feast-icon-blue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/feast-icon-grey.svg b/ui/src/feast-icon-grey.svg new file mode 100644 index 00000000000..5dca752aa3b --- /dev/null +++ b/ui/src/feast-icon-grey.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/feast-icon-white.svg b/ui/src/feast-icon-white.svg new file mode 100644 index 00000000000..c1949594477 --- /dev/null +++ b/ui/src/feast-icon-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/feast-workmark.svg b/ui/src/feast-workmark.svg new file mode 100644 index 00000000000..3257387737f --- /dev/null +++ b/ui/src/feast-workmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/feature-service.svg b/ui/src/feature-service.svg new file mode 100644 index 00000000000..81ec81e74db --- /dev/null +++ b/ui/src/feature-service.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui/src/feature-view.svg b/ui/src/feature-view.svg new file mode 100644 index 00000000000..92102a4af33 --- /dev/null +++ b/ui/src/feature-view.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ui/src/flags.tsx b/ui/src/flags.tsx new file mode 100644 index 00000000000..5c44beb8542 --- /dev/null +++ b/ui/src/flags.tsx @@ -0,0 +1,3 @@ +const enabledFeatureStatistics = false; + +export { enabledFeatureStatistics }; diff --git a/ui/src/hacks/RouteAdapter.ts b/ui/src/hacks/RouteAdapter.ts new file mode 100644 index 00000000000..e7743c9d90b --- /dev/null +++ b/ui/src/hacks/RouteAdapter.ts @@ -0,0 +1,39 @@ +import React from "react"; +import { Location } from "history"; +import { + useLocation, + useNavigate, + Location as RouterLocation, +} from "react-router-dom"; + +// via: https://github.com/pbeshai/use-query-params/issues/196#issuecomment-996893750 +interface RouteAdapterProps { + children: React.FunctionComponent<{ + history: { + replace(location: Location): void; + push(location: Location): void; + }; + location: RouterLocation; + }>; +} + +// Via: https://github.com/pbeshai/use-query-params/blob/cd44e7fb3394620f757bfb09ff57b7f296d9a5e6/examples/react-router-6/src/index.js#L36 +const RouteAdapter = ({ children }: RouteAdapterProps) => { + const navigate = useNavigate(); + const location = useLocation(); + + const adaptedHistory = React.useMemo( + () => ({ + replace(location: Location) { + navigate(location, { replace: true, state: location.state }); + }, + push(location: Location) { + navigate(location, { replace: false, state: location.state }); + }, + }), + [navigate] + ); + return children && children({ history: adaptedHistory, location }); +}; + +export default RouteAdapter; diff --git a/ui/src/hooks/useDocumentTitle.ts b/ui/src/hooks/useDocumentTitle.ts new file mode 100644 index 00000000000..42fde3be111 --- /dev/null +++ b/ui/src/hooks/useDocumentTitle.ts @@ -0,0 +1,18 @@ +import { useEffect, useState } from "react"; + +const useDocumentTitle = (title: string) => { + const [document_title, set] = useState(title); + useEffect(() => { + document.title = document_title; + }, [document_title]); + + const setDoucmentTitle = (newTitle: string) => { + if (document_title !== newTitle) { + set(newTitle); + } + }; + + return setDoucmentTitle; +}; + +export { useDocumentTitle }; diff --git a/ui/src/hooks/useFCOExploreSuggestions.ts b/ui/src/hooks/useFCOExploreSuggestions.ts new file mode 100644 index 00000000000..e6a2a1e0eb5 --- /dev/null +++ b/ui/src/hooks/useFCOExploreSuggestions.ts @@ -0,0 +1,133 @@ +import { encodeSearchQueryString } from "./useSearchInputWithTags"; +import { FEAST_FCO_TYPES } from "../parsers/types"; + +import { FeastFeatureViewType } from "../parsers/feastFeatureViews"; +import { useParams } from "react-router-dom"; +import { useFeatureViewTagsAggregation } from "./useTagsAggregation"; + +interface ExplorationSuggestionItem { + name: string; + link: string; + label: string; + count: number; +} + +interface ExplorationSuggestion { + title: string; + items: ExplorationSuggestionItem[]; +} + +const FCO_TO_URL_NAME_MAP: Record = { + dataSource: "/data-source", + entity: "/entity", + featureView: "/feature-view", + featureService: "/feature-service", +}; + +const createSearchLink = ( + FCOType: FEAST_FCO_TYPES, + key: string, + value: string +) => { + const URL = FCO_TO_URL_NAME_MAP[FCOType]; + + return URL + "?" + encodeSearchQueryString(`${key}:${value}`); +}; + +const NUMBER_OF_SUGGESTION_GROUPS = 2; +const NUMBER_OF_VALUES_PER_GROUP = 4; + +const sortTagByUniqueValues = ( + tagAggregation: Record> +) => { + return Object.entries(tagAggregation).sort( + ([a, valuesOfA], [b, valuesOfB]) => { + return Object.keys(valuesOfB).length - Object.keys(valuesOfA).length; + } + ); +}; + +const sortTagsByTotalUsage = ( + tagAggregation: Record> +) => { + return Object.entries(tagAggregation).sort( + ([a, valuesOfA], [b, valuesOfB]) => { + const countOfA = Object.values(valuesOfA).reduce((memo, current) => { + return memo + current.length; + }, 0); + + const countOfB = Object.values(valuesOfB).reduce((memo, current) => { + return memo + current.length; + }, 0); + + return countOfB - countOfA; + } + ); +}; + +const generateExplorationSuggestions = ( + tagAggregation: Record>, + projectName: string +) => { + const suggestions: ExplorationSuggestion[] = []; + + if (tagAggregation) { + const SortedCandidates = + sortTagByUniqueValues(tagAggregation); + + SortedCandidates.slice(0, NUMBER_OF_SUGGESTION_GROUPS).forEach( + ([selectedTag, selectedTagValuesMap]) => { + suggestions.push({ + title: `Feature Views by "${selectedTag}"`, + items: Object.entries(selectedTagValuesMap) + .sort(([a, entriesOfA], [b, entriesOfB]) => { + return entriesOfB.length - entriesOfA.length; + }) + .slice(0, NUMBER_OF_VALUES_PER_GROUP) + .map(([tagValue, fvEntries]) => { + return { + name: tagValue, + link: + `/p/${projectName}` + + createSearchLink( + FEAST_FCO_TYPES["featureView"], + selectedTag, + tagValue + ), + label: `Feature Services where ${selectedTag} is '${tagValue}'`, + count: fvEntries.length, + }; + }), + }); + } + ); + } + + return suggestions; +}; + +const useFCOExploreSuggestions = () => { + const query = useFeatureViewTagsAggregation(); + const tagAggregation = query.data; + + const { projectName } = useParams(); + + let data: ExplorationSuggestion[] | undefined = undefined; + + if (query.isSuccess && tagAggregation && projectName) { + data = generateExplorationSuggestions(tagAggregation, projectName); + } + + return { + ...query, + data, + }; +}; + +export default useFCOExploreSuggestions; +export { + generateExplorationSuggestions, + sortTagByUniqueValues, + sortTagsByTotalUsage, +}; +export type { ExplorationSuggestion }; diff --git a/ui/src/hooks/useMatchSubpath.ts b/ui/src/hooks/useMatchSubpath.ts new file mode 100644 index 00000000000..b8a72f9e3d7 --- /dev/null +++ b/ui/src/hooks/useMatchSubpath.ts @@ -0,0 +1,15 @@ +import { useResolvedPath, useMatch } from "react-router"; + +const useMatchSubpath = (to: string) => { + const resolved = useResolvedPath(to); + + return useMatch({ path: resolved.pathname, end: false }) !== null; +}; + +const useMatchExact = (to: string) => { + const resolved = useResolvedPath(to); + + return useMatch({ path: resolved.pathname, end: true }) !== null; +}; + +export { useMatchSubpath, useMatchExact }; diff --git a/ui/src/hooks/useSearchInputWithTags.ts b/ui/src/hooks/useSearchInputWithTags.ts new file mode 100644 index 00000000000..53d6784a0ce --- /dev/null +++ b/ui/src/hooks/useSearchInputWithTags.ts @@ -0,0 +1,321 @@ +import { useState } from "react"; + +import { useQueryParam, StringParam } from "use-query-params"; +import { encodeQueryParams } from "serialize-query-params"; +import { stringify } from "query-string"; + +import { sortTagsByTotalUsage } from "./useFCOExploreSuggestions"; + +type tagTokenType = Record<"key" | "value", string>; +type tagTokenGroupsType = Record; +type tagAggregationRecordType = + | Record> + | undefined; + +type SuggestionModes = "KEY" | "VALUE"; + +interface filterInputInterface { + tagTokenGroups: tagTokenGroupsType; + searchTokens: string[]; +} + +interface TagSuggestionInstance { + suggestion: string; + description: string; +} + +const generateEmptyStateSuggestions = ( + tagsAggregationData: tagAggregationRecordType +) => { + if (tagsAggregationData) { + return sortTagsByTotalUsage(tagsAggregationData).map( + ([tagKey, recordOfTagValues]) => { + const uniqueValues = Object.keys(recordOfTagValues).length; + const totalEntries = Object.values(recordOfTagValues).reduce( + (memo, current) => { + return memo + current.length; + }, + 0 + ); + + return { + suggestion: tagKey, + description: `${uniqueValues} unique tag values. ${totalEntries} total entries.`, + }; + } + ); + } else { + return []; + } +}; + +const generateTagKeySuggestions = ( + input: string, + tagsAggregationData: tagAggregationRecordType +) => { + if (tagsAggregationData) { + return Object.entries(tagsAggregationData) + .filter(([potentialTagKey, summary]) => { + return potentialTagKey.indexOf(input) >= 0; + }) + .map(([potentialTagKey, summary]) => { + const tagValueVariants = Object.entries(summary); + + return { + suggestion: potentialTagKey, + description: `${tagValueVariants.length} different tag values`, + }; + }); + } else { + return []; + } +}; + +const generateTagValueSuggestions = ( + input: string, + tagsAggregationData: tagAggregationRecordType +) => { + if (tagsAggregationData) { + const [currentTagKey, currentTagValue] = input.split(":"); + const entriesWithTagKey = tagsAggregationData[currentTagKey]; + + const summarizeCallback = (entry: unknown[]) => { + const potentialTagKey = entry[0] as string; + const summary = entry[1] as unknown[]; + + return { + suggestion: potentialTagKey, + description: `${summary.length} entries`, + }; + }; + + if (entriesWithTagKey) { + if (currentTagValue && currentTagValue.length > 0) { + return Object.entries(entriesWithTagKey) + .filter(([potentialTagValue, entries]) => { + return ( + potentialTagValue.indexOf(currentTagValue) >= 0 // && + // potentialTagValue !== currentTagValue // Don't show exact matches, b/c that means we probably already selected it + ); + }) + .map(summarizeCallback); + } else { + return Object.entries(entriesWithTagKey).map(summarizeCallback); + } + } else { + return []; + } + } else { + return []; + } +}; + +function getAllSpacePositions(s: string) { + const indices: number[] = []; + while ( + s.indexOf(" ", indices.length ? indices[indices.length - 1] + 1 : 0) !== + -1 && + indices.length < 100 + ) { + const position = indices[indices.length - 1] || 0; + const index = s.indexOf(" ", position + 1); + indices.push(index); + } + return indices; +} + +interface TagSplitterReturnInterface { + chunks: string[]; + tokenInFocusIndex: number; + currentTag: string; +} + +const parseTokenInput = ( + cursorPosition: number | undefined, + tagsString: string +): TagSplitterReturnInterface => { + // Get where the spaces in the tagString, plus a start and end value + // e.g. "A:a B:b" would return + // [0, 3, 7] + const chunks = tagsString.split(" "); + + const allSpacePositions = [0] + .concat(getAllSpacePositions(tagsString)) + .concat(tagsString.length + 1); + + let tokenInFocusIndex = 0; + if (cursorPosition) { + tokenInFocusIndex = allSpacePositions.findIndex((value, index) => { + return ( + cursorPosition >= value && + cursorPosition <= allSpacePositions[index + 1] + ); + }); + } + + const currentTag = chunks[tokenInFocusIndex] || ""; + + return { + currentTag, + chunks, + tokenInFocusIndex, + }; +}; + +const useSearchQuery = () => { + const [query, setQuery] = useQueryParam("q", StringParam); + const searchString = query || ""; + + const searchTokens = searchString.split(" ").filter((t) => t.length >= 3); + + const setSearchString = (d: string) => { + setQuery(d); + }; + + return { + searchString, + searchTokens, + setSearchString, + }; +}; + +const useTagsWithSuggestions = ( + tagsAggregationData: tagAggregationRecordType +) => { + const [rawtagsString, setTagsStringParam] = useQueryParam( + "tags", + StringParam + ); + + const tagsString = rawtagsString || ""; + + // Spaces in the beginning of the string + // really messes with parseTokenInput(). Just prevent it. + const setTagsString = (s: string) => { + setTagsStringParam(s.trimStart()); + }; + + const [cursorPosition, setCursor] = useState(undefined); + const setCursorPosition = (position: number | undefined) => { + setCursor(position); + }; + + // Parse input into tokens, and detect which token + // we are focused on given the current cursor position + const { chunks, tokenInFocusIndex, currentTag } = parseTokenInput( + cursorPosition, + tagsString + ); + + const suggestionMode: SuggestionModes = + currentTag.indexOf(":") < 0 ? "KEY" : "VALUE"; + + let tagSuggestions: TagSuggestionInstance[] = []; + if (tagsAggregationData) { + if (currentTag.length > 0) { + if (suggestionMode === "KEY") { + tagSuggestions = generateTagKeySuggestions( + currentTag, + tagsAggregationData + ); + } else { + tagSuggestions = generateTagValueSuggestions( + currentTag, + tagsAggregationData + ); + } + } else { + // Current Tag is empty + tagSuggestions = generateEmptyStateSuggestions(tagsAggregationData); + } + } + + // Helper method for accepting suggestions + const setSuggestionAtPositionInTagsString = ( + suggestion: string, + position: number + ) => { + const nextTagsTokens = chunks.slice(0); + nextTagsTokens[position] = suggestion; + + setTagsString(nextTagsTokens.join(" ")); + }; + + const acceptSuggestion = (suggestion: TagSuggestionInstance) => { + if (suggestionMode === "KEY") { + const newKeyText = suggestion.suggestion + ":"; + + setSuggestionAtPositionInTagsString(newKeyText, tokenInFocusIndex); + } else { + const [currentTagKey] = currentTag.split(":"); + + const newTagText = `${currentTagKey}:` + suggestion.suggestion; + + setSuggestionAtPositionInTagsString(newTagText, tokenInFocusIndex); + } + }; + + const tagKeysSet = new Set(); + + const tagTokens: tagTokenType[] = chunks + .filter((chunk: string) => { + return chunk.indexOf(":") > 0; + }) + .map((chunk) => { + const parts = chunk.split(":"); + tagKeysSet.add(parts[0]); + + return { + key: parts[0], + value: parts[1], + }; + }); + + const tagTokenGroups = tagTokens.reduce( + (memo: Record, current) => { + if (memo[current.key]) { + memo[current.key].push(current.value); + } else { + memo[current.key] = [current.value]; + } + + return memo; + }, + {} + ); + + return { + setCursorPosition, + currentTag, + tagsString, + setTagsString, + tagTokens, + tagTokenGroups, + tagKeysSet, // Used to determine which columns to add to search results, + suggestionMode, + tagSuggestions, + acceptSuggestion, + }; +}; + +const encodeSearchQueryString = (query: string) => { + return stringify( + encodeQueryParams( + { + tags: StringParam, + }, + { + tags: query, + } + ) + ); +}; + +export { useTagsWithSuggestions, useSearchQuery }; +export { encodeSearchQueryString }; +export type { + filterInputInterface, + tagTokenGroupsType, + TagSuggestionInstance, + SuggestionModes, +}; diff --git a/ui/src/hooks/useTagsAggregation.ts b/ui/src/hooks/useTagsAggregation.ts new file mode 100644 index 00000000000..21480fa8b0c --- /dev/null +++ b/ui/src/hooks/useTagsAggregation.ts @@ -0,0 +1,85 @@ +import { useContext, useMemo } from "react"; +import RegistryPathContext from "../contexts/RegistryPathContext"; +import { FeastFeatureServiceType } from "../parsers/feastFeatureServices"; +import { FeastFeatureViewType } from "../parsers/feastFeatureViews"; +import useLoadRegistry from "../queries/useLoadRegistry"; + +// Usage of generic type parameter T +// https://stackoverflow.com/questions/53203409/how-to-tell-typescript-that-im-returning-an-array-of-arrays-of-the-input-type +const buildTagCollection = ( + array: T[], + recordExtractor: (unknownFCO: T) => Record | undefined // Assumes that tags are always a Record +): Record> => { + const tagCollection = array.reduce( + (memo: Record>, fco: T) => { + const tags = recordExtractor(fco); + + if (tags) { + Object.entries(tags).forEach(([tagKey, tagValue]) => { + if (!memo[tagKey]) { + memo[tagKey] = { + [tagValue]: [fco], + }; + } else { + if (!memo[tagKey][tagValue]) { + memo[tagKey][tagValue] = [fco]; + } else { + memo[tagKey][tagValue].push(fco); + } + } + }); + } + + return memo; + }, + {} + ); + + return tagCollection; +}; + +const useFeatureViewTagsAggregation = () => { + const registryUrl = useContext(RegistryPathContext); + const query = useLoadRegistry(registryUrl); + + const data = useMemo(() => { + return query.data && query.data.objects && query.data.objects.featureViews + ? buildTagCollection( + query.data.objects.featureViews, + (fv) => { + return fv.spec.tags; + } + ) + : undefined; + }, [query.data]); + + return { + ...query, + data, + }; +}; + +const useFeatureServiceTagsAggregation = () => { + const registryUrl = useContext(RegistryPathContext); + const query = useLoadRegistry(registryUrl); + + const data = useMemo(() => { + return query.data && + query.data.objects && + query.data.objects.featureServices + ? buildTagCollection( + query.data.objects.featureServices, + (fs) => { + return fs.spec.tags; + } + ) + : undefined; + }, [query.data]); + + return { + ...query, + data, + }; +}; + +export { useFeatureViewTagsAggregation, useFeatureServiceTagsAggregation }; diff --git a/ui/src/index.css b/ui/src/index.css new file mode 100644 index 00000000000..60869353c81 --- /dev/null +++ b/ui/src/index.css @@ -0,0 +1,25 @@ +@supports (font-variation-settings: normal) { + html { + font-family: "Inter var", "system-ui"; + } +} + +html { + background: url("feast-icon-grey.svg") no-repeat -6vh 56vh; + background-size: 50vh; + background-attachment: fixed; +} + +body { + margin: 0; + font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", + "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", + monospace; +} diff --git a/ui/src/index.tsx b/ui/src/index.tsx new file mode 100644 index 00000000000..21008a1103e --- /dev/null +++ b/ui/src/index.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import "./index.css"; +import App from "./App"; +import reportWebVitals from "./reportWebVitals"; +import { BrowserRouter } from "react-router-dom"; +import { QueryClient, QueryClientProvider } from "react-query"; +import { QueryParamProvider } from "use-query-params"; +import RouteAdapter from "./hacks/RouteAdapter"; + +const queryClient = new QueryClient(); + +ReactDOM.render( + + + + + + + + + , + document.getElementById("root") +); + +// If you want to start measuring performance in your app, pass a function +// to log results (for example: reportWebVitals(console.log)) +// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals +reportWebVitals(); diff --git a/ui/src/logo.svg b/ui/src/logo.svg new file mode 100644 index 00000000000..9dfc1c058ce --- /dev/null +++ b/ui/src/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/mocks/handlers.ts b/ui/src/mocks/handlers.ts new file mode 100644 index 00000000000..f69458717e8 --- /dev/null +++ b/ui/src/mocks/handlers.ts @@ -0,0 +1,32 @@ +import { rest } from "msw"; +import registry from "../../public/registry.json"; + +const projectsListWithDefaultProject = rest.get( + "/projects-list.json", + (req, res, ctx) => { + return res( + ctx.status(200), + ctx.json({ + default: "credit_score_project", + projects: [ + { + name: "Credit Score Project", + description: + "Project for credit scoring team and associated models.", + id: "credit_score_project", + registryPath: "/registry.json", + }, + ], + }) + ); + } +); + +const creditHistoryRegistry = rest.get("/registry.json", (req, res, ctx) => { + return res(ctx.status(200), ctx.json(registry)); +}); + +export { + projectsListWithDefaultProject, + creditHistoryRegistry +}; diff --git a/ui/src/pages/CustomTabUtils.tsx b/ui/src/pages/CustomTabUtils.tsx new file mode 100644 index 00000000000..577e1b86035 --- /dev/null +++ b/ui/src/pages/CustomTabUtils.tsx @@ -0,0 +1,219 @@ +import React, { useState, useEffect } from "react"; + +import { + DataSourceCustomTabs, + FeatureServiceCustomTabs, + RegularFeatureViewCustomTabs, + EntityCustomTabs, + OnDemandFeatureViewCustomTabs, + DatasetCustomTabs, +} from "../custom-tabs/CustomTabsRegistry"; +import { + useResolvedPath, + resolvePath, + useLocation, + NavigateFunction, + Route, +} from "react-router"; + +import { + CustomTabRegistrationInterface, + DataSourceCustomTabRegistrationInterface, + EntityCustomTabRegistrationInterface, + FeatureServiceCustomTabRegistrationInterface, + RegularFeatureViewCustomTabRegistrationInterface, + OnDemandFeatureViewCustomTabRegistrationInterface, + DatasetCustomTabRegistrationInterface, +} from "../custom-tabs/types"; + +import RegularFeatureViewCustomTabLoadingWrapper from "../utils/custom-tabs/RegularFeatureViewCustomTabLoadingWrapper"; +import OnDemandFeatureViewCustomTabLoadingWrapper from "../utils/custom-tabs/OnDemandFeatureViewCustomTabLoadingWrapper"; +import FeatureServiceCustomTabLoadingWrapper from "../utils/custom-tabs/FeatureServiceCustomTabLoadingWrapper"; +import DataSourceCustomTabLoadingWrapper from "../utils/custom-tabs/DataSourceCustomTabLoadingWrapper"; +import EntityCustomTabLoadingWrapper from "../utils/custom-tabs/EntityCustomTabLoadingWrapper"; +import DatasetCustomTabLoadingWrapper from "../utils/custom-tabs/DatasetCustomTabLoadingWrapper"; + +interface NavigationTabInterface { + label: string; + isSelected: boolean; + onClick: () => void; +} + +const useGenericCustomTabsNavigation = < + T extends CustomTabRegistrationInterface +>( + entries: T[], + navigate: NavigateFunction +) => { + // Check for Duplicates + const arrayOfPaths = entries.map((tab) => tab.path); + + const duplicatedPaths = arrayOfPaths.filter( + (item, index) => arrayOfPaths.indexOf(item) !== index + ); + + // Throw error if multiple custom tabs being registered to the same path + if (duplicatedPaths.length) { + throw new Error( + `More than one tabs registered for path url: ${duplicatedPaths.join( + ", " + )}` + ); + } + + const [customNavigationTabs, setTabs] = useState( + [] + ); + + const featureViewRoot = useResolvedPath(""); // Root of Feature View Section + const { pathname } = useLocation(); // Current Location + + useEffect(() => { + setTabs( + entries.map(({ label, path }) => { + const resolvedTabPath = resolvePath(path, featureViewRoot.pathname); + + return { + label, + // Can't use the match hooks here b/c we're in a loop due + // to React hooks needing a predictable number of + // hooks to be run. See: https://reactjs.org/docs/hooks-rules.html + isSelected: pathname === resolvedTabPath.pathname, + onClick: () => { + navigate(path); + }, + }; + }) + ); + }, [pathname, navigate, featureViewRoot.pathname, entries]); + + return { + customNavigationTabs, + }; +}; + +const useRegularFeatureViewCustomTabs = (navigate: NavigateFunction) => { + return useGenericCustomTabsNavigation( + RegularFeatureViewCustomTabs, + navigate + ); +}; + +const useOnDemandFeatureViewCustomTabs = (navigate: NavigateFunction) => { + return useGenericCustomTabsNavigation( + OnDemandFeatureViewCustomTabs, + navigate + ); +}; + +const useFeatureServiceCustomTabs = (navigate: NavigateFunction) => { + return useGenericCustomTabsNavigation( + FeatureServiceCustomTabs, + navigate + ); +}; + +const useDataSourceCustomTabs = (navigate: NavigateFunction) => { + return useGenericCustomTabsNavigation( + DataSourceCustomTabs, + navigate + ); +}; + +const useEntityCustomTabs = (navigate: NavigateFunction) => { + return useGenericCustomTabsNavigation( + EntityCustomTabs, + navigate + ); +}; + +const useDatasetCustomTabs = (navigate: NavigateFunction) => { + return useGenericCustomTabsNavigation( + DatasetCustomTabs, + navigate + ); +}; + +// Creating Routes +interface InnerComponent { + label: string; + path: string; + Component: (props: T) => JSX.Element; +} +type WrapperComponentType = ({ + Component, +}: { + Component: (props: T) => JSX.Element; +}) => JSX.Element; + +const genericCustomTabRoutes = ( + tabs: InnerComponent[], + WrapperComponent: WrapperComponentType +) => { + return tabs.map(({ path, Component }) => { + const WrappedComponent = () => { + return ; + }; + + return ( + } /> + ); + }); +}; + +const regularFeatureViewCustomTabRoutes = () => { + return genericCustomTabRoutes( + RegularFeatureViewCustomTabs, + RegularFeatureViewCustomTabLoadingWrapper + ); +}; + +const onDemandFeatureViewCustomTabRoutes = () => { + return genericCustomTabRoutes( + OnDemandFeatureViewCustomTabs, + OnDemandFeatureViewCustomTabLoadingWrapper + ); +}; + +const featureServiceCustomTabRoutes = () => { + return genericCustomTabRoutes( + FeatureServiceCustomTabs, + FeatureServiceCustomTabLoadingWrapper + ); +}; + +const dataSourceCustomTabRoutes = () => { + return genericCustomTabRoutes( + DataSourceCustomTabs, + DataSourceCustomTabLoadingWrapper + ); +}; + +const entityCustomTabRoutes = () => { + return genericCustomTabRoutes( + EntityCustomTabs, + EntityCustomTabLoadingWrapper + ); +}; + +const datasetCustomTabRoutes = () => { + return genericCustomTabRoutes( + DatasetCustomTabs, + DatasetCustomTabLoadingWrapper + ); +}; + +export { + useRegularFeatureViewCustomTabs, + regularFeatureViewCustomTabRoutes, + useOnDemandFeatureViewCustomTabs, + onDemandFeatureViewCustomTabRoutes, + useFeatureServiceCustomTabs, + featureServiceCustomTabRoutes, + useDataSourceCustomTabs, + dataSourceCustomTabRoutes, + useEntityCustomTabs, + entityCustomTabRoutes, + useDatasetCustomTabs, + datasetCustomTabRoutes, +}; diff --git a/ui/src/pages/Layout.tsx b/ui/src/pages/Layout.tsx new file mode 100644 index 00000000000..f4f5efd0e3b --- /dev/null +++ b/ui/src/pages/Layout.tsx @@ -0,0 +1,60 @@ +import React from "react"; + +import { + EuiPage, + EuiPageSideBar, + EuiPageBody, + EuiErrorBoundary, + EuiHorizontalRule, + EuiSpacer, +} from "@elastic/eui"; +import Sidebar from "./Sidebar"; +import { Outlet } from "react-router"; +import ProjectSelector from "../components/ProjectSelector"; +import { useParams } from "react-router-dom"; +import RegistryPathContext from "../contexts/RegistryPathContext"; +import useLoadProjectsList from "../queries/useLoadProjectsList"; +import feastWorkMark from "../feast-workmark.svg"; + +const Layout = () => { + let { projectName } = useParams(); + + const { data } = useLoadProjectsList(); + + const currentProject = data?.projects.find((project) => { + return project.id === projectName; + }); + + const registryPath = currentProject?.registryPath || ""; + + return ( + + + + Feast + + + {registryPath && ( + + + + + )} + + + + + + + + + + ); +}; + +export default Layout; diff --git a/ui/src/pages/NoMatch.tsx b/ui/src/pages/NoMatch.tsx new file mode 100644 index 00000000000..6e2461ee61d --- /dev/null +++ b/ui/src/pages/NoMatch.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +const NoMatch = () => { + return
404
; +}; + +export default NoMatch; diff --git a/ui/src/pages/ProjectOverviewPage.tsx b/ui/src/pages/ProjectOverviewPage.tsx new file mode 100644 index 00000000000..00e6bf1aa75 --- /dev/null +++ b/ui/src/pages/ProjectOverviewPage.tsx @@ -0,0 +1,99 @@ +import React, { useContext } from "react"; + +import { + EuiPageContent, + EuiPageContentBody, + EuiText, + EuiFlexGroup, + EuiFlexItem, + EuiTitle, + EuiSpacer, + EuiLoadingContent, + EuiEmptyPrompt, +} from "@elastic/eui"; + +import { useDocumentTitle } from "../hooks/useDocumentTitle"; +import ObjectsCountStats from "../components/ObjectsCountStats"; +import ExplorePanel from "../components/ExplorePanel"; +import useLoadRegistry from "../queries/useLoadRegistry"; +import RegistryPathContext from "../contexts/RegistryPathContext"; + +const ProjectOverviewPage = () => { + useDocumentTitle("Feast Home"); + const registryUrl = useContext(RegistryPathContext); + const { isLoading, isSuccess, isError, data } = useLoadRegistry(registryUrl); + + return ( + + + +

+ {isLoading && } + {isSuccess && data?.project && `Project: ${data.project}`} +

+
+ + + + + {isLoading && } + {isError && ( + Error Loading Project Configs} + body={ +

+ There was an error loading the Project Configurations. + Please check that feature_store.json file is + available and well-formed. +

+ } + /> + )} + {isSuccess && + (data?.description ? ( + +
{data.description}
+
+ ) : ( + +

+ Welcome to your new Feast project. In this UI, you can see + Data Sources, Entities, Feature Views and Feature Services + registered in Feast. +

+

+ It look like this project already have some objects + registered. If you are new to this project, we suggest + starting by exploring the Feature Services, as they + represent the collection of Feature Views serving a + particular model. +

+

+ Note: We encourage you to replace this + welcome message with more suitable content for your team. + You can do so by specifying a{" "} + project_description in your{" "} + feature_store.yaml file. +

+
+ ))} + +
+ + + +
+
+
+ ); +}; + +export default ProjectOverviewPage; diff --git a/ui/src/pages/RootProjectSelectionPage.tsx b/ui/src/pages/RootProjectSelectionPage.tsx new file mode 100644 index 00000000000..115f7ba53b1 --- /dev/null +++ b/ui/src/pages/RootProjectSelectionPage.tsx @@ -0,0 +1,76 @@ +import React, { useEffect } from "react"; +import { + EuiCard, + EuiFlexGrid, + EuiFlexItem, + EuiIcon, + EuiLoadingContent, + EuiPageContent, + EuiPageContentBody, + EuiText, + EuiTitle, + EuiHorizontalRule, +} from "@elastic/eui"; +import useLoadProjectsList from "../queries/useLoadProjectsList"; +import { useNavigate } from "react-router-dom"; +import feastIconBlue from "../feast-icon-blue.svg"; + +const RootProjectSelectionPage = () => { + const { isLoading, isSuccess, data } = useLoadProjectsList(); + const navigate = useNavigate(); + + useEffect(() => { + if (data && data.default) { + // If a default is set, redirect there. + navigate(`/p/${data.default}`); + } + + if (data && data.projects.length === 1) { + // If there is only one project, redirect there. + navigate(`/p/${data.projects[0].id}`); + } + }, [data, navigate]); + + const projectCards = data?.projects.map((item, index) => { + return ( + + } + title={`${item.name}`} + description={item?.description || ""} + onClick={() => { + navigate(`/p/${item.id}`); + }} + /> + + ); + }); + + return ( + + + +

Welcome to Feast

+
+ +

Select one of the projects.

+
+ + {isLoading && } + {isSuccess && data?.projects && ( + + {projectCards} + + )} +
+
+ ); +}; + +export default RootProjectSelectionPage; diff --git a/ui/src/pages/Sidebar.tsx b/ui/src/pages/Sidebar.tsx new file mode 100644 index 00000000000..50081856e9d --- /dev/null +++ b/ui/src/pages/Sidebar.tsx @@ -0,0 +1,127 @@ +import React, { useContext, useState } from "react"; + +import { EuiIcon, EuiSideNav, htmlIdGenerator } from "@elastic/eui"; +import { useNavigate, useParams } from "react-router-dom"; +import { useMatchSubpath } from "../hooks/useMatchSubpath"; +import useLoadRegistry from "../queries/useLoadRegistry"; +import RegistryPathContext from "../contexts/RegistryPathContext"; + +import DataSourceIcon from "../data-source-icon.svg"; +import EntityIcon from "../entity-icon.svg"; +import FeatureViewIcon from "../feature-view.svg"; +import FeatureServiceIcon from "../feature-service.svg"; +import DatasetIcon from "../dataset-icon.svg"; + +const SideNav = () => { + const registryUrl = useContext(RegistryPathContext); + const { isSuccess, data } = useLoadRegistry(registryUrl); + const { projectName } = useParams(); + + const [isSideNavOpenOnMobile, setisSideNavOpenOnMobile] = useState(false); + + const navigate = useNavigate(); + + const toggleOpenOnMobile = () => { + setisSideNavOpenOnMobile(!isSideNavOpenOnMobile); + }; + + const dataSourcesLabel = `Data Sources ${ + isSuccess && data?.objects.dataSources + ? `(${data?.objects.dataSources?.length})` + : "" + }`; + + const entitiesLabel = `Entities ${ + isSuccess && data?.objects.entities + ? `(${data?.objects.entities?.length})` + : "" + }`; + + const featureViewsLabel = `Feature Views ${ + isSuccess && data?.mergedFVList && data?.mergedFVList.length > 0 + ? `(${data?.mergedFVList.length})` + : "" + }`; + + const featureServicesLabel = `Feature Services ${ + isSuccess && data?.objects.featureServices + ? `(${data?.objects.featureServices?.length})` + : "" + }`; + + const savedDatasetsLabel = `Datasets ${ + isSuccess && data?.objects.savedDatasets + ? `(${data?.objects.savedDatasets?.length})` + : "" + }`; + + const sideNav = [ + { + name: "Home", + id: htmlIdGenerator("basicExample")(), + onClick: () => { + navigate(`/p/${projectName}/`); + }, + items: [ + { + name: dataSourcesLabel, + id: htmlIdGenerator("dataSources")(), + icon: , + onClick: () => { + navigate(`/p/${projectName}/data-source`); + }, + isSelected: useMatchSubpath("data-source"), + }, + { + name: entitiesLabel, + id: htmlIdGenerator("entities")(), + icon: , + onClick: () => { + navigate(`/p/${projectName}/entity`); + }, + isSelected: useMatchSubpath("entity"), + }, + { + name: featureViewsLabel, + id: htmlIdGenerator("featureView")(), + icon: , + onClick: () => { + navigate(`/p/${projectName}/feature-view`); + }, + isSelected: useMatchSubpath("feature-view"), + }, + { + name: featureServicesLabel, + id: htmlIdGenerator("featureService")(), + icon: , + onClick: () => { + navigate(`/p/${projectName}/feature-service`); + }, + isSelected: useMatchSubpath("feature-service"), + }, + { + name: savedDatasetsLabel, + id: htmlIdGenerator("savedDatasets")(), + icon: , + onClick: () => { + navigate(`/p/${projectName}/data-set`); + }, + isSelected: useMatchSubpath("data-set"), + }, + ], + }, + ]; + + return ( + toggleOpenOnMobile()} + isOpenOnMobile={isSideNavOpenOnMobile} + style={{ width: 192 }} + items={sideNav} + /> + ); +}; + +export default SideNav; diff --git a/ui/src/pages/data-sources/BatchSourcePropertiesView.tsx b/ui/src/pages/data-sources/BatchSourcePropertiesView.tsx new file mode 100644 index 00000000000..6d5e6ea86fd --- /dev/null +++ b/ui/src/pages/data-sources/BatchSourcePropertiesView.tsx @@ -0,0 +1,116 @@ +import React from "react"; +import { + EuiCodeBlock, + EuiDescriptionList, + EuiDescriptionListDescription, + EuiDescriptionListTitle, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiSpacer, + EuiTitle, + } from "@elastic/eui"; + +interface BatchSourcePropertiesViewProps { + batchSource: { + type?: string | undefined; + dataSourceClassType?: string | undefined; + fileOptions?: { + fileUrl?: string | undefined; + } | undefined; + meta?: { + latestEventTimestamp?: Date | undefined; + earliestEventTimestamp?: Date | undefined; + } | undefined; + bigqueryOptions?: { + dbtModelSerialized?: string | undefined + } | undefined; + } +} + +const BatchSourcePropertiesView = (props: BatchSourcePropertiesViewProps) => { + const batchSource = props.batchSource; + return ( + + + + + {(batchSource.dataSourceClassType || batchSource.type) && + + Source Type + {batchSource.dataSourceClassType ? ( + + {batchSource.dataSourceClassType + .split(".") + .at(-1)} + ) + : batchSource.type ? ( + {batchSource.type} + ) + : ""} + } + + {batchSource.fileOptions && ( + + + File URL + + + {batchSource.fileOptions + ? batchSource.fileOptions.fileUrl + : ""} + + + )} + {batchSource.meta?.latestEventTimestamp && ( + + + Latest Event + + + {batchSource.meta.latestEventTimestamp.toLocaleDateString( + "en-CA" + )} + + + )} + {batchSource.meta?.earliestEventTimestamp && ( + + + Earliest Event + + + {batchSource.meta.earliestEventTimestamp.toLocaleDateString( + "en-CA" + )} + + + )} + + + + {batchSource.bigqueryOptions?.dbtModelSerialized && ( + + + + )} + {batchSource.bigqueryOptions?.dbtModelSerialized && ( + + +

Dbt Transformation

+
+ + {batchSource.bigqueryOptions.dbtModelSerialized} + +
+ )} +
+
); +}; + +export default BatchSourcePropertiesView; diff --git a/ui/src/pages/data-sources/DataSourceDbt.tsx b/ui/src/pages/data-sources/DataSourceDbt.tsx new file mode 100644 index 00000000000..43864a135ed --- /dev/null +++ b/ui/src/pages/data-sources/DataSourceDbt.tsx @@ -0,0 +1,33 @@ +import React from "react"; +import { + EuiCodeBlock, + EuiPanel, + EuiHorizontalRule, + EuiTitle, + } from "@elastic/eui"; +import { useParams } from "react-router"; +import useLoadDataSource from "./useLoadDataSource"; + +const DataSourceDbt = () => { + let { dataSourceName } = useParams(); + + const dsName = dataSourceName === undefined ? "" : dataSourceName; + + const { isSuccess, data } = useLoadDataSource(dsName); + + return isSuccess && data && data.bigqueryOptions ? ( + + +

Dbt Transformation

+
+ + + {data.bigqueryOptions.dbtModelSerialized} + +
+ ) : ( + No data so sad + ); +}; + +export default DataSourceDbt; diff --git a/ui/src/pages/data-sources/DataSourceIndexEmptyState.tsx b/ui/src/pages/data-sources/DataSourceIndexEmptyState.tsx new file mode 100644 index 00000000000..1a925770cc6 --- /dev/null +++ b/ui/src/pages/data-sources/DataSourceIndexEmptyState.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import { EuiEmptyPrompt, EuiTitle, EuiLink, EuiButton } from "@elastic/eui"; + +import feastIconBlue from "../../feast-icon-blue.svg"; + +const DataSourceIndexEmptyState = () => { + return ( + There are no data sources} + body={ +

+ This project does not have any Data Sources. Learn more about creating + Data Sources in Feast Docs. +

+ } + actions={ + { + window.open( + "https://docs.feast.dev/getting-started/concepts/data-source", + "_blank" + ); + }} + > + Open Data Sources Docs + + } + footer={ + <> + +

Want to learn more?

+
+ + Read Feast documentation + + + } + /> + ); +}; + +export default DataSourceIndexEmptyState; diff --git a/ui/src/pages/data-sources/DataSourceInstance.tsx b/ui/src/pages/data-sources/DataSourceInstance.tsx new file mode 100644 index 00000000000..f2ef3c9b9b3 --- /dev/null +++ b/ui/src/pages/data-sources/DataSourceInstance.tsx @@ -0,0 +1,82 @@ +import React from "react"; +import { Route, Routes, useNavigate, useParams } from "react-router-dom"; +import { + EuiPageHeader, + EuiPageContent, + EuiPageContentBody, +} from "@elastic/eui"; + +import DataSourceIcon from "../../data-source-icon.svg"; +import { useMatchExact, useMatchSubpath } from "../../hooks/useMatchSubpath"; +import { useDocumentTitle } from "../../hooks/useDocumentTitle"; +import DataSourceRawData from "./DataSourceRawData"; +import DataSourceOverviewTab from "./DataSourceOverviewTab"; +import DataSourceDbt from "./DataSourceDbt"; +import useLoadDataSource from "./useLoadDataSource"; + +import { + useDataSourceCustomTabs, + dataSourceCustomTabRoutes, +} from "../CustomTabUtils"; + +const DataSourceInstance = () => { + const navigate = useNavigate(); + let { dataSourceName } = useParams(); + + useDocumentTitle(`${dataSourceName} | Data Source | Feast`); + const dsName = dataSourceName === undefined ? "" : dataSourceName; + const { isSuccess, data } = useLoadDataSource(dsName); + + let tabs = [ + { + label: "Overview", + isSelected: useMatchExact(""), + onClick: () => { + navigate(""); + }, + }, + ]; + + const dbtTab = { + label: "Dbt Definition", + isSelected: useMatchSubpath("dbt"), + onClick: () => { + navigate("dbt"); + }, + }; + if (isSuccess && data?.bigqueryOptions?.dbtModelSerialized) { + tabs.push(dbtTab); + } + + const { customNavigationTabs } = useDataSourceCustomTabs(navigate); + tabs = tabs.concat(customNavigationTabs); + + return ( + + + + + + } /> + } /> + } /> + {dataSourceCustomTabRoutes()} + + + + + ); +}; + +export default DataSourceInstance; diff --git a/ui/src/pages/data-sources/DataSourceOverviewTab.tsx b/ui/src/pages/data-sources/DataSourceOverviewTab.tsx new file mode 100644 index 00000000000..f7c05000e78 --- /dev/null +++ b/ui/src/pages/data-sources/DataSourceOverviewTab.tsx @@ -0,0 +1,120 @@ +import { + EuiFlexGroup, + EuiHorizontalRule, + EuiLoadingSpinner, + EuiText, + EuiTitle, +} from "@elastic/eui"; +import { + EuiPanel, + EuiFlexItem, + EuiDescriptionList, + EuiDescriptionListTitle, + EuiDescriptionListDescription, + EuiSpacer, +} from "@elastic/eui"; +import React from "react"; +import { useParams } from "react-router-dom"; +import BatchSourcePropertiesView from "./BatchSourcePropertiesView"; +import FeatureViewEdgesList from "../entities/FeatureViewEdgesList"; +import RequestDataSourceSchemaTable from "./RequestDataSourceSchemaTable"; +import useLoadDataSource from "./useLoadDataSource"; + +const DataSourceOverviewTab = () => { + let { dataSourceName } = useParams(); + + const dsName = dataSourceName === undefined ? "" : dataSourceName; + const { isLoading, isSuccess, isError, data, consumingFeatureViews } = + useLoadDataSource(dsName); + const isEmpty = data === undefined; + console.log(consumingFeatureViews); + + return ( + + {isLoading && ( + + Loading + + )} + {isEmpty &&

No data source with name: {dataSourceName}

} + {isError &&

Error loading data source: {dataSourceName}

} + {isSuccess && data && ( + + + + + + + +

Properties

+
+ + {data.fileOptions || data.bigqueryOptions ? ( + + ) : data.requestDataOptions ? ( + + + + Source Type + + + {data.type} + + + + ): ( + "" + )} +
+
+
+ + + + {data.requestDataOptions ? ( + + +

Request Source Schema

+
+ + { + return { + fieldName: field, + valueType: type, + }; + })} + /> +
+ ) : ( + "" + )} +
+
+
+ + + +

Consuming Feature Views

+
+ + {consumingFeatureViews && consumingFeatureViews.length > 0 ? ( + { + return f.target.name; + })} + /> + ) : ( + No consuming feature views + )} +
+
+
+
+ )} +
+ ); +}; +export default DataSourceOverviewTab; diff --git a/ui/src/pages/data-sources/DataSourceRawData.tsx b/ui/src/pages/data-sources/DataSourceRawData.tsx new file mode 100644 index 00000000000..130eae6ba2a --- /dev/null +++ b/ui/src/pages/data-sources/DataSourceRawData.tsx @@ -0,0 +1,22 @@ +import React from "react"; +import { EuiPanel } from "@elastic/eui"; +import { useParams } from "react-router"; +import useLoadDataSource from "./useLoadDataSource"; + +const DataSourceRawData = () => { + let { dataSourceName } = useParams(); + + const dsName = dataSourceName === undefined ? "" : dataSourceName; + + const { isSuccess, data } = useLoadDataSource(dsName); + + return isSuccess && data ? ( + +
{JSON.stringify(data, null, 2)}
+
+ ) : ( + No data so sad + ); +}; + +export default DataSourceRawData; diff --git a/ui/src/pages/data-sources/DataSourcesListingTable.tsx b/ui/src/pages/data-sources/DataSourcesListingTable.tsx new file mode 100644 index 00000000000..661d18c7e9d --- /dev/null +++ b/ui/src/pages/data-sources/DataSourcesListingTable.tsx @@ -0,0 +1,54 @@ +import React from "react"; +import { EuiBasicTable } from "@elastic/eui"; +import EuiCustomLink from "../../components/EuiCustomLink"; +import { FeastDatasourceType } from "../../parsers/feastDatasources"; +import { useParams } from "react-router-dom"; + +interface DatasourcesListingTableProps { + dataSources: FeastDatasourceType[]; +} + +const DatasourcesListingTable = ({ + dataSources, +}: DatasourcesListingTableProps) => { + const { projectName } = useParams(); + + const columns = [ + { + name: "Name", + field: "name", + sortable: true, + render: (name: string) => { + return ( + + {name} + + ); + }, + }, + { + name: "Type", + field: "type", + sortable: true, + }, + ]; + + const getRowProps = (item: FeastDatasourceType) => { + return { + "data-test-subj": `row-${item.name}`, + }; + }; + + return ( + + ); +}; + +export default DatasourcesListingTable; diff --git a/ui/src/pages/data-sources/Index.tsx b/ui/src/pages/data-sources/Index.tsx new file mode 100644 index 00000000000..1e36fca8577 --- /dev/null +++ b/ui/src/pages/data-sources/Index.tsx @@ -0,0 +1,67 @@ +import React, { useContext } from "react"; + +import { + EuiPageHeader, + EuiPageContent, + EuiPageContentBody, + EuiLoadingSpinner, +} from "@elastic/eui"; + +import DataSourceIcon from "../../data-source-icon.svg"; + +import useLoadRegistry from "../../queries/useLoadRegistry"; +import DatasourcesListingTable from "./DataSourcesListingTable"; +import { useDocumentTitle } from "../../hooks/useDocumentTitle"; +import RegistryPathContext from "../../contexts/RegistryPathContext"; +import DataSourceIndexEmptyState from "./DataSourceIndexEmptyState"; + +const useLoadDatasources = () => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.objects.dataSources; + + return { + ...registryQuery, + data, + }; +}; + +const Index = () => { + const { isLoading, isSuccess, isError, data } = useLoadDatasources(); + + useDocumentTitle(`Data Sources | Feast`); + + return ( + + + + + {isLoading && ( +

+ Loading +

+ )} + {isError &&

We encountered an error while loading.

} + {isSuccess && !data && } + {isSuccess && data && } +
+
+
+ ); +}; + +export default Index; diff --git a/ui/src/pages/data-sources/RequestDataSourceSchemaTable.tsx b/ui/src/pages/data-sources/RequestDataSourceSchemaTable.tsx new file mode 100644 index 00000000000..60ef4c406a4 --- /dev/null +++ b/ui/src/pages/data-sources/RequestDataSourceSchemaTable.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { EuiBasicTable } from "@elastic/eui"; +import { FEAST_FEATURE_VALUE_TYPES } from "../../parsers/types"; + +interface RequestDataSourceSchemaField { + fieldName: string; + valueType: FEAST_FEATURE_VALUE_TYPES; +} + +interface RequestDataSourceSchema { + fields: RequestDataSourceSchemaField[]; +} + +const RequestDataSourceSchemaTable = ({ fields }: RequestDataSourceSchema) => { + console.log(fields); + const columns = [ + { + name: "Field", + field: "fieldName", + }, + { + name: "Value Type", + field: "valueType", + }, + ]; + + const getRowProps = (item: RequestDataSourceSchemaField) => { + return { + "data-test-subj": `row-${item.fieldName}`, + }; + }; + + return ( + + ); +}; + +export default RequestDataSourceSchemaTable; diff --git a/ui/src/pages/data-sources/useLoadDataSource.ts b/ui/src/pages/data-sources/useLoadDataSource.ts new file mode 100644 index 00000000000..0a589df7ef0 --- /dev/null +++ b/ui/src/pages/data-sources/useLoadDataSource.ts @@ -0,0 +1,35 @@ +import { useContext } from "react"; +import RegistryPathContext from "../../contexts/RegistryPathContext"; +import { FEAST_FCO_TYPES } from "../../parsers/types"; +import useLoadRegistry from "../../queries/useLoadRegistry"; + +const useLoadDataSource = (dataSourceName: string) => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.objects.dataSources?.find( + (ds) => ds.name === dataSourceName + ); + + const consumingFeatureViews = + registryQuery.data === undefined + ? undefined + : registryQuery.data.relationships.filter( + (relationship) => { + return (relationship.source.type === FEAST_FCO_TYPES.dataSource && + relationship.source.name === data?.name && + relationship.target.type === FEAST_FCO_TYPES.featureView); + } + ); + + return { + ...registryQuery, + data, + consumingFeatureViews + }; +}; + +export default useLoadDataSource; diff --git a/ui/src/pages/entities/EntitiesListingTable.tsx b/ui/src/pages/entities/EntitiesListingTable.tsx new file mode 100644 index 00000000000..95bc4e6d858 --- /dev/null +++ b/ui/src/pages/entities/EntitiesListingTable.tsx @@ -0,0 +1,63 @@ +import React from "react"; +import { EuiBasicTable } from "@elastic/eui"; +import EuiCustomLink from "../../components/EuiCustomLink"; +import { FeastEntityType } from "../../parsers/feastEntities"; +import useFeatureViewEdgesByEntity from "./useFeatureViewEdgesByEntity"; +import { useParams } from "react-router"; + +interface EntitiesListingTableProps { + entities: FeastEntityType[]; +} + +const EntitiesListingTable = ({ entities }: EntitiesListingTableProps) => { + const { isSuccess, data } = useFeatureViewEdgesByEntity(); + const { projectName } = useParams(); + + const columns = [ + { + name: "Name", + field: "spec.name", + sortable: true, + render: (name: string) => { + return ( + + {name} + + ); + }, + }, + { + name: "Type", + field: "spec.valueType", + sortable: true, + render: (valueType: string) => { + return valueType; + }, + }, + { + name: "# of FVs", + render: (item: FeastEntityType) => { + if (isSuccess && data) { + return data[item.spec.name] ? data[item.spec.name].length : "0"; + } else { + return "."; + } + }, + }, + ]; + + const getRowProps = (item: FeastEntityType) => { + return { + "data-test-subj": `row-${item.spec.name}`, + }; + }; + + return ( + + ); +}; + +export default EntitiesListingTable; diff --git a/ui/src/pages/entities/EntityIndexEmptyState.tsx b/ui/src/pages/entities/EntityIndexEmptyState.tsx new file mode 100644 index 00000000000..6c311106e23 --- /dev/null +++ b/ui/src/pages/entities/EntityIndexEmptyState.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import { EuiEmptyPrompt, EuiTitle, EuiLink, EuiButton } from "@elastic/eui"; + +import feastIconBlue from "../../feast-icon-blue.svg"; + +const EntityIndexEmptyState = () => { + return ( + There are no entities} + body={ +

+ This project does not have any Entities. Learn more about creating + Entities in Feast Docs. +

+ } + actions={ + { + window.open( + "https://docs.feast.dev/getting-started/concepts/entity", + "_blank" + ); + }} + > + Open Entities Docs + + } + footer={ + <> + +

Want to learn more?

+
+ + Read Feast documentation + + + } + /> + ); +}; + +export default EntityIndexEmptyState; diff --git a/ui/src/pages/entities/EntityInstance.tsx b/ui/src/pages/entities/EntityInstance.tsx new file mode 100644 index 00000000000..eef81b94098 --- /dev/null +++ b/ui/src/pages/entities/EntityInstance.tsx @@ -0,0 +1,59 @@ +import React from "react"; +import { Route, Routes, useNavigate, useParams } from "react-router-dom"; +import { + EuiPageHeader, + EuiPageContent, + EuiPageContentBody, +} from "@elastic/eui"; + +import EntityIcon from "../../entity-icon.svg"; +import { useMatchExact, useMatchSubpath } from "../../hooks/useMatchSubpath"; +import EntityRawData from "./EntityRawData"; +import EntityOverviewTab from "./EntityOverviewTab"; +import { useDocumentTitle } from "../../hooks/useDocumentTitle"; +import { useEntityCustomTabs, entityCustomTabRoutes } from "../CustomTabUtils"; + +const EntityInstance = () => { + const navigate = useNavigate(); + let { entityName } = useParams(); + + const { customNavigationTabs } = useEntityCustomTabs(navigate); + + useDocumentTitle(`${entityName} | Entity | Feast`); + + return ( + + { + navigate(""); + }, + }, + ...customNavigationTabs, + ]} + /> + + + + } /> + {entityCustomTabRoutes()} + + + + + ); +}; + +export default EntityInstance; diff --git a/ui/src/pages/entities/EntityOverviewTab.tsx b/ui/src/pages/entities/EntityOverviewTab.tsx new file mode 100644 index 00000000000..ed539ff5eed --- /dev/null +++ b/ui/src/pages/entities/EntityOverviewTab.tsx @@ -0,0 +1,125 @@ +import { + EuiFlexGroup, + EuiHorizontalRule, + EuiLoadingSpinner, + EuiTitle, +} from "@elastic/eui"; +import { + EuiPanel, + EuiText, + EuiFlexItem, + EuiSpacer, + EuiDescriptionList, + EuiDescriptionListTitle, + EuiDescriptionListDescription, +} from "@elastic/eui"; +import React from "react"; +import { useParams } from "react-router-dom"; +import TagsDisplay from "../../components/TagsDisplay"; +import FeatureViewEdgesList from "./FeatureViewEdgesList"; +import useFeatureViewEdgesByEntity from "./useFeatureViewEdgesByEntity"; +import useLoadEntity from "./useLoadEntity"; + +const EntityOverviewTab = () => { + let { entityName } = useParams(); + + const eName = entityName === undefined ? "" : entityName; + const { isLoading, isSuccess, isError, data } = useLoadEntity(eName); + const isEmpty = data === undefined; + + const fvEdges = useFeatureViewEdgesByEntity(); + const fvEdgesSuccess = fvEdges.isSuccess; + const fvEdgesData = fvEdges.data; + + return ( + + {isLoading && ( + + Loading + + )} + {isEmpty &&

No entity with name: {entityName}

} + {isError &&

Error loading entity: {entityName}

} + {isSuccess && data && ( + + + + + +

Properties

+
+ + + Join Key + + {data.spec.joinKey} + + + Description + + {data.spec.description} + + + Value Type + + {data.spec.valueType} + + +
+ + + + Created + + {data.meta.createdTimestamp.toLocaleDateString("en-CA")} + + + Updated + + {data.meta.lastUpdatedTimestamp.toLocaleDateString("en-CA")} + + + +
+ + + +

Feature Views

+
+ + {fvEdgesSuccess && fvEdgesData ? ( + fvEdgesData[eName] ? ( + { + return r.target.name; + })} + /> + ) : ( + No feature views have this entity + ) + ) : ( + + Error loading feature views that have this entity. + + )} +
+ + + +

Labels

+
+ + {data.spec.labels ? ( + + ) : ( + No labels specified on this entity. + )} +
+
+
+
+ )} +
+ ); +}; +export default EntityOverviewTab; diff --git a/ui/src/pages/entities/EntityRawData.tsx b/ui/src/pages/entities/EntityRawData.tsx new file mode 100644 index 00000000000..cabfbaf88a2 --- /dev/null +++ b/ui/src/pages/entities/EntityRawData.tsx @@ -0,0 +1,22 @@ +import React from "react"; +import { EuiPanel } from "@elastic/eui"; +import { useParams } from "react-router"; +import useLoadEntity from "./useLoadEntity"; + +const EntityRawData = () => { + let { entityName } = useParams(); + + const eName = entityName === undefined ? "" : entityName; + + const { isSuccess, data } = useLoadEntity(eName); + + return isSuccess && data ? ( + +
{JSON.stringify(data, null, 2)}
+
+ ) : ( + No data so sad + ); +}; + +export default EntityRawData; diff --git a/ui/src/pages/entities/FeatureViewEdgesList.tsx b/ui/src/pages/entities/FeatureViewEdgesList.tsx new file mode 100644 index 00000000000..95bc51c56d7 --- /dev/null +++ b/ui/src/pages/entities/FeatureViewEdgesList.tsx @@ -0,0 +1,89 @@ +import React from "react"; +import { EuiBasicTable, EuiLoadingSpinner } from "@elastic/eui"; +import EuiCustomLink from "../../components/EuiCustomLink"; +import { useParams } from "react-router-dom"; +import useLoadRelationshipData from "../../queries/useLoadRelationshipsData"; +import { EntityRelation } from "../../parsers/parseEntityRelationships"; +import { FEAST_FCO_TYPES } from "../../parsers/types"; + +interface FeatureViewEdgesListInterace { + fvNames: string[]; +} + +const whereFSconsumesThisFv = (fvName: string) => { + return (r: EntityRelation) => { + return ( + r.source.name === fvName && + r.target.type === FEAST_FCO_TYPES.featureService + ); + }; +}; + +const useGetFSConsumersOfFV = (fvList: string[]) => { + const relationshipQuery = useLoadRelationshipData(); + + const data = relationshipQuery.data + ? fvList.reduce((memo: Record, fvName) => { + if (relationshipQuery.data) { + memo[fvName] = relationshipQuery.data + .filter(whereFSconsumesThisFv(fvName)) + .map((fs) => { + return fs.target.name; + }); + } + + return memo; + }, {}) + : undefined; + + return { + ...relationshipQuery, + data, + }; +}; + +const FeatureViewEdgesList = ({ fvNames }: FeatureViewEdgesListInterace) => { + const { projectName } = useParams(); + + const { isLoading, data } = useGetFSConsumersOfFV(fvNames); + + const columns = [ + { + name: "Name", + field: "", + render: (name: string) => { + return ( + + {name} + + ); + }, + }, + { + name: "FS Consumers", + render: (name: string) => { + return ( + + {isLoading && } + {data && data[name].length} + + ); + }, + }, + ]; + + const getRowProps = (item: string) => { + return { + "data-test-subj": `row-${item}`, + }; + }; + + return ( + + ); +}; + +export default FeatureViewEdgesList; diff --git a/ui/src/pages/entities/Index.tsx b/ui/src/pages/entities/Index.tsx new file mode 100644 index 00000000000..ed427804a93 --- /dev/null +++ b/ui/src/pages/entities/Index.tsx @@ -0,0 +1,63 @@ +import React, { useContext } from "react"; + +import { + EuiPageHeader, + EuiPageContent, + EuiPageContentBody, + EuiLoadingSpinner, +} from "@elastic/eui"; + +import EntityIcon from "../../entity-icon.svg"; + +import useLoadRegistry from "../../queries/useLoadRegistry"; +import EntitiesListingTable from "./EntitiesListingTable"; +import { useDocumentTitle } from "../../hooks/useDocumentTitle"; +import RegistryPathContext from "../../contexts/RegistryPathContext"; +import EntityIndexEmptyState from "./EntityIndexEmptyState"; + +const useLoadEntities = () => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.objects.entities; + + return { + ...registryQuery, + data, + }; +}; + +const Index = () => { + const { isLoading, isSuccess, isError, data } = useLoadEntities(); + + useDocumentTitle(`Entities | Feast`); + + return ( + + + + + {isLoading && ( +

+ Loading +

+ )} + {isError &&

We encountered an error while loading.

} + {isSuccess && !data && } + {isSuccess && data && } +
+
+
+ ); +}; + +export default Index; diff --git a/ui/src/pages/entities/useFeatureViewEdgesByEntity.ts b/ui/src/pages/entities/useFeatureViewEdgesByEntity.ts new file mode 100644 index 00000000000..01ea88cdb35 --- /dev/null +++ b/ui/src/pages/entities/useFeatureViewEdgesByEntity.ts @@ -0,0 +1,30 @@ +import useLoadRelationshipData from "../../queries/useLoadRelationshipsData"; +import { EntityRelation } from "../../parsers/parseEntityRelationships"; + +const entityGroupByName = (data: EntityRelation[]) => { + return data + .filter((edge) => { + return edge.source.type === "entity"; + }) + .reduce((memo: Record, current) => { + if (memo[current.source.name]) { + memo[current.source.name].push(current); + } else { + memo[current.source.name] = [current]; + } + + return memo; + }, {}); +}; + +const useFeatureViewEdgesByEntity = () => { + const query = useLoadRelationshipData(); + + return { + ...query, + data: + query.isSuccess && query.data ? entityGroupByName(query.data) : undefined, + }; +}; + +export default useFeatureViewEdgesByEntity; diff --git a/ui/src/pages/entities/useLoadEntity.ts b/ui/src/pages/entities/useLoadEntity.ts new file mode 100644 index 00000000000..a1ca6d55c16 --- /dev/null +++ b/ui/src/pages/entities/useLoadEntity.ts @@ -0,0 +1,22 @@ +import { useContext } from "react"; +import RegistryPathContext from "../../contexts/RegistryPathContext"; +import useLoadRegistry from "../../queries/useLoadRegistry"; + +const useLoadEntity = (entityName: string) => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.objects.entities?.find( + (fv) => fv.spec.name === entityName + ); + + return { + ...registryQuery, + data, + }; +}; + +export default useLoadEntity; diff --git a/ui/src/pages/feature-services/FeatureServiceIndexEmptyState.tsx b/ui/src/pages/feature-services/FeatureServiceIndexEmptyState.tsx new file mode 100644 index 00000000000..f842c0ccbd8 --- /dev/null +++ b/ui/src/pages/feature-services/FeatureServiceIndexEmptyState.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import { EuiEmptyPrompt, EuiTitle, EuiLink, EuiButton } from "@elastic/eui"; + +import feastIconBlue from "../../feast-icon-blue.svg"; + +const FeatureServiceIndexEmptyState = () => { + return ( + There are no feature services} + body={ +

+ This project does not have any Feature Services. Learn more about + creating Feature Services in Feast Docs. +

+ } + actions={ + { + window.open( + "https://docs.feast.dev/getting-started/concepts/feature-service", + "_blank" + ); + }} + > + Open Feature Services Docs + + } + footer={ + <> + +

Want to learn more?

+
+ + Read Feast documentation + + + } + /> + ); +}; + +export default FeatureServiceIndexEmptyState; diff --git a/ui/src/pages/feature-services/FeatureServiceInstance.tsx b/ui/src/pages/feature-services/FeatureServiceInstance.tsx new file mode 100644 index 00000000000..10b6130764d --- /dev/null +++ b/ui/src/pages/feature-services/FeatureServiceInstance.tsx @@ -0,0 +1,62 @@ +import React from "react"; +import { Route, Routes, useNavigate, useParams } from "react-router-dom"; +import { + EuiPageHeader, + EuiPageContent, + EuiPageContentBody, +} from "@elastic/eui"; + +import FeatureServiceIcon from "../../feature-service.svg"; +import { useMatchExact } from "../../hooks/useMatchSubpath"; +import FeatureServiceOverviewTab from "./FeatureServiceOverviewTab"; +import { useDocumentTitle } from "../../hooks/useDocumentTitle"; + +import { + useFeatureServiceCustomTabs, + featureServiceCustomTabRoutes, +} from "../CustomTabUtils"; + +const FeatureServiceInstance = () => { + const navigate = useNavigate(); + let { featureServiceName } = useParams(); + + useDocumentTitle(`${featureServiceName} | Feature Service | Feast`); + + const { customNavigationTabs } = useFeatureServiceCustomTabs(navigate); + + return ( + + { + navigate(""); + }, + }, + ...customNavigationTabs, + ]} + /> + + + + } /> + {featureServiceCustomTabRoutes()} + + + + + ); +}; + +export default FeatureServiceInstance; diff --git a/ui/src/pages/feature-services/FeatureServiceListingTable.tsx b/ui/src/pages/feature-services/FeatureServiceListingTable.tsx new file mode 100644 index 00000000000..b452b6e4b63 --- /dev/null +++ b/ui/src/pages/feature-services/FeatureServiceListingTable.tsx @@ -0,0 +1,96 @@ +import React from "react"; +import { + EuiBasicTable, + EuiTableComputedColumnType, + EuiTableFieldDataColumnType, +} from "@elastic/eui"; +import EuiCustomLink from "../../components/EuiCustomLink"; +import { + FeastFeatureInServiceType, + FeastFeatureServiceType, +} from "../../parsers/feastFeatureServices"; +import { useParams } from "react-router"; + +interface FeatureServiceListingTableProps { + tagKeysSet: Set; + featureServices: FeastFeatureServiceType[]; +} + +type FeatureServiceTypeColumn = + | EuiTableFieldDataColumnType + | EuiTableComputedColumnType; + +const FeatureServiceListingTable = ({ + tagKeysSet, + featureServices, +}: FeatureServiceListingTableProps) => { + const { projectName } = useParams(); + + const columns: FeatureServiceTypeColumn[] = [ + { + name: "Name", + field: "spec.name", + render: (name: string) => { + return ( + + {name} + + ); + }, + }, + { + name: "# of Features", + field: "spec.features", + render: (featureViews: FeastFeatureInServiceType[]) => { + var numFeatures = 0; + featureViews.forEach((featureView) => { + numFeatures += featureView.featureColumns.length; + }); + return numFeatures; + }, + }, + { + name: "Created at", + field: "meta.createdTimestamp", + render: (date: Date) => { + return date.toLocaleDateString("en-CA"); + }, + }, + ]; + + tagKeysSet.forEach((key) => { + columns.push({ + name: key, + render: (item: FeastFeatureServiceType) => { + let tag = n/a; + + const value = item.spec.tags ? item.spec.tags[key] : undefined; + + if (value) { + tag = {value}; + } + + return tag; + }, + }); + }); + + const getRowProps = (item: FeastFeatureServiceType) => { + return { + "data-test-subj": `row-${item.spec.name}`, + }; + }; + + return ( + + ); +}; + +export default FeatureServiceListingTable; diff --git a/ui/src/pages/feature-services/FeatureServiceOverviewTab.tsx b/ui/src/pages/feature-services/FeatureServiceOverviewTab.tsx new file mode 100644 index 00000000000..1655a3624bd --- /dev/null +++ b/ui/src/pages/feature-services/FeatureServiceOverviewTab.tsx @@ -0,0 +1,169 @@ +import { + EuiBadge, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiLoadingSpinner, + EuiPanel, + EuiSpacer, + EuiStat, + EuiText, + EuiTextAlign, + EuiTitle, +} from "@elastic/eui"; +import React from "react"; +import { useParams } from "react-router"; +import { useNavigate } from "react-router-dom"; +import FeaturesInServiceList from "../../components/FeaturesInServiceDisplay"; +import TagsDisplay from "../../components/TagsDisplay"; +import { encodeSearchQueryString } from "../../hooks/useSearchInputWithTags"; +import FeatureViewEdgesList from "../entities/FeatureViewEdgesList"; +import useLoadFeatureService from "./useLoadFeatureService"; + +const FeatureServiceOverviewTab = () => { + let { featureServiceName, projectName } = useParams(); + + const fsName = featureServiceName === undefined ? "" : featureServiceName; + + const { isLoading, isSuccess, isError, data, entities } = + useLoadFeatureService(fsName); + const isEmpty = data === undefined; + + let numFeatures = 0; + let numFeatureViews = 0; + if (data) { + data.spec.features.forEach((featureView) => { + numFeatureViews += 1; + numFeatures += featureView.featureColumns.length; + }); + } + + const navigate = useNavigate(); + + return ( + + {isLoading && ( + + Loading + + )} + {isEmpty &&

No feature service with name: {featureServiceName}

} + {isError &&

Error loading feature service: {featureServiceName}

} + {isSuccess && data && ( + + + + + + + +

from

+
+
+ + + + + + +
+ + + + +

Features

+
+ + {data.spec.features ? ( + + ) : ( + + No features specified for this feature service. + + )} +
+
+ + + +

Tags

+
+ + {data.spec.tags ? ( + { + return ( + `/p/${projectName}/feature-service?` + + encodeSearchQueryString(`${key}:${value}`) + ); + }} + /> + ) : ( + No Tags specified on this feature service. + )} +
+ + + +

Entities

+
+ + {entities ? ( + + {entities.map((entity) => { + return ( + + { + navigate( + `/p/${projectName}/entity/${entity.name}` + ); + }} + onClickAriaLabel={entity.name} + data-test-sub="testExample1" + > + {entity.name} + + + ); + })} + + ) : ( + No Entities. + )} +
+ + + +

All Feature Views

+
+ + {data.spec.features.length > 0 ? ( + { + return f.featureViewName; + })} + /> + ) : ( + No feature views in this feature service + )} +
+
+
+
+ )} +
+ ); +}; + +export default FeatureServiceOverviewTab; diff --git a/ui/src/pages/feature-services/FeatureServiceRawData.tsx b/ui/src/pages/feature-services/FeatureServiceRawData.tsx new file mode 100644 index 00000000000..0f171a05b6f --- /dev/null +++ b/ui/src/pages/feature-services/FeatureServiceRawData.tsx @@ -0,0 +1,22 @@ +import React from "react"; +import { EuiPanel } from "@elastic/eui"; +import { useParams } from "react-router"; +import useLoadFeatureService from "./useLoadFeatureService"; + +const FeatureServiceRawData = () => { + let { featureServiceName } = useParams(); + + const fsName = featureServiceName === undefined ? "" : featureServiceName; + + const { isSuccess, data } = useLoadFeatureService(fsName); + + return isSuccess && data ? ( + +
{JSON.stringify(data, null, 2)}
+
+ ) : ( + No data so sad + ); +}; + +export default FeatureServiceRawData; diff --git a/ui/src/pages/feature-services/Index.tsx b/ui/src/pages/feature-services/Index.tsx new file mode 100644 index 00000000000..5f3f2c06335 --- /dev/null +++ b/ui/src/pages/feature-services/Index.tsx @@ -0,0 +1,176 @@ +import React, { useContext } from "react"; + +import { + EuiPageHeader, + EuiPageContent, + EuiPageContentBody, + EuiLoadingSpinner, + EuiTitle, + EuiSpacer, + EuiFlexGroup, + EuiFlexItem, + EuiFieldSearch, +} from "@elastic/eui"; + +import FeatureServiceIcon from "../../feature-service.svg"; + +import useLoadRegistry from "../../queries/useLoadRegistry"; +import FeatureServiceListingTable from "./FeatureServiceListingTable"; +import { + useSearchQuery, + useTagsWithSuggestions, + filterInputInterface, + tagTokenGroupsType, +} from "../../hooks/useSearchInputWithTags"; +import { FeastFeatureServiceType } from "../../parsers/feastFeatureServices"; +import { useDocumentTitle } from "../../hooks/useDocumentTitle"; +import RegistryPathContext from "../../contexts/RegistryPathContext"; +import FeatureServiceIndexEmptyState from "./FeatureServiceIndexEmptyState"; +import TagSearch from "../../components/TagSearch"; +import { useFeatureServiceTagsAggregation } from "../../hooks/useTagsAggregation"; + +const useLoadFeatureServices = () => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.objects.featureServices; + + return { + ...registryQuery, + data, + }; +}; + +const shouldIncludeFSsGivenTokenGroups = ( + entry: FeastFeatureServiceType, + tagTokenGroups: tagTokenGroupsType +) => { + return Object.entries(tagTokenGroups).every(([key, values]) => { + const entryTagValue = entry.spec.tags ? entry.spec.tags[key] : undefined; + + if (entryTagValue) { + return values.every((value) => { + return value.length > 0 ? entryTagValue.indexOf(value) >= 0 : true; // Don't filter if the string is empty + }); + } else { + return false; + } + }); +}; + +const filterFn = ( + data: FeastFeatureServiceType[], + filterInput: filterInputInterface +) => { + let filteredByTags = data; + + if (Object.keys(filterInput.tagTokenGroups).length) { + filteredByTags = data.filter((entry) => { + return shouldIncludeFSsGivenTokenGroups( + entry, + filterInput.tagTokenGroups + ); + }); + } + + if (filterInput.searchTokens.length) { + return filteredByTags.filter((entry) => { + return filterInput.searchTokens.find((token) => { + return token.length >= 3 && entry.spec.name.indexOf(token) >= 0; + }); + }); + } + + return filteredByTags; +}; + +const Index = () => { + const { isLoading, isSuccess, isError, data } = useLoadFeatureServices(); + const tagAggregationQuery = useFeatureServiceTagsAggregation(); + + useDocumentTitle(`Feature Services | Feast`); + + const { searchString, searchTokens, setSearchString } = useSearchQuery(); + + const { + currentTag, + tagsString, + tagTokenGroups, + tagKeysSet, + tagSuggestions, + suggestionMode, + setTagsString, + acceptSuggestion, + setCursorPosition, + } = useTagsWithSuggestions(tagAggregationQuery.data); + + const filterResult = data + ? filterFn(data, { tagTokenGroups, searchTokens }) + : data; + + return ( + + + + + {isLoading && ( +

+ Loading +

+ )} + {isError &&

We encountered an error while loading.

} + {isSuccess && !data && } + {isSuccess && filterResult && ( + + + + +

Search

+
+ { + setSearchString(e.target.value); + }} + /> +
+ + + +
+ + +
+ )} +
+
+
+ ); +}; + +export default Index; diff --git a/ui/src/pages/feature-services/useLoadFeatureService.ts b/ui/src/pages/feature-services/useLoadFeatureService.ts new file mode 100644 index 00000000000..be2242eae04 --- /dev/null +++ b/ui/src/pages/feature-services/useLoadFeatureService.ts @@ -0,0 +1,48 @@ +import { FEAST_FCO_TYPES } from "../../parsers/types"; +import { useContext } from "react"; +import RegistryPathContext from "../../contexts/RegistryPathContext"; + +import useLoadRegistry from "../../queries/useLoadRegistry"; +import { EntityReference } from "../../parsers/parseEntityRelationships"; + +const useLoadFeatureService = (featureServiceName: string) => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.objects.featureServices?.find( + (fs) => fs.spec.name === featureServiceName + ); + + let entities = + data === undefined + ? undefined + : registryQuery.data?.indirectRelationships + .filter((relationship) => { + return ( + relationship.target.type === FEAST_FCO_TYPES.featureService && + relationship.target.name === data.spec.name && + relationship.source.type === FEAST_FCO_TYPES.entity + ); + }) + .map((relationship) => { + return relationship.source; + }); + // Deduplicate on name of entity + if (entities) { + let entityToName: { [key: string]: EntityReference } = {}; + for (let entity of entities) { + entityToName[entity.name] = entity; + } + entities = Object.values(entityToName); + } + return { + ...registryQuery, + data, + entities, + }; +}; + +export default useLoadFeatureService; diff --git a/ui/src/pages/feature-views/ConsumingFeatureServicesList.tsx b/ui/src/pages/feature-views/ConsumingFeatureServicesList.tsx new file mode 100644 index 00000000000..fc98fe8e5ea --- /dev/null +++ b/ui/src/pages/feature-views/ConsumingFeatureServicesList.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import { EuiBasicTable } from "@elastic/eui"; +import EuiCustomLink from "../../components/EuiCustomLink"; +import { useParams } from "react-router-dom"; + +interface ConsumingFeatureServicesListInterace { + fsNames: string[]; +} + +const ConsumingFeatureServicesList = ({ + fsNames, +}: ConsumingFeatureServicesListInterace) => { + const { projectName } = useParams(); + + const columns = [ + { + name: "Name", + field: "", + render: (name: string) => { + return ( + + {name} + + ); + }, + }, + ]; + + const getRowProps = (item: string) => { + return { + "data-test-subj": `row-${item}`, + }; + }; + + return ( + + ); +}; + +export default ConsumingFeatureServicesList; diff --git a/ui/src/pages/feature-views/FeatureViewIndexEmptyState.tsx b/ui/src/pages/feature-views/FeatureViewIndexEmptyState.tsx new file mode 100644 index 00000000000..0bfdf480c22 --- /dev/null +++ b/ui/src/pages/feature-views/FeatureViewIndexEmptyState.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import { EuiEmptyPrompt, EuiTitle, EuiLink, EuiButton } from "@elastic/eui"; + +import feastIconBlue from "../../feast-icon-blue.svg"; + +const FeatureViewIndexEmptyState = () => { + return ( + There are no feature views} + body={ +

+ This project does not have any Feature Views. Learn more about + creating Feature Views in Feast Docs. +

+ } + actions={ + { + window.open( + "https://docs.feast.dev/getting-started/concepts/feature-view", + "_blank" + ); + }} + > + Open Feature View Docs + + } + footer={ + <> + +

Want to learn more?

+
+ + Read Feast documentation + + + } + /> + ); +}; + +export default FeatureViewIndexEmptyState; diff --git a/ui/src/pages/feature-views/FeatureViewInstance.tsx b/ui/src/pages/feature-views/FeatureViewInstance.tsx new file mode 100644 index 00000000000..b0fa7c32b03 --- /dev/null +++ b/ui/src/pages/feature-views/FeatureViewInstance.tsx @@ -0,0 +1,53 @@ +import React from "react"; + +import { useParams } from "react-router-dom"; +import { EuiLoadingSpinner } from "@elastic/eui"; + +import { FeastFeatureViewType } from "../../parsers/feastFeatureViews"; +import RegularFeatureInstance from "./RegularFeatureViewInstance"; +import { FEAST_FV_TYPES } from "../../parsers/mergedFVTypes"; +import { FeastODFVType } from "../../parsers/feastODFVS"; +import useLoadFeatureView from "./useLoadFeatureView"; +import OnDemandFeatureInstance from "./OnDemandFeatureViewInstance"; + +const FeatureViewInstance = () => { + const { featureViewName } = useParams(); + + const fvName = featureViewName === undefined ? "" : featureViewName; + + const { isLoading, isSuccess, isError, data } = useLoadFeatureView(fvName); + const isEmpty = data === undefined; + + if (isLoading) { + return ( + + Loading + + ); + } + if (isEmpty) { + return

No feature view with name: {featureViewName}

; + } + + if (isError) { + isError &&

Error loading feature view: {featureViewName}

; + } + + if (isSuccess && !isEmpty) { + if (data.type === FEAST_FV_TYPES.regular) { + const fv: FeastFeatureViewType = data.object; + + return ; + } + + if (data.type === FEAST_FV_TYPES.ondemand) { + const odfv: FeastODFVType = data.object; + + return ; + } + } + + return

No Data So Sad

; +}; + +export default FeatureViewInstance; diff --git a/ui/src/pages/feature-views/FeatureViewListingTable.tsx b/ui/src/pages/feature-views/FeatureViewListingTable.tsx new file mode 100644 index 00000000000..59f8b1ed7aa --- /dev/null +++ b/ui/src/pages/feature-views/FeatureViewListingTable.tsx @@ -0,0 +1,90 @@ +import React from "react"; +import { + EuiBasicTable, + EuiBadge, + EuiTableFieldDataColumnType, +} from "@elastic/eui"; +import EuiCustomLink from "../../components/EuiCustomLink"; +import { genericFVType } from "../../parsers/mergedFVTypes"; +import { EuiTableComputedColumnType } from "@elastic/eui/src/components/basic_table"; +import { useParams } from "react-router-dom"; + +interface FeatureViewListingTableProps { + tagKeysSet: Set; + featureViews: genericFVType[]; +} + +type genericFVTypeColumn = + | EuiTableFieldDataColumnType + | EuiTableComputedColumnType; + +const FeatureViewListingTable = ({ + tagKeysSet, + featureViews, +}: FeatureViewListingTableProps) => { + const { projectName } = useParams(); + + const columns: genericFVTypeColumn[] = [ + { + name: "Name", + field: "name", + sortable: true, + render: (name: string, item: genericFVType) => { + return ( + + {name} {item.type === "ondemand" && ondemand} + + ); + }, + }, + { + name: "# of Features", + field: "features", + sortable: true, + render: (features: unknown[]) => { + return features.length; + }, + }, + ]; + + // Add columns if they come up in search + tagKeysSet.forEach((key) => { + columns.push({ + name: key, + render: (item: genericFVType) => { + let tag = n/a; + + if (item.type === "regular") { + const value = item.object.spec.tags + ? item.object.spec.tags[key] + : undefined; + + if (value) { + tag = {value}; + } + } + + return tag; + }, + }); + }); + + const getRowProps = (item: genericFVType) => { + return { + "data-test-subj": `row-${item.name}`, + }; + }; + + return ( + + ); +}; + +export default FeatureViewListingTable; diff --git a/ui/src/pages/feature-views/FeatureViewRawData.tsx b/ui/src/pages/feature-views/FeatureViewRawData.tsx new file mode 100644 index 00000000000..1347ef8dcfe --- /dev/null +++ b/ui/src/pages/feature-views/FeatureViewRawData.tsx @@ -0,0 +1,22 @@ +import React from "react"; +import { EuiPanel } from "@elastic/eui"; +import { useParams } from "react-router"; +import useLoadFeatureView from "./useLoadFeatureView"; + +const FeatureViewRawData = () => { + let { featureViewName } = useParams(); + + const fvName = featureViewName === undefined ? "" : featureViewName; + + const { isSuccess, data } = useLoadFeatureView(fvName); + + return isSuccess && data ? ( + +
{JSON.stringify(data, null, 2)}
+
+ ) : ( + No data so sad + ); +}; + +export default FeatureViewRawData; diff --git a/ui/src/pages/feature-views/FeatureViewSummaryStatisticsTab.tsx b/ui/src/pages/feature-views/FeatureViewSummaryStatisticsTab.tsx new file mode 100644 index 00000000000..7371d4a73bf --- /dev/null +++ b/ui/src/pages/feature-views/FeatureViewSummaryStatisticsTab.tsx @@ -0,0 +1,84 @@ +import React from "react"; + +import { EuiEmptyPrompt, EuiLoadingContent, EuiTitle } from "@elastic/eui"; +import { useParams } from "react-router-dom"; +import useLoadFeatureViewSummaryStatistics from "../../queries/useLoadFeatureViewSummaryStatistics"; +import { + NumericColumnSummaryStatisticType, + StringColumnSummaryStatisticType, +} from "../../parsers/featureViewSummaryStatistics"; +import NumericFeaturesTable from "../../components/NumericFeaturesTable"; + +interface ColumnsByGroup { + INT64?: NumericColumnSummaryStatisticType[]; + STRING?: StringColumnSummaryStatisticType[]; +} + +const FeatureViewSummaryStatisticsTab = () => { + let { featureViewName } = useParams(); + + if (!featureViewName) { + throw new Error("Unable to get Feature View Name"); + } + + const { isError, data } = + useLoadFeatureViewSummaryStatistics(featureViewName); + + if (isError) { + return ( + Error loading Statistics} + body={ +

+ There was an error loading statistics for{" "} + {featureViewName}. Please check that statistics + have been generated. +

+ } + /> + ); + } + + if (data) { + const columnsByGroup = Object.entries( + data.columnsSummaryStatistics + ).reduce((memo, [key, columnStatistics]) => { + if (columnStatistics.valueType === "INT64") { + if (!memo["INT64"]) { + memo[columnStatistics.valueType] = [columnStatistics]; + } else { + memo["INT64"].push(columnStatistics); + } + } + + if (columnStatistics.valueType === "STRING") { + if (!memo["STRING"]) { + memo[columnStatistics.valueType] = [columnStatistics]; + } else { + memo["STRING"].push(columnStatistics); + } + } + + return memo; + }, {}); + + return ( + + {columnsByGroup["INT64"] && ( + <> + +

Numeric Columns

+
+ + + )} +
+ ); + } + + return ; +}; + +export default FeatureViewSummaryStatisticsTab; diff --git a/ui/src/pages/feature-views/Index.tsx b/ui/src/pages/feature-views/Index.tsx new file mode 100644 index 00000000000..c54bd45b380 --- /dev/null +++ b/ui/src/pages/feature-views/Index.tsx @@ -0,0 +1,178 @@ +import React, { useContext } from "react"; + +import { + EuiPageHeader, + EuiPageContent, + EuiPageContentBody, + EuiLoadingSpinner, + EuiSpacer, + EuiTitle, + EuiFieldSearch, + EuiFlexGroup, + EuiFlexItem, +} from "@elastic/eui"; + +import FeatureViewIcon from "../../feature-view.svg"; + +import useLoadRegistry from "../../queries/useLoadRegistry"; +import FeatureViewListingTable from "./FeatureViewListingTable"; +import { + filterInputInterface, + useSearchQuery, + useTagsWithSuggestions, +} from "../../hooks/useSearchInputWithTags"; +import { genericFVType, regularFVInterface } from "../../parsers/mergedFVTypes"; +import { useDocumentTitle } from "../../hooks/useDocumentTitle"; +import RegistryPathContext from "../../contexts/RegistryPathContext"; +import FeatureViewIndexEmptyState from "./FeatureViewIndexEmptyState"; +import { useFeatureViewTagsAggregation } from "../../hooks/useTagsAggregation"; +import TagSearch from "../../components/TagSearch"; + +const useLoadFeatureViews = () => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.mergedFVList; + + return { + ...registryQuery, + data, + }; +}; + +const shouldIncludeFVsGivenTokenGroups = ( + entry: regularFVInterface, + tagTokenGroups: Record +) => { + return Object.entries(tagTokenGroups).every(([key, values]) => { + const entryTagValue = entry.object.spec.tags + ? entry.object.spec.tags[key] + : undefined; + + if (entryTagValue) { + return values.every((value) => { + return value.length > 0 ? entryTagValue.indexOf(value) >= 0 : true; // Don't filter if the string is empty + }); + } else { + return false; + } + }); +}; + +const filterFn = (data: genericFVType[], filterInput: filterInputInterface) => { + let filteredByTags = data; + + if (Object.keys(filterInput.tagTokenGroups).length) { + filteredByTags = data.filter((entry) => { + if (entry.type === "regular") { + return shouldIncludeFVsGivenTokenGroups( + entry, + filterInput.tagTokenGroups + ); + } else { + return false; // ODFVs don't have tags yet + } + }); + } + + if (filterInput.searchTokens.length) { + return filteredByTags.filter((entry) => { + return filterInput.searchTokens.find((token) => { + return token.length >= 3 && entry.name.indexOf(token) >= 0; + }); + }); + } + + return filteredByTags; +}; + +const Index = () => { + const { isLoading, isSuccess, isError, data } = useLoadFeatureViews(); + const tagAggregationQuery = useFeatureViewTagsAggregation(); + + useDocumentTitle(`Feature Views | Feast`); + + const { searchString, searchTokens, setSearchString } = useSearchQuery(); + + const { + currentTag, + tagsString, + tagTokenGroups, + tagKeysSet, + tagSuggestions, + suggestionMode, + setTagsString, + acceptSuggestion, + setCursorPosition, + } = useTagsWithSuggestions(tagAggregationQuery.data); + + const filterResult = data + ? filterFn(data, { tagTokenGroups, searchTokens }) + : data; + + return ( + + + + + {isLoading && ( +

+ Loading +

+ )} + {isError &&

We encountered an error while loading.

} + {isSuccess && data?.length === 0 && } + {isSuccess && data && data.length > 0 && filterResult && ( + + + + +

Search

+
+ { + setSearchString(e.target.value); + }} + /> +
+ + + +
+ + +
+ )} +
+
+
+ ); +}; + +export default Index; diff --git a/ui/src/pages/feature-views/OnDemandFeatureViewInstance.tsx b/ui/src/pages/feature-views/OnDemandFeatureViewInstance.tsx new file mode 100644 index 00000000000..32f63732b71 --- /dev/null +++ b/ui/src/pages/feature-views/OnDemandFeatureViewInstance.tsx @@ -0,0 +1,68 @@ +import React from "react"; +import { Route, Routes, useNavigate } from "react-router"; +import { useParams } from "react-router-dom"; +import { + EuiPageHeader, + EuiPageContent, + EuiPageContentBody, +} from "@elastic/eui"; + +import FeatureViewIcon from "../../feature-view.svg"; +import { useMatchExact } from "../../hooks/useMatchSubpath"; +import { FeastODFVType } from "../../parsers/feastODFVS"; +import OnDemandFeatureViewOverviewTab from "./OnDemandFeatureViewOverviewTab"; + +import { + useOnDemandFeatureViewCustomTabs, + onDemandFeatureViewCustomTabRoutes, +} from "../CustomTabUtils"; + +interface OnDemandFeatureInstanceProps { + data: FeastODFVType; +} + +const OnDemandFeatureInstance = ({ data }: OnDemandFeatureInstanceProps) => { + const navigate = useNavigate(); + let { featureViewName } = useParams(); + + const { customNavigationTabs } = useOnDemandFeatureViewCustomTabs(navigate); + + return ( + + { + navigate(""); + }, + }, + ...customNavigationTabs, + ]} + /> + + + + } + /> + {onDemandFeatureViewCustomTabRoutes()} + + + + + ); +}; + +export default OnDemandFeatureInstance; diff --git a/ui/src/pages/feature-views/OnDemandFeatureViewOverviewTab.tsx b/ui/src/pages/feature-views/OnDemandFeatureViewOverviewTab.tsx new file mode 100644 index 00000000000..9bd725534ee --- /dev/null +++ b/ui/src/pages/feature-views/OnDemandFeatureViewOverviewTab.tsx @@ -0,0 +1,140 @@ +import { + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiText, + EuiTitle, + EuiPanel, + EuiCodeBlock, + EuiSpacer, +} from "@elastic/eui"; +import React from "react"; +import FeaturesListDisplay from "../../components/FeaturesListDisplay"; +import { + FeastODFVType, + RequestDataSourceType, + FeatureViewProjectionType, +} from "../../parsers/feastODFVS"; +import { EntityRelation } from "../../parsers/parseEntityRelationships"; +import { FEAST_FCO_TYPES } from "../../parsers/types"; +import useLoadRelationshipData from "../../queries/useLoadRelationshipsData"; +import FeatureViewProjectionDisplayPanel from "./components/FeatureViewProjectionDisplayPanel"; +import RequestDataDisplayPanel from "./components/RequestDataDisplayPanel"; +import ConsumingFeatureServicesList from "./ConsumingFeatureServicesList"; + +interface OnDemandFeatureViewOverviewTabProps { + data: FeastODFVType; +} + +const whereFSconsumesThisFv = (fvName: string) => { + return (r: EntityRelation) => { + return ( + r.source.name === fvName && + r.target.type === FEAST_FCO_TYPES.featureService + ); + }; +}; + +const OnDemandFeatureViewOverviewTab = ({ + data, +}: OnDemandFeatureViewOverviewTabProps) => { + const inputs = Object.entries(data.spec.inputs); + + const relationshipQuery = useLoadRelationshipData(); + const fsNames = relationshipQuery.data + ? relationshipQuery.data + .filter(whereFSconsumesThisFv(data.spec.name)) + .map((fs) => { + return fs.target.name; + }) + : []; + + return ( + + + + + +

Transformation

+
+ + + {data.spec.userDefinedFunction.body} + +
+
+
+ + + + +

Features ({data.spec.features.length})

+
+ + {data.spec.features ? ( + + ) : ( + No Tags sepcified on this feature view. + )} +
+
+ + + +

Inputs ({inputs.length})

+
+ + + {inputs.map(([key, inputGroup]) => { + if ((inputGroup as RequestDataSourceType).requestDataSource) { + return ( + + + + ); + } + + if (inputGroup as FeatureViewProjectionType) { + return ( + + + + ); + } + + return ( + + + {JSON.stringify(inputGroup, null, 2)} + + + ); + })} + +
+ + + +

Consuming Feature Services

+
+ + {fsNames.length > 0 ? ( + + ) : ( + No services consume this feature view + )} +
+
+
+
+ ); +}; + +export default OnDemandFeatureViewOverviewTab; diff --git a/ui/src/pages/feature-views/RegularFeatureViewInstance.tsx b/ui/src/pages/feature-views/RegularFeatureViewInstance.tsx new file mode 100644 index 00000000000..05f5c994375 --- /dev/null +++ b/ui/src/pages/feature-views/RegularFeatureViewInstance.tsx @@ -0,0 +1,85 @@ +import React from "react"; +import { Route, Routes, useNavigate } from "react-router"; +import { + EuiPageHeader, + EuiPageContent, + EuiPageContentBody, +} from "@elastic/eui"; + +import FeatureViewIcon from "../../feature-view.svg"; +import { enabledFeatureStatistics } from "../,,/../../flags"; +import { useMatchExact, useMatchSubpath } from "../../hooks/useMatchSubpath"; +import { FeastFeatureViewType } from "../../parsers/feastFeatureViews"; +import RegularFeatureViewOverviewTab from "./RegularFeatureViewOverviewTab"; +import FeatureViewSummaryStatisticsTab from "./FeatureViewSummaryStatisticsTab"; + +import { + useRegularFeatureViewCustomTabs, + regularFeatureViewCustomTabRoutes, +} from "../CustomTabUtils"; + +interface RegularFeatureInstanceProps { + data: FeastFeatureViewType; +} + +const RegularFeatureInstance = ({ data }: RegularFeatureInstanceProps) => { + const navigate = useNavigate(); + + const { customNavigationTabs } = useRegularFeatureViewCustomTabs(navigate); + let tabs = [ + { + label: "Overview", + isSelected: useMatchExact(""), + onClick: () => { + navigate(""); + }, + }, + ]; + + let statisticsIsSelected = useMatchSubpath("statistics"); + if (enabledFeatureStatistics) { + tabs.push({ + label: "Statistics", + isSelected: statisticsIsSelected, + onClick: () => { + navigate("statistics"); + }, + }); + } + + tabs.push(...customNavigationTabs); + + return ( + + + + + + } + /> + } + /> + {regularFeatureViewCustomTabRoutes()} + + + + + ); +}; + +export default RegularFeatureInstance; diff --git a/ui/src/pages/feature-views/RegularFeatureViewOverviewTab.tsx b/ui/src/pages/feature-views/RegularFeatureViewOverviewTab.tsx new file mode 100644 index 00000000000..70a7fdec173 --- /dev/null +++ b/ui/src/pages/feature-views/RegularFeatureViewOverviewTab.tsx @@ -0,0 +1,197 @@ +import { + EuiBadge, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiPanel, + EuiSpacer, + EuiStat, + EuiText, + EuiTitle, +} from "@elastic/eui"; +import React from "react"; + +import { useNavigate, useParams } from "react-router"; +import FeaturesListDisplay from "../../components/FeaturesListDisplay"; +import TagsDisplay from "../../components/TagsDisplay"; +import { encodeSearchQueryString } from "../../hooks/useSearchInputWithTags"; +import { FeastFeatureViewType } from "../../parsers/feastFeatureViews"; +import { EntityRelation } from "../../parsers/parseEntityRelationships"; +import { FEAST_FCO_TYPES } from "../../parsers/types"; +import useLoadRelationshipData from "../../queries/useLoadRelationshipsData"; +import BatchSourcePropertiesView from "../data-sources/BatchSourcePropertiesView"; +import ConsumingFeatureServicesList from "./ConsumingFeatureServicesList"; + +const whereFSconsumesThisFv = (fvName: string) => { + return (r: EntityRelation) => { + return ( + r.source.name === fvName && + r.target.type === FEAST_FCO_TYPES.featureService + ); + }; +}; + +interface RegularFeatureViewOverviewTabProps { + data: FeastFeatureViewType; +} + +const RegularFeatureViewOverviewTab = ({ + data, +}: RegularFeatureViewOverviewTabProps) => { + const navigate = useNavigate(); + + const { projectName } = useParams(); + const { featureViewName } = useParams(); + + const fvName = featureViewName === undefined ? "" : featureViewName; + + const relationshipQuery = useLoadRelationshipData(); + + const fsNames = relationshipQuery.data + ? relationshipQuery.data.filter(whereFSconsumesThisFv(fvName)).map((fs) => { + return fs.target.name; + }) + : []; + const numOfFs = fsNames.length; + + return ( + + + + + + {data.spec.batchSource.meta && ( + + + + )} + + {data.meta.lastUpdatedTimestamp && ( + + + + )} + + + + + + +

Features ({data.spec.features.length})

+
+ + {data.spec.features ? ( + + ) : ( + No Tags specified on this feature view. + )} +
+
+ + + +

Entities

+
+ + {data.spec.entities ? ( + + {data.spec.entities.map((entity) => { + return ( + + { + navigate(`/p/${projectName}/entity/${entity}`); + }} + onClickAriaLabel={entity} + data-test-sub="testExample1" + > + {entity} + + + ); + })} + + ) : ( + No Entities. + )} +
+ + + +

Consuming Feature Services

+
+ + {fsNames.length > 0 ? ( + + ) : ( + No services consume this feature view + )} +
+ + + +

Tags

+
+ + {data.spec.tags ? ( + { + return ( + `/p/${projectName}/feature-view?` + + encodeSearchQueryString(`${key}:${value}`) + ); + }} + /> + ) : ( + No Tags specified on this feature view. + )} +
+
+
+ + + + + +

Batch Source

+
+ + +
+
+
+ + + +

Materialization Intervals

+
+ + {data.meta.materializationIntervals?.map((interval, i) => { + return ( +

+ {interval.startTime.toLocaleDateString("en-CA")} to{" "} + {interval.endTime.toLocaleDateString("en-CA")} +

+ ); + })} +
+
+
+ ); +}; + +export default RegularFeatureViewOverviewTab; diff --git a/ui/src/pages/feature-views/components/FeatureViewProjectionDisplayPanel.tsx b/ui/src/pages/feature-views/components/FeatureViewProjectionDisplayPanel.tsx new file mode 100644 index 00000000000..7b110f326d7 --- /dev/null +++ b/ui/src/pages/feature-views/components/FeatureViewProjectionDisplayPanel.tsx @@ -0,0 +1,47 @@ +import React from "react"; +import { EuiBasicTable, EuiPanel, EuiText, EuiTitle } from "@elastic/eui"; + +import { FeatureViewProjectionType } from "../../../parsers/feastODFVS"; +import { useParams } from "react-router-dom"; +import EuiCustomLink from "../../../components/EuiCustomLink"; + +interface RequestDataDisplayPanelProps extends FeatureViewProjectionType {} + +const FeatureViewProjectionDisplayPanel = ({ + featureViewProjection, +}: RequestDataDisplayPanelProps) => { + const { projectName } = useParams(); + + const columns = [ + { + name: "Column Name", + field: "name", + }, + { + name: "Type", + field: "valueType", + }, + ]; + + return ( + + + Feature View + + + + {featureViewProjection.featureViewName} + + + + + ); +}; + +export default FeatureViewProjectionDisplayPanel; diff --git a/ui/src/pages/feature-views/components/RequestDataDisplayPanel.tsx b/ui/src/pages/feature-views/components/RequestDataDisplayPanel.tsx new file mode 100644 index 00000000000..a6e546d9d89 --- /dev/null +++ b/ui/src/pages/feature-views/components/RequestDataDisplayPanel.tsx @@ -0,0 +1,52 @@ +import React from "react"; +import { EuiBasicTable, EuiPanel, EuiText, EuiTitle } from "@elastic/eui"; +import { useParams } from "react-router-dom"; +import { RequestDataSourceType } from "../../../parsers/feastODFVS"; +import EuiCustomLink from "../../../components/EuiCustomLink"; + +interface RequestDataDisplayPanelProps extends RequestDataSourceType {} + +const RequestDataDisplayPanel = ({ + requestDataSource, +}: RequestDataDisplayPanelProps) => { + const { projectName } = useParams(); + + const items = Object.entries(requestDataSource.requestDataOptions.schema).map( + ([key, type]) => { + return { + key, + type, + }; + } + ); + + const columns = [ + { + name: "Key", + field: "key", + }, + { + name: "Type", + field: "type", + }, + ]; + + return ( + + + Request Data + + + + {requestDataSource.name} + + + + + ); +}; + +export default RequestDataDisplayPanel; diff --git a/ui/src/pages/feature-views/useLoadFeatureView.ts b/ui/src/pages/feature-views/useLoadFeatureView.ts new file mode 100644 index 00000000000..ded7900ea94 --- /dev/null +++ b/ui/src/pages/feature-views/useLoadFeatureView.ts @@ -0,0 +1,55 @@ +import { useContext } from "react"; +import RegistryPathContext from "../../contexts/RegistryPathContext"; +import useLoadRegistry from "../../queries/useLoadRegistry"; + +const useLoadFeatureView = (featureViewName: string) => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.mergedFVMap[featureViewName]; + + return { + ...registryQuery, + data, + }; +}; + +const useLoadRegularFeatureView = (featureViewName: string) => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.objects.featureViews?.find((fv) => { + return fv.spec.name === featureViewName; + }); + + return { + ...registryQuery, + data, + }; +}; + +const useLoadOnDemandFeatureView = (featureViewName: string) => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.objects.onDemandFeatureViews?.find((fv) => { + return fv.spec.name === featureViewName; + }); + + return { + ...registryQuery, + data, + }; +}; + +export default useLoadFeatureView; +export { useLoadRegularFeatureView, useLoadOnDemandFeatureView }; diff --git a/ui/src/pages/saved-data-sets/DatasetExpectationsTab.tsx b/ui/src/pages/saved-data-sets/DatasetExpectationsTab.tsx new file mode 100644 index 00000000000..f9dff39fad0 --- /dev/null +++ b/ui/src/pages/saved-data-sets/DatasetExpectationsTab.tsx @@ -0,0 +1,41 @@ +import React from "react"; +import { EuiPanel } from "@elastic/eui"; +import { useParams } from "react-router"; +import useLoadDataset from "./useLoadDataset"; + +const DatasetExpectationsTab = () => { + let { datasetName } = useParams(); + + if (!datasetName) { + throw new Error("Unable to get dataset name."); + } + const { isSuccess, data } = useLoadDataset(datasetName); + + if (!data || !data.spec.profile) { + return ( + + No data so sad + + ); + } + + let expectationsData; + + try { + expectationsData = JSON.parse(data.spec.profile); + } catch (e) { + throw new Error(`Unable to parse Expectations Profile: ${e}`); + } + + return isSuccess && expectationsData ? ( + +
{JSON.stringify(expectationsData, null, 2)}
+
+ ) : ( + + No data so sad + + ); +}; + +export default DatasetExpectationsTab; diff --git a/ui/src/pages/saved-data-sets/DatasetFeaturesTable.tsx b/ui/src/pages/saved-data-sets/DatasetFeaturesTable.tsx new file mode 100644 index 00000000000..6f670f37f5e --- /dev/null +++ b/ui/src/pages/saved-data-sets/DatasetFeaturesTable.tsx @@ -0,0 +1,28 @@ +import { EuiBasicTable } from "@elastic/eui"; +import React from "react"; + +interface DatasetFeatureEntry { + featureName: string; + featureViewName: string; +} + +interface DatasetFeaturesTableProps { + features: DatasetFeatureEntry[]; +} + +const DatasetFeaturesTable = ({ features }: DatasetFeaturesTableProps) => { + const columns = [ + { + name: "Feature", + field: "featureName", + }, + { + name: "Sourc Feature View", + field: "featureViewName", + }, + ]; + + return ; +}; + +export default DatasetFeaturesTable; diff --git a/ui/src/pages/saved-data-sets/DatasetInstance.tsx b/ui/src/pages/saved-data-sets/DatasetInstance.tsx new file mode 100644 index 00000000000..e2714d42235 --- /dev/null +++ b/ui/src/pages/saved-data-sets/DatasetInstance.tsx @@ -0,0 +1,71 @@ +import React from "react"; +import { Route, Routes, useNavigate, useParams } from "react-router-dom"; +import { + EuiPageHeader, + EuiPageContent, + EuiPageContentBody, +} from "@elastic/eui"; + +import DatasetIcon from "../../dataset-icon.svg"; + +import { useMatchExact, useMatchSubpath } from "../../hooks/useMatchSubpath"; +import DatasetOverviewTab from "./DatasetOverviewTab"; +import { useDocumentTitle } from "../../hooks/useDocumentTitle"; +import DatasetExpectationsTab from "./DatasetExpectationsTab"; +import { + datasetCustomTabRoutes, + useDatasetCustomTabs, +} from "../CustomTabUtils"; + +const DatasetInstance = () => { + const navigate = useNavigate(); + let { datasetName } = useParams(); + + useDocumentTitle(`${datasetName} | Saved Datasets | Feast`); + + const { customNavigationTabs } = useDatasetCustomTabs(navigate); + + return ( + + { + navigate(""); + }, + }, + { + label: "Expectations", + isSelected: useMatchSubpath("expectations"), + onClick: () => { + navigate("expectations"); + }, + }, + ...customNavigationTabs, + ]} + /> + + + + } /> + } /> + {datasetCustomTabRoutes()} + + + + + ); +}; + +export default DatasetInstance; diff --git a/ui/src/pages/saved-data-sets/DatasetJoinKeysTable.tsx b/ui/src/pages/saved-data-sets/DatasetJoinKeysTable.tsx new file mode 100644 index 00000000000..e8206916148 --- /dev/null +++ b/ui/src/pages/saved-data-sets/DatasetJoinKeysTable.tsx @@ -0,0 +1,23 @@ +import { EuiBasicTable } from "@elastic/eui"; +import React from "react"; + +interface DatasetJoinKey { + name: string; +} + +interface DatasetJoinKeysTableProps { + joinKeys: DatasetJoinKey[]; +} + +const DatasetJoinKeysTable = ({ joinKeys }: DatasetJoinKeysTableProps) => { + const columns = [ + { + name: "Name", + field: "name", + }, + ]; + + return ; +}; + +export default DatasetJoinKeysTable; diff --git a/ui/src/pages/saved-data-sets/DatasetOverviewTab.tsx b/ui/src/pages/saved-data-sets/DatasetOverviewTab.tsx new file mode 100644 index 00000000000..a20c83b1e21 --- /dev/null +++ b/ui/src/pages/saved-data-sets/DatasetOverviewTab.tsx @@ -0,0 +1,105 @@ +import { + EuiFlexGroup, + EuiHorizontalRule, + EuiLoadingSpinner, + EuiTitle, + EuiPanel, + EuiFlexItem, + EuiSpacer, + EuiDescriptionList, + EuiDescriptionListTitle, + EuiDescriptionListDescription, +} from "@elastic/eui"; +import React from "react"; +import { useParams } from "react-router-dom"; +import DatasetFeaturesTable from "./DatasetFeaturesTable"; +import DatasetJoinKeysTable from "./DatasetJoinKeysTable"; +import useLoadDataset from "./useLoadDataset"; + +const EntityOverviewTab = () => { + let { datasetName } = useParams(); + + if (!datasetName) { + throw new Error( + "Route doesn't have a 'datasetName' part. This route is likely rendering the wrong component." + ); + } + + const { isLoading, isSuccess, isError, data } = useLoadDataset(datasetName); + const isEmpty = data === undefined; + + return ( + + {isLoading && ( + + Loading + + )} + {isEmpty &&

No dataset with name: {datasetName}

} + {isError &&

Error loading dataset: {datasetName}

} + {isSuccess && data && ( + + + + + +

Features

+
+ + { + const [featureViewName, featureName] = + joinedName.split(":"); + + return { + featureViewName, + featureName, + }; + })} + /> +
+ + + +

Join Keys

+
+ + { + return { name: joinKey }; + })} + /> +
+
+ + + +

Properties

+
+ + + + Source Feature Service + + + {data.spec.featureService} + + +
+ + + + Created + + {data.meta.createdTimestamp.toLocaleDateString("en-CA")} + + + +
+
+
+ )} +
+ ); +}; +export default EntityOverviewTab; diff --git a/ui/src/pages/saved-data-sets/DatasetRawData.tsx b/ui/src/pages/saved-data-sets/DatasetRawData.tsx new file mode 100644 index 00000000000..efd17abcb6d --- /dev/null +++ b/ui/src/pages/saved-data-sets/DatasetRawData.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import { EuiPanel } from "@elastic/eui"; +import { useParams } from "react-router"; +import useLoadDataset from "./useLoadDataset"; + +const EntityRawData = () => { + let { datasetName } = useParams(); + + if (!datasetName) { + throw new Error("Unable to get dataset name."); + } + const { isSuccess, data } = useLoadDataset(datasetName); + + return isSuccess && data ? ( + +
{JSON.stringify(data, null, 2)}
+
+ ) : ( + + No data so sad + + ); +}; + +export default EntityRawData; diff --git a/ui/src/pages/saved-data-sets/DatasetsIndexEmptyState.tsx b/ui/src/pages/saved-data-sets/DatasetsIndexEmptyState.tsx new file mode 100644 index 00000000000..535a5fa1209 --- /dev/null +++ b/ui/src/pages/saved-data-sets/DatasetsIndexEmptyState.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import { EuiEmptyPrompt, EuiTitle, EuiLink, EuiButton } from "@elastic/eui"; + +import feastIconBlue from "../../feast-icon-blue.svg"; + +const DatasetsIndexEmptyState = () => { + return ( + There are no saved datasets} + body={ +

+ You currently do not have any saved datasets. Learn more about + creating saved datasets in Feast Docs. +

+ } + actions={ + { + window.open( + "https://docs.feast.dev/getting-started/concepts/dataset#creating-saved-dataset-from-historical-retrieval", + "_blank" + ); + }} + > + Open Dataset Docs + + } + footer={ + <> + +

Want to learn more?

+
+ + Read Feast documentation + + + } + /> + ); +}; + +export default DatasetsIndexEmptyState; diff --git a/ui/src/pages/saved-data-sets/DatasetsListingTable.tsx b/ui/src/pages/saved-data-sets/DatasetsListingTable.tsx new file mode 100644 index 00000000000..6b85c86b168 --- /dev/null +++ b/ui/src/pages/saved-data-sets/DatasetsListingTable.tsx @@ -0,0 +1,53 @@ +import React from "react"; +import { EuiBasicTable } from "@elastic/eui"; +import EuiCustomLink from "../../components/EuiCustomLink"; +import { useParams } from "react-router"; +import { FeastSavedDatasetType } from "../../parsers/feastSavedDataset"; + +interface DatasetsListingTableProps { + datasets: FeastSavedDatasetType[]; +} + +const DatasetsListingTable = ({ datasets }: DatasetsListingTableProps) => { + const { projectName } = useParams(); + + const columns = [ + { + name: "Name", + field: "spec.name", + sortable: true, + render: (name: string) => { + return ( + + {name} + + ); + }, + }, + { + name: "Source Feature Service", + field: "spec.featureService", + }, + { + name: "Created", + render: (item: FeastSavedDatasetType) => { + return item.meta.createdTimestamp.toLocaleDateString("en-CA"); + }, + }, + ]; + + const getRowProps = (item: FeastSavedDatasetType) => { + return { + "data-test-subj": `row-${item.spec.name}`, + }; + }; + + return ( + + ); +}; + +export default DatasetsListingTable; diff --git a/ui/src/pages/saved-data-sets/Index.tsx b/ui/src/pages/saved-data-sets/Index.tsx new file mode 100644 index 00000000000..0d551982794 --- /dev/null +++ b/ui/src/pages/saved-data-sets/Index.tsx @@ -0,0 +1,67 @@ +import React, { useContext } from "react"; + +import { + EuiPageHeader, + EuiPageContent, + EuiPageContentBody, + EuiLoadingSpinner, +} from "@elastic/eui"; + +import DatasetIcon from "../../dataset-icon.svg"; + +import useLoadRegistry from "../../queries/useLoadRegistry"; +import { useDocumentTitle } from "../../hooks/useDocumentTitle"; +import RegistryPathContext from "../../contexts/RegistryPathContext"; +import DatasetsListingTable from "./DatasetsListingTable"; +import DatasetsIndexEmptyState from "./DatasetsIndexEmptyState"; + +const useLoadSavedDataSets = () => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.objects.savedDatasets; + + return { + ...registryQuery, + data, + }; +}; + +const Index = () => { + const { isLoading, isSuccess, isError, data } = useLoadSavedDataSets(); + + useDocumentTitle(`Saved Datasets | Feast`); + + return ( + + + + + {isLoading && ( +

+ Loading +

+ )} + {isError &&

We encountered an error while loading.

} + {isSuccess && data && } + {isSuccess && !data && } +
+
+
+ ); +}; + +export default Index; diff --git a/ui/src/pages/saved-data-sets/useLoadDataset.ts b/ui/src/pages/saved-data-sets/useLoadDataset.ts new file mode 100644 index 00000000000..a3dbd3225d8 --- /dev/null +++ b/ui/src/pages/saved-data-sets/useLoadDataset.ts @@ -0,0 +1,22 @@ +import { useContext } from "react"; +import RegistryPathContext from "../../contexts/RegistryPathContext"; +import useLoadRegistry from "../../queries/useLoadRegistry"; + +const useLoadEntity = (entityName: string) => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.objects.savedDatasets?.find( + (fv) => fv.spec.name === entityName + ); + + return { + ...registryQuery, + data, + }; +}; + +export default useLoadEntity; diff --git a/ui/src/parsers/feastDatasources.ts b/ui/src/parsers/feastDatasources.ts new file mode 100644 index 00000000000..a9f58d716c3 --- /dev/null +++ b/ui/src/parsers/feastDatasources.ts @@ -0,0 +1,28 @@ +import { z } from "zod"; +import { FEAST_FEATURE_VALUE_TYPES } from "./types"; + +const FeastDatasourceSchema = z.object({ + type: z.string(), + eventTimestampColumn: z.string().optional(), + createdTimestampColumn: z.string().optional(), + fileOptions: z.object({ + fileUrl: z.string().optional(), + }).optional(), + name: z.string(), + meta: z.object({ + latestEventTimestamp: z.string().transform((val) => new Date(val)), + earliestEventTimestamp: z.string().transform((val) => new Date(val)), + }).optional(), + requestDataOptions: z.object({ + schema: z.record(z.nativeEnum(FEAST_FEATURE_VALUE_TYPES)), + }).optional(), + bigqueryOptions: z.object({ + tableRef: z.string().optional(), + dbtModelSerialized: z.string().optional() + }).optional(), +}); + +type FeastDatasourceType = z.infer; + +export { FeastDatasourceSchema }; +export type { FeastDatasourceType }; diff --git a/ui/src/parsers/feastEntities.ts b/ui/src/parsers/feastEntities.ts new file mode 100644 index 00000000000..d6fb337c0a3 --- /dev/null +++ b/ui/src/parsers/feastEntities.ts @@ -0,0 +1,21 @@ +import { z } from "zod"; +import { FEAST_FEATURE_VALUE_TYPES } from "./types"; + +const FeastEntitySchema = z.object({ + spec: z.object({ + name: z.string(), + valueType: z.nativeEnum(FEAST_FEATURE_VALUE_TYPES), + joinKey: z.string(), + description: z.string().optional(), + labels: z.record(z.string()).optional(), + }), + meta: z.object({ + createdTimestamp: z.string().transform((val) => new Date(val)), + lastUpdatedTimestamp: z.string().transform((val) => new Date(val)), + }), +}); + +type FeastEntityType = z.infer; + +export { FeastEntitySchema }; +export type { FeastEntityType }; diff --git a/ui/src/parsers/feastFeatureServices.ts b/ui/src/parsers/feastFeatureServices.ts new file mode 100644 index 00000000000..96c03e38efe --- /dev/null +++ b/ui/src/parsers/feastFeatureServices.ts @@ -0,0 +1,30 @@ +import { z } from "zod"; +import { FEAST_FEATURE_VALUE_TYPES } from "./types"; + +const FeatureColumnInService = z.object({ + name: z.string(), + valueType: z.nativeEnum(FEAST_FEATURE_VALUE_TYPES), +}); + +const FeatureInServiceSchema = z.object({ + featureViewName: z.string(), + featureColumns: z.array(FeatureColumnInService), +}); + +const FeastFeatureServiceSchema = z.object({ + spec: z.object({ + name: z.string(), + features: z.array(FeatureInServiceSchema), + tags: z.record(z.string()).optional(), + description: z.string().optional(), + }), + meta: z.object({ + createdTimestamp: z.string().transform((val) => new Date(val)), + }), +}); + +type FeastFeatureServiceType = z.infer; +type FeastFeatureInServiceType = z.infer; + +export { FeastFeatureServiceSchema }; +export type { FeastFeatureServiceType, FeastFeatureInServiceType }; diff --git a/ui/src/parsers/feastFeatureViews.ts b/ui/src/parsers/feastFeatureViews.ts new file mode 100644 index 00000000000..013f70b1fe7 --- /dev/null +++ b/ui/src/parsers/feastFeatureViews.ts @@ -0,0 +1,59 @@ +import { z } from "zod"; +import { FEAST_FEATURE_VALUE_TYPES } from "./types"; + +const FeastFeatureColumnSchema = z.object({ + name: z.string(), + valueType: z.nativeEnum(FEAST_FEATURE_VALUE_TYPES), +}); + +const FeastBatchSourceSchema = z.object({ + type: z.string(), + eventTimestampColumn: z.string().optional(), + createdTimestampColumn: z.string().optional(), + fileOptions: z.object({ + fileUrl: z.string().optional(), + }).optional(), + name: z.string(), + meta: z.object({ + earliestEventTimestamp: z.string().transform((val) => new Date(val)), + latestEventTimestamp: z.string().transform((val) => new Date(val)), + }).optional(), + requestDataOptions: z.object({ + schema: z.record(z.nativeEnum(FEAST_FEATURE_VALUE_TYPES)), + }).optional(), + bigqueryOptions: z.object({ + tableRef: z.string().optional(), + dbtModelSerialized: z.string().optional() + }).optional(), + dataSourceClassType: z.string(), +}); + +const FeastFeatureViewSchema = z.object({ + spec: z.object({ + name: z.string(), + entities: z.array(z.string()), + features: z.array(FeastFeatureColumnSchema), + ttl: z.string().transform((val) => parseInt(val)), + batchSource: FeastBatchSourceSchema, + online: z.boolean(), + tags: z.record(z.string()).optional(), + }), + meta: z.object({ + createdTimestamp: z.string().transform((val) => new Date(val)), + lastUpdatedTimestamp: z.string().transform((val) => new Date(val)), + materializationIntervals: z + .array( + z.object({ + startTime: z.string().transform((val) => new Date(val)), + endTime: z.string().transform((val) => new Date(val)), + }) + ) + .optional(), + }), +}); + +type FeastFeatureViewType = z.infer; +type FeastFeatureColumnType = z.infer; + +export { FeastFeatureViewSchema, FeastFeatureColumnSchema }; +export type { FeastFeatureViewType, FeastFeatureColumnType }; diff --git a/ui/src/parsers/feastODFVS.ts b/ui/src/parsers/feastODFVS.ts new file mode 100644 index 00000000000..ebac09e1634 --- /dev/null +++ b/ui/src/parsers/feastODFVS.ts @@ -0,0 +1,48 @@ +import { z } from "zod"; +import { FeastFeatureColumnSchema } from "./feastFeatureViews"; +import { FEAST_FEATURE_VALUE_TYPES } from "./types"; + +const FeatureViewProjectionSchema = z.object({ + featureViewProjection: z.object({ + featureViewName: z.string(), + featureColumns: z.array(FeastFeatureColumnSchema), + }), +}); + +const RequestDataSourceSchema = z.object({ + requestDataSource: z.object({ + type: z.string(), + name: z.string(), + requestDataOptions: z.object({ + schema: z.record(z.nativeEnum(FEAST_FEATURE_VALUE_TYPES)), + }), + }), +}); + +const ODFVInputsSchema = z.union([ + FeatureViewProjectionSchema, + RequestDataSourceSchema, +]); + +const FeastODFVSchema = z.object({ + spec: z.object({ + name: z.string(), + features: z.array(FeastFeatureColumnSchema), + inputs: z.record(ODFVInputsSchema), + userDefinedFunction: z.object({ + name: z.string(), + body: z.string(), + }), + }), + meta: z.object({ + createdTimestamp: z.string().transform((val) => new Date(val)), + lastUpdatedTimestamp: z.string().transform((val) => new Date(val)), + }), +}); + +type FeastODFVType = z.infer; +type RequestDataSourceType = z.infer; +type FeatureViewProjectionType = z.infer; + +export { FeastODFVSchema }; +export type { FeastODFVType, RequestDataSourceType, FeatureViewProjectionType }; diff --git a/ui/src/parsers/feastRegistry.ts b/ui/src/parsers/feastRegistry.ts new file mode 100644 index 00000000000..98e4fccca2a --- /dev/null +++ b/ui/src/parsers/feastRegistry.ts @@ -0,0 +1,22 @@ +import { z } from "zod"; +import { FeastDatasourceSchema } from "./feastDatasources"; +import { FeastEntitySchema } from "./feastEntities"; +import { FeastFeatureServiceSchema } from "./feastFeatureServices"; +import { FeastFeatureViewSchema } from "./feastFeatureViews"; +import { FeastSavedDatasetSchema } from "./feastSavedDataset"; +import { FeastODFVSchema } from "./feastODFVS"; + +const FeastRegistrySchema = z.object({ + project: z.string(), + dataSources: z.array(FeastDatasourceSchema).optional(), + entities: z.array(FeastEntitySchema).optional(), + featureViews: z.array(FeastFeatureViewSchema).optional(), + onDemandFeatureViews: z.array(FeastODFVSchema).optional(), + featureServices: z.array(FeastFeatureServiceSchema).optional(), + savedDatasets: z.array(FeastSavedDatasetSchema).optional(), +}); + +type FeastRegistryType = z.infer; + +export { FeastRegistrySchema }; +export type { FeastRegistryType }; diff --git a/ui/src/parsers/feastSavedDataset.ts b/ui/src/parsers/feastSavedDataset.ts new file mode 100644 index 00000000000..2c97acda742 --- /dev/null +++ b/ui/src/parsers/feastSavedDataset.ts @@ -0,0 +1,37 @@ +import { z } from "zod"; + +const FeastSavedDatasetSchema = z.object({ + spec: z.object({ + name: z.string(), + features: z.array(z.string()), + joinKeys: z.array(z.string()), + storage: z.object({ + fileStorage: z.object({ + fileFormat: z.object({ + parquestFormat: z.object({}).optional(), + }), + fileUrl: z.string(), + }), + }), + featureService: z + .object({ + spec: z.object({ + name: z.string(), + }), + }) + .transform((obj) => { + return obj.spec.name; + }), + profile: z.string().optional(), + }), + meta: z.object({ + createdTimestamp: z.string().transform((val) => new Date(val)), + minEventTimestamp: z.string().transform((val) => new Date(val)), + maxEventTimestamp: z.string().transform((val) => new Date(val)), + }), +}); + +type FeastSavedDatasetType = z.infer; + +export { FeastSavedDatasetSchema }; +export type { FeastSavedDatasetType }; diff --git a/ui/src/parsers/featureViewSummaryStatistics.ts b/ui/src/parsers/featureViewSummaryStatistics.ts new file mode 100644 index 00000000000..f8eca669d37 --- /dev/null +++ b/ui/src/parsers/featureViewSummaryStatistics.ts @@ -0,0 +1,56 @@ +import { z } from "zod"; + +const histogramSchema = z.array( + z.object({ + x0: z.number(), + x1: z.number(), + count: z.number(), + }) +); + +const numericColumnSummaryStaticsSchema = z.object({ + name: z.string(), + valueType: z.literal("INT64"), + sampleValues: z.array(z.number()), + histogram: histogramSchema.optional(), + proportionOfZeros: z.number().optional(), + proportionMissing: z.number().optional(), + min: z.number().optional(), + max: z.number().optional(), +}); + +const stringColumnSummaryStaticsSchema = z.object({ + name: z.string(), + valueType: z.literal("STRING"), + sampleValues: z.array(z.string()), +}); + +const columnsSummaryStatisticsSchema = z.union([ + numericColumnSummaryStaticsSchema, + stringColumnSummaryStaticsSchema, +]); + +const featureViewSummaryStatisticsSchema = z.object({ + columnsSummaryStatistics: z.record(columnsSummaryStatisticsSchema), +}); + +type FeatureViewSummaryStatisticsType = z.infer< + typeof featureViewSummaryStatisticsSchema +>; + +type NumericColumnSummaryStatisticType = z.infer< + typeof numericColumnSummaryStaticsSchema +>; +type StringColumnSummaryStatisticType = z.infer< + typeof stringColumnSummaryStaticsSchema +>; + +type HistogramDataType = z.infer; + +export { featureViewSummaryStatisticsSchema }; +export type { + FeatureViewSummaryStatisticsType, + HistogramDataType, + NumericColumnSummaryStatisticType, + StringColumnSummaryStatisticType, +}; diff --git a/ui/src/parsers/mergedFVTypes.ts b/ui/src/parsers/mergedFVTypes.ts new file mode 100644 index 00000000000..6a53b18e94d --- /dev/null +++ b/ui/src/parsers/mergedFVTypes.ts @@ -0,0 +1,63 @@ +import { + FeastFeatureColumnType, + FeastFeatureViewType, +} from "./feastFeatureViews"; +import { FeastODFVType } from "./feastODFVS"; +import { FeastRegistryType } from "./feastRegistry"; + +enum FEAST_FV_TYPES { + regular = "regular", + ondemand = "ondemand", +} + +interface regularFVInterface { + name: string; + type: FEAST_FV_TYPES.regular; + features: FeastFeatureColumnType[]; + object: FeastFeatureViewType; +} + +interface ODFVInterface { + name: string; + type: FEAST_FV_TYPES.ondemand; + features: FeastFeatureColumnType[]; + object: FeastODFVType; +} + +type genericFVType = regularFVInterface | ODFVInterface; + +const mergedFVTypes = (objects: FeastRegistryType) => { + const mergedFVMap: Record = {}; + + const mergedFVList: genericFVType[] = []; + + objects.featureViews?.forEach((fv) => { + const obj: genericFVType = { + name: fv.spec.name, + type: FEAST_FV_TYPES.regular, + features: fv.spec.features, + object: fv, + }; + + mergedFVMap[fv.spec.name] = obj; + mergedFVList.push(obj); + }); + + objects.onDemandFeatureViews?.forEach((odfv) => { + const obj: genericFVType = { + name: odfv.spec.name, + type: FEAST_FV_TYPES.ondemand, + features: odfv.spec.features, + object: odfv, + }; + + mergedFVMap[odfv.spec.name] = obj; + mergedFVList.push(obj); + }); + + return { mergedFVMap, mergedFVList }; +}; + +export default mergedFVTypes; +export { FEAST_FV_TYPES }; +export type { genericFVType, regularFVInterface, ODFVInterface }; diff --git a/ui/src/parsers/parseEntityRelationships.ts b/ui/src/parsers/parseEntityRelationships.ts new file mode 100644 index 00000000000..f6e1b1af1f7 --- /dev/null +++ b/ui/src/parsers/parseEntityRelationships.ts @@ -0,0 +1,95 @@ +import { FeastRegistryType } from "./feastRegistry"; +import { FEAST_FCO_TYPES } from "./types"; + +interface EntityReference { + type: FEAST_FCO_TYPES; + name: string; +} + +interface EntityRelation { + source: EntityReference; + target: EntityReference; +} + +const parseEntityRelationships = (objects: FeastRegistryType) => { + const links: EntityRelation[] = []; + + objects.featureServices?.forEach((fs) => { + fs.spec.features.forEach((feature) => { + links.push({ + source: { + type: FEAST_FCO_TYPES["featureView"], + name: feature.featureViewName, + }, + target: { + type: FEAST_FCO_TYPES["featureService"], + name: fs.spec.name, + }, + }); + }); + }); + + objects.featureViews?.forEach((fv) => { + fv.spec.entities.forEach((ent) => { + links.push({ + source: { + type: FEAST_FCO_TYPES["entity"], + name: ent, + }, + target: { + type: FEAST_FCO_TYPES["featureView"], + name: fv.spec.name, + }, + }); + }); + if (fv.spec.batchSource) { + links.push({ + source: { + type: FEAST_FCO_TYPES["dataSource"], + name: fv.spec.batchSource.name + }, + target: { + type: FEAST_FCO_TYPES["featureView"], + name: fv.spec.name, + } + }) + } + }); + + objects.onDemandFeatureViews?.forEach((fv) => { + Object.values(fv.spec.inputs).forEach((input: { [key: string]: any }) => { + if (input.requestDataSource) { + links.push({ + source: { + type: FEAST_FCO_TYPES["dataSource"], + name: input.requestDataSource.name, + }, + target: { + type: FEAST_FCO_TYPES["featureView"], + name: fv.spec.name, + }, + }); + } else if (input.featureViewProjection?.featureViewName) { + const source_fv = objects.featureViews?.find(el => el.spec.name === input.featureViewProjection.featureViewName); + if (!source_fv) { + return; + } + links.push({ + source: { + type: FEAST_FCO_TYPES["dataSource"], + name: source_fv?.spec.batchSource.name, + }, + target: { + type: FEAST_FCO_TYPES["featureView"], + name: fv.spec.name, + }, + }); + } + }); + }); + + return links; +}; + +export default parseEntityRelationships; +export type { EntityRelation, EntityReference }; diff --git a/ui/src/parsers/parseIndirectRelationships.ts b/ui/src/parsers/parseIndirectRelationships.ts new file mode 100644 index 00000000000..d7d532ad3e7 --- /dev/null +++ b/ui/src/parsers/parseIndirectRelationships.ts @@ -0,0 +1,33 @@ +import { FeastRegistryType } from "./feastRegistry"; +import { EntityRelation } from "./parseEntityRelationships"; +import { FEAST_FCO_TYPES } from "./types"; + +const parseIndirectRelationships = ( + relationships: EntityRelation[], + objects: FeastRegistryType +) => { + const indirectLinks: EntityRelation[] = []; + + // Only contains Entity -> FS or DS -> FS relationships + objects.featureServices?.forEach((featureService) => { + featureService.spec.features.forEach((featureView) => { + relationships + .filter( + (relationship) => + relationship.target.name === featureView.featureViewName + ) + .forEach((relationship) => { + indirectLinks.push({ + source: relationship.source, + target: { + type: FEAST_FCO_TYPES["featureService"], + name: featureService.spec.name, + }, + }); + }); + }); + }); + return indirectLinks; +}; + +export default parseIndirectRelationships; diff --git a/ui/src/parsers/types.ts b/ui/src/parsers/types.ts new file mode 100644 index 00000000000..e32d5b102ea --- /dev/null +++ b/ui/src/parsers/types.ts @@ -0,0 +1,19 @@ +enum FEAST_FCO_TYPES { + dataSource = "dataSource", + entity = "entity", + featureView = "featureView", + featureService = "featureService", +} + +enum FEAST_FEATURE_VALUE_TYPES { + FLOAT = "FLOAT", + INT64 = "INT64", + STRING = "STRING", + BOOL = "BOOL", + BYTES = "BYTES", + INT32 = "INT32", + DOUBLE = "DOUBLE", + UNIX_TIMESTAMP = "UNIX_TIMESTAMP" +} + +export { FEAST_FCO_TYPES, FEAST_FEATURE_VALUE_TYPES }; diff --git a/ui/src/queries/useLoadFeatureViewSummaryStatistics.ts b/ui/src/queries/useLoadFeatureViewSummaryStatistics.ts new file mode 100644 index 00000000000..06040298666 --- /dev/null +++ b/ui/src/queries/useLoadFeatureViewSummaryStatistics.ts @@ -0,0 +1,37 @@ +import { useQuery } from "react-query"; +import { useParams } from "react-router-dom"; +import { + featureViewSummaryStatisticsSchema, + FeatureViewSummaryStatisticsType, +} from "../parsers/featureViewSummaryStatistics"; + +const useLoadFeatureViewSummaryStatistics = (featureViewName: string) => { + const { projectName } = useParams(); + + const queryKey = `featureViewSummaryStatistics:${featureViewName}`; + const url = `/metadata/${projectName}/featureView/${featureViewName}.json`; + + return useQuery( + queryKey, + () => { + return fetch(url, { + headers: { + "Content-Type": "application/json", + }, + }) + .then((res) => { + return res.json(); + }) + .then((json) => { + const summary = featureViewSummaryStatisticsSchema.parse(json); + + return summary; + }); + }, + { + staleTime: 15 * 60 * 1000, // Given that we are reading from a registry dump, this seems reasonable for now. + } + ); +}; + +export default useLoadFeatureViewSummaryStatistics; diff --git a/ui/src/queries/useLoadProjectsList.ts b/ui/src/queries/useLoadProjectsList.ts new file mode 100644 index 00000000000..2383a793192 --- /dev/null +++ b/ui/src/queries/useLoadProjectsList.ts @@ -0,0 +1,37 @@ +import { useQuery } from "react-query"; +import { z } from "zod"; + +const ProjectEntrySchema = z.object({ + id: z.string(), + name: z.string(), + description: z.string().optional(), + registryPath: z.string(), +}); + +const ProjectsListSchema = z.object({ + default: z.string().optional(), + projects: z.array(ProjectEntrySchema), +}); + +type ProjectsListType = z.infer; + +const useLoadProjectsList = () => { + return useQuery("feast-projects-list", () => { + return fetch("/projects-list.json", { + headers: { + "Content-Type": "application/json", + }, + }) + .then((res) => { + return res.json(); + }) + .then((json) => { + const configs = ProjectsListSchema.parse(json); + + return configs; + }); + }); +}; + +export default useLoadProjectsList; +export type { ProjectsListType }; diff --git a/ui/src/queries/useLoadRegistry.ts b/ui/src/queries/useLoadRegistry.ts new file mode 100644 index 00000000000..ffb06756437 --- /dev/null +++ b/ui/src/queries/useLoadRegistry.ts @@ -0,0 +1,72 @@ +import { useQuery } from "react-query"; +import { + FeastRegistrySchema, + FeastRegistryType, +} from "../parsers/feastRegistry"; +import mergedFVTypes, { genericFVType } from "../parsers/mergedFVTypes"; +import parseEntityRelationships, { + EntityRelation, +} from "../parsers/parseEntityRelationships"; +import parseIndirectRelationships from "../parsers/parseIndirectRelationships"; + +interface FeatureStoreAllData { + project: string; + description?: string; + objects: FeastRegistryType; + relationships: EntityRelation[]; + mergedFVMap: Record; + mergedFVList: genericFVType[]; + indirectRelationships: EntityRelation[]; +} + +const useLoadRegistry = (url: string) => { + return useQuery( + `registry:${url}`, + () => { + return fetch(url, { + headers: { + "Content-Type": "application/json", + }, + }) + .then((res) => { + return res.json(); + }) + .then((json) => { + const objects = FeastRegistrySchema.parse(json); + + const { mergedFVMap, mergedFVList } = mergedFVTypes(objects); + + const relationships = parseEntityRelationships(objects); + + // Only contains Entity -> FS or DS -> FS relationships + const indirectRelationships = parseIndirectRelationships( + relationships, + objects + ); + + // console.log({ + // objects, + // mergedFVMap, + // mergedFVList, + // relationships, + // indirectRelationships, + // }); + + return { + project: objects.project, + objects, + mergedFVMap, + mergedFVList, + relationships, + indirectRelationships, + }; + }); + }, + { + staleTime: Infinity, // Given that we are reading from a registry dump, this seems reasonable for now. + } + ); +}; + +export default useLoadRegistry; +export type { FeatureStoreAllData }; diff --git a/ui/src/queries/useLoadRelationshipsData.ts b/ui/src/queries/useLoadRelationshipsData.ts new file mode 100644 index 00000000000..6f65af7e764 --- /dev/null +++ b/ui/src/queries/useLoadRelationshipsData.ts @@ -0,0 +1,20 @@ +import { useContext } from "react"; +import RegistryPathContext from "../contexts/RegistryPathContext"; +import useLoadRegistry from "./useLoadRegistry"; + +const useLoadRelationshipData = () => { + const registryUrl = useContext(RegistryPathContext); + const registryQuery = useLoadRegistry(registryUrl); + + const data = + registryQuery.data === undefined + ? undefined + : registryQuery.data.relationships; + + return { + ...registryQuery, + data, + }; +}; + +export default useLoadRelationshipData; diff --git a/ui/src/react-app-env.d.ts b/ui/src/react-app-env.d.ts new file mode 100644 index 00000000000..6431bc5fc6b --- /dev/null +++ b/ui/src/react-app-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/ui/src/reportWebVitals.ts b/ui/src/reportWebVitals.ts new file mode 100644 index 00000000000..49a2a16e0fb --- /dev/null +++ b/ui/src/reportWebVitals.ts @@ -0,0 +1,15 @@ +import { ReportHandler } from 'web-vitals'; + +const reportWebVitals = (onPerfEntry?: ReportHandler) => { + if (onPerfEntry && onPerfEntry instanceof Function) { + import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + getCLS(onPerfEntry); + getFID(onPerfEntry); + getFCP(onPerfEntry); + getLCP(onPerfEntry); + getTTFB(onPerfEntry); + }); + } +}; + +export default reportWebVitals; diff --git a/ui/src/setupTests.ts b/ui/src/setupTests.ts new file mode 100644 index 00000000000..8f2609b7b3e --- /dev/null +++ b/ui/src/setupTests.ts @@ -0,0 +1,5 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +import '@testing-library/jest-dom'; diff --git a/ui/src/test-utils.tsx b/ui/src/test-utils.tsx new file mode 100644 index 00000000000..c62770b9289 --- /dev/null +++ b/ui/src/test-utils.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import { render } from "@testing-library/react"; +import { QueryClient, QueryClientProvider } from "react-query"; +import { QueryParamProvider } from "use-query-params"; +import { MemoryRouter as Router } from "react-router-dom"; +import RouteAdapter from "./hacks/RouteAdapter"; + +interface ProvidersProps { + children: React.ReactElement; +} + +const queryClient = new QueryClient(); + +const AllTheProviders = ({ children }: ProvidersProps) => { + return ( + + + + {children} + + + + ); +}; + +const customRender = ( + ui: React.ReactElement, + options?: Record +) => render(ui, { wrapper: AllTheProviders, ...options }); + +// re-export everything +export * from "@testing-library/react"; + +// override render method +export { customRender as render }; diff --git a/ui/src/utils/custom-tabs/DataSourceCustomTabLoadingWrapper.tsx b/ui/src/utils/custom-tabs/DataSourceCustomTabLoadingWrapper.tsx new file mode 100644 index 00000000000..1ffc20f423b --- /dev/null +++ b/ui/src/utils/custom-tabs/DataSourceCustomTabLoadingWrapper.tsx @@ -0,0 +1,27 @@ +import React from "react"; +import { useParams } from "react-router-dom"; + +import { DataSourceCustomTabProps } from "../../custom-tabs/types"; +import useLoadDataSource from "../../pages/data-sources/useLoadDataSource"; + +interface DataSourceCustomTabLoadingWrapperProps { + Component: (props: DataSourceCustomTabProps) => JSX.Element; +} + +const DataSourceCustomTabLoadingWrapper = ({ + Component, +}: DataSourceCustomTabLoadingWrapperProps) => { + let { dataSourceName } = useParams(); + + if (!dataSourceName) { + throw new Error( + `This route has no 'dataSourceName' part. This route is likely not supposed to render this component.` + ); + } + + const feastObjectQuery = useLoadDataSource(dataSourceName); + + return ; +}; + +export default DataSourceCustomTabLoadingWrapper; diff --git a/ui/src/utils/custom-tabs/DatasetCustomTabLoadingWrapper.tsx b/ui/src/utils/custom-tabs/DatasetCustomTabLoadingWrapper.tsx new file mode 100644 index 00000000000..789b0563ccb --- /dev/null +++ b/ui/src/utils/custom-tabs/DatasetCustomTabLoadingWrapper.tsx @@ -0,0 +1,27 @@ +import React from "react"; +import { useParams } from "react-router-dom"; + +import { DatasetCustomTabProps } from "../../custom-tabs/types"; +import useLoadDataset from "../../pages/saved-data-sets/useLoadDataset"; + +interface DatasetCustomTabLoadingWrapperProps { + Component: (props: DatasetCustomTabProps) => JSX.Element; +} + +const DatasetCustomTabLoadingWrapper = ({ + Component, +}: DatasetCustomTabLoadingWrapperProps) => { + let { datasetName } = useParams(); + + if (!datasetName) { + throw new Error( + "Route doesn't have a 'datasetName' part. This route is likely rendering the wrong component." + ); + } + + const feastObjectQuery = useLoadDataset(datasetName); + + return ; +}; + +export default DatasetCustomTabLoadingWrapper; diff --git a/ui/src/utils/custom-tabs/EntityCustomTabLoadingWrapper.tsx b/ui/src/utils/custom-tabs/EntityCustomTabLoadingWrapper.tsx new file mode 100644 index 00000000000..0aa95cafb53 --- /dev/null +++ b/ui/src/utils/custom-tabs/EntityCustomTabLoadingWrapper.tsx @@ -0,0 +1,27 @@ +import React from "react"; +import { useParams } from "react-router-dom"; + +import { EntityCustomTabProps } from "../../custom-tabs/types"; +import useLoadEntity from "../../pages/entities/useLoadEntity"; + +interface EntityCustomTabLoadingWrapperProps { + Component: (props: EntityCustomTabProps) => JSX.Element; +} + +const EntityCustomTabLoadingWrapper = ({ + Component, +}: EntityCustomTabLoadingWrapperProps) => { + let { entityName } = useParams(); + + if (!entityName) { + throw new Error( + `This route has no 'entityName' part. This route is likely not supposed to render this component.` + ); + } + + const feastObjectQuery = useLoadEntity(entityName); + + return ; +}; + +export default EntityCustomTabLoadingWrapper; diff --git a/ui/src/utils/custom-tabs/FeatureServiceCustomTabLoadingWrapper.tsx b/ui/src/utils/custom-tabs/FeatureServiceCustomTabLoadingWrapper.tsx new file mode 100644 index 00000000000..816c36988fd --- /dev/null +++ b/ui/src/utils/custom-tabs/FeatureServiceCustomTabLoadingWrapper.tsx @@ -0,0 +1,29 @@ +import React from "react"; +import { useParams } from "react-router-dom"; + +import { FeatureServiceCustomTabProps } from "../../custom-tabs/types"; +import useLoadFeatureService from "../../pages/feature-services/useLoadFeatureService"; + +interface FeatureServiceCustomTabLoadingWrapperProps { + Component: (props: FeatureServiceCustomTabProps) => JSX.Element; +} + +const FeatureServiceCustomTabLoadingWrapper = ({ + Component, +}: FeatureServiceCustomTabLoadingWrapperProps) => { + const { featureServiceName } = useParams(); + + if (!featureServiceName) { + throw new Error( + `This route has no 'featureServiceName' part. This route is likely not supposed to render this component.` + ); + } + + const feastObjectQuery = useLoadFeatureService(featureServiceName); + + return ( + + ); +}; + +export default FeatureServiceCustomTabLoadingWrapper; diff --git a/ui/src/utils/custom-tabs/OnDemandFeatureViewCustomTabLoadingWrapper.tsx b/ui/src/utils/custom-tabs/OnDemandFeatureViewCustomTabLoadingWrapper.tsx new file mode 100644 index 00000000000..bd005b7a0a2 --- /dev/null +++ b/ui/src/utils/custom-tabs/OnDemandFeatureViewCustomTabLoadingWrapper.tsx @@ -0,0 +1,46 @@ +import React from "react"; + +import { useParams } from "react-router-dom"; +import useLoadFeatureView from "../../pages/feature-views/useLoadFeatureView"; +import { + OnDemandFeatureViewCustomTabProps, + OnDemandFeatureViewQueryReturnType, +} from "../../custom-tabs/types"; +import { FEAST_FV_TYPES } from "../../parsers/mergedFVTypes"; + +interface OnDemandFeatureViewCustomTabLoadingWrapperProps { + Component: (props: OnDemandFeatureViewCustomTabProps) => JSX.Element; +} + +const OnDemandFeatureViewCustomTabLoadingWrapper = ({ + Component, +}: OnDemandFeatureViewCustomTabLoadingWrapperProps) => { + const { featureViewName } = useParams(); + + if (!featureViewName) { + throw new Error( + `This route has no 'featureViewName' part. This route is likely not supposed to render this component.` + ); + } + + const feastObjectQuery = useLoadFeatureView(featureViewName); + + if ( + feastObjectQuery.isSuccess && + feastObjectQuery.data && + feastObjectQuery.data.type !== FEAST_FV_TYPES.ondemand + ) { + throw new Error( + `This should not happen. Somehow a custom tab on a ODFV page received data that does not have the shape?` + ); + } + + return ( + + ); +}; + +export default OnDemandFeatureViewCustomTabLoadingWrapper; diff --git a/ui/src/utils/custom-tabs/RegularFeatureViewCustomTabLoadingWrapper.tsx b/ui/src/utils/custom-tabs/RegularFeatureViewCustomTabLoadingWrapper.tsx new file mode 100644 index 00000000000..1a8288216a1 --- /dev/null +++ b/ui/src/utils/custom-tabs/RegularFeatureViewCustomTabLoadingWrapper.tsx @@ -0,0 +1,46 @@ +import React from "react"; + +import { useParams } from "react-router-dom"; +import useLoadFeatureView from "../../pages/feature-views/useLoadFeatureView"; +import { + RegularFeatureViewCustomTabProps, + RegularFeatureViewQueryReturnType, +} from "../../custom-tabs/types"; +import { FEAST_FV_TYPES } from "../../parsers/mergedFVTypes"; + +interface RegularFeatureViewCustomTabLoadingWrapperProps { + Component: (props: RegularFeatureViewCustomTabProps) => JSX.Element; +} + +const RegularFeatureViewCustomTabLoadingWrapper = ({ + Component, +}: RegularFeatureViewCustomTabLoadingWrapperProps) => { + const { featureViewName } = useParams(); + + if (!featureViewName) { + throw new Error( + `This route has no 'featureViewName' part. This route is likely not supposed to render this component.` + ); + } + + const feastObjectQuery = useLoadFeatureView(featureViewName); + + if ( + feastObjectQuery.isSuccess && + feastObjectQuery.data && + feastObjectQuery.data.type !== FEAST_FV_TYPES.regular + ) { + throw new Error( + `This should not happen. Somehow a custom tab on a Regular FV page received data that does not have the shape?` + ); + } + + return ( + + ); +}; + +export default RegularFeatureViewCustomTabLoadingWrapper; diff --git a/ui/tsconfig.json b/ui/tsconfig.json new file mode 100644 index 00000000000..a273b0cfc0e --- /dev/null +++ b/ui/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": [ + "src" + ] +} diff --git a/ui/yarn.lock b/ui/yarn.lock new file mode 100644 index 00000000000..2d523de6582 --- /dev/null +++ b/ui/yarn.lock @@ -0,0 +1,10810 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" + integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.0" + +"@apideck/better-ajv-errors@^0.3.1": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.3.tgz#ab0b1e981e1749bf59736cf7ebe25cfc9f949c15" + integrity sha512-9o+HO2MbJhJHjDYZaDxJmSDckvDpiuItEsrIShV0DXeCshXWRHhqYyU/PKHMkuClOmFnZhRd6wzv4vpDu/dRKg== + dependencies: + json-schema "^0.4.0" + jsonpointer "^5.0.0" + leven "^3.1.0" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" + integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== + +"@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.7.2", "@babel/core@^7.8.0": + version "7.17.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.5.tgz#6cd2e836058c28f06a4ca8ee7ed955bbf37c8225" + integrity sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.17.2" + "@babel/parser" "^7.17.3" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + +"@babel/eslint-parser@^7.16.3": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.17.0.tgz#eabb24ad9f0afa80e5849f8240d0e5facc2d90d6" + integrity sha512-PUEJ7ZBXbRkbq3qqM/jZ2nIuakUBqCYc7Qf52Lj7dlZ6zERnqisdHioL0l4wwQZnmskMeasqUNzLBFKs3nylXA== + dependencies: + eslint-scope "^5.1.1" + eslint-visitor-keys "^2.1.0" + semver "^6.3.0" + +"@babel/generator@^7.17.3", "@babel/generator@^7.7.2": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" + integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== + dependencies: + "@babel/types" "^7.17.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" + integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b" + integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" + integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== + dependencies: + "@babel/compat-data" "^7.16.4" + "@babel/helper-validator-option" "^7.16.7" + browserslist "^4.17.5" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.17.1", "@babel/helper-create-class-features-plugin@^7.17.6": + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz#3778c1ed09a7f3e65e6d6e0f6fbfcc53809d92c9" + integrity sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + +"@babel/helper-create-regexp-features-plugin@^7.16.7": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz#1dcc7d40ba0c6b6b25618997c5dbfd310f186fe1" + integrity sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + regexpu-core "^5.0.1" + +"@babel/helper-define-polyfill-provider@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" + integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== + dependencies: + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-explode-assignable-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a" + integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== + dependencies: + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-member-expression-to-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" + integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" + integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-transforms@^7.16.7": + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz#3c3b03cc6617e33d68ef5a27a67419ac5199ccd0" + integrity sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" + +"@babel/helper-optimise-call-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" + integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" + integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + +"@babel/helper-remap-async-to-generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3" + integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-wrap-function" "^7.16.8" + "@babel/types" "^7.16.8" + +"@babel/helper-replace-supers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" + integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-simple-access@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" + integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" + integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + +"@babel/helper-validator-option@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" + integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== + +"@babel/helper-wrap-function@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200" + integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw== + dependencies: + "@babel/helper-function-name" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.8" + "@babel/types" "^7.16.8" + +"@babel/helpers@^7.17.2": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417" + integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.0" + "@babel/types" "^7.17.0" + +"@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" + integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" + integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" + integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" + +"@babel/plugin-proposal-async-generator-functions@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" + integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.8" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-proposal-class-properties@^7.16.0", "@babel/plugin-proposal-class-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" + integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-proposal-class-static-block@^7.16.7": + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz#164e8fd25f0d80fa48c5a4d1438a6629325ad83c" + integrity sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.17.6" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-proposal-decorators@^7.16.4": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.2.tgz#c36372ddfe0360cac1ee331a238310bddca11493" + integrity sha512-WH8Z95CwTq/W8rFbMqb9p3hicpt4RX4f0K659ax2VHxgOyT6qQmUaEVEjIh4WR9Eh9NymkVn5vwsrE68fAQNUw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.17.1" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/plugin-syntax-decorators" "^7.17.0" + charcodes "^0.2.0" + +"@babel/plugin-proposal-dynamic-import@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" + integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-proposal-export-namespace-from@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" + integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" + integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-proposal-logical-assignment-operators@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" + integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" + integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-proposal-numeric-separator@^7.16.0", "@babel/plugin-proposal-numeric-separator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9" + integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-proposal-object-rest-spread@^7.16.7": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz#d9eb649a54628a51701aef7e0ea3d17e2b9dd390" + integrity sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw== + dependencies: + "@babel/compat-data" "^7.17.0" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.16.7" + +"@babel/plugin-proposal-optional-catch-binding@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf" + integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-proposal-optional-chaining@^7.16.0", "@babel/plugin-proposal-optional-chaining@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" + integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-proposal-private-methods@^7.16.0", "@babel/plugin-proposal-private-methods@^7.16.11": + version "7.16.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50" + integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.10" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-proposal-private-property-in-object@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" + integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" + integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-decorators@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.0.tgz#a2be3b2c9fe7d78bd4994e790896bc411e2f166d" + integrity sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-flow@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.16.7.tgz#202b147e5892b8452bbb0bb269c7ed2539ab8832" + integrity sha512-UDo3YGQO0jH6ytzVwgSLv9i/CzMcUjbKenL67dTrAZPPv6GFAtDhe6jqnvmoKzC/7htNTohhos+onPtDMqJwaQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.12.13", "@babel/plugin-syntax-jsx@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz#50b6571d13f764266a113d77c82b4a6508bbe665" + integrity sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.16.7", "@babel/plugin-syntax-typescript@^7.7.2": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8" + integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-arrow-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" + integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-async-to-generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" + integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.8" + +"@babel/plugin-transform-block-scoped-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" + integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-block-scoping@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" + integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-classes@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" + integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" + integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-destructuring@^7.16.7": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz#c445f75819641788a27a0a3a759d9df911df6abc" + integrity sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241" + integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-duplicate-keys@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" + integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-exponentiation-operator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b" + integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-flow-strip-types@^7.16.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.16.7.tgz#291fb140c78dabbf87f2427e7c7c332b126964b8" + integrity sha512-mzmCq3cNsDpZZu9FADYYyfZJIOrSONmHcop2XEKPdBNMa4PDC4eEvcOvzZaCNcjKu72v0XQlA5y1g58aLRXdYg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-flow" "^7.16.7" + +"@babel/plugin-transform-for-of@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" + integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" + integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== + dependencies: + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" + integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-member-expression-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" + integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-modules-amd@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" + integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== + dependencies: + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-commonjs@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" + integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== + dependencies: + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-systemjs@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7" + integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw== + dependencies: + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-umd@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" + integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== + dependencies: + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" + integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + +"@babel/plugin-transform-new-target@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" + integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-object-super@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" + integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + +"@babel/plugin-transform-parameters@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" + integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-property-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" + integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-react-constant-elements@^7.12.1": + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.17.6.tgz#6cc273c2f612a6a50cb657e63ee1303e5e68d10a" + integrity sha512-OBv9VkyyKtsHZiHLoSfCn+h6yU7YKX8nrs32xUmOa1SRSk+t03FosB6fBZ0Yz4BpD1WV7l73Nsad+2Tz7APpqw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-react-display-name@^7.16.0", "@babel/plugin-transform-react-display-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz#7b6d40d232f4c0f550ea348593db3b21e2404340" + integrity sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-react-jsx-development@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz#43a00724a3ed2557ed3f276a01a929e6686ac7b8" + integrity sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.16.7" + +"@babel/plugin-transform-react-jsx@^7.16.7": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz#eac1565da176ccb1a715dae0b4609858808008c1" + integrity sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-jsx" "^7.16.7" + "@babel/types" "^7.17.0" + +"@babel/plugin-transform-react-pure-annotations@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz#232bfd2f12eb551d6d7d01d13fe3f86b45eb9c67" + integrity sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-regenerator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb" + integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== + dependencies: + regenerator-transform "^0.14.2" + +"@babel/plugin-transform-reserved-words@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" + integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-runtime@^7.16.4": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz#0a2e08b5e2b2d95c4b1d3b3371a2180617455b70" + integrity sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.5.0" + babel-plugin-polyfill-regenerator "^0.3.0" + semver "^6.3.0" + +"@babel/plugin-transform-shorthand-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" + integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-spread@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" + integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + +"@babel/plugin-transform-sticky-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660" + integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-template-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" + integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-typeof-symbol@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" + integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-typescript@^7.16.7": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz#591ce9b6b83504903fa9dd3652c357c2ba7a1ee0" + integrity sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-typescript" "^7.16.7" + +"@babel/plugin-transform-unicode-escapes@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3" + integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-unicode-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2" + integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.16.4": + version "7.16.11" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" + integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== + dependencies: + "@babel/compat-data" "^7.16.8" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-option" "^7.16.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-async-generator-functions" "^7.16.8" + "@babel/plugin-proposal-class-properties" "^7.16.7" + "@babel/plugin-proposal-class-static-block" "^7.16.7" + "@babel/plugin-proposal-dynamic-import" "^7.16.7" + "@babel/plugin-proposal-export-namespace-from" "^7.16.7" + "@babel/plugin-proposal-json-strings" "^7.16.7" + "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7" + "@babel/plugin-proposal-numeric-separator" "^7.16.7" + "@babel/plugin-proposal-object-rest-spread" "^7.16.7" + "@babel/plugin-proposal-optional-catch-binding" "^7.16.7" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-private-methods" "^7.16.11" + "@babel/plugin-proposal-private-property-in-object" "^7.16.7" + "@babel/plugin-proposal-unicode-property-regex" "^7.16.7" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-transform-arrow-functions" "^7.16.7" + "@babel/plugin-transform-async-to-generator" "^7.16.8" + "@babel/plugin-transform-block-scoped-functions" "^7.16.7" + "@babel/plugin-transform-block-scoping" "^7.16.7" + "@babel/plugin-transform-classes" "^7.16.7" + "@babel/plugin-transform-computed-properties" "^7.16.7" + "@babel/plugin-transform-destructuring" "^7.16.7" + "@babel/plugin-transform-dotall-regex" "^7.16.7" + "@babel/plugin-transform-duplicate-keys" "^7.16.7" + "@babel/plugin-transform-exponentiation-operator" "^7.16.7" + "@babel/plugin-transform-for-of" "^7.16.7" + "@babel/plugin-transform-function-name" "^7.16.7" + "@babel/plugin-transform-literals" "^7.16.7" + "@babel/plugin-transform-member-expression-literals" "^7.16.7" + "@babel/plugin-transform-modules-amd" "^7.16.7" + "@babel/plugin-transform-modules-commonjs" "^7.16.8" + "@babel/plugin-transform-modules-systemjs" "^7.16.7" + "@babel/plugin-transform-modules-umd" "^7.16.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.8" + "@babel/plugin-transform-new-target" "^7.16.7" + "@babel/plugin-transform-object-super" "^7.16.7" + "@babel/plugin-transform-parameters" "^7.16.7" + "@babel/plugin-transform-property-literals" "^7.16.7" + "@babel/plugin-transform-regenerator" "^7.16.7" + "@babel/plugin-transform-reserved-words" "^7.16.7" + "@babel/plugin-transform-shorthand-properties" "^7.16.7" + "@babel/plugin-transform-spread" "^7.16.7" + "@babel/plugin-transform-sticky-regex" "^7.16.7" + "@babel/plugin-transform-template-literals" "^7.16.7" + "@babel/plugin-transform-typeof-symbol" "^7.16.7" + "@babel/plugin-transform-unicode-escapes" "^7.16.7" + "@babel/plugin-transform-unicode-regex" "^7.16.7" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.16.8" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.5.0" + babel-plugin-polyfill-regenerator "^0.3.0" + core-js-compat "^3.20.2" + semver "^6.3.0" + +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@^7.12.5", "@babel/preset-react@^7.16.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.7.tgz#4c18150491edc69c183ff818f9f2aecbe5d93852" + integrity sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-option" "^7.16.7" + "@babel/plugin-transform-react-display-name" "^7.16.7" + "@babel/plugin-transform-react-jsx" "^7.16.7" + "@babel/plugin-transform-react-jsx-development" "^7.16.7" + "@babel/plugin-transform-react-pure-annotations" "^7.16.7" + +"@babel/preset-typescript@^7.16.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" + integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-option" "^7.16.7" + "@babel/plugin-transform-typescript" "^7.16.7" + +"@babel/runtime-corejs3@^7.10.2": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz#fdca2cd05fba63388babe85d349b6801b008fd13" + integrity sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg== + dependencies: + core-js-pure "^3.20.2" + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" + integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/template@^7.16.7", "@babel/template@^7.3.3": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3", "@babel/traverse@^7.7.2": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" + integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.17.3" + "@babel/types" "^7.17.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" + integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + +"@base2/pretty-print-object@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz#371ba8be66d556812dc7fb169ebc3c08378f69d4" + integrity sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA== + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@csstools/normalize.css@*": + version "12.0.0" + resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-12.0.0.tgz#a9583a75c3f150667771f30b60d9f059473e62c4" + integrity sha512-M0qqxAcwCsIVfpFQSlGN5XjXWu8l5JDZN+fPt1LeW5SZexQTgnaEvgXAY+CeygRw0EeppWHi12JxESWiWrB0Sg== + +"@csstools/postcss-color-function@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@csstools/postcss-color-function/-/postcss-color-function-1.0.2.tgz#0843fe19be08eeb22e5d2242a6ac06f8b87b9ed2" + integrity sha512-uayvFqfa0hITPwVduxRYNL9YBD/anTqula0tu2llalaxblEd7QPuETSN3gB5PvTYxSfd0d8kS4Fypgo5JaUJ6A== + dependencies: + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" + +"@csstools/postcss-font-format-keywords@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.0.tgz#7e7df948a83a0dfb7eb150a96e2390ac642356a1" + integrity sha512-oO0cZt8do8FdVBX8INftvIA4lUrKUSCcWUf9IwH9IPWOgKT22oAZFXeHLoDK7nhB2SmkNycp5brxfNMRLIhd6Q== + dependencies: + postcss-value-parser "^4.2.0" + +"@csstools/postcss-hwb-function@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.0.tgz#d6785c1c5ba8152d1d392c66f3a6a446c6034f6d" + integrity sha512-VSTd7hGjmde4rTj1rR30sokY3ONJph1reCBTUXqeW1fKwETPy1x4t/XIeaaqbMbC5Xg4SM/lyXZ2S8NELT2TaA== + dependencies: + postcss-value-parser "^4.2.0" + +"@csstools/postcss-ic-unit@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.0.tgz#f484db59fc94f35a21b6d680d23b0ec69b286b7f" + integrity sha512-i4yps1mBp2ijrx7E96RXrQXQQHm6F4ym1TOD0D69/sjDjZvQ22tqiEvaNw7pFZTUO5b9vWRHzbHzP9+UKuw+bA== + dependencies: + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" + +"@csstools/postcss-is-pseudo-class@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.0.tgz#219a1c1d84de7d9e9b7e662a57fdc194eac38ea7" + integrity sha512-WnfZlyuh/CW4oS530HBbrKq0G8BKl/bsNr5NMFoubBFzJfvFRGJhplCgIJYWUidLuL3WJ/zhMtDIyNFTqhx63Q== + dependencies: + postcss-selector-parser "^6.0.9" + +"@csstools/postcss-normalize-display-values@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.0.tgz#ce698f688c28517447aedf15a9037987e3d2dc97" + integrity sha512-bX+nx5V8XTJEmGtpWTO6kywdS725t71YSLlxWt78XoHUbELWgoCXeOFymRJmL3SU1TLlKSIi7v52EWqe60vJTQ== + dependencies: + postcss-value-parser "^4.2.0" + +"@csstools/postcss-oklab-function@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.0.1.tgz#a12348eae202d4ded908a06aa92cf19a946b6cec" + integrity sha512-Bnly2FWWSTZX20hDJLYHpurhp1ot+ZGvojLOsrHa9frzOVruOv4oPYMZ6wQomi9KsbZZ+Af/CuRYaGReTyGtEg== + dependencies: + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" + +"@csstools/postcss-progressive-custom-properties@^1.1.0", "@csstools/postcss-progressive-custom-properties@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.2.0.tgz#7d53b773de50874c3885918dcb10cac97bf66ed5" + integrity sha512-YLpFPK5OaLIRKZhUfnrZPT9s9cmtqltIOg7W6jPcxmiDpnZ4lk+odfufZttOAgcg6IHWvNLgcITSLpJxIQB/qQ== + dependencies: + postcss-value-parser "^4.2.0" + +"@elastic/datemath@^5.0.3": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@elastic/datemath/-/datemath-5.0.3.tgz#7baccdab672b9a3ecb7fe8387580670936b58573" + integrity sha512-8Hbr1Uyjm5OcYBfEB60K7sCP6U3IXuWDaLaQmYv3UxgI4jqBWbakoemwWvsqPVUvnwEjuX6z7ghPZbefs8xiaA== + dependencies: + tslib "^1.9.3" + +"@elastic/eui@^50.0.0": + version "50.0.0" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-50.0.0.tgz#f744ff437c80b48f352fa53d17930e4824b3e0ae" + integrity sha512-wt98SiSX3OAL+5+JD2SnZf4DNzjFSYzLXJJ7e9VYVX2QhE5ucOJXg2sUQ97Tj6J9xLWctpsZT3llkiGeT4yc4Q== + dependencies: + "@types/chroma-js" "^2.0.0" + "@types/lodash" "^4.14.160" + "@types/numeral" "^0.0.28" + "@types/react-beautiful-dnd" "^13.1.2" + "@types/react-input-autosize" "^2.2.1" + "@types/react-virtualized-auto-sizer" "^1.0.1" + "@types/react-window" "^1.8.5" + "@types/refractor" "^3.0.0" + "@types/resize-observer-browser" "^0.1.5" + "@types/vfile-message" "^2.0.0" + chroma-js "^2.1.0" + classnames "^2.2.6" + lodash "^4.17.21" + mdast-util-to-hast "^10.0.0" + numeral "^2.0.6" + prop-types "^15.6.0" + react-beautiful-dnd "^13.1.0" + react-dropzone "^11.5.3" + react-element-to-jsx-string "^14.3.4" + react-focus-on "^3.5.4" + react-input-autosize "^3.0.0" + react-is "^17.0.2" + react-virtualized-auto-sizer "^1.0.6" + react-window "^1.8.6" + refractor "^3.5.0" + rehype-raw "^5.0.0" + rehype-react "^6.0.0" + rehype-stringify "^8.0.0" + remark-breaks "^2.0.2" + remark-emoji "^2.1.0" + remark-parse "^8.0.3" + remark-rehype "^8.0.0" + tabbable "^3.0.0" + text-diff "^1.0.1" + unified "^9.2.0" + unist-util-visit "^2.0.3" + url-parse "^1.5.10" + uuid "^8.3.0" + vfile "^4.2.0" + +"@emotion/babel-plugin@^11.7.1": + version "11.7.2" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.7.2.tgz#fec75f38a6ab5b304b0601c74e2a5e77c95e5fa0" + integrity sha512-6mGSCWi9UzXut/ZAN6lGFu33wGR3SJisNl3c0tvlmb8XChH1b2SUvxvnOh7hvLpqyRdHHU9AiazV3Cwbk5SXKQ== + dependencies: + "@babel/helper-module-imports" "^7.12.13" + "@babel/plugin-syntax-jsx" "^7.12.13" + "@babel/runtime" "^7.13.10" + "@emotion/hash" "^0.8.0" + "@emotion/memoize" "^0.7.5" + "@emotion/serialize" "^1.0.2" + babel-plugin-macros "^2.6.1" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "4.0.13" + +"@emotion/cache@^11.7.1": + version "11.7.1" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.7.1.tgz#08d080e396a42e0037848214e8aa7bf879065539" + integrity sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A== + dependencies: + "@emotion/memoize" "^0.7.4" + "@emotion/sheet" "^1.1.0" + "@emotion/utils" "^1.0.0" + "@emotion/weak-memoize" "^0.2.5" + stylis "4.0.13" + +"@emotion/hash@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" + integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== + +"@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" + integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ== + +"@emotion/react@^11.8.1": + version "11.8.1" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.8.1.tgz#5358b8c78367063881e26423057c030c57ce52eb" + integrity sha512-XGaie4nRxmtP1BZYBXqC5JGqMYF2KRKKI7vjqNvQxyRpekVAZhb6QqrElmZCAYXH1L90lAelADSVZC4PFsrJ8Q== + dependencies: + "@babel/runtime" "^7.13.10" + "@emotion/babel-plugin" "^11.7.1" + "@emotion/cache" "^11.7.1" + "@emotion/serialize" "^1.0.2" + "@emotion/sheet" "^1.1.0" + "@emotion/utils" "^1.1.0" + "@emotion/weak-memoize" "^0.2.5" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.2.tgz#77cb21a0571c9f68eb66087754a65fa97bfcd965" + integrity sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A== + dependencies: + "@emotion/hash" "^0.8.0" + "@emotion/memoize" "^0.7.4" + "@emotion/unitless" "^0.7.5" + "@emotion/utils" "^1.0.0" + csstype "^3.0.2" + +"@emotion/sheet@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.1.0.tgz#56d99c41f0a1cda2726a05aa6a20afd4c63e58d2" + integrity sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g== + +"@emotion/unitless@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" + integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== + +"@emotion/utils@^1.0.0", "@emotion/utils@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.1.0.tgz#86b0b297f3f1a0f2bdb08eeac9a2f49afd40d0cf" + integrity sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ== + +"@emotion/weak-memoize@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" + integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== + +"@eslint/eslintrc@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.0.tgz#7ce1547a5c46dfe56e1e45c3c9ed18038c721c6a" + integrity sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.3.1" + globals "^13.9.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@humanwhocodes/config-array@^0.9.2": + version "0.9.5" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" + integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba" + integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^27.5.1" + jest-util "^27.5.1" + slash "^3.0.0" + +"@jest/core@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626" + integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ== + dependencies: + "@jest/console" "^27.5.1" + "@jest/reporters" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.8.1" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^27.5.1" + jest-config "^27.5.1" + jest-haste-map "^27.5.1" + jest-message-util "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-resolve-dependencies "^27.5.1" + jest-runner "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + jest-watcher "^27.5.1" + micromatch "^4.0.4" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74" + integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA== + dependencies: + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + +"@jest/fake-timers@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" + integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ== + dependencies: + "@jest/types" "^27.5.1" + "@sinonjs/fake-timers" "^8.0.1" + "@types/node" "*" + jest-message-util "^27.5.1" + jest-mock "^27.5.1" + jest-util "^27.5.1" + +"@jest/globals@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b" + integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/types" "^27.5.1" + expect "^27.5.1" + +"@jest/reporters@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04" + integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^5.1.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-haste-map "^27.5.1" + jest-resolve "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^4.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^8.1.0" + +"@jest/source-map@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" + integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.2.9" + source-map "^0.6.0" + +"@jest/test-result@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb" + integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag== + dependencies: + "@jest/console" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b" + integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ== + dependencies: + "@jest/test-result" "^27.5.1" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-runtime "^27.5.1" + +"@jest/transform@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409" + integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^27.5.1" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-regex-util "^27.5.1" + jest-util "^27.5.1" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" + integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" + integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.11" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" + integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + +"@jridgewell/trace-mapping@^0.3.0": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" + integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@mapbox/hast-util-table-cell-style@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@mapbox/hast-util-table-cell-style/-/hast-util-table-cell-style-0.2.0.tgz#1003f59d54fae6f638cb5646f52110fb3da95b4d" + integrity sha512-gqaTIGC8My3LVSnU38IwjHVKJC94HSonjvFHDk8/aSrApL8v4uWgm8zJkK7MJIIbHuNOr/+Mv2KkQKcxs6LEZA== + dependencies: + unist-util-visit "^1.4.1" + +"@mswjs/cookies@^0.1.7": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@mswjs/cookies/-/cookies-0.1.7.tgz#d334081b2c51057a61c1dd7b76ca3cac02251651" + integrity sha512-bDg1ReMBx+PYDB4Pk7y1Q07Zz1iKIEUWQpkEXiA2lEWg9gvOZ8UBmGXilCEUvyYoRFlmr/9iXTRR69TrgSwX/Q== + dependencies: + "@types/set-cookie-parser" "^2.4.0" + set-cookie-parser "^2.4.6" + +"@mswjs/interceptors@^0.13.5": + version "0.13.6" + resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.13.6.tgz#db46ba29c9ec118aefcf6ef61ecc38b25837967f" + integrity sha512-28FzF44Q84h9vxQ0XBpEz940KC/q3fzlo+TtaIyfilnJ7+HeIcnVfRM4hkp0/q2Uh466PmgpD4BH7A0F0kCBbQ== + dependencies: + "@open-draft/until" "^1.0.3" + "@xmldom/xmldom" "^0.7.5" + debug "^4.3.3" + headers-polyfill "^3.0.4" + outvariant "^1.2.1" + strict-event-emitter "^0.2.0" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@open-draft/until@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-1.0.3.tgz#db9cc719191a62e7d9200f6e7bab21c5b848adca" + integrity sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q== + +"@pmmmwh/react-refresh-webpack-plugin@^0.5.3": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.4.tgz#df0d0d855fc527db48aac93c218a0bf4ada41f99" + integrity sha512-zZbZeHQDnoTlt2AF+diQT0wsSXpvWiaIOZwBRdltNFhG1+I3ozyaw7U/nBiUwyJ0D+zwdXp0E3bWOl38Ag2BMw== + dependencies: + ansi-html-community "^0.0.8" + common-path-prefix "^3.0.0" + core-js-pure "^3.8.1" + error-stack-parser "^2.0.6" + find-up "^5.0.0" + html-entities "^2.1.0" + loader-utils "^2.0.0" + schema-utils "^3.0.0" + source-map "^0.7.3" + +"@rollup/plugin-babel@^5.2.0": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283" + integrity sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@rollup/pluginutils" "^3.1.0" + +"@rollup/plugin-node-resolve@^11.2.1": + version "11.2.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz#82aa59397a29cd4e13248b106e6a4a1880362a60" + integrity sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg== + dependencies: + "@rollup/pluginutils" "^3.1.0" + "@types/resolve" "1.17.1" + builtin-modules "^3.1.0" + deepmerge "^4.2.2" + is-module "^1.0.0" + resolve "^1.19.0" + +"@rollup/plugin-replace@^2.4.1": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz#a2d539314fbc77c244858faa523012825068510a" + integrity sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg== + dependencies: + "@rollup/pluginutils" "^3.1.0" + magic-string "^0.25.7" + +"@rollup/pluginutils@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== + dependencies: + "@types/estree" "0.0.39" + estree-walker "^1.0.1" + picomatch "^2.2.2" + +"@rushstack/eslint-patch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323" + integrity sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A== + +"@sinonjs/commons@^1.7.0": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" + integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^8.0.1": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7" + integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@surma/rollup-plugin-off-main-thread@^2.2.3": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz#ee34985952ca21558ab0d952f00298ad2190c053" + integrity sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ== + dependencies: + ejs "^3.1.6" + json5 "^2.2.0" + magic-string "^0.25.0" + string.prototype.matchall "^4.0.6" + +"@svgr/babel-plugin-add-jsx-attribute@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz#81ef61947bb268eb9d50523446f9c638fb355906" + integrity sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg== + +"@svgr/babel-plugin-remove-jsx-attribute@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz#6b2c770c95c874654fd5e1d5ef475b78a0a962ef" + integrity sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg== + +"@svgr/babel-plugin-remove-jsx-empty-expression@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz#25621a8915ed7ad70da6cea3d0a6dbc2ea933efd" + integrity sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA== + +"@svgr/babel-plugin-replace-jsx-attribute-value@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz#0b221fc57f9fcd10e91fe219e2cd0dd03145a897" + integrity sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ== + +"@svgr/babel-plugin-svg-dynamic-title@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz#139b546dd0c3186b6e5db4fefc26cb0baea729d7" + integrity sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg== + +"@svgr/babel-plugin-svg-em-dimensions@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz#6543f69526632a133ce5cabab965deeaea2234a0" + integrity sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw== + +"@svgr/babel-plugin-transform-react-native-svg@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz#00bf9a7a73f1cad3948cdab1f8dfb774750f8c80" + integrity sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q== + +"@svgr/babel-plugin-transform-svg-component@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz#583a5e2a193e214da2f3afeb0b9e8d3250126b4a" + integrity sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ== + +"@svgr/babel-preset@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-5.5.0.tgz#8af54f3e0a8add7b1e2b0fcd5a882c55393df327" + integrity sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig== + dependencies: + "@svgr/babel-plugin-add-jsx-attribute" "^5.4.0" + "@svgr/babel-plugin-remove-jsx-attribute" "^5.4.0" + "@svgr/babel-plugin-remove-jsx-empty-expression" "^5.0.1" + "@svgr/babel-plugin-replace-jsx-attribute-value" "^5.0.1" + "@svgr/babel-plugin-svg-dynamic-title" "^5.4.0" + "@svgr/babel-plugin-svg-em-dimensions" "^5.4.0" + "@svgr/babel-plugin-transform-react-native-svg" "^5.4.0" + "@svgr/babel-plugin-transform-svg-component" "^5.5.0" + +"@svgr/core@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@svgr/core/-/core-5.5.0.tgz#82e826b8715d71083120fe8f2492ec7d7874a579" + integrity sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ== + dependencies: + "@svgr/plugin-jsx" "^5.5.0" + camelcase "^6.2.0" + cosmiconfig "^7.0.0" + +"@svgr/hast-util-to-babel-ast@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz#5ee52a9c2533f73e63f8f22b779f93cd432a5461" + integrity sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ== + dependencies: + "@babel/types" "^7.12.6" + +"@svgr/plugin-jsx@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz#1aa8cd798a1db7173ac043466d7b52236b369000" + integrity sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA== + dependencies: + "@babel/core" "^7.12.3" + "@svgr/babel-preset" "^5.5.0" + "@svgr/hast-util-to-babel-ast" "^5.5.0" + svg-parser "^2.0.2" + +"@svgr/plugin-svgo@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz#02da55d85320549324e201c7b2e53bf431fcc246" + integrity sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ== + dependencies: + cosmiconfig "^7.0.0" + deepmerge "^4.2.2" + svgo "^1.2.2" + +"@svgr/webpack@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-5.5.0.tgz#aae858ee579f5fa8ce6c3166ef56c6a1b381b640" + integrity sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g== + dependencies: + "@babel/core" "^7.12.3" + "@babel/plugin-transform-react-constant-elements" "^7.12.1" + "@babel/preset-env" "^7.12.1" + "@babel/preset-react" "^7.12.5" + "@svgr/core" "^5.5.0" + "@svgr/plugin-jsx" "^5.5.0" + "@svgr/plugin-svgo" "^5.5.0" + loader-utils "^2.0.0" + +"@testing-library/dom@^8.0.0": + version "8.11.3" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.11.3.tgz#38fd63cbfe14557021e88982d931e33fb7c1a808" + integrity sha512-9LId28I+lx70wUiZjLvi1DB/WT2zGOxUh46glrSNMaWVx849kKAluezVzZrXJfTKKoQTmEOutLes/bHg4Bj3aA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^4.2.0" + aria-query "^5.0.0" + chalk "^4.1.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.4.4" + pretty-format "^27.0.2" + +"@testing-library/jest-dom@^5.16.2": + version "5.16.2" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.2.tgz#f329b36b44aa6149cd6ced9adf567f8b6aa1c959" + integrity sha512-6ewxs1MXWwsBFZXIk4nKKskWANelkdUehchEOokHsN8X7c2eKXGw+77aRV63UU8f/DTSVUPLaGxdrj4lN7D/ug== + dependencies: + "@babel/runtime" "^7.9.2" + "@types/testing-library__jest-dom" "^5.9.1" + aria-query "^5.0.0" + chalk "^3.0.0" + css "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.5.6" + lodash "^4.17.15" + redent "^3.0.0" + +"@testing-library/react@^12.1.3": + version "12.1.3" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.3.tgz#ef26c5f122661ea9b6f672b23dc6b328cadbbf26" + integrity sha512-oCULRXWRrBtC9m6G/WohPo1GLcLesH7T4fuKzRAKn1CWVu9BzXtqLXDDTA6KhFNNtRwLtfSMr20HFl+Qrdrvmg== + dependencies: + "@babel/runtime" "^7.12.5" + "@testing-library/dom" "^8.0.0" + "@types/react-dom" "*" + +"@testing-library/user-event@^13.5.0": + version "13.5.0" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-13.5.0.tgz#69d77007f1e124d55314a2b73fd204b333b13295" + integrity sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg== + dependencies: + "@babel/runtime" "^7.12.5" + +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + +"@trysound/sax@0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" + integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== + +"@types/aria-query@^4.2.0": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc" + integrity sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig== + +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14": + version "7.1.18" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.18.tgz#1a29abcc411a9c05e2094c98f9a1b7da6cdf49f8" + integrity sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" + integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43" + integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== + dependencies: + "@babel/types" "^7.3.0" + +"@types/body-parser@*": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bonjour@^3.5.9": + version "3.5.10" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" + integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + dependencies: + "@types/node" "*" + +"@types/chroma-js@^2.0.0": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@types/chroma-js/-/chroma-js-2.1.3.tgz#0b03d737ff28fad10eb884e0c6cedd5ffdc4ba0a" + integrity sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g== + +"@types/connect-history-api-fallback@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" + integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + +"@types/d3-array@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.2.tgz#71c35bca8366a40d1b8fce9279afa4a77fb0065d" + integrity sha512-5mjGjz6XOXKOCdTajXTZ/pMsg236RdiwKPrRPWAEf/2S/+PzwY+LLYShUpeysWaMvsdS7LArh6GdUefoxpchsQ== + +"@types/d3-axis@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.1.tgz#6afc20744fa5cc0cbc3e2bd367b140a79ed3e7a8" + integrity sha512-zji/iIbdd49g9WN0aIsGcwcTBUkgLsCSwB+uH+LPVDAiKWENMtI3cJEWt+7/YYwelMoZmbBfzA3qCdrZ2XFNnw== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-brush@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.1.tgz#ae5f17ce391935ca88b29000e60ee20452c6357c" + integrity sha512-B532DozsiTuQMHu2YChdZU0qsFJSio3Q6jmBYGYNp3gMDzBmuFFgPt9qKA4VYuLZMp4qc6eX7IUFUEsvHiXZAw== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-chord@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.1.tgz#54c8856c19c8e4ab36a53f73ba737de4768ad248" + integrity sha512-eQfcxIHrg7V++W8Qxn6QkqBNBokyhdWSAS73AbkbMzvLQmVVBviknoz2SRS/ZJdIOmhcmmdCRE/NFOm28Z1AMw== + +"@types/d3-color@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.0.2.tgz#53f2d6325f66ee79afd707c05ac849e8ae0edbb0" + integrity sha512-WVx6zBiz4sWlboCy7TCgjeyHpNjMsoF36yaagny1uXfbadc9f+5BeBf7U+lRmQqY3EHbGQpP8UdW8AC+cywSwQ== + +"@types/d3-contour@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.1.tgz#9ff4e2fd2a3910de9c5097270a7da8a6ef240017" + integrity sha512-C3zfBrhHZvrpAAK3YXqLWVAGo87A4SvJ83Q/zVJ8rFWJdKejUnDYaWZPkA8K84kb2vDA/g90LTQAz7etXcgoQQ== + dependencies: + "@types/d3-array" "*" + "@types/geojson" "*" + +"@types/d3-delaunay@*": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.0.tgz#c09953ac7e5460997f693d2d7bf3522e0d4a88e6" + integrity sha512-iGm7ZaGLq11RK3e69VeMM6Oqj2SjKUB9Qhcyd1zIcqn2uE8w9GFB445yCY46NOQO3ByaNyktX1DK+Etz7ZaX+w== + +"@types/d3-dispatch@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.1.tgz#a1b18ae5fa055a6734cb3bd3cbc6260ef19676e3" + integrity sha512-NhxMn3bAkqhjoxabVJWKryhnZXXYYVQxaBnbANu0O94+O/nX9qSjrA1P1jbAQJxJf+VC72TxDX/YJcKue5bRqw== + +"@types/d3-drag@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.1.tgz#fb1e3d5cceeee4d913caa59dedf55c94cb66e80f" + integrity sha512-o1Va7bLwwk6h03+nSM8dpaGEYnoIG19P0lKqlic8Un36ymh9NSkNFX1yiXMKNMx8rJ0Kfnn2eovuFaL6Jvj0zA== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-dsv@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.0.tgz#f3c61fb117bd493ec0e814856feb804a14cfc311" + integrity sha512-o0/7RlMl9p5n6FQDptuJVMxDf/7EDEv2SYEO/CwdG2tr1hTfUVi0Iavkk2ax+VpaQ/1jVhpnj5rq1nj8vwhn2A== + +"@types/d3-ease@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.0.tgz#c29926f8b596f9dadaeca062a32a45365681eae0" + integrity sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA== + +"@types/d3-fetch@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.1.tgz#f9fa88b81aa2eea5814f11aec82ecfddbd0b8fe0" + integrity sha512-toZJNOwrOIqz7Oh6Q7l2zkaNfXkfR7mFSJvGvlD/Ciq/+SQ39d5gynHJZ/0fjt83ec3WL7+u3ssqIijQtBISsw== + dependencies: + "@types/d3-dsv" "*" + +"@types/d3-force@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.3.tgz#76cb20d04ae798afede1ea6e41750763ff5a9c82" + integrity sha512-z8GteGVfkWJMKsx6hwC3SiTSLspL98VNpmvLpEFJQpZPq6xpA1I8HNBDNSpukfK0Vb0l64zGFhzunLgEAcBWSA== + +"@types/d3-format@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.1.tgz#194f1317a499edd7e58766f96735bdc0216bb89d" + integrity sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg== + +"@types/d3-geo@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.0.2.tgz#e7ec5f484c159b2c404c42d260e6d99d99f45d9a" + integrity sha512-DbqK7MLYA8LpyHQfv6Klz0426bQEf7bRTvhMy44sNGVyZoWn//B0c+Qbeg8Osi2Obdc9BLLXYAKpyWege2/7LQ== + dependencies: + "@types/geojson" "*" + +"@types/d3-hierarchy@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.0.2.tgz#ca63f2f4da15b8f129c5b7dffd71d904cba6aca2" + integrity sha512-+krnrWOZ+aQB6v+E+jEkmkAx9HvsNAD+1LCD0vlBY3t+HwjKnsBFbpVLx6WWzDzCIuiTWdAxXMEnGnVXpB09qQ== + +"@types/d3-interpolate@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz#e7d17fa4a5830ad56fe22ce3b4fac8541a9572dc" + integrity sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw== + dependencies: + "@types/d3-color" "*" + +"@types/d3-path@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.0.0.tgz#939e3a784ae4f80b1fde8098b91af1776ff1312b" + integrity sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg== + +"@types/d3-polygon@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.0.tgz#5200a3fa793d7736fa104285fa19b0dbc2424b93" + integrity sha512-D49z4DyzTKXM0sGKVqiTDTYr+DHg/uxsiWDAkNrwXYuiZVd9o9wXZIo+YsHkifOiyBkmSWlEngHCQme54/hnHw== + +"@types/d3-quadtree@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.2.tgz#433112a178eb7df123aab2ce11c67f51cafe8ff5" + integrity sha512-QNcK8Jguvc8lU+4OfeNx+qnVy7c0VrDJ+CCVFS9srBo2GL9Y18CnIxBdTF3v38flrGy5s1YggcoAiu6s4fLQIw== + +"@types/d3-random@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.1.tgz#5c8d42b36cd4c80b92e5626a252f994ca6bfc953" + integrity sha512-IIE6YTekGczpLYo/HehAy3JGF1ty7+usI97LqraNa8IiDur+L44d0VOjAvFQWJVdZOJHukUJw+ZdZBlgeUsHOQ== + +"@types/d3-scale-chromatic@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#103124777e8cdec85b20b51fd3397c682ee1e954" + integrity sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw== + +"@types/d3-scale@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.2.tgz#41be241126af4630524ead9cb1008ab2f0f26e69" + integrity sha512-Yk4htunhPAwN0XGlIwArRomOjdoBFXC3+kCxK2Ubg7I9shQlVSJy/pG/Ht5ASN+gdMIalpk8TJ5xV74jFsetLA== + dependencies: + "@types/d3-time" "*" + +"@types/d3-selection@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.2.tgz#23e48a285b24063630bbe312cc0cfe2276de4a59" + integrity sha512-d29EDd0iUBrRoKhPndhDY6U/PYxOWqgIZwKTooy2UkBfU7TNZNpRho0yLWPxlatQrFWk2mnTu71IZQ4+LRgKlQ== + +"@types/d3-shape@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.0.2.tgz#4b1ca4ddaac294e76b712429726d40365cd1e8ca" + integrity sha512-5+ButCmIfNX8id5seZ7jKj3igdcxx+S9IDBiT35fQGTLZUfkFgTv+oBH34xgeoWDKpWcMITSzBILWQtBoN5Piw== + dependencies: + "@types/d3-path" "*" + +"@types/d3-time-format@*": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.0.tgz#ee7b6e798f8deb2d9640675f8811d0253aaa1946" + integrity sha512-yjfBUe6DJBsDin2BMIulhSHmr5qNR5Pxs17+oW4DoVPyVIXZ+m6bs7j1UVKP08Emv6jRmYrYqxYzO63mQxy1rw== + +"@types/d3-time@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.0.tgz#e1ac0f3e9e195135361fa1a1d62f795d87e6e819" + integrity sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg== + +"@types/d3-timer@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.0.tgz#e2505f1c21ec08bda8915238e397fb71d2fc54ce" + integrity sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g== + +"@types/d3-transition@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.1.tgz#c9a96125567173d6163a6985b874f79154f4cc3d" + integrity sha512-Sv4qEI9uq3bnZwlOANvYK853zvpdKEm1yz9rcc8ZTsxvRklcs9Fx4YFuGA3gXoQN/c/1T6QkVNjhaRO/cWj94g== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-zoom@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.1.tgz#4bfc7e29625c4f79df38e2c36de52ec3e9faf826" + integrity sha512-7s5L9TjfqIYQmQQEUcpMAcBOahem7TRoSO/+Gkz02GbMVuULiZzjF2BOdw291dbO2aNon4m2OdFsRGaCq2caLQ== + dependencies: + "@types/d3-interpolate" "*" + "@types/d3-selection" "*" + +"@types/d3@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.1.0.tgz#8f32a7e7f434d8f920c8b1ebdfed55e18c033720" + integrity sha512-gYWvgeGjEl+zmF8c+U1RNIKqe7sfQwIXeLXO5Os72TjDjCEtgpvGBvZ8dXlAuSS1m6B90Y1Uo6Bm36OGR/OtCA== + dependencies: + "@types/d3-array" "*" + "@types/d3-axis" "*" + "@types/d3-brush" "*" + "@types/d3-chord" "*" + "@types/d3-color" "*" + "@types/d3-contour" "*" + "@types/d3-delaunay" "*" + "@types/d3-dispatch" "*" + "@types/d3-drag" "*" + "@types/d3-dsv" "*" + "@types/d3-ease" "*" + "@types/d3-fetch" "*" + "@types/d3-force" "*" + "@types/d3-format" "*" + "@types/d3-geo" "*" + "@types/d3-hierarchy" "*" + "@types/d3-interpolate" "*" + "@types/d3-path" "*" + "@types/d3-polygon" "*" + "@types/d3-quadtree" "*" + "@types/d3-random" "*" + "@types/d3-scale" "*" + "@types/d3-scale-chromatic" "*" + "@types/d3-selection" "*" + "@types/d3-shape" "*" + "@types/d3-time" "*" + "@types/d3-time-format" "*" + "@types/d3-timer" "*" + "@types/d3-transition" "*" + "@types/d3-zoom" "*" + +"@types/eslint-scope@^3.7.3": + version "3.7.3" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" + integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.4.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304" + integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/eslint@^7.28.2": + version "7.29.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.29.0.tgz#e56ddc8e542815272720bb0b4ccc2aff9c3e1c78" + integrity sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": + version "4.17.28" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" + integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@*", "@types/express@^4.17.13": + version "4.17.13" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" + integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.18" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/geojson@*": + version "7946.0.8" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca" + integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA== + +"@types/graceful-fs@^4.1.2": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + dependencies: + "@types/node" "*" + +"@types/hast@^2.0.0": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" + integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + dependencies: + "@types/unist" "*" + +"@types/hoist-non-react-statics@^3.3.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + +"@types/html-minifier-terser@^6.0.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" + integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + +"@types/http-proxy@^1.17.8": + version "1.17.8" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55" + integrity sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@*", "@types/jest@^27.4.1": + version "27.4.1" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d" + integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw== + dependencies: + jest-matcher-utils "^27.0.0" + pretty-format "^27.0.0" + +"@types/js-levenshtein@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz#ba05426a43f9e4e30b631941e0aa17bf0c890ed5" + integrity sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g== + +"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.9" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" + integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + +"@types/lodash@^4.14.160": + version "4.14.179" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.179.tgz#490ec3288088c91295780237d2497a3aa9dfb5c5" + integrity sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w== + +"@types/mdast@^3.0.0": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" + integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + dependencies: + "@types/unist" "*" + +"@types/mime@^1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" + integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== + +"@types/node@*", "@types/node@^17.0.21": + version "17.0.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644" + integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ== + +"@types/numeral@^0.0.28": + version "0.0.28" + resolved "https://registry.yarnpkg.com/@types/numeral/-/numeral-0.0.28.tgz#e43928f0bda10b169b6f7ecf99e3ddf836b8ebe4" + integrity sha512-Sjsy10w6XFHDktJJdXzBJmoondAKW+LcGpRFH+9+zXEDj0cOH8BxJuZA9vUDSMAzU1YRJlsPKmZEEiTYDlICLw== + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + +"@types/parse5@^5.0.0": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" + integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== + +"@types/prettier@^2.1.5": + version "2.4.4" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.4.tgz#5d9b63132df54d8909fce1c3f8ca260fdd693e17" + integrity sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA== + +"@types/prismjs@*": + version "1.26.0" + resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.0.tgz#a1c3809b0ad61c62cac6d4e0c56d610c910b7654" + integrity sha512-ZTaqn/qSqUuAq1YwvOFQfVW1AR/oQJlLSZVustdjwI+GZ8kr0MSHBj0tsXPW1EqHubx50gtBEjbPGsdZwQwCjQ== + +"@types/prop-types@*": + version "15.7.4" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" + integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== + +"@types/q@^1.5.1": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df" + integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ== + +"@types/qs@*": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/react-beautiful-dnd@^13.1.2": + version "13.1.2" + resolved "https://registry.yarnpkg.com/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz#510405abb09f493afdfd898bf83995dc6385c130" + integrity sha512-+OvPkB8CdE/bGdXKyIhc/Lm2U7UAYCCJgsqmopFmh9gbAudmslkI8eOrPDjg4JhwSE6wytz4a3/wRjKtovHVJg== + dependencies: + "@types/react" "*" + +"@types/react-dom@*", "@types/react-dom@^17.0.13": + version "17.0.13" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.13.tgz#a3323b974ee4280070982b3112351bb1952a7809" + integrity sha512-wEP+B8hzvy6ORDv1QBhcQia4j6ea4SFIBttHYpXKPFZRviBvknq0FRh3VrIxeXUmsPkwuXVZrVGG7KUVONmXCQ== + dependencies: + "@types/react" "*" + +"@types/react-input-autosize@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@types/react-input-autosize/-/react-input-autosize-2.2.1.tgz#6a335212e7fce1e1a4da56ae2095c8c5c35fbfe6" + integrity sha512-RxzEjd4gbLAAdLQ92Q68/AC+TfsAKTc4evsArUH1aIShIMqQMIMjsxoSnwyjtbFTO/AGIW/RQI94XSdvOxCz/w== + dependencies: + "@types/react" "*" + +"@types/react-redux@^7.1.20": + version "7.1.23" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.23.tgz#3c2bb1bcc698ae69d70735f33c5a8e95f41ac528" + integrity sha512-D02o3FPfqQlfu2WeEYwh3x2otYd2Dk1o8wAfsA0B1C2AJEFxE663Ozu7JzuWbznGgW248NaOF6wsqCGNq9d3qw== + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + redux "^4.0.0" + +"@types/react-virtualized-auto-sizer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.1.tgz#b3187dae1dfc4c15880c9cfc5b45f2719ea6ebd4" + integrity sha512-GH8sAnBEM5GV9LTeiz56r4ZhMOUSrP43tAQNSRVxNexDjcNKLCEtnxusAItg1owFUFE6k0NslV26gqVClVvong== + dependencies: + "@types/react" "*" + +"@types/react-window@^1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@types/react-window/-/react-window-1.8.5.tgz#285fcc5cea703eef78d90f499e1457e9b5c02fc1" + integrity sha512-V9q3CvhC9Jk9bWBOysPGaWy/Z0lxYcTXLtLipkt2cnRj1JOSFNF7wqGpkScSXMgBwC+fnVRg/7shwgddBG5ICw== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^17.0.39": + version "17.0.39" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce" + integrity sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/refractor@^3.0.0": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/refractor/-/refractor-3.0.2.tgz#2d42128d59f78f84d2c799ffc5ab5cadbcba2d82" + integrity sha512-2HMXuwGuOqzUG+KUTm9GDJCHl0LCBKsB5cg28ujEmVi/0qgTb6jOmkVSO5K48qXksyl2Fr3C0Q2VrgD4zbwyXg== + dependencies: + "@types/prismjs" "*" + +"@types/resize-observer-browser@^0.1.5": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@types/resize-observer-browser/-/resize-observer-browser-0.1.7.tgz#294aaadf24ac6580b8fbd1fe3ab7b59fe85f9ef3" + integrity sha512-G9eN0Sn0ii9PWQ3Vl72jDPgeJwRWhv2Qk/nQkJuWmRmOB4HX3/BhD5SE1dZs/hzPZL/WKnvF0RHdTSG54QJFyg== + +"@types/resolve@1.17.1": + version "1.17.1" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" + integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== + dependencies: + "@types/node" "*" + +"@types/retry@^0.12.0": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" + integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== + +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + +"@types/serve-index@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" + integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + dependencies: + "@types/express" "*" + +"@types/serve-static@*": + version "1.13.10" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" + integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/set-cookie-parser@^2.4.0": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@types/set-cookie-parser/-/set-cookie-parser-2.4.2.tgz#b6a955219b54151bfebd4521170723df5e13caad" + integrity sha512-fBZgytwhYAUkj/jC/FAV4RQ5EerRup1YQsXQCh8rZfiHkc4UahC192oH0smGwsXol3cL3A5oETuAHeQHmhXM4w== + dependencies: + "@types/node" "*" + +"@types/sockjs@^0.3.33": + version "0.3.33" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" + integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + dependencies: + "@types/node" "*" + +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + +"@types/testing-library__jest-dom@^5.9.1": + version "5.14.3" + resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.3.tgz#ee6c7ffe9f8595882ee7bda8af33ae7b8789ef17" + integrity sha512-oKZe+Mf4ioWlMuzVBaXQ9WDnEm1+umLx0InILg+yvZVBBDmzV5KfZyLrCvadtWcx8+916jLmHafcmqqffl+iIw== + dependencies: + "@types/jest" "*" + +"@types/trusted-types@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" + integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg== + +"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" + integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + +"@types/vfile-message@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/vfile-message/-/vfile-message-2.0.0.tgz#690e46af0fdfc1f9faae00cd049cc888957927d5" + integrity sha512-GpTIuDpb9u4zIO165fUy9+fXcULdD8HFRNli04GehoMVbeNq7D6OBnqSmg3lxZnC+UvgUhEWKxdKiwYUkGltIw== + dependencies: + vfile-message "*" + +"@types/ws@^8.2.2": + version "8.5.2" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.2.tgz#77e0c2e360e9579da930ffcfa53c5975ea3bdd26" + integrity sha512-VXI82ykONr5tacHEojnErTQk+KQSoYbW1NB6iz6wUwrNd+BqfkfggQNoNdCqhJSzbNumShPERbM+Pc5zpfhlbw== + dependencies: + "@types/node" "*" + +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^16.0.0": + version "16.0.4" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" + integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@^5.5.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz#2809052b85911ced9c54a60dac10e515e9114497" + integrity sha512-vLktb2Uec81fxm/cfz2Hd6QaWOs8qdmVAZXLdOBX6JFJDhf6oDZpMzZ4/LZ6SFM/5DgDcxIMIvy3F+O9yZBuiQ== + dependencies: + "@typescript-eslint/scope-manager" "5.13.0" + "@typescript-eslint/type-utils" "5.13.0" + "@typescript-eslint/utils" "5.13.0" + debug "^4.3.2" + functional-red-black-tree "^1.0.1" + ignore "^5.1.8" + regexpp "^3.2.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/experimental-utils@^5.0.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.13.0.tgz#5f9c509998a4b0b5662c23a758ac0e178dc7bb98" + integrity sha512-A0btJxjB9gH6yJsARONe5xd0ykgj1+0fO1TRWoUBn2hT3haWiZeh4f1FILKW0z/9OBchT5zCOz3hiJfRK/vumA== + dependencies: + "@typescript-eslint/utils" "5.13.0" + +"@typescript-eslint/parser@^5.5.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.13.0.tgz#0394ed8f2f849273c0bf4b811994d177112ced5c" + integrity sha512-GdrU4GvBE29tm2RqWOM0P5QfCtgCyN4hXICj/X9ibKED16136l9ZpoJvCL5pSKtmJzA+NRDzQ312wWMejCVVfg== + dependencies: + "@typescript-eslint/scope-manager" "5.13.0" + "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/typescript-estree" "5.13.0" + debug "^4.3.2" + +"@typescript-eslint/scope-manager@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz#cf6aff61ca497cb19f0397eea8444a58f46156b6" + integrity sha512-T4N8UvKYDSfVYdmJq7g2IPJYCRzwtp74KyDZytkR4OL3NRupvswvmJQJ4CX5tDSurW2cvCc1Ia1qM7d0jpa7IA== + dependencies: + "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/visitor-keys" "5.13.0" + +"@typescript-eslint/type-utils@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.13.0.tgz#b0efd45c85b7bab1125c97b752cab3a86c7b615d" + integrity sha512-/nz7qFizaBM1SuqAKb7GLkcNn2buRdDgZraXlkhz+vUGiN1NZ9LzkA595tHHeduAiS2MsHqMNhE2zNzGdw43Yg== + dependencies: + "@typescript-eslint/utils" "5.13.0" + debug "^4.3.2" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.13.0.tgz#da1de4ae905b1b9ff682cab0bed6b2e3be9c04e5" + integrity sha512-LmE/KO6DUy0nFY/OoQU0XelnmDt+V8lPQhh8MOVa7Y5k2gGRd6U9Kp3wAjhB4OHg57tUO0nOnwYQhRRyEAyOyg== + +"@typescript-eslint/typescript-estree@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz#b37c07b748ff030a3e93d87c842714e020b78141" + integrity sha512-Q9cQow0DeLjnp5DuEDjLZ6JIkwGx3oYZe+BfcNuw/POhtpcxMTy18Icl6BJqTSd+3ftsrfuVb7mNHRZf7xiaNA== + dependencies: + "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/visitor-keys" "5.13.0" + debug "^4.3.2" + globby "^11.0.4" + is-glob "^4.0.3" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.13.0", "@typescript-eslint/utils@^5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.13.0.tgz#2328feca700eb02837298339a2e49c46b41bd0af" + integrity sha512-+9oHlPWYNl6AwwoEt5TQryEHwiKRVjz7Vk6kaBeD3/kwHE5YqTGHtm/JZY8Bo9ITOeKutFaXnBlMgSATMJALUQ== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.13.0" + "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/typescript-estree" "5.13.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/visitor-keys@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz#f45ff55bcce16403b221ac9240fbeeae4764f0fd" + integrity sha512-HLKEAS/qA1V7d9EzcpLFykTePmOQqOFim8oCvhY3pZgQ8Hi38hYpHd9e5GN6nQBFQNecNhws5wkS9Y5XIO0s/g== + dependencies: + "@typescript-eslint/types" "5.13.0" + eslint-visitor-keys "^3.0.0" + +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + +"@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + +"@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@xtuc/long" "4.2.2" + +"@xmldom/xmldom@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.5.tgz#09fa51e356d07d0be200642b0e4f91d8e6dd408d" + integrity sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +abab@^2.0.3, abab@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + +acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + +acorn-jsx@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-node@^1.6.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" + integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== + dependencies: + acorn "^7.0.0" + acorn-walk "^7.0.0" + xtend "^4.0.2" + +acorn-walk@^7.0.0, acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + +acorn@^7.0.0, acorn@^7.1.1: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + +address@^1.0.1, address@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" + integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== + +adjust-sourcemap-loader@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz#fc4a0fd080f7d10471f30a7320f25560ade28c99" + integrity sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A== + dependencies: + loader-utils "^2.0.0" + regex-parser "^2.2.11" + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.10.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.0, ajv@^8.6.0, ajv@^8.8.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" + integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3, anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb" + integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +aria-hidden@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254" + integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA== + dependencies: + tslib "^1.0.0" + +aria-query@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" + integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== + dependencies: + "@babel/runtime" "^7.10.2" + "@babel/runtime-corejs3" "^7.10.2" + +aria-query@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.0.0.tgz#210c21aaf469613ee8c9a62c7f86525e058db52c" + integrity sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-flatten@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + +array-includes@^3.1.3, array-includes@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" + integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.flat@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" + integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + +array.prototype.flatmap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446" + integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.19.0" + +asap@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + +ast-types-flow@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" + integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= + +async@0.9.x: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= + +async@^2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +attr-accept@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.2.tgz#646613809660110749e92f2c10833b70968d929b" + integrity sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg== + +autoprefixer@^10.4.2: + version "10.4.2" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b" + integrity sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ== + dependencies: + browserslist "^4.19.1" + caniuse-lite "^1.0.30001297" + fraction.js "^4.1.2" + normalize-range "^0.1.2" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" + +axe-core@^4.3.5: + version "4.4.1" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.1.tgz#7dbdc25989298f9ad006645cd396782443757413" + integrity sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw== + +axobject-query@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" + integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== + +babel-jest@^27.4.2, babel-jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" + integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg== + dependencies: + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^27.5.1" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-loader@^8.2.3: + version "8.2.3" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" + integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== + dependencies: + find-cache-dir "^3.3.1" + loader-utils "^1.4.0" + make-dir "^3.1.0" + schema-utils "^2.6.5" + +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e" + integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" + "@types/babel__traverse" "^7.0.6" + +babel-plugin-macros@^2.6.1: + version "2.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" + integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== + dependencies: + "@babel/runtime" "^7.7.2" + cosmiconfig "^6.0.0" + resolve "^1.12.0" + +babel-plugin-macros@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" + integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== + dependencies: + "@babel/runtime" "^7.12.5" + cosmiconfig "^7.0.0" + resolve "^1.19.0" + +babel-plugin-named-asset-import@^0.3.8: + version "0.3.8" + resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz#6b7fa43c59229685368683c28bc9734f24524cc2" + integrity sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q== + +babel-plugin-polyfill-corejs2@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" + integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== + dependencies: + "@babel/compat-data" "^7.13.11" + "@babel/helper-define-polyfill-provider" "^0.3.1" + semver "^6.1.1" + +babel-plugin-polyfill-corejs3@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" + integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.1" + core-js-compat "^3.21.0" + +babel-plugin-polyfill-regenerator@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" + integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.1" + +babel-plugin-transform-react-remove-prop-types@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" + integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81" + integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag== + dependencies: + babel-plugin-jest-hoist "^27.5.1" + babel-preset-current-node-syntax "^1.0.0" + +babel-preset-react-app@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz#ed6005a20a24f2c88521809fa9aea99903751584" + integrity sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg== + dependencies: + "@babel/core" "^7.16.0" + "@babel/plugin-proposal-class-properties" "^7.16.0" + "@babel/plugin-proposal-decorators" "^7.16.4" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.0" + "@babel/plugin-proposal-numeric-separator" "^7.16.0" + "@babel/plugin-proposal-optional-chaining" "^7.16.0" + "@babel/plugin-proposal-private-methods" "^7.16.0" + "@babel/plugin-transform-flow-strip-types" "^7.16.0" + "@babel/plugin-transform-react-display-name" "^7.16.0" + "@babel/plugin-transform-runtime" "^7.16.4" + "@babel/preset-env" "^7.16.4" + "@babel/preset-react" "^7.16.0" + "@babel/preset-typescript" "^7.16.0" + "@babel/runtime" "^7.16.3" + babel-plugin-macros "^3.1.0" + babel-plugin-transform-react-remove-prop-types "^0.4.24" + +bail@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" + integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= + +bfj@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/bfj/-/bfj-7.0.2.tgz#1988ce76f3add9ac2913fd8ba47aad9e651bfbb2" + integrity sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw== + dependencies: + bluebird "^3.5.5" + check-types "^11.1.1" + hoopy "^0.1.4" + tryer "^1.0.1" + +big-integer@^1.6.16: + version "1.6.51" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" + integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +bluebird@^3.5.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +body-parser@1.19.2: + version "1.19.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" + integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.8.1" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.9.7" + raw-body "2.4.3" + type-is "~1.6.18" + +bonjour@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" + integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= + dependencies: + array-flatten "^2.1.0" + deep-equal "^1.0.1" + dns-equal "^1.0.0" + dns-txt "^2.0.2" + multicast-dns "^6.0.1" + multicast-dns-service-types "^1.1.0" + +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.1, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +broadcast-channel@^3.4.1: + version "3.7.0" + resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-3.7.0.tgz#2dfa5c7b4289547ac3f6705f9c00af8723889937" + integrity sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg== + dependencies: + "@babel/runtime" "^7.7.2" + detect-node "^2.1.0" + js-sha3 "0.8.0" + microseconds "0.2.0" + nano-time "1.0.0" + oblivious-set "1.0.0" + rimraf "3.0.2" + unload "2.2.0" + +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^4.18.1, browserslist@^4.19.1, browserslist@^4.19.3: + version "4.19.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.3.tgz#29b7caad327ecf2859485f696f9604214bedd383" + integrity sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg== + dependencies: + caniuse-lite "^1.0.30001312" + electron-to-chromium "^1.4.71" + escalade "^3.1.1" + node-releases "^2.0.2" + picocolors "^1.0.0" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-indexof@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" + integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +builtin-modules@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" + integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA== + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0, camelcase@^6.2.1: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001297, caniuse-lite@^1.0.30001312: + version "1.0.30001312" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" + integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== + +case-sensitive-paths-webpack-plugin@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4" + integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw== + +ccount@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" + integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== + +chalk@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" + integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +char-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-2.0.1.tgz#6dafdb25f9d3349914079f010ba8d0e6ff9cd01e" + integrity sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw== + +character-entities-html4@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.4.tgz#0e64b0a3753ddbf1fdc044c5fd01d0199a02e125" + integrity sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g== + +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + +charcodes@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/charcodes/-/charcodes-0.2.0.tgz#5208d327e6cc05f99eb80ffc814707572d1f14e4" + integrity sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ== + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +check-types@^11.1.1: + version "11.1.2" + resolved "https://registry.yarnpkg.com/check-types/-/check-types-11.1.2.tgz#86a7c12bf5539f6324eb0e70ca8896c0e38f3e2f" + integrity sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ== + +chokidar@^3.4.2, chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chroma-js@^2.1.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-2.4.2.tgz#dffc214ed0c11fa8eefca2c36651d8e57cbfb2b0" + integrity sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A== + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +ci-info@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2" + integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== + +cjs-module-lexer@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" + integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== + +classnames@^2.2.6: + version "2.3.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" + integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== + +clean-css@^5.2.2: + version "5.2.4" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.4.tgz#982b058f8581adb2ae062520808fb2429bd487a4" + integrity sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg== + dependencies: + source-map "~0.6.0" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" + integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== + +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== + dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" + q "^1.1.2" + +collapse-white-space@^1.0.2: + version "1.0.6" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" + integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== + +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@^1.1.4, color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colord@^2.9.1: + version "2.9.2" + resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" + integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ== + +colorette@^2.0.10: + version "2.0.16" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" + integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +comma-separated-tokens@^1.0.0: + version "1.0.8" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" + integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== + +commander@7, commander@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +common-path-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" + integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== + +common-tags@^1.8.0: + version "1.8.2" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" + integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +confusing-browser-globals@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" + integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== + +connect-history-api-fallback@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" + integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== + dependencies: + safe-buffer "~5.1.1" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.4.2, cookie@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +core-js-compat@^3.20.2, core-js-compat@^3.21.0: + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.1.tgz#cac369f67c8d134ff8f9bd1623e3bc2c42068c82" + integrity sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g== + dependencies: + browserslist "^4.19.1" + semver "7.0.0" + +core-js-pure@^3.20.2, core-js-pure@^3.8.1: + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" + integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== + +core-js@^3.19.2: + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94" + integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cosmiconfig@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" + integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.7.2" + +cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" + integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + +css-blank-pseudo@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz#36523b01c12a25d812df343a32c322d2a2324561" + integrity sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ== + dependencies: + postcss-selector-parser "^6.0.9" + +css-box-model@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1" + integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw== + dependencies: + tiny-invariant "^1.0.6" + +css-declaration-sorter@^6.0.3: + version "6.1.4" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz#b9bfb4ed9a41f8dcca9bf7184d849ea94a8294b4" + integrity sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw== + dependencies: + timsort "^0.3.0" + +css-has-pseudo@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz#57f6be91ca242d5c9020ee3e51bbb5b89fc7af73" + integrity sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw== + dependencies: + postcss-selector-parser "^6.0.9" + +css-loader@^6.5.1: + version "6.6.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.6.0.tgz#c792ad5510bd1712618b49381bd0310574fafbd3" + integrity sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.5" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.3.5" + +css-minimizer-webpack-plugin@^3.2.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f" + integrity sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q== + dependencies: + cssnano "^5.0.6" + jest-worker "^27.0.2" + postcss "^8.3.5" + schema-utils "^4.0.0" + serialize-javascript "^6.0.0" + source-map "^0.6.1" + +css-prefers-color-scheme@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz#ca8a22e5992c10a5b9d315155e7caee625903349" + integrity sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA== + +css-select-base-adapter@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + +css-select@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" + integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== + dependencies: + boolbase "^1.0.0" + css-what "^3.2.1" + domutils "^1.7.0" + nth-check "^1.0.2" + +css-select@^4.1.3: + version "4.2.1" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" + integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== + dependencies: + boolbase "^1.0.0" + css-what "^5.1.0" + domhandler "^4.3.0" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-tree@1.0.0-alpha.37: + version "1.0.0-alpha.37" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" + integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== + dependencies: + mdn-data "2.0.4" + source-map "^0.6.1" + +css-tree@^1.1.2, css-tree@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + +css-what@^3.2.1: + version "3.4.2" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" + integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== + +css-what@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" + integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== + +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= + +css@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d" + integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ== + dependencies: + inherits "^2.0.4" + source-map "^0.6.1" + source-map-resolve "^0.6.0" + +cssdb@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-6.4.0.tgz#54899b9042e302be3090b8510ea71fefd08c9e6b" + integrity sha512-8NMWrur/ewSNrRNZndbtOTXc2Xb2b+NCTPHj8VErFYvJUlgsMAiBGaFaxG6hjy9zbCjj2ZLwSQrMM+tormO8qA== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +cssnano-preset-default@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.0.tgz#2579d38b9217746f2cf9f938954a91e00418ded6" + integrity sha512-3N5Vcptj2pqVKpHVqH6ezOJvqikR2PdLTbTrsrhF61FbLRQuujAqZ2sKN5rvcMsb7hFjrNnjZT8CGEkxoN/Pwg== + dependencies: + css-declaration-sorter "^6.0.3" + cssnano-utils "^3.1.0" + postcss-calc "^8.2.3" + postcss-colormin "^5.3.0" + postcss-convert-values "^5.1.0" + postcss-discard-comments "^5.1.0" + postcss-discard-duplicates "^5.1.0" + postcss-discard-empty "^5.1.0" + postcss-discard-overridden "^5.1.0" + postcss-merge-longhand "^5.1.0" + postcss-merge-rules "^5.1.0" + postcss-minify-font-values "^5.1.0" + postcss-minify-gradients "^5.1.0" + postcss-minify-params "^5.1.0" + postcss-minify-selectors "^5.2.0" + postcss-normalize-charset "^5.1.0" + postcss-normalize-display-values "^5.1.0" + postcss-normalize-positions "^5.1.0" + postcss-normalize-repeat-style "^5.1.0" + postcss-normalize-string "^5.1.0" + postcss-normalize-timing-functions "^5.1.0" + postcss-normalize-unicode "^5.1.0" + postcss-normalize-url "^5.1.0" + postcss-normalize-whitespace "^5.1.0" + postcss-ordered-values "^5.1.0" + postcss-reduce-initial "^5.1.0" + postcss-reduce-transforms "^5.1.0" + postcss-svgo "^5.1.0" + postcss-unique-selectors "^5.1.0" + +cssnano-utils@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" + integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== + +cssnano@^5.0.6: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.0.tgz#cf977d660a5824d0d5542639ed1d4045afd84cbe" + integrity sha512-wWxave1wMlThGg4ueK98jFKaNqXnQd1nVZpSkQ9XvR+YymlzP1ofWqES1JkHtI250LksP9z5JH+oDcrKDJezAg== + dependencies: + cssnano-preset-default "^5.2.0" + lilconfig "^2.0.3" + yaml "^1.10.2" + +csso@^4.0.2, csso@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" + integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== + dependencies: + css-tree "^1.1.2" + +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + +csstype@^3.0.2: + version "3.0.11" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33" + integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw== + +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.1.1.tgz#7797eb53ead6b9083c75a45a681e93fc41bc468c" + integrity sha512-33qQ+ZoZlli19IFiQx4QEpf2CBEayMRzhlisJHSCsSUbDXv6ZishqS1x7uFVClKG4Wr7rZVHvaAttoLow6GqdQ== + dependencies: + internmap "1 - 2" + +d3-axis@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322" + integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw== + +d3-brush@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c" + integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "3" + d3-transition "3" + +d3-chord@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966" + integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g== + dependencies: + d3-path "1 - 3" + +"d3-color@1 - 3", d3-color@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.0.1.tgz#03316e595955d1fcd39d9f3610ad41bb90194d0a" + integrity sha512-6/SlHkDOBLyQSJ1j1Ghs82OIUXpKWlR0hCsw0XrLSQhuUPuCSmLQ1QPH98vpnQxMUQM2/gfAkUEWsupVpd9JGw== + +d3-contour@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-3.0.1.tgz#2c64255d43059599cd0dba8fe4cc3d51ccdd9bbd" + integrity sha512-0Oc4D0KyhwhM7ZL0RMnfGycLN7hxHB8CMmwZ3+H26PWAG0ozNuYG5hXSDNgmP1SgJkQMrlG6cP20HoaSbvcJTQ== + dependencies: + d3-array "2 - 3" + +d3-delaunay@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.2.tgz#7fd3717ad0eade2fc9939f4260acfb503f984e92" + integrity sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ== + dependencies: + delaunator "5" + +"d3-dispatch@1 - 3", d3-dispatch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" + integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== + +"d3-drag@2 - 3", d3-drag@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba" + integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== + dependencies: + d3-dispatch "1 - 3" + d3-selection "3" + +"d3-dsv@1 - 3", d3-dsv@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73" + integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q== + dependencies: + commander "7" + iconv-lite "0.6" + rw "1" + +"d3-ease@1 - 3", d3-ease@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== + +d3-fetch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22" + integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw== + dependencies: + d3-dsv "1 - 3" + +d3-force@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4" + integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg== + dependencies: + d3-dispatch "1 - 3" + d3-quadtree "1 - 3" + d3-timer "1 - 3" + +"d3-format@1 - 3", d3-format@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== + +d3-geo@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.0.1.tgz#4f92362fd8685d93e3b1fae0fd97dc8980b1ed7e" + integrity sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA== + dependencies: + d3-array "2.5.0 - 3" + +d3-hierarchy@3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.1.tgz#9cbb0ffd2375137a351e6cfeed344a06d4ff4597" + integrity sha512-LtAIu54UctRmhGKllleflmHalttH3zkfSi4NlKrTAoFKjC+AFBJohsCAdgCBYQwH0F8hIOGY89X1pPqAchlMkA== + +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +"d3-path@1 - 3", d3-path@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.0.1.tgz#f09dec0aaffd770b7995f1a399152bf93052321e" + integrity sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w== + +d3-polygon@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398" + integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg== + +"d3-quadtree@1 - 3", d3-quadtree@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f" + integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw== + +d3-random@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4" + integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ== + +d3-scale-chromatic@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#15b4ceb8ca2bb0dcb6d1a641ee03d59c3b62376a" + integrity sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g== + dependencies: + d3-color "1 - 3" + d3-interpolate "1 - 3" + +d3-scale@4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + +"d3-selection@2 - 3", d3-selection@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" + integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== + +d3-shape@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.1.0.tgz#c8a495652d83ea6f524e482fca57aa3f8bc32556" + integrity sha512-tGDh1Muf8kWjEDT/LswZJ8WF85yDZLvVJpYU9Nq+8+yW1Z5enxrmXOhTArlkaElU+CTn0OTVNli+/i+HP45QEQ== + dependencies: + d3-path "1 - 3" + +"d3-time-format@2 - 4", d3-time-format@4: + version "4.1.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== + dependencies: + d3-time "1 - 3" + +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.0.0.tgz#65972cb98ae2d4954ef5c932e8704061335d4975" + integrity sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ== + dependencies: + d3-array "2 - 3" + +"d3-timer@1 - 3", d3-timer@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== + +"d3-transition@2 - 3", d3-transition@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f" + integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w== + dependencies: + d3-color "1 - 3" + d3-dispatch "1 - 3" + d3-ease "1 - 3" + d3-interpolate "1 - 3" + d3-timer "1 - 3" + +d3-zoom@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" + integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "2 - 3" + d3-transition "2 - 3" + +d3@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/d3/-/d3-7.3.0.tgz#f3d5a22c1f658952a6491cf50132f5267ed7a40a" + integrity sha512-MDRLJCMK232OJQRqGljQ/gCxtB8k3/sLKFjftMjzPB3nKVUODpdW9Rb3vcq7U8Ka5YKoZkAmp++Ur6I+6iNWIw== + dependencies: + d3-array "3" + d3-axis "3" + d3-brush "3" + d3-chord "3" + d3-color "3" + d3-contour "3" + d3-delaunay "6" + d3-dispatch "3" + d3-drag "3" + d3-dsv "3" + d3-ease "3" + d3-fetch "3" + d3-force "3" + d3-format "3" + d3-geo "3" + d3-hierarchy "3" + d3-interpolate "3" + d3-path "3" + d3-polygon "3" + d3-quadtree "3" + d3-random "3" + d3-scale "4" + d3-scale-chromatic "3" + d3-selection "3" + d3-shape "3" + d3-time "3" + d3-time-format "4" + d3-timer "3" + d3-transition "3" + d3-zoom "3" + +damerau-levenshtein@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" + integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== + +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + +debug@2.6.9, debug@^2.6.0, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + +debug@^3.1.1, debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decimal.js@^10.2.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" + integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= + +deep-equal@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +deep-is@^0.1.3, deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== + dependencies: + execa "^5.0.0" + +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= + +del@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" + integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== + dependencies: + globby "^11.0.1" + graceful-fs "^4.2.4" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.2" + p-map "^4.0.0" + rimraf "^3.0.2" + slash "^3.0.0" + +delaunator@5: + version "5.0.0" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b" + integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw== + dependencies: + robust-predicates "^3.0.0" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +detect-node-es@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== + +detect-node@^2.0.4, detect-node@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + +detect-port-alt@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275" + integrity sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q== + dependencies: + address "^1.0.1" + debug "^2.6.0" + +detective@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" + integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg== + dependencies: + acorn-node "^1.6.1" + defined "^1.0.0" + minimist "^1.1.1" + +didyoumean@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" + integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== + +diff-sequences@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" + integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +dlv@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" + integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== + +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= + +dns-packet@^1.3.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" + integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== + dependencies: + ip "^1.1.0" + safe-buffer "^5.0.1" + +dns-txt@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" + integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= + dependencies: + buffer-indexof "^1.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9: + version "0.5.13" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.13.tgz#102ee5f25eacce09bdf1cfa5a298f86da473be4b" + integrity sha512-R305kwb5CcMDIpSHUnLyIAp7SrSPBx6F0VfQFB3M75xVMHhXJJIdePYgbPPh1o57vCHNu5QztokWUPsLjWzFqw== + +dom-converter@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" + integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== + dependencies: + utila "~0.4" + +dom-serializer@0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +dom-serializer@^1.0.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" + integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +domelementtype@1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" + integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== + +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + +domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" + integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== + dependencies: + domelementtype "^2.2.0" + +domutils@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^2.5.2, domutils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +dotenv-expand@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" + integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== + +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== + +duplexer@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +ejs@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a" + integrity sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw== + dependencies: + jake "^10.6.1" + +electron-to-chromium@^1.4.71: + version "1.4.75" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.75.tgz#d1ad9bb46f2f1bf432118c2be21d27ffeae82fdd" + integrity sha512-LxgUNeu3BVU7sXaKjUDD9xivocQLxFtq6wgERrutdY/yIOps3ODOZExK1jg8DTEg4U8TUCb5MLGeWFOYuxjF3Q== + +emittery@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" + integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +emoticon@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/emoticon/-/emoticon-3.2.0.tgz#c008ca7d7620fac742fe1bf4af8ff8fed154ae7f" + integrity sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +enhanced-resolve@^5.9.2: + version "5.9.2" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz#0224dcd6a43389ebfb2d55efee517e5466772dd9" + integrity sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +error-stack-parser@^2.0.6: + version "2.0.7" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.7.tgz#b0c6e2ce27d0495cf78ad98715e0cad1219abb57" + integrity sha512-chLOW0ZGRf4s8raLrDxa5sdkvPec5YdvwbFnqJme4rk0rFajP8mPtrDL1+I+CwrQDCjswDA5sREX7jYQDQs9vA== + dependencies: + stackframe "^1.1.1" + +es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" + integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.1" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.1" + is-string "^1.0.7" + is-weakref "^1.0.1" + object-inspect "^1.11.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-config-react-app@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-7.0.0.tgz#0fa96d5ec1dfb99c029b1554362ab3fa1c3757df" + integrity sha512-xyymoxtIt1EOsSaGag+/jmcywRuieQoA2JbPCjnw9HukFj9/97aGPoZVFioaotzk1K5Qt9sHO5EutZbkrAXS0g== + dependencies: + "@babel/core" "^7.16.0" + "@babel/eslint-parser" "^7.16.3" + "@rushstack/eslint-patch" "^1.1.0" + "@typescript-eslint/eslint-plugin" "^5.5.0" + "@typescript-eslint/parser" "^5.5.0" + babel-preset-react-app "^10.0.1" + confusing-browser-globals "^1.0.11" + eslint-plugin-flowtype "^8.0.3" + eslint-plugin-import "^2.25.3" + eslint-plugin-jest "^25.3.0" + eslint-plugin-jsx-a11y "^6.5.1" + eslint-plugin-react "^7.27.1" + eslint-plugin-react-hooks "^4.3.0" + eslint-plugin-testing-library "^5.0.1" + +eslint-import-resolver-node@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" + integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== + dependencies: + debug "^3.2.7" + resolve "^1.20.0" + +eslint-module-utils@^2.7.2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee" + integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ== + dependencies: + debug "^3.2.7" + find-up "^2.1.0" + +eslint-plugin-flowtype@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz#e1557e37118f24734aa3122e7536a038d34a4912" + integrity sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ== + dependencies: + lodash "^4.17.21" + string-natural-compare "^3.0.1" + +eslint-plugin-import@^2.25.3: + version "2.25.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1" + integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA== + dependencies: + array-includes "^3.1.4" + array.prototype.flat "^1.2.5" + debug "^2.6.9" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.6" + eslint-module-utils "^2.7.2" + has "^1.0.3" + is-core-module "^2.8.0" + is-glob "^4.0.3" + minimatch "^3.0.4" + object.values "^1.1.5" + resolve "^1.20.0" + tsconfig-paths "^3.12.0" + +eslint-plugin-jest@^25.3.0: + version "25.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz#ff4ac97520b53a96187bad9c9814e7d00de09a6a" + integrity sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ== + dependencies: + "@typescript-eslint/experimental-utils" "^5.0.0" + +eslint-plugin-jsx-a11y@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8" + integrity sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g== + dependencies: + "@babel/runtime" "^7.16.3" + aria-query "^4.2.2" + array-includes "^3.1.4" + ast-types-flow "^0.0.7" + axe-core "^4.3.5" + axobject-query "^2.2.0" + damerau-levenshtein "^1.0.7" + emoji-regex "^9.2.2" + has "^1.0.3" + jsx-ast-utils "^3.2.1" + language-tags "^1.0.5" + minimatch "^3.0.4" + +eslint-plugin-react-hooks@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172" + integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA== + +eslint-plugin-react@^7.27.1: + version "7.29.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.3.tgz#f4eab757f2756d25d6d4c2a58a9e20b004791f05" + integrity sha512-MzW6TuCnDOcta67CkpDyRfRsEVx9FNMDV8wZsDqe1luHPdGTrQIUaUXD27Ja3gHsdOIs/cXzNchWGlqm+qRVRg== + dependencies: + array-includes "^3.1.4" + array.prototype.flatmap "^1.2.5" + doctrine "^2.1.0" + estraverse "^5.3.0" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.5" + object.fromentries "^2.0.5" + object.hasown "^1.1.0" + object.values "^1.1.5" + prop-types "^15.8.1" + resolve "^2.0.0-next.3" + semver "^6.3.0" + string.prototype.matchall "^4.0.6" + +eslint-plugin-testing-library@^5.0.1: + version "5.0.6" + resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.0.6.tgz#86b0aff2ed0c80f63966c2a4894c06bff382b6d5" + integrity sha512-mMU4+slZsWKHNxtxc5TE2+bs9S//e2uFPlcpTapPhVdnctgn0+G/DaUu6VbT0JLiVMcbBjy3IcfddK+abZawbw== + dependencies: + "@typescript-eslint/utils" "^5.13.0" + +eslint-scope@5.1.1, eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" + integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== + +eslint-webpack-plugin@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz#83dad2395e5f572d6f4d919eedaa9cf902890fcb" + integrity sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg== + dependencies: + "@types/eslint" "^7.28.2" + jest-worker "^27.3.1" + micromatch "^4.0.4" + normalize-path "^3.0.0" + schema-utils "^3.1.1" + +eslint@^8.3.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.10.0.tgz#931be395eb60f900c01658b278e05b6dae47199d" + integrity sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw== + dependencies: + "@eslint/eslintrc" "^1.2.0" + "@humanwhocodes/config-array" "^0.9.2" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^6.0.1" + globals "^13.6.0" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" + integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ== + dependencies: + acorn "^8.7.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^3.3.0" + +esprima@^4.0.0, esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events@^3.2.0, events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + +expect@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74" + integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw== + dependencies: + "@jest/types" "^27.5.1" + jest-get-type "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + +express@^4.17.1: + version "4.17.3" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" + integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.19.2" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.4.2" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "~1.1.2" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.9.7" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.17.2" + serve-static "1.14.2" + setprototypeof "1.2.0" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.11, fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + dependencies: + bser "2.1.1" + +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +file-loader@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +file-selector@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-0.4.0.tgz#59ec4f27aa5baf0841e9c6385c8386bef4d18b17" + integrity sha512-iACCiXeMYOvZqlF1kTiYINzgepRBymz1wwjiuup9u9nayhb6g4fSwiyJ/6adli+EPwrWtpgQAh2PoS7HukEGEg== + dependencies: + tslib "^2.0.3" + +filelist@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b" + integrity sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ== + dependencies: + minimatch "^3.0.4" + +filesize@^8.0.6: + version "8.0.7" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8" + integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ== + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +filter-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" + integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs= + +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-cache-dir@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.5" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" + integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== + +focus-lock@^0.10.2: + version "0.10.2" + resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.10.2.tgz#561c62bae8387ecba1dd8e58a6df5ec29835c644" + integrity sha512-DSaI/UHZ/02sg1P616aIWgToQcrKKBmcCvomDZ1PZvcJFj350PnWhSJxJ76T3e5/GbtQEARIACtbrdlrF9C5kA== + dependencies: + tslib "^2.0.3" + +follow-redirects@^1.0.0: + version "1.14.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" + integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== + +fork-ts-checker-webpack-plugin@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e" + integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw== + dependencies: + "@babel/code-frame" "^7.8.3" + "@types/json-schema" "^7.0.5" + chalk "^4.1.0" + chokidar "^3.4.2" + cosmiconfig "^6.0.0" + deepmerge "^4.2.2" + fs-extra "^9.0.0" + glob "^7.1.6" + memfs "^3.1.2" + minimatch "^3.0.4" + schema-utils "2.7.0" + semver "^7.3.2" + tapable "^1.0.0" + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fraction.js@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.3.tgz#be65b0f20762ef27e1e793860bc2dfb716e99e65" + integrity sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +fs-extra@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.1.tgz#27de43b4320e833f6867cc044bfce29fdf0ef3b8" + integrity sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^9.0.0, fs-extra@^9.0.1: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-monkey@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" + integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^2.3.2, fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + +get-own-enumerable-property-symbols@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" + integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.1, glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.6.0, globals@^13.9.0: + version "13.12.1" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.1.tgz#ec206be932e6c77236677127577aa8e50bf1c5cb" + integrity sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw== + dependencies: + type-fest "^0.20.2" + +globby@^11.0.1, globby@^11.0.4: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + +graphql@^16.3.0: + version "16.3.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05" + integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A== + +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== + dependencies: + duplexer "^0.1.2" + +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + +harmony-reflect@^1.4.6: + version "1.6.2" + resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710" + integrity sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g== + +has-bigints@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.1, has-symbols@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hast-to-hyperscript@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz#9b67fd188e4c81e8ad66f803855334173920218d" + integrity sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA== + dependencies: + "@types/unist" "^2.0.3" + comma-separated-tokens "^1.0.0" + property-information "^5.3.0" + space-separated-tokens "^1.0.0" + style-to-object "^0.3.0" + unist-util-is "^4.0.0" + web-namespaces "^1.0.0" + +hast-util-from-parse5@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz#554e34abdeea25ac76f5bd950a1f0180e0b3bc2a" + integrity sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA== + dependencies: + "@types/parse5" "^5.0.0" + hastscript "^6.0.0" + property-information "^5.0.0" + vfile "^4.0.0" + vfile-location "^3.2.0" + web-namespaces "^1.0.0" + +hast-util-is-element@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz#3b3ed5159a2707c6137b48637fbfe068e175a425" + integrity sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ== + +hast-util-parse-selector@^2.0.0: + version "2.2.5" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a" + integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== + +hast-util-raw@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-6.1.0.tgz#e16a3c2642f65cc7c480c165400a40d604ab75d0" + integrity sha512-5FoZLDHBpka20OlZZ4I/+RBw5piVQ8iI1doEvffQhx5CbCyTtP8UCq8Tw6NmTAMtXgsQxmhW7Ly8OdFre5/YMQ== + dependencies: + "@types/hast" "^2.0.0" + hast-util-from-parse5 "^6.0.0" + hast-util-to-parse5 "^6.0.0" + html-void-elements "^1.0.0" + parse5 "^6.0.0" + unist-util-position "^3.0.0" + unist-util-visit "^2.0.0" + vfile "^4.0.0" + web-namespaces "^1.0.0" + xtend "^4.0.0" + zwitch "^1.0.0" + +hast-util-to-html@^7.1.1: + version "7.1.3" + resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-7.1.3.tgz#9f339ca9bea71246e565fc79ff7dbfe98bb50f5e" + integrity sha512-yk2+1p3EJTEE9ZEUkgHsUSVhIpCsL/bvT8E5GzmWc+N1Po5gBw+0F8bo7dpxXR0nu0bQVxVZGX2lBGF21CmeDw== + dependencies: + ccount "^1.0.0" + comma-separated-tokens "^1.0.0" + hast-util-is-element "^1.0.0" + hast-util-whitespace "^1.0.0" + html-void-elements "^1.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + stringify-entities "^3.0.1" + unist-util-is "^4.0.0" + xtend "^4.0.0" + +hast-util-to-parse5@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479" + integrity sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ== + dependencies: + hast-to-hyperscript "^9.0.0" + property-information "^5.0.0" + web-namespaces "^1.0.0" + xtend "^4.0.0" + zwitch "^1.0.0" + +hast-util-whitespace@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz#e4fe77c4a9ae1cb2e6c25e02df0043d0164f6e41" + integrity sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A== + +hastscript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" + integrity sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w== + dependencies: + "@types/hast" "^2.0.0" + comma-separated-tokens "^1.0.0" + hast-util-parse-selector "^2.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +headers-polyfill@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-3.0.4.tgz#cd70c815a441dd882372fcd6eda212ce997c9b18" + integrity sha512-I1DOM1EdWYntdrnCvqQtcKwSSuiTzoqOExy4v1mdcFixFZABlWP4IPHdmoLtPda0abMHqDOY4H9svhQ10DFR4w== + +history@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b" + integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ== + dependencies: + "@babel/runtime" "^7.7.6" + +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +hoopy@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" + integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== + +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + +html-entities@^2.1.0, html-entities@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" + integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +html-minifier-terser@^6.0.2: + version "6.1.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" + integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== + dependencies: + camel-case "^4.1.2" + clean-css "^5.2.2" + commander "^8.3.0" + he "^1.2.0" + param-case "^3.0.4" + relateurl "^0.2.7" + terser "^5.10.0" + +html-void-elements@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" + integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== + +html-webpack-plugin@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" + integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== + dependencies: + "@types/html-minifier-terser" "^6.0.0" + html-minifier-terser "^6.0.2" + lodash "^4.17.21" + pretty-error "^4.0.0" + tapable "^2.0.0" + +htmlparser2@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" + integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + domutils "^2.5.2" + entities "^2.0.0" + +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= + +http-errors@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" + integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.1" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.5.tgz#d7c30d5d3c90d865b4a2e870181f9d6f22ac7ac5" + integrity sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA== + +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + +http-proxy-middleware@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz#5df04f69a89f530c2284cd71eeaa51ba52243289" + integrity sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA== + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" + +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +iconv-lite@0.4.24, iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@0.6, iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + +idb@^6.1.4: + version "6.1.5" + resolved "https://registry.yarnpkg.com/idb/-/idb-6.1.5.tgz#dbc53e7adf1ac7c59f9b2bf56e00b4ea4fce8c7b" + integrity sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw== + +identity-obj-proxy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" + integrity sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ= + dependencies: + harmony-reflect "^1.4.6" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.8, ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + +immer@^9.0.7: + version "9.0.12" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" + integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== + +import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@^1.3.5: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +inline-style-parser@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" + integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== + +inquirer@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.0.tgz#f44f008dd344bbfc4b30031f45d984e034a3ac3a" + integrity sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.1" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.21" + mute-stream "0.0.8" + ora "^5.4.1" + run-async "^2.4.0" + rxjs "^7.2.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + +inter-ui@^3.19.3: + version "3.19.3" + resolved "https://registry.yarnpkg.com/inter-ui/-/inter-ui-3.19.3.tgz#cf4b4b6d30de8d5463e2462588654b325206488c" + integrity sha512-5FG9fjuYOXocIfjzcCBhICL5cpvwEetseL3FU6tP3d6Bn7g8wODhB+I9RNGRTizCT7CUG4GOK54OPxqq3msQgg== + +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +ip@^1.1.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" + integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-buffer@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-callable@^1.1.4, is-callable@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== + +is-core-module@^2.2.0, is-core-module@^2.8.0, is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== + dependencies: + has "^1.0.3" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= + +is-negative-zero@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-node-process@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.0.1.tgz#4fc7ac3a91e8aac58175fe0578abbc56f2831b23" + integrity sha512-5IcdXuf++TTNt3oGl9EBdkvndXA8gmc4bz/Y+mdEpWh3Mcn/+kOw6hI7LD5CocqJWMzeb0I0ClndRVNdEPuJXQ== + +is-number-object@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" + integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +is-path-cwd@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-obj@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + +is-plain-object@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + +is-regex@^1.0.4, is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= + +is-root@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" + integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== + +is-shared-array-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" + integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-weakref@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-whitespace-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" + integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== + +is-word-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" + integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" + integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.4" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" + integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jake@^10.6.1: + version "10.8.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b" + integrity sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A== + dependencies: + async "0.9.x" + chalk "^2.4.2" + filelist "^1.0.1" + minimatch "^3.0.4" + +jest-changed-files@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" + integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw== + dependencies: + "@jest/types" "^27.5.1" + execa "^5.0.0" + throat "^6.0.1" + +jest-circus@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc" + integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^0.7.0" + expect "^27.5.1" + is-generator-fn "^2.0.0" + jest-each "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + slash "^3.0.0" + stack-utils "^2.0.3" + throat "^6.0.1" + +jest-cli@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145" + integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw== + dependencies: + "@jest/core" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + import-local "^3.0.2" + jest-config "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + prompts "^2.0.1" + yargs "^16.2.0" + +jest-config@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41" + integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA== + dependencies: + "@babel/core" "^7.8.0" + "@jest/test-sequencer" "^27.5.1" + "@jest/types" "^27.5.1" + babel-jest "^27.5.1" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.1" + graceful-fs "^4.2.9" + jest-circus "^27.5.1" + jest-environment-jsdom "^27.5.1" + jest-environment-node "^27.5.1" + jest-get-type "^27.5.1" + jest-jasmine2 "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-runner "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^27.5.1" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" + integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-docblock@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0" + integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ== + dependencies: + detect-newline "^3.0.0" + +jest-each@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e" + integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ== + dependencies: + "@jest/types" "^27.5.1" + chalk "^4.0.0" + jest-get-type "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + +jest-environment-jsdom@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546" + integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + jest-util "^27.5.1" + jsdom "^16.6.0" + +jest-environment-node@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e" + integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + jest-util "^27.5.1" + +jest-get-type@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" + integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== + +jest-haste-map@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" + integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng== + dependencies: + "@jest/types" "^27.5.1" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^27.5.1" + jest-serializer "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + micromatch "^4.0.4" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + +jest-jasmine2@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" + integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/source-map" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + expect "^27.5.1" + is-generator-fn "^2.0.0" + jest-each "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + throat "^6.0.1" + +jest-leak-detector@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8" + integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ== + dependencies: + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" + integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== + dependencies: + chalk "^4.0.0" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-message-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" + integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^27.5.1" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^27.5.1" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6" + integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + +jest-pnp-resolver@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" + integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== + +jest-regex-util@^27.0.0, jest-regex-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" + integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== + +jest-resolve-dependencies@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" + integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg== + dependencies: + "@jest/types" "^27.5.1" + jest-regex-util "^27.5.1" + jest-snapshot "^27.5.1" + +jest-resolve@^27.4.2, jest-resolve@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384" + integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw== + dependencies: + "@jest/types" "^27.5.1" + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-pnp-resolver "^1.2.2" + jest-util "^27.5.1" + jest-validate "^27.5.1" + resolve "^1.20.0" + resolve.exports "^1.1.0" + slash "^3.0.0" + +jest-runner@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5" + integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ== + dependencies: + "@jest/console" "^27.5.1" + "@jest/environment" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.8.1" + graceful-fs "^4.2.9" + jest-docblock "^27.5.1" + jest-environment-jsdom "^27.5.1" + jest-environment-node "^27.5.1" + jest-haste-map "^27.5.1" + jest-leak-detector "^27.5.1" + jest-message-util "^27.5.1" + jest-resolve "^27.5.1" + jest-runtime "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + source-map-support "^0.5.6" + throat "^6.0.1" + +jest-runtime@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af" + integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/globals" "^27.5.1" + "@jest/source-map" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + execa "^5.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-message-util "^27.5.1" + jest-mock "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-serializer@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64" + integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.9" + +jest-snapshot@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1" + integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA== + dependencies: + "@babel/core" "^7.7.2" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.0.0" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/babel__traverse" "^7.0.4" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^27.5.1" + graceful-fs "^4.2.9" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + jest-haste-map "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-util "^27.5.1" + natural-compare "^1.4.0" + pretty-format "^27.5.1" + semver "^7.3.2" + +jest-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" + integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" + integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ== + dependencies: + "@jest/types" "^27.5.1" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^27.5.1" + leven "^3.1.0" + pretty-format "^27.5.1" + +jest-watch-typeahead@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/jest-watch-typeahead/-/jest-watch-typeahead-1.0.0.tgz#4de2ca1eb596acb1889752afbab84b74fcd99173" + integrity sha512-jxoszalAb394WElmiJTFBMzie/RDCF+W7Q29n5LzOPtcoQoHWfdUtHFkbhgf5NwWe8uMOxvKb/g7ea7CshfkTw== + dependencies: + ansi-escapes "^4.3.1" + chalk "^4.0.0" + jest-regex-util "^27.0.0" + jest-watcher "^27.0.0" + slash "^4.0.0" + string-length "^5.0.1" + strip-ansi "^7.0.1" + +jest-watcher@^27.0.0, jest-watcher@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2" + integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw== + dependencies: + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + jest-util "^27.5.1" + string-length "^4.0.1" + +jest-worker@^26.2.1: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest-worker@^27.0.2, jest-worker@^27.3.1, jest-worker@^27.4.5, jest-worker@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^27.4.3: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc" + integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ== + dependencies: + "@jest/core" "^27.5.1" + import-local "^3.0.2" + jest-cli "^27.5.1" + +js-levenshtein@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" + integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== + +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsdom@^16.6.0: + version "16.7.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" + integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== + dependencies: + abab "^2.0.5" + acorn "^8.2.4" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.3.0" + data-urls "^2.0.0" + decimal.js "^10.2.1" + domexception "^2.0.1" + escodegen "^2.0.0" + form-data "^3.0.0" + html-encoding-sniffer "^2.0.1" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.0" + parse5 "6.0.1" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.5.0" + ws "^7.4.6" + xml-name-validator "^3.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-schema@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.2, json5@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== + dependencies: + minimist "^1.2.5" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonpointer@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.0.tgz#f802669a524ec4805fa7389eadbc9921d5dc8072" + integrity sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg== + +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b" + integrity sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA== + dependencies: + array-includes "^3.1.3" + object.assign "^4.1.2" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +klona@^2.0.4, klona@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" + integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== + +language-subtag-registry@~0.3.2: + version "0.3.21" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" + integrity sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg== + +language-tags@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" + integrity sha1-0yHbxNowuovzAk4ED6XBRmH5GTo= + dependencies: + language-subtag-registry "~0.3.2" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lilconfig@^2.0.3, lilconfig@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" + integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +loader-runner@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" + integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== + +loader-utils@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + +loader-utils@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" + integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + +loader-utils@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.0.tgz#bcecc51a7898bee7473d4bc6b845b23af8304d4f" + integrity sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ== + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + +lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lz-string@^1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" + integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY= + +magic-string@^0.25.0, magic-string@^0.25.7: + version "0.25.9" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" + integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== + dependencies: + sourcemap-codec "^1.4.8" + +make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +markdown-escapes@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" + integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== + +match-sorter@^6.0.2: + version "6.3.1" + resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.1.tgz#98cc37fda756093424ddf3cbc62bfe9c75b92bda" + integrity sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw== + dependencies: + "@babel/runtime" "^7.12.5" + remove-accents "0.4.2" + +mdast-util-definitions@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz#c5c1a84db799173b4dcf7643cda999e440c24db2" + integrity sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ== + dependencies: + unist-util-visit "^2.0.0" + +mdast-util-to-hast@^10.0.0, mdast-util-to-hast@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.2.0.tgz#61875526a017d8857b71abc9333942700b2d3604" + integrity sha512-JoPBfJ3gBnHZ18icCwHR50orC9kNH81tiR1gs01D8Q5YpV6adHNO9nKNuFBCJQ941/32PT1a63UF/DitmS3amQ== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + mdast-util-definitions "^4.0.0" + mdurl "^1.0.0" + unist-builder "^2.0.0" + unist-util-generated "^1.0.0" + unist-util-position "^3.0.0" + unist-util-visit "^2.0.0" + +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== + +mdurl@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +memfs@^3.1.2, memfs@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" + integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== + dependencies: + fs-monkey "1.0.3" + +"memoize-one@>=3.1.1 <6", memoize-one@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" + integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +micromatch@^4.0.2, micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +microseconds@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39" + integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA== + +mime-db@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== + +"mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== + dependencies: + mime-db "1.51.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + +mini-css-extract-plugin@^2.4.5: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz#578aebc7fc14d32c0ad304c2c34f08af44673f5e" + integrity sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w== + dependencies: + schema-utils "^4.0.0" + +minimalistic-assert@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimatch@3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^3.0.4, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +mkdirp@^0.5.5, mkdirp@~0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +moment@^2.29.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +msw@^0.38.2: + version "0.38.2" + resolved "https://registry.yarnpkg.com/msw/-/msw-0.38.2.tgz#0c3637b392b65d5cc781468036c4be5965382c58" + integrity sha512-gD2vkV/ol3+zaC6AHKlPxB4zvl5mTV1uzhcv+0H6kwlbaiTZe/vVwiEGPeE9mQroAFvh0c8uJmltDebEys28qA== + dependencies: + "@mswjs/cookies" "^0.1.7" + "@mswjs/interceptors" "^0.13.5" + "@open-draft/until" "^1.0.3" + "@types/cookie" "^0.4.1" + "@types/js-levenshtein" "^1.1.1" + chalk "4.1.1" + chokidar "^3.4.2" + cookie "^0.4.2" + graphql "^16.3.0" + headers-polyfill "^3.0.4" + inquirer "^8.2.0" + is-node-process "^1.0.1" + js-levenshtein "^1.1.6" + node-fetch "^2.6.7" + path-to-regexp "^6.2.0" + statuses "^2.0.0" + strict-event-emitter "^0.2.0" + type-fest "^1.2.2" + yargs "^17.3.1" + +multicast-dns-service-types@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" + integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= + +multicast-dns@^6.0.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" + integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== + dependencies: + dns-packet "^1.3.1" + thunky "^1.0.2" + +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + +nano-time@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef" + integrity sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8= + dependencies: + big-integer "^1.6.16" + +nanoid@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" + integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + +node-emoji@^1.10.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" + integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== + dependencies: + lodash "^4.17.21" + +node-fetch@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-forge@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c" + integrity sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w== + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + +node-releases@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" + integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= + +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" + integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +nth-check@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + +nth-check@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" + integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== + dependencies: + boolbase "^1.0.0" + +numeral@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/numeral/-/numeral-2.0.6.tgz#4ad080936d443c2561aed9f2197efffe25f4e506" + integrity sha1-StCAk21EPCVhrtnyGX7//iX05QY= + +nwsapi@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-hash@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" + integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== + +object-inspect@^1.11.0, object-inspect@^1.9.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" + integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.0, object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.entries@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" + integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.fromentries@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251" + integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.getownpropertydescriptors@^2.1.0: + version "2.1.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz#b223cf38e17fefb97a63c10c91df72ccb386df9e" + integrity sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.hasown@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.0.tgz#7232ed266f34d197d15cac5880232f7a4790afe5" + integrity sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.values@^1.1.0, object.values@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" + integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +oblivious-set@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/oblivious-set/-/oblivious-set-1.0.0.tgz#c8316f2c2fb6ff7b11b6158db3234c49f733c566" + integrity sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw== + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^5.1.0, onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +open@^8.0.9, open@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" + integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +outvariant@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.2.1.tgz#e630f6cdc1dbf398ed857e36f219de4a005ccd35" + integrity sha512-bcILvFkvpMXh66+Ubax/inxbKRyWTUiiFIW2DWkiS79wakrLGn3Ydy+GvukadiyfZjaL6C7YhIem4EZSM282wA== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-retry@^4.5.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" + integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== + dependencies: + "@types/retry" "^0.12.0" + retry "^0.13.1" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + +parse-json@^5.0.0, parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse5@6.0.1, parse5@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6, path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + +path-to-regexp@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.0.tgz#f7b3803336104c346889adece614669230645f38" + integrity sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +picocolors@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" + integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pirates@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== + +pkg-dir@^4.1.0, pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-up@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" + integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== + dependencies: + find-up "^3.0.0" + +portfinder@^1.0.28: + version "1.0.28" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" + integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== + dependencies: + async "^2.6.2" + debug "^3.1.1" + mkdirp "^0.5.5" + +postcss-attribute-case-insensitive@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.0.tgz#39cbf6babf3ded1e4abf37d09d6eda21c644105c" + integrity sha512-b4g9eagFGq9T5SWX4+USfVyjIb3liPnjhHHRMP7FMB2kFVpYyfEscV0wP3eaXhKlcHKUut8lt5BGoeylWA/dBQ== + dependencies: + postcss-selector-parser "^6.0.2" + +postcss-browser-comments@^4: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz#bcfc86134df5807f5d3c0eefa191d42136b5e72a" + integrity sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg== + +postcss-calc@^8.2.3: + version "8.2.4" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" + integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== + dependencies: + postcss-selector-parser "^6.0.9" + postcss-value-parser "^4.2.0" + +postcss-color-functional-notation@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.2.tgz#f59ccaeb4ee78f1b32987d43df146109cc743073" + integrity sha512-DXVtwUhIk4f49KK5EGuEdgx4Gnyj6+t2jBSEmxvpIK9QI40tWrpS2Pua8Q7iIZWBrki2QOaeUdEaLPPa91K0RQ== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-color-hex-alpha@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.3.tgz#61a0fd151d28b128aa6a8a21a2dad24eebb34d52" + integrity sha512-fESawWJCrBV035DcbKRPAVmy21LpoyiXdPTuHUfWJ14ZRjY7Y7PA6P4g8z6LQGYhU1WAxkTxjIjurXzoe68Glw== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-color-rebeccapurple@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.0.2.tgz#5d397039424a58a9ca628762eb0b88a61a66e079" + integrity sha512-SFc3MaocHaQ6k3oZaFwH8io6MdypkUtEy/eXzXEB1vEQlO3S3oDc/FSZA8AsS04Z25RirQhlDlHLh3dn7XewWw== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-colormin@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz#3cee9e5ca62b2c27e84fce63affc0cfb5901956a" + integrity sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg== + dependencies: + browserslist "^4.16.6" + caniuse-api "^3.0.0" + colord "^2.9.1" + postcss-value-parser "^4.2.0" + +postcss-convert-values@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.0.tgz#f8d3abe40b4ce4b1470702a0706343eac17e7c10" + integrity sha512-GkyPbZEYJiWtQB0KZ0X6qusqFHUepguBCNFi9t5JJc7I2OTXG7C0twbTLvCfaKOLl3rSXmpAwV7W5txd91V84g== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-custom-media@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz#1be6aff8be7dc9bf1fe014bde3b71b92bb4552f1" + integrity sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g== + +postcss-custom-properties@^12.1.4: + version "12.1.4" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-12.1.4.tgz#e3d8a8000f28094453b836dff5132385f2862285" + integrity sha512-i6AytuTCoDLJkWN/MtAIGriJz3j7UX6bV7Z5t+KgFz+dwZS15/mlTJY1S0kRizlk6ba0V8u8hN50Fz5Nm7tdZw== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-custom-selectors@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-6.0.0.tgz#022839e41fbf71c47ae6e316cb0e6213012df5ef" + integrity sha512-/1iyBhz/W8jUepjGyu7V1OPcGbc636snN1yXEQCinb6Bwt7KxsiU7/bLQlp8GwAXzCh7cobBU5odNn/2zQWR8Q== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-dir-pseudo-class@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.4.tgz#9afe49ea631f0cb36fa0076e7c2feb4e7e3f049c" + integrity sha512-I8epwGy5ftdzNWEYok9VjW9whC4xnelAtbajGv4adql4FIF09rnrxnA9Y8xSHN47y7gqFIv10C5+ImsLeJpKBw== + dependencies: + postcss-selector-parser "^6.0.9" + +postcss-discard-comments@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.0.tgz#87be4e0953bf599935837b940c701f8d4eca7d0b" + integrity sha512-L0IKF4jAshRyn03SkEO6ar/Ipz2oLywVbg2THf2EqqdNkBwmVMxuTR/RoAltOw4piiaLt3gCAdrbAqmTBInmhg== + +postcss-discard-duplicates@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" + integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== + +postcss-discard-empty@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.0.tgz#7f51b16cd1b89f8180bbc7cee34d6cbabf2ef810" + integrity sha512-782T/buGgb3HOuHOJAHpdyKzAAKsv/BxWqsutnZ+QsiHEcDkY7v+6WWdturuBiSal6XMOO1p1aJvwXdqLD5vhA== + +postcss-discard-overridden@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" + integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== + +postcss-double-position-gradients@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.0.tgz#a8614fb3a2a4b8877bffb8961b770e00322bbad1" + integrity sha512-oz73I08yMN3oxjj0s8mED1rG+uOYoK3H8N9RjQofyg52KBRNmePJKg3fVwTpL2U5ZFbCzXoZBsUD/CvZdlqE4Q== + dependencies: + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" + +postcss-env-function@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-4.0.5.tgz#b9614d50abd91e4c88a114644a9766880dabe393" + integrity sha512-gPUJc71ji9XKyl0WSzAalBeEA/89kU+XpffpPxSaaaZ1c48OL36r1Ep5R6+9XAPkIiDlSvVAwP4io12q/vTcvA== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-flexbugs-fixes@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz#2028e145313074fc9abe276cb7ca14e5401eb49d" + integrity sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ== + +postcss-focus-visible@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz#50c9ea9afa0ee657fb75635fabad25e18d76bf9e" + integrity sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw== + dependencies: + postcss-selector-parser "^6.0.9" + +postcss-focus-within@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz#5b1d2ec603195f3344b716c0b75f61e44e8d2e20" + integrity sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ== + dependencies: + postcss-selector-parser "^6.0.9" + +postcss-font-variant@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz#efd59b4b7ea8bb06127f2d031bfbb7f24d32fa66" + integrity sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA== + +postcss-gap-properties@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-3.0.3.tgz#6401bb2f67d9cf255d677042928a70a915e6ba60" + integrity sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ== + +postcss-image-set-function@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-4.0.6.tgz#bcff2794efae778c09441498f40e0c77374870a9" + integrity sha512-KfdC6vg53GC+vPd2+HYzsZ6obmPqOk6HY09kttU19+Gj1nC3S3XBVEXDHxkhxTohgZqzbUb94bKXvKDnYWBm/A== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-initial@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-4.0.1.tgz#529f735f72c5724a0fb30527df6fb7ac54d7de42" + integrity sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ== + +postcss-js@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.0.tgz#31db79889531b80dc7bc9b0ad283e418dce0ac00" + integrity sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ== + dependencies: + camelcase-css "^2.0.1" + +postcss-lab-function@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-4.1.1.tgz#8b37dfcb9ca4ff82bbe7192c7ba3cc2bccbc0ef1" + integrity sha512-j3Z0WQCimY2tMle++YcmygnnVbt6XdnrCV1FO2IpzaCSmtTF2oO8h4ZYUA1Q+QHYroIiaWPvNHt9uBR4riCksQ== + dependencies: + "@csstools/postcss-progressive-custom-properties" "^1.1.0" + postcss-value-parser "^4.2.0" + +postcss-load-config@^3.1.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.3.tgz#21935b2c43b9a86e6581a576ca7ee1bde2bd1d23" + integrity sha512-5EYgaM9auHGtO//ljHH+v/aC/TQ5LHXtL7bQajNAUBKUVKiYE8rYpFms7+V26D9FncaGe2zwCoPQsFKb5zF/Hw== + dependencies: + lilconfig "^2.0.4" + yaml "^1.10.2" + +postcss-loader@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef" + integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q== + dependencies: + cosmiconfig "^7.0.0" + klona "^2.0.5" + semver "^7.3.5" + +postcss-logical@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-5.0.4.tgz#ec75b1ee54421acc04d5921576b7d8db6b0e6f73" + integrity sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g== + +postcss-media-minmax@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz#7140bddec173e2d6d657edbd8554a55794e2a5b5" + integrity sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ== + +postcss-merge-longhand@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.0.tgz#f716bffbf0bdfbde6ea78c36088e21559f8a0a95" + integrity sha512-Gr46srN2tsLD8fudKYoHO56RG0BLQ2nsBRnSZGY04eNBPwTeWa9KeHrbL3tOLAHyB2aliikycPH2TMJG1U+W6g== + dependencies: + postcss-value-parser "^4.2.0" + stylehacks "^5.1.0" + +postcss-merge-rules@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.0.tgz#a2d5117eba09c8686a5471d97bd9afcf30d1b41f" + integrity sha512-NecukEJovQ0mG7h7xV8wbYAkXGTO3MPKnXvuiXzOKcxoOodfTTKYjeo8TMhAswlSkjcPIBlnKbSFcTuVSDaPyQ== + dependencies: + browserslist "^4.16.6" + caniuse-api "^3.0.0" + cssnano-utils "^3.1.0" + postcss-selector-parser "^6.0.5" + +postcss-minify-font-values@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" + integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-minify-gradients@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.0.tgz#de0260a67a13b7b321a8adc3150725f2c6612377" + integrity sha512-J/TMLklkONn3LuL8wCwfwU8zKC1hpS6VcxFkNUNjmVt53uKqrrykR3ov11mdUYyqVMEx67slMce0tE14cE4DTg== + dependencies: + colord "^2.9.1" + cssnano-utils "^3.1.0" + postcss-value-parser "^4.2.0" + +postcss-minify-params@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.0.tgz#e0b1f4e05cfd396682f612856485907e4064f25e" + integrity sha512-q67dcts4Hct6x8+JmhBgctHkbvUsqGIg2IItenjE63iZXMbhjr7AlVZkNnKtIGt/1Wsv7p/7YzeSII6Q+KPXRg== + dependencies: + browserslist "^4.16.6" + cssnano-utils "^3.1.0" + postcss-value-parser "^4.2.0" + +postcss-minify-selectors@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.0.tgz#17c2be233e12b28ffa8a421a02fc8b839825536c" + integrity sha512-vYxvHkW+iULstA+ctVNx0VoRAR4THQQRkG77o0oa4/mBS0OzGvvzLIvHDv/nNEM0crzN2WIyFU5X7wZhaUK3RA== + dependencies: + postcss-selector-parser "^6.0.5" + +postcss-modules-extract-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" + integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== + +postcss-modules-local-by-default@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" + integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" + integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-nested@5.0.6: + version "5.0.6" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.6.tgz#466343f7fc8d3d46af3e7dba3fcd47d052a945bc" + integrity sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA== + dependencies: + postcss-selector-parser "^6.0.6" + +postcss-nesting@^10.1.2: + version "10.1.2" + resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-10.1.2.tgz#2e5f811b3d75602ea18a95dd445bde5297145141" + integrity sha512-dJGmgmsvpzKoVMtDMQQG/T6FSqs6kDtUDirIfl4KnjMCiY9/ETX8jdKyCd20swSRAbUYkaBKV20pxkzxoOXLqQ== + dependencies: + postcss-selector-parser "^6.0.8" + +postcss-normalize-charset@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" + integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== + +postcss-normalize-display-values@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" + integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-positions@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.0.tgz#902a7cb97cf0b9e8b1b654d4a43d451e48966458" + integrity sha512-8gmItgA4H5xiUxgN/3TVvXRoJxkAWLW6f/KKhdsH03atg0cB8ilXnrB5PpSshwVu/dD2ZsRFQcR1OEmSBDAgcQ== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-repeat-style@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.0.tgz#f6d6fd5a54f51a741cc84a37f7459e60ef7a6398" + integrity sha512-IR3uBjc+7mcWGL6CtniKNQ4Rr5fTxwkaDHwMBDGGs1x9IVRkYIT/M4NelZWkAOBdV6v3Z9S46zqaKGlyzHSchw== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-string@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" + integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-timing-functions@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" + integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-unicode@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.0.tgz#3d23aede35e160089a285e27bf715de11dc9db75" + integrity sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ== + dependencies: + browserslist "^4.16.6" + postcss-value-parser "^4.2.0" + +postcss-normalize-url@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" + integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew== + dependencies: + normalize-url "^6.0.1" + postcss-value-parser "^4.2.0" + +postcss-normalize-whitespace@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.0.tgz#aed8b4580c9ad6e8eac034177291187ea16a059c" + integrity sha512-7O1FanKaJkpWFyCghFzIkLhehujV/frGkdofGLwhg5upbLyGsSfiTcZAdSzoPsSUgyPCkBkNMeWR8yVgPdQybg== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize/-/postcss-normalize-10.0.1.tgz#464692676b52792a06b06880a176279216540dd7" + integrity sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA== + dependencies: + "@csstools/normalize.css" "*" + postcss-browser-comments "^4" + sanitize.css "*" + +postcss-opacity-percentage@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.2.tgz#bd698bb3670a0a27f6d657cc16744b3ebf3b1145" + integrity sha512-lyUfF7miG+yewZ8EAk9XUBIlrHyUE6fijnesuz+Mj5zrIHIEw6KcIZSOk/elVMqzLvREmXB83Zi/5QpNRYd47w== + +postcss-ordered-values@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.0.tgz#04ef429e0991b0292bc918b135cd4c038f7b889f" + integrity sha512-wU4Z4D4uOIH+BUKkYid36gGDJNQtkVJT7Twv8qH6UyfttbbJWyw4/xIPuVEkkCtQLAJ0EdsNSh8dlvqkXb49TA== + dependencies: + cssnano-utils "^3.1.0" + postcss-value-parser "^4.2.0" + +postcss-overflow-shorthand@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.3.tgz#ebcfc0483a15bbf1b27fdd9b3c10125372f4cbc2" + integrity sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg== + +postcss-page-break@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-3.0.4.tgz#7fbf741c233621622b68d435babfb70dd8c1ee5f" + integrity sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ== + +postcss-place@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-7.0.4.tgz#eb026650b7f769ae57ca4f938c1addd6be2f62c9" + integrity sha512-MrgKeiiu5OC/TETQO45kV3npRjOFxEHthsqGtkh3I1rPbZSbXGD/lZVi9j13cYh+NA8PIAPyk6sGjT9QbRyvSg== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-preset-env@^7.0.1: + version "7.4.2" + resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-7.4.2.tgz#2ff3e4787bd9d89710659535855d6ce85ce6110b" + integrity sha512-AmOkb8AeNNQwE/z2fHl1iwOIt8J50V8WR0rmLagcgIDoqlJZWjV3NdtOPnLGco1oN8DZe+Ss5B9ULbBeS6HfeA== + dependencies: + "@csstools/postcss-color-function" "^1.0.2" + "@csstools/postcss-font-format-keywords" "^1.0.0" + "@csstools/postcss-hwb-function" "^1.0.0" + "@csstools/postcss-ic-unit" "^1.0.0" + "@csstools/postcss-is-pseudo-class" "^2.0.0" + "@csstools/postcss-normalize-display-values" "^1.0.0" + "@csstools/postcss-oklab-function" "^1.0.1" + "@csstools/postcss-progressive-custom-properties" "^1.2.0" + autoprefixer "^10.4.2" + browserslist "^4.19.3" + css-blank-pseudo "^3.0.3" + css-has-pseudo "^3.0.4" + css-prefers-color-scheme "^6.0.3" + cssdb "^6.4.0" + postcss-attribute-case-insensitive "^5.0.0" + postcss-color-functional-notation "^4.2.2" + postcss-color-hex-alpha "^8.0.3" + postcss-color-rebeccapurple "^7.0.2" + postcss-custom-media "^8.0.0" + postcss-custom-properties "^12.1.4" + postcss-custom-selectors "^6.0.0" + postcss-dir-pseudo-class "^6.0.4" + postcss-double-position-gradients "^3.1.0" + postcss-env-function "^4.0.5" + postcss-focus-visible "^6.0.4" + postcss-focus-within "^5.0.4" + postcss-font-variant "^5.0.0" + postcss-gap-properties "^3.0.3" + postcss-image-set-function "^4.0.6" + postcss-initial "^4.0.1" + postcss-lab-function "^4.1.1" + postcss-logical "^5.0.4" + postcss-media-minmax "^5.0.0" + postcss-nesting "^10.1.2" + postcss-opacity-percentage "^1.1.2" + postcss-overflow-shorthand "^3.0.3" + postcss-page-break "^3.0.4" + postcss-place "^7.0.4" + postcss-pseudo-class-any-link "^7.1.1" + postcss-replace-overflow-wrap "^4.0.0" + postcss-selector-not "^5.0.0" + postcss-value-parser "^4.2.0" + +postcss-pseudo-class-any-link@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.1.tgz#534eb1dadd9945eb07830dbcc06fb4d5d865b8e0" + integrity sha512-JRoLFvPEX/1YTPxRxp1JO4WxBVXJYrSY7NHeak5LImwJ+VobFMwYDQHvfTXEpcn+7fYIeGkC29zYFhFWIZD8fg== + dependencies: + postcss-selector-parser "^6.0.9" + +postcss-reduce-initial@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.0.tgz#fc31659ea6e85c492fb2a7b545370c215822c5d6" + integrity sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw== + dependencies: + browserslist "^4.16.6" + caniuse-api "^3.0.0" + +postcss-reduce-transforms@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" + integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-replace-overflow-wrap@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz#d2df6bed10b477bf9c52fab28c568b4b29ca4319" + integrity sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw== + +postcss-selector-not@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-5.0.0.tgz#ac5fc506f7565dd872f82f5314c0f81a05630dc7" + integrity sha512-/2K3A4TCP9orP4TNS7u3tGdRFVKqz/E6pX3aGnriPG0jU78of8wsUcqE4QAhWEU0d+WnMSF93Ah3F//vUtK+iQ== + dependencies: + balanced-match "^1.0.0" + +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.8, postcss-selector-parser@^6.0.9: + version "6.0.9" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" + integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-svgo@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d" + integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA== + dependencies: + postcss-value-parser "^4.2.0" + svgo "^2.7.0" + +postcss-unique-selectors@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.0.tgz#70a945da1b0599d00f617222a44ba1d82a676694" + integrity sha512-LmUhgGobtpeVJJHuogzjLRwJlN7VH+BL5c9GKMVJSS/ejoyePZkXvNsYUtk//F6vKOGK86gfRS0xH7fXQSDtvA== + dependencies: + postcss-selector-parser "^6.0.5" + +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^7.0.35: + version "7.0.39" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" + integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== + dependencies: + picocolors "^0.2.1" + source-map "^0.6.1" + +postcss@^8.3.5, postcss@^8.4.4, postcss@^8.4.5, postcss@^8.4.6: + version "8.4.7" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.7.tgz#f99862069ec4541de386bf57f5660a6c7a0875a8" + integrity sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A== + dependencies: + nanoid "^3.3.1" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +pretty-bytes@^5.3.0, pretty-bytes@^5.4.1: + version "5.6.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" + integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== + +pretty-error@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" + integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== + dependencies: + lodash "^4.17.20" + renderkid "^3.0.0" + +pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + +prismjs@~1.27.0: + version "1.27.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" + integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +promise@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e" + integrity sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q== + dependencies: + asap "~2.0.6" + +prompts@^2.0.1, prompts@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +property-information@^5.0.0, property-information@^5.3.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" + integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== + dependencies: + xtend "^4.0.0" + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +psl@^1.1.33: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + +qs@6.9.7: + version "6.9.7" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" + integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== + +query-string@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.1.tgz#754620669db978625a90f635f12617c271a088e1" + integrity sha512-MplouLRDHBZSG9z7fpuAAcI7aAYjDLhtsiVZsevsfaHWDS2IDdORKbSd1kWUA+V4zyva/HZoSfpwnYMMQDhb0w== + dependencies: + decode-uri-component "^0.2.0" + filter-obj "^1.1.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +raf-schd@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a" + integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ== + +raf@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" + integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== + dependencies: + performance-now "^2.1.0" + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" + integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== + dependencies: + bytes "3.1.2" + http-errors "1.8.1" + iconv-lite "0.4.24" + unpipe "1.0.0" + +react-app-polyfill@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz#95221e0a9bd259e5ca6b177c7bb1cb6768f68fd7" + integrity sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w== + dependencies: + core-js "^3.19.2" + object-assign "^4.1.1" + promise "^8.1.0" + raf "^3.4.1" + regenerator-runtime "^0.13.9" + whatwg-fetch "^3.6.2" + +react-beautiful-dnd@^13.1.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz#ec97c81093593526454b0de69852ae433783844d" + integrity sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA== + dependencies: + "@babel/runtime" "^7.9.2" + css-box-model "^1.2.0" + memoize-one "^5.1.1" + raf-schd "^4.0.2" + react-redux "^7.2.0" + redux "^4.0.4" + use-memo-one "^1.1.1" + +react-clientside-effect@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.5.tgz#e2c4dc3c9ee109f642fac4f5b6e9bf5bcd2219a3" + integrity sha512-2bL8qFW1TGBHozGGbVeyvnggRpMjibeZM2536AKNENLECutp2yfs44IL8Hmpn8qjFQ2K7A9PnYf3vc7aQq/cPA== + dependencies: + "@babel/runtime" "^7.12.13" + +react-dev-utils@^12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.0.tgz#4eab12cdb95692a077616770b5988f0adf806526" + integrity sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ== + dependencies: + "@babel/code-frame" "^7.16.0" + address "^1.1.2" + browserslist "^4.18.1" + chalk "^4.1.2" + cross-spawn "^7.0.3" + detect-port-alt "^1.1.6" + escape-string-regexp "^4.0.0" + filesize "^8.0.6" + find-up "^5.0.0" + fork-ts-checker-webpack-plugin "^6.5.0" + global-modules "^2.0.0" + globby "^11.0.4" + gzip-size "^6.0.0" + immer "^9.0.7" + is-root "^2.1.0" + loader-utils "^3.2.0" + open "^8.4.0" + pkg-up "^3.1.0" + prompts "^2.4.2" + react-error-overlay "^6.0.10" + recursive-readdir "^2.2.2" + shell-quote "^1.7.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +react-dom@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" + integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + scheduler "^0.20.2" + +react-dropzone@^11.5.3: + version "11.7.1" + resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-11.7.1.tgz#3851bb75b26af0bf1b17ce1449fd980e643b9356" + integrity sha512-zxCMwhfPy1olUEbw3FLNPLhAm/HnaYH5aELIEglRbqabizKAdHs0h+WuyOpmA+v1JXn0++fpQDdNfUagWt5hJQ== + dependencies: + attr-accept "^2.2.2" + file-selector "^0.4.0" + prop-types "^15.8.1" + +react-element-to-jsx-string@^14.3.4: + version "14.3.4" + resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-14.3.4.tgz#709125bc72f06800b68f9f4db485f2c7d31218a8" + integrity sha512-t4ZwvV6vwNxzujDQ+37bspnLwA4JlgUPWhLjBJWsNIDceAf6ZKUTCjdm08cN6WeZ5pTMKiCJkmAYnpmR4Bm+dg== + dependencies: + "@base2/pretty-print-object" "1.0.1" + is-plain-object "5.0.0" + react-is "17.0.2" + +react-error-overlay@^6.0.10: + version "6.0.10" + resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.10.tgz#0fe26db4fa85d9dbb8624729580e90e7159a59a6" + integrity sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA== + +react-focus-lock@^2.6.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.8.1.tgz#a28f06a4ef5eab7d4ef0d859512772ec1331d529" + integrity sha512-4kb9I7JIiBm0EJ+CsIBQ+T1t5qtmwPRbFGYFQ0t2q2qIpbFbYTHDjnjJVFB7oMBtXityEOQehblJPjqSIf3Amg== + dependencies: + "@babel/runtime" "^7.0.0" + focus-lock "^0.10.2" + prop-types "^15.6.2" + react-clientside-effect "^1.2.5" + use-callback-ref "^1.2.5" + use-sidecar "^1.0.5" + +react-focus-on@^3.5.4: + version "3.5.4" + resolved "https://registry.yarnpkg.com/react-focus-on/-/react-focus-on-3.5.4.tgz#be45a9d0495f3bb6f5249704c85362df94980ecf" + integrity sha512-HnU0YGKhNSUsC4k6K8L+2wk8mC/qdg+CsS7A1bWLMgK7UuBphdECs2esnS6cLmBoVNjsFnCm/vMypeezKOdK3A== + dependencies: + aria-hidden "^1.1.3" + react-focus-lock "^2.6.0" + react-remove-scroll "^2.4.1" + react-style-singleton "^2.1.1" + tslib "^2.3.1" + use-callback-ref "^1.2.5" + use-sidecar "^1.0.5" + +react-input-autosize@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-3.0.0.tgz#6b5898c790d4478d69420b55441fcc31d5c50a85" + integrity sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg== + dependencies: + prop-types "^15.5.8" + +react-is@17.0.2, react-is@^17.0.1, react-is@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-is@^16.13.1, react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-query@^3.34.16: + version "3.34.16" + resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.34.16.tgz#279ea180bcaeaec49c7864b29d1711ee9f152594" + integrity sha512-7FvBvjgEM4YQ8nPfmAr+lJfbW95uyW/TVjFoi2GwCkF33/S8ajx45tuPHPFGWs4qYwPy1mzwxD4IQfpUDrefNQ== + dependencies: + "@babel/runtime" "^7.5.5" + broadcast-channel "^3.4.1" + match-sorter "^6.0.2" + +react-redux@^7.2.0: + version "7.2.6" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.6.tgz#49633a24fe552b5f9caf58feb8a138936ddfe9aa" + integrity sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ== + dependencies: + "@babel/runtime" "^7.15.4" + "@types/react-redux" "^7.1.20" + hoist-non-react-statics "^3.3.2" + loose-envify "^1.4.0" + prop-types "^15.7.2" + react-is "^17.0.2" + +react-refresh@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" + integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A== + +react-remove-scroll-bar@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.2.0.tgz#d4d545a7df024f75d67e151499a6ab5ac97c8cdd" + integrity sha512-UU9ZBP1wdMR8qoUs7owiVcpaPwsQxUDC2lypP6mmixaGlARZa7ZIBx1jcuObLdhMOvCsnZcvetOho0wzPa9PYg== + dependencies: + react-style-singleton "^2.1.0" + tslib "^1.0.0" + +react-remove-scroll@^2.4.1: + version "2.4.4" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.4.4.tgz#2dfff377cf17efc00de39dad51c143fc7a1b9e3e" + integrity sha512-EyC5ohYhaeKbThMSQxuN2i+QC5HqV3AJvNZKEdiATITexu0gHm00+5ko0ltNS1ajYJVeDgVG2baRSCei0AUWlQ== + dependencies: + react-remove-scroll-bar "^2.1.0" + react-style-singleton "^2.1.0" + tslib "^1.0.0" + use-callback-ref "^1.2.3" + use-sidecar "^1.0.1" + +react-router-dom@6: + version "6.2.2" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.2.2.tgz#f1a2c88365593c76b9612ae80154a13fcb72e442" + integrity sha512-AtYEsAST7bDD4dLSQHDnk/qxWLJdad5t1HFa1qJyUrCeGgEuCSw0VB/27ARbF9Fi/W5598ujvJOm3ujUCVzuYQ== + dependencies: + history "^5.2.0" + react-router "6.2.2" + +react-router@6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.2.2.tgz#495e683a0c04461eeb3d705fe445d6cf42f0c249" + integrity sha512-/MbxyLzd7Q7amp4gDOGaYvXwhEojkJD5BtExkuKmj39VEE0m3l/zipf6h2WIB2jyAO0lI6NGETh4RDcktRm4AQ== + dependencies: + history "^5.2.0" + +react-scripts@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-5.0.0.tgz#6547a6d7f8b64364ef95273767466cc577cb4b60" + integrity sha512-3i0L2CyIlROz7mxETEdfif6Sfhh9Lfpzi10CtcGs1emDQStmZfWjJbAIMtRD0opVUjQuFWqHZyRZ9PPzKCFxWg== + dependencies: + "@babel/core" "^7.16.0" + "@pmmmwh/react-refresh-webpack-plugin" "^0.5.3" + "@svgr/webpack" "^5.5.0" + babel-jest "^27.4.2" + babel-loader "^8.2.3" + babel-plugin-named-asset-import "^0.3.8" + babel-preset-react-app "^10.0.1" + bfj "^7.0.2" + browserslist "^4.18.1" + camelcase "^6.2.1" + case-sensitive-paths-webpack-plugin "^2.4.0" + css-loader "^6.5.1" + css-minimizer-webpack-plugin "^3.2.0" + dotenv "^10.0.0" + dotenv-expand "^5.1.0" + eslint "^8.3.0" + eslint-config-react-app "^7.0.0" + eslint-webpack-plugin "^3.1.1" + file-loader "^6.2.0" + fs-extra "^10.0.0" + html-webpack-plugin "^5.5.0" + identity-obj-proxy "^3.0.0" + jest "^27.4.3" + jest-resolve "^27.4.2" + jest-watch-typeahead "^1.0.0" + mini-css-extract-plugin "^2.4.5" + postcss "^8.4.4" + postcss-flexbugs-fixes "^5.0.2" + postcss-loader "^6.2.1" + postcss-normalize "^10.0.1" + postcss-preset-env "^7.0.1" + prompts "^2.4.2" + react-app-polyfill "^3.0.0" + react-dev-utils "^12.0.0" + react-refresh "^0.11.0" + resolve "^1.20.0" + resolve-url-loader "^4.0.0" + sass-loader "^12.3.0" + semver "^7.3.5" + source-map-loader "^3.0.0" + style-loader "^3.3.1" + tailwindcss "^3.0.2" + terser-webpack-plugin "^5.2.5" + webpack "^5.64.4" + webpack-dev-server "^4.6.0" + webpack-manifest-plugin "^4.0.2" + workbox-webpack-plugin "^6.4.1" + optionalDependencies: + fsevents "^2.3.2" + +react-style-singleton@^2.1.0, react-style-singleton@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.1.1.tgz#ce7f90b67618be2b6b94902a30aaea152ce52e66" + integrity sha512-jNRp07Jza6CBqdRKNgGhT3u9umWvils1xsuMOjZlghBDH2MU0PL2WZor4PGYjXpnRCa9DQSlHMs/xnABWOwYbA== + dependencies: + get-nonce "^1.0.0" + invariant "^2.2.4" + tslib "^1.0.0" + +react-virtualized-auto-sizer@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.6.tgz#66c5b1c9278064c5ef1699ed40a29c11518f97ca" + integrity sha512-7tQ0BmZqfVF6YYEWcIGuoR3OdYe8I/ZFbNclFlGOC3pMqunkYF/oL30NCjSGl9sMEb17AnzixDz98Kqc3N76HQ== + +react-window@^1.8.6: + version "1.8.6" + resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.6.tgz#d011950ac643a994118632665aad0c6382e2a112" + integrity sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg== + dependencies: + "@babel/runtime" "^7.0.0" + memoize-one ">=3.1.1 <6" + +react@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" + integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +readable-stream@^2.0.1: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6, readable-stream@^3.4.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +recursive-readdir@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" + integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== + dependencies: + minimatch "3.0.4" + +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + +redux@^4.0.0, redux@^4.0.4: + version "4.1.2" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104" + integrity sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw== + dependencies: + "@babel/runtime" "^7.9.2" + +refractor@^3.5.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a" + integrity sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA== + dependencies: + hastscript "^6.0.0" + parse-entities "^2.0.0" + prismjs "~1.27.0" + +regenerate-unicode-properties@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" + integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.9: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + +regenerator-transform@^0.14.2: + version "0.14.5" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== + dependencies: + "@babel/runtime" "^7.8.4" + +regex-parser@^2.2.11: + version "2.2.11" + resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58" + integrity sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q== + +regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307" + integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +regexpu-core@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.0.1.tgz#c531122a7840de743dcf9c83e923b5560323ced3" + integrity sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^10.0.1" + regjsgen "^0.6.0" + regjsparser "^0.8.2" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.0.0" + +regjsgen@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d" + integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA== + +regjsparser@^0.8.2: + version "0.8.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f" + integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA== + dependencies: + jsesc "~0.5.0" + +rehype-raw@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/rehype-raw/-/rehype-raw-5.1.0.tgz#66d5e8d7188ada2d31bc137bc19a1000cf2c6b7e" + integrity sha512-MDvHAb/5mUnif2R+0IPCYJU8WjHa9UzGtM/F4AVy5GixPlDZ1z3HacYy4xojDU+uBa+0X/3PIfyQI26/2ljJNA== + dependencies: + hast-util-raw "^6.1.0" + +rehype-react@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/rehype-react/-/rehype-react-6.2.1.tgz#9b9bf188451ad6f63796b784fe1f51165c67b73a" + integrity sha512-f9KIrjktvLvmbGc7si25HepocOg4z0MuNOtweigKzBcDjiGSTGhyz6VSgaV5K421Cq1O+z4/oxRJ5G9owo0KVg== + dependencies: + "@mapbox/hast-util-table-cell-style" "^0.2.0" + hast-to-hyperscript "^9.0.0" + +rehype-stringify@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/rehype-stringify/-/rehype-stringify-8.0.0.tgz#9b6afb599bcf3165f10f93fc8548f9a03d2ec2ba" + integrity sha512-VkIs18G0pj2xklyllrPSvdShAV36Ff3yE5PUO9u36f6+2qJFnn22Z5gKwBOwgXviux4UC7K+/j13AnZfPICi/g== + dependencies: + hast-util-to-html "^7.1.1" + +relateurl@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= + +remark-breaks@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/remark-breaks/-/remark-breaks-2.0.2.tgz#55fdec6c7da84f659aa7fdb1aa95b632870cee8d" + integrity sha512-LsQnPPQ7Fzp9RTjj4IwdEmjPOr9bxe9zYKWhs9ZQOg9hMg8rOfeeqQ410cvVdIK87Famqza1CKRxNkepp2EvUA== + dependencies: + unist-util-visit "^2.0.0" + +remark-emoji@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-2.2.0.tgz#1c702090a1525da5b80e15a8f963ef2c8236cac7" + integrity sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w== + dependencies: + emoticon "^3.2.0" + node-emoji "^1.10.0" + unist-util-visit "^2.0.3" + +remark-parse@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-8.0.3.tgz#9c62aa3b35b79a486454c690472906075f40c7e1" + integrity sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q== + dependencies: + ccount "^1.0.0" + collapse-white-space "^1.0.2" + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + is-word-character "^1.0.0" + markdown-escapes "^1.0.0" + parse-entities "^2.0.0" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + trim "0.0.1" + trim-trailing-lines "^1.0.0" + unherit "^1.0.4" + unist-util-remove-position "^2.0.0" + vfile-location "^3.0.0" + xtend "^4.0.1" + +remark-rehype@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-8.1.0.tgz#610509a043484c1e697437fa5eb3fd992617c945" + integrity sha512-EbCu9kHgAxKmW1yEYjx3QafMyGY3q8noUbNUI5xyKbaFP89wbhDrKxyIQNukNYthzjNHZu6J7hwFg7hRm1svYA== + dependencies: + mdast-util-to-hast "^10.2.0" + +remove-accents@0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5" + integrity sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U= + +renderkid@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" + integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== + dependencies: + css-select "^4.1.3" + dom-converter "^0.2.0" + htmlparser2 "^6.1.0" + lodash "^4.17.21" + strip-ansi "^6.0.1" + +repeat-string@^1.5.4: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-url-loader@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz#d50d4ddc746bb10468443167acf800dcd6c3ad57" + integrity sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA== + dependencies: + adjust-sourcemap-loader "^4.0.0" + convert-source-map "^1.7.0" + loader-utils "^2.0.0" + postcss "^7.0.35" + source-map "0.6.1" + +resolve.exports@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" + integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== + +resolve@^1.12.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^2.0.0-next.3: + version "2.0.0-next.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.3.tgz#d41016293d4a8586a39ca5d9b5f15cbea1f55e46" + integrity sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +robust-predicates@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.1.tgz#ecde075044f7f30118682bd9fb3f123109577f9a" + integrity sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g== + +rollup-plugin-terser@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" + integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ== + dependencies: + "@babel/code-frame" "^7.10.4" + jest-worker "^26.2.1" + serialize-javascript "^4.0.0" + terser "^5.0.0" + +rollup@^2.43.1: + version "2.69.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.69.0.tgz#82aa86682a45e9760146b736c1643bf435506156" + integrity sha512-kjER91tHyek8gAkuz7+558vSnTQ+pITEok1P0aNOS45ZXyngaqPsXJmSel4QPQnJo7EJMjXUU1/GErWkWiKORg== + optionalDependencies: + fsevents "~2.3.2" + +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +rw@1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q= + +rxjs@^7.2.0: + version "7.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.4.tgz#3d6bd407e6b7ce9a123e76b1e770dc5761aa368d" + integrity sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ== + dependencies: + tslib "^2.1.0" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sanitize.css@*: + version "13.0.0" + resolved "https://registry.yarnpkg.com/sanitize.css/-/sanitize.css-13.0.0.tgz#2675553974b27964c75562ade3bd85d79879f173" + integrity sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA== + +sass-loader@^12.3.0: + version "12.6.0" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.6.0.tgz#5148362c8e2cdd4b950f3c63ac5d16dbfed37bcb" + integrity sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA== + dependencies: + klona "^2.0.4" + neo-async "^2.6.2" + +sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +saxes@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + +scheduler@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" + integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +schema-utils@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" + integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== + dependencies: + "@types/json-schema" "^7.0.4" + ajv "^6.12.2" + ajv-keywords "^3.4.1" + +schema-utils@^2.6.5: + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== + dependencies: + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" + +schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= + +selfsigned@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.0.tgz#e927cd5377cbb0a1075302cff8df1042cc2bce5b" + integrity sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ== + dependencies: + node-forge "^1.2.0" + +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.2, semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + +send@0.17.2: + version "0.17.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" + integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "1.8.1" + mime "1.6.0" + ms "2.1.3" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" + +serialize-javascript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +serialize-query-params@^1.3.5: + version "1.3.6" + resolved "https://registry.yarnpkg.com/serialize-query-params/-/serialize-query-params-1.3.6.tgz#5dd5225db85ce747fe6fbc4897628504faafec6d" + integrity sha512-VlH7sfWNyPVZClPkRacopn6sn5uQMXBsjPVz1+pBHX895VpcYVznfJtZ49e6jymcrz+l/vowkepCZn/7xEAEdw== + +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.14.2: + version "1.14.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" + integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.2" + +set-cookie-parser@^2.4.6: + version "2.4.8" + resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz#d0da0ed388bc8f24e706a391f9c9e252a13c58b2" + integrity sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg== + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" + integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.2, signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + +sockjs@^0.3.21: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + +source-list-map@^2.0.0, source-list-map@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +source-map-js@^1.0.1, source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map-loader@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-3.0.1.tgz#9ae5edc7c2d42570934be4c95d1ccc6352eba52d" + integrity sha512-Vp1UsfyPvgujKQzi4pyDiTOnE3E4H+yHvkVRN3c/9PJmQS4CQJExvcDvaX/D+RV+xQben9HJ56jMJS3CgUeWyA== + dependencies: + abab "^2.0.5" + iconv-lite "^0.6.3" + source-map-js "^1.0.1" + +source-map-resolve@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2" + integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + +source-map-support@^0.5.6, source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.5.0, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.7.3, source-map@~0.7.2: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + +source-map@^0.8.0-beta.0: + version "0.8.0-beta.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11" + integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA== + dependencies: + whatwg-url "^7.0.0" + +sourcemap-codec@^1.4.8: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + +space-separated-tokens@^1.0.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" + integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +stack-utils@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" + integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== + dependencies: + escape-string-regexp "^2.0.0" + +stackframe@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.1.tgz#1033a3473ee67f08e2f2fc8eba6aef4f845124e1" + integrity sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg== + +state-toggle@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" + integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== + +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +statuses@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +strict-event-emitter@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.2.0.tgz#78e2f75dc6ea502e5d8a877661065a1e2deedecd" + integrity sha512-zv7K2egoKwkQkZGEaH8m+i2D0XiKzx5jNsiSul6ja2IYFvil10A59Z9Y7PPAAe5OW53dQUf9CfsHKzjZzKkm1w== + dependencies: + events "^3.3.0" + +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-length@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-5.0.1.tgz#3d647f497b6e8e8d41e422f7e0b23bc536c8381e" + integrity sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow== + dependencies: + char-regex "^2.0.0" + strip-ansi "^7.0.1" + +string-natural-compare@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" + integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.matchall@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa" + integrity sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + regexp.prototype.flags "^1.3.1" + side-channel "^1.0.4" + +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +stringify-entities@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-3.1.0.tgz#b8d3feac256d9ffcc9fa1fefdcf3ca70576ee903" + integrity sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg== + dependencies: + character-entities-html4 "^1.0.0" + character-entities-legacy "^1.0.0" + xtend "^4.0.0" + +stringify-object@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== + dependencies: + get-own-enumerable-property-symbols "^3.0.0" + is-obj "^1.0.1" + is-regexp "^1.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.0, strip-ansi@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" + integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== + dependencies: + ansi-regex "^6.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-comments@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-2.0.1.tgz#4ad11c3fbcac177a67a40ac224ca339ca1c1ba9b" + integrity sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +style-loader@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" + integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== + +style-to-object@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" + integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== + dependencies: + inline-style-parser "0.1.1" + +stylehacks@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.0.tgz#a40066490ca0caca04e96c6b02153ddc39913520" + integrity sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q== + dependencies: + browserslist "^4.16.6" + postcss-selector-parser "^6.0.4" + +stylis@4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91" + integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-hyperlinks@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" + integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +svg-parser@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" + integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== + +svgo@^1.2.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" + js-yaml "^3.13.1" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" + +svgo@^2.7.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" + integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== + dependencies: + "@trysound/sax" "0.2.0" + commander "^7.2.0" + css-select "^4.1.3" + css-tree "^1.1.3" + csso "^4.2.0" + picocolors "^1.0.0" + stable "^0.1.8" + +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +tabbable@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-3.1.2.tgz#f2d16cccd01f400e38635c7181adfe0ad965a4a2" + integrity sha512-wjB6puVXTYO0BSFtCmWQubA/KIn7Xvajw0x0l6eJUudMG/EAiJvIUnyNX6xO4NpGrJ16lbD0eUseB9WxW0vlpQ== + +tailwindcss@^3.0.2: + version "3.0.23" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.23.tgz#c620521d53a289650872a66adfcb4129d2200d10" + integrity sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA== + dependencies: + arg "^5.0.1" + chalk "^4.1.2" + chokidar "^3.5.3" + color-name "^1.1.4" + cosmiconfig "^7.0.1" + detective "^5.2.0" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.2.11" + glob-parent "^6.0.2" + is-glob "^4.0.3" + normalize-path "^3.0.0" + object-hash "^2.2.0" + postcss "^8.4.6" + postcss-js "^4.0.0" + postcss-load-config "^3.1.0" + postcss-nested "5.0.6" + postcss-selector-parser "^6.0.9" + postcss-value-parser "^4.2.0" + quick-lru "^5.1.1" + resolve "^1.22.0" + +tapable@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +temp-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" + integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== + +tempy@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.6.0.tgz#65e2c35abc06f1124a97f387b08303442bde59f3" + integrity sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw== + dependencies: + is-stream "^2.0.0" + temp-dir "^2.0.0" + type-fest "^0.16.0" + unique-string "^2.0.0" + +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + +terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.5: + version "5.3.1" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz#0320dcc270ad5372c1e8993fabbd927929773e54" + integrity sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g== + dependencies: + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.0" + source-map "^0.6.1" + terser "^5.7.2" + +terser@^5.0.0, terser@^5.10.0, terser@^5.7.2: + version "5.12.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.12.0.tgz#728c6bff05f7d1dcb687d8eace0644802a9dae8a" + integrity sha512-R3AUhNBGWiFc77HXag+1fXpAxTAFRQTJemlJKjAgD9r8xXTpjNKqIXwHM/o7Rh+O0kUJtS3WQVdBeMKFk5sw9A== + dependencies: + acorn "^8.5.0" + commander "^2.20.0" + source-map "~0.7.2" + source-map-support "~0.5.20" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-diff@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/text-diff/-/text-diff-1.0.1.tgz#6c105905435e337857375c9d2f6ca63e453ff565" + integrity sha1-bBBZBUNeM3hXN1ydL2ymPkU/9WU= + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +throat@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" + integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= + +tiny-invariant@^1.0.6: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9" + integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tough-cookie@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" + integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.1.2" + +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= + dependencies: + punycode "^2.1.0" + +tr46@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" + integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== + dependencies: + punycode "^2.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +trim-trailing-lines@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" + integrity sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ== + +trim@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= + +trough@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" + integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== + +tryer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" + integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== + +tsconfig-paths@^3.12.0: + version "3.13.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz#f3e9b8f6876698581d94470c03c95b3a48c0e3d7" + integrity sha512-nWuffZppoaYK0vQ1SQmkSsQzJoHA4s6uzdb2waRpD806x9yfq153AdVsWz4je2qZcW+pENrMQXbGQ3sMCkXuhw== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + +tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.16.0: + version "0.16.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860" + integrity sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^1.2.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" + integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typescript@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4" + integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg== + +unbox-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" + integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.1" + has-symbols "^1.0.2" + which-boxed-primitive "^1.0.2" + +unherit@^1.0.4: + version "1.1.3" + resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" + integrity sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ== + dependencies: + inherits "^2.0.0" + xtend "^4.0.0" + +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" + integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" + integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== + +unified@^9.2.0: + version "9.2.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" + integrity sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ== + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^2.0.0" + trough "^1.0.0" + vfile "^4.0.0" + +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + +unist-builder@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" + integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== + +unist-util-generated@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b" + integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== + +unist-util-is@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-3.0.0.tgz#d9e84381c2468e82629e4a5be9d7d05a2dd324cd" + integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== + +unist-util-is@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" + integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== + +unist-util-position@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47" + integrity sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA== + +unist-util-remove-position@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz#5d19ca79fdba712301999b2b73553ca8f3b352cc" + integrity sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA== + dependencies: + unist-util-visit "^2.0.0" + +unist-util-stringify-position@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" + integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== + dependencies: + "@types/unist" "^2.0.2" + +unist-util-stringify-position@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.2.tgz#5c6aa07c90b1deffd9153be170dce628a869a447" + integrity sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg== + dependencies: + "@types/unist" "^2.0.0" + +unist-util-visit-parents@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9" + integrity sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g== + dependencies: + unist-util-is "^3.0.0" + +unist-util-visit-parents@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" + integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + +unist-util-visit@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3" + integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw== + dependencies: + unist-util-visit-parents "^2.0.0" + +unist-util-visit@^2.0.0, unist-util-visit@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" + integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + unist-util-visit-parents "^3.0.0" + +universalify@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unload@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7" + integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA== + dependencies: + "@babel/runtime" "^7.6.2" + detect-node "^2.0.4" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= + +upath@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +url-parse@^1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +use-callback-ref@^1.2.3, use-callback-ref@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.2.5.tgz#6115ed242cfbaed5915499c0a9842ca2912f38a5" + integrity sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg== + +use-memo-one@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.2.tgz#0c8203a329f76e040047a35a1197defe342fab20" + integrity sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ== + +use-query-params@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/use-query-params/-/use-query-params-1.2.3.tgz#306c31a0cbc714e8a3b4bd7e91a6a9aaccaa5e22" + integrity sha512-cdG0tgbzK+FzsV6DAt2CN8Saa3WpRnze7uC4Rdh7l15epSFq7egmcB/zuREvPNwO5Yk80nUpDZpiyHsoq50d8w== + dependencies: + serialize-query-params "^1.3.5" + +use-sidecar@^1.0.1, use-sidecar@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.0.5.tgz#ffff2a17c1df42e348624b699ba6e5c220527f2b" + integrity sha512-k9jnrjYNwN6xYLj1iaGhonDghfvmeTmYjAiGvOr7clwKfPjMXJf4/HOr7oT5tJwYafgp2tG2l3eZEOfoELiMcA== + dependencies: + detect-node-es "^1.1.0" + tslib "^1.9.3" + +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util.promisify@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" + +utila@~0.4: + version "0.4.0" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" + integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@^8.3.0, uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +v8-to-istanbul@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" + integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +vfile-location@^3.0.0, vfile-location@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-3.2.0.tgz#d8e41fbcbd406063669ebf6c33d56ae8721d0f3c" + integrity sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA== + +vfile-message@*: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.2.tgz#a2908f64d9e557315ec9d7ea3a910f658ac05f7d" + integrity sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^3.0.0" + +vfile-message@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" + integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^2.0.0" + +vfile@^4.0.0, vfile@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" + integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + unist-util-stringify-position "^2.0.0" + vfile-message "^2.0.0" + +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + +walker@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +watchpack@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" + integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + +web-namespaces@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" + integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== + +web-vitals@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-2.1.4.tgz#76563175a475a5e835264d373704f9dde718290c" + integrity sha512-sVWcwhU5mX6crfI5Vd2dC4qchyTqxV8URinzt25XqVh+bHEPGH4C3NPrNionCP7Obx59wrYEbNlw4Z8sjALzZg== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + +webpack-dev-middleware@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f" + integrity sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg== + dependencies: + colorette "^2.0.10" + memfs "^3.4.1" + mime-types "^2.1.31" + range-parser "^1.2.1" + schema-utils "^4.0.0" + +webpack-dev-server@^4.6.0: + version "4.7.4" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz#d0ef7da78224578384e795ac228d8efb63d5f945" + integrity sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A== + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" + "@types/serve-index" "^1.9.1" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.2.2" + ansi-html-community "^0.0.8" + bonjour "^3.5.0" + chokidar "^3.5.3" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^1.6.0" + default-gateway "^6.0.3" + del "^6.0.0" + express "^4.17.1" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.0" + ipaddr.js "^2.0.1" + open "^8.0.9" + p-retry "^4.5.0" + portfinder "^1.0.28" + schema-utils "^4.0.0" + selfsigned "^2.0.0" + serve-index "^1.9.1" + sockjs "^0.3.21" + spdy "^4.0.2" + strip-ansi "^7.0.0" + webpack-dev-middleware "^5.3.1" + ws "^8.4.2" + +webpack-manifest-plugin@^4.0.2: + version "4.1.1" + resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz#10f8dbf4714ff93a215d5a45bcc416d80506f94f" + integrity sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow== + dependencies: + tapable "^2.0.0" + webpack-sources "^2.2.0" + +webpack-sources@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack-sources@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd" + integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA== + dependencies: + source-list-map "^2.0.1" + source-map "^0.6.1" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@^5.64.4: + version "5.70.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.70.0.tgz#3461e6287a72b5e6e2f4872700bc8de0d7500e6d" + integrity sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.4.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.9.2" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-better-errors "^1.0.2" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.3.1" + webpack-sources "^3.2.3" + +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-fetch@^3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" + integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== + +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +whatwg-url@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" + integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + +whatwg-url@^8.0.0, whatwg-url@^8.5.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" + integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== + dependencies: + lodash "^4.7.0" + tr46 "^2.1.0" + webidl-conversions "^6.1.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.3, word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +workbox-background-sync@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-6.5.1.tgz#df79c6a4a22945d8a44493a4947a6ed0f720ef86" + integrity sha512-T5a35fagLXQvV8Dr4+bDU+XYsP90jJ3eBLjZMKuCNELMQZNj+VekCODz1QK44jgoBeQk+vp94pkZV6G+e41pgg== + dependencies: + idb "^6.1.4" + workbox-core "6.5.1" + +workbox-broadcast-update@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-6.5.1.tgz#9aecb116979b0709480b84cfd1beca7a901d01d4" + integrity sha512-mb/oyblyEpDbw167cCTyHnC3RqCnCQHtFYuYZd+QTpuExxM60qZuBH1AuQCgvLtDcztBKdEYK2VFD9SZYgRbaQ== + dependencies: + workbox-core "6.5.1" + +workbox-build@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-6.5.1.tgz#6b5e8f090bb608267868540d3072b44b8531b3bc" + integrity sha512-coDUDzHvFZ1ADOl3wKCsCSyOBvkPKlPgcQDb6LMMShN1zgF31Mev/1HzN3+9T2cjjWAgFwZKkuRyExqc1v21Zw== + dependencies: + "@apideck/better-ajv-errors" "^0.3.1" + "@babel/core" "^7.11.1" + "@babel/preset-env" "^7.11.0" + "@babel/runtime" "^7.11.2" + "@rollup/plugin-babel" "^5.2.0" + "@rollup/plugin-node-resolve" "^11.2.1" + "@rollup/plugin-replace" "^2.4.1" + "@surma/rollup-plugin-off-main-thread" "^2.2.3" + ajv "^8.6.0" + common-tags "^1.8.0" + fast-json-stable-stringify "^2.1.0" + fs-extra "^9.0.1" + glob "^7.1.6" + lodash "^4.17.20" + pretty-bytes "^5.3.0" + rollup "^2.43.1" + rollup-plugin-terser "^7.0.0" + source-map "^0.8.0-beta.0" + stringify-object "^3.3.0" + strip-comments "^2.0.1" + tempy "^0.6.0" + upath "^1.2.0" + workbox-background-sync "6.5.1" + workbox-broadcast-update "6.5.1" + workbox-cacheable-response "6.5.1" + workbox-core "6.5.1" + workbox-expiration "6.5.1" + workbox-google-analytics "6.5.1" + workbox-navigation-preload "6.5.1" + workbox-precaching "6.5.1" + workbox-range-requests "6.5.1" + workbox-recipes "6.5.1" + workbox-routing "6.5.1" + workbox-strategies "6.5.1" + workbox-streams "6.5.1" + workbox-sw "6.5.1" + workbox-window "6.5.1" + +workbox-cacheable-response@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-6.5.1.tgz#f71d0a75b3d6846e39594955e99ac42fd26f8693" + integrity sha512-3TdtH/luDiytmM+Cn72HCBLZXmbeRNJqZx2yaVOfUZhj0IVwZqQXhNarlGE9/k6U5Jelb+TtpH2mLVhnzfiSMg== + dependencies: + workbox-core "6.5.1" + +workbox-core@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.5.1.tgz#0dba3bccf883a46dfa61cc412eaa3cb09bb549e6" + integrity sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw== + +workbox-expiration@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.5.1.tgz#9f105fcf3362852754884ad153888070ce98b692" + integrity sha512-iY/cTADAQATMmPkUBRmQdacqq0TJd2wMHimBQz+tRnPGHSMH+/BoLPABPnu7O7rT/g/s59CUYYRGxe3mEgoJCA== + dependencies: + idb "^6.1.4" + workbox-core "6.5.1" + +workbox-google-analytics@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-6.5.1.tgz#685224d439c1e7a943f8241d65e2a34ee95a4ba0" + integrity sha512-qZU46/h4dbionYT6Yk6iBkUwpiEzAfnO1W7KkI+AMmY7G9/gA03dQQ7rpTw8F4vWrG7ahTUGWDFv6fERtaw1BQ== + dependencies: + workbox-background-sync "6.5.1" + workbox-core "6.5.1" + workbox-routing "6.5.1" + workbox-strategies "6.5.1" + +workbox-navigation-preload@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.5.1.tgz#a244e3bdf99ce86da7210315ca1ba5aef3710825" + integrity sha512-aKrgAbn2IMgzTowTi/ZyKdQUcES2m++9aGtpxqsX7Gn9ovCY8zcssaMEAMMwrIeveij5HiWNBrmj6MWDHi+0rg== + dependencies: + workbox-core "6.5.1" + +workbox-precaching@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.5.1.tgz#177b6424f1e71e601b9c3d6864decad2655f9ff9" + integrity sha512-EzlPBxvmjGfE56YZzsT/vpVkpLG1XJhoplgXa5RPyVWLUL1LbwEAxhkrENElSS/R9tgiTw80IFwysidfUqLihg== + dependencies: + workbox-core "6.5.1" + workbox-routing "6.5.1" + workbox-strategies "6.5.1" + +workbox-range-requests@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-6.5.1.tgz#f40f84aa8765940543eba16131d02f12b38e2fdc" + integrity sha512-57Da/qRbd9v33YlHX0rlSUVFmE4THCjKqwkmfhY3tNLnSKN2L5YBS3qhWeDO0IrMNgUj+rGve2moKYXeUqQt4A== + dependencies: + workbox-core "6.5.1" + +workbox-recipes@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-recipes/-/workbox-recipes-6.5.1.tgz#d2fb21743677cc3ca9e1fc9e3b68f0d1587df205" + integrity sha512-DGsyKygHggcGPQpWafC/Nmbm1Ny3sB2vE9r//3UbeidXiQ+pLF14KEG1/0NNGRaY+lfOXOagq6d1H7SC8KA+rA== + dependencies: + workbox-cacheable-response "6.5.1" + workbox-core "6.5.1" + workbox-expiration "6.5.1" + workbox-precaching "6.5.1" + workbox-routing "6.5.1" + workbox-strategies "6.5.1" + +workbox-routing@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.5.1.tgz#5488795ae850fe3ae435241143b54ff25ab0db70" + integrity sha512-yAAncdTwanvlR8KPjubyvFKeAok8ZcIws6UKxvIAg0I+wsf7UYi93DXNuZr6RBSQrByrN6HkCyjuhmk8P63+PA== + dependencies: + workbox-core "6.5.1" + +workbox-strategies@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.5.1.tgz#51cabbddad5a1956eb9d51cf6ce01ab0a6372756" + integrity sha512-JNaTXPy8wXzKkr+6za7/eJX9opoZk7UgY261I2kPxl80XQD8lMjz0vo9EOcBwvD72v3ZhGJbW84ZaDwFEhFvWA== + dependencies: + workbox-core "6.5.1" + +workbox-streams@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-6.5.1.tgz#12036817385fa4449a86a3ef77fce1cb00ecad9f" + integrity sha512-7jaTWm6HRGJ/ewECnhb+UgjTT50R42E0/uNCC4eTKQwnLO/NzNGjoXTdQgFjo4zteR+L/K6AtFAiYKH3ZJbAYw== + dependencies: + workbox-core "6.5.1" + workbox-routing "6.5.1" + +workbox-sw@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-6.5.1.tgz#f9256b40f0a7e94656ccd06f127ba19a92cd23c5" + integrity sha512-hVrQa19yo9wzN1fQQ/h2JlkzFpkuH2qzYT2/rk7CLaWt6tLnTJVFCNHlGRRPhytZSf++LoIy7zThT714sowT/Q== + +workbox-webpack-plugin@^6.4.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-webpack-plugin/-/workbox-webpack-plugin-6.5.1.tgz#da88b4b6d8eff855958f0e7ebb7aa3eea50a8282" + integrity sha512-SHtlQBpKruI16CAYhICDMkgjXE2fH5Yp+D+1UmBfRVhByZYzusVOykvnPm8ObJb9d/tXgn9yoppoxafFS7D4vQ== + dependencies: + fast-json-stable-stringify "^2.1.0" + pretty-bytes "^5.4.1" + upath "^1.2.0" + webpack-sources "^1.4.3" + workbox-build "6.5.1" + +workbox-window@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-6.5.1.tgz#7b5ca29467b1da45dc9e2b5a1b89159d3eb9957a" + integrity sha512-oRlun9u7b7YEjo2fIDBqJkU2hXtrEljXcOytRhfeQRbqXxjUOpFgXSGRSAkmDx1MlKUNOSbr+zfi8h5n7In3yA== + dependencies: + "@types/trusted-types" "^2.0.2" + workbox-core "6.5.1" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@^7.4.6: + version "7.5.7" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" + integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== + +ws@^8.4.2: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + +xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-parser@^21.0.0: + version "21.0.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35" + integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^17.3.1: + version "17.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" + integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zod@^3.13.4: + version "3.13.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.13.4.tgz#5d6fe03ef4824a637d7ef50b5441cf6ab3acede0" + integrity sha512-LZRucWt4j/ru5azOkJxCfpR87IyFDn8h2UODdqvXzZLb3K7bb9chUrUIGTy3BPsr8XnbQYfQ5Md5Hu2OYIo1mg== + +zwitch@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" + integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==