Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d78957353d | |||
| b208493af9 | |||
| 4aa1485246 | |||
| e1e1d321dd | |||
| 3971b37abc | |||
| cf1bd3ea6b | |||
| 9b901766e3 | |||
| e19ee78e70 | |||
| c7c55ab95c | |||
| d7ddf01ea0 | |||
| c539af1a67 | |||
| d93d24b52d | |||
| 5dbfad68ad | |||
| 92c4506cfa | |||
| fe80bed6bd | |||
| b6e69021b2 | |||
| 12e624a496 | |||
| e95b44c690 | |||
| 4ee947d55c | |||
| 21212c0a1d | |||
| d1376a2200 | |||
| 7d2daf4f6a | |||
| da4562d308 | |||
| f51de52ff7 | |||
| 987632df39 | |||
| 28a3c3e53f | |||
| 1bd86f5abd | |||
| 989fbc25f8 | |||
| 0f935ceb48 | |||
| f844a435fd | |||
| 3a970e7a27 | |||
| 307c2bcdef | |||
| d62928aaae | |||
| d08a1e3ef6 | |||
| 2292041f9f | |||
| 75e4bf1d6e | |||
| 97add04276 | |||
| 1423f55d78 | |||
| 46d0b70399 | |||
| 168ca802d1 | |||
| 8c07e91f39 | |||
| 7979950c3b | |||
| 9846ba13e0 | |||
| 83839f7faf | |||
| 85fa3b1f8f | |||
| 4190f9a633 | |||
| 743ce27d2e | |||
| 399a2450ff | |||
| 934f16f0a5 | |||
| 0aeb13c181 | |||
| 5899bf2026 | |||
| 3b137964fc | |||
| 1bfdd0043f | |||
| 999c12748c | |||
| 6f283fd736 | |||
| 65d31046a0 | |||
| 601d632ae4 | |||
| 8466c5e750 | |||
| aa786c0db8 | |||
| f3faee389b | |||
| 5ac0aa8f74 | |||
| a589d11d01 | |||
| 1a05868381 | |||
| a35c3bae08 | |||
| 0c908786e0 | |||
| 2ba196d6a8 | |||
| 0e00999d79 | |||
| 5adceeb9a5 | |||
| b5920e35e3 | |||
| fb8f248366 | |||
| 7a931bd018 | |||
| a004f85145 | |||
| eeb086c77f | |||
| 54b195f851 | |||
| 5dc79134b2 | |||
| f3fad47d9e | |||
| 489534cb73 | |||
| e7801619cd | |||
| 7b75b5f9bb | |||
| 0022d848d6 | |||
| d47c4ea99a | |||
| 62354f2ab8 | |||
| 3a0adb406f | |||
| 2a39421524 | |||
| a7dc68822f | |||
| 3ad87aecc6 | |||
| 2ab714f575 | |||
| 9e60fb8d73 | |||
| a846522830 | |||
| 3d7d276236 | |||
| 2660af7ce3 | |||
| f5af86fd46 | |||
| 4bad2d7b03 | |||
| a79930916e | |||
| 9ea283e8d2 | |||
| bd6d192006 | |||
| 39848eda0b |
@@ -1,12 +1,12 @@
|
||||
name: CI
|
||||
# This workflow is triggered on pushes & pull requests
|
||||
on: [push, pull_request]
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
container: techknowlogick/xgo:go-1.13.x
|
||||
container: techknowlogick/xgo:go-1.17.x
|
||||
|
||||
# Service containers to run with `build` (Required for end-to-end testing)
|
||||
services:
|
||||
|
||||
@@ -20,16 +20,18 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v2
|
||||
# Login against a Docker registry except on PR
|
||||
# https://github.com/docker/login-action
|
||||
- name: Log into registry ${{ env.REGISTRY }}
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -38,8 +40,10 @@ jobs:
|
||||
# https://github.com/docker/metadata-action
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
flavor: |
|
||||
latest=false
|
||||
tags: |
|
||||
type=ref,enable=true,event=branch,suffix=-collector
|
||||
type=ref,enable=true,event=tag,suffix=-collector
|
||||
@@ -48,14 +52,16 @@ jobs:
|
||||
# Build and push Docker image with Buildx (don't push on PR)
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
context: .
|
||||
file: docker/Dockerfile.collector
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
web:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -67,14 +73,14 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v2
|
||||
# Login against a Docker registry except on PR
|
||||
# https://github.com/docker/login-action
|
||||
- name: Log into registry ${{ env.REGISTRY }}
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -83,25 +89,29 @@ jobs:
|
||||
# https://github.com/docker/metadata-action
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
flavor: |
|
||||
latest=false
|
||||
tags: |
|
||||
type=ref,enable=true,event=branch,suffix=-web
|
||||
type=ref,enable=true,event=tag,suffix=-web
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
- name: "Generate frontend version information"
|
||||
run: "cd webapp/frontend && ./git.version.sh"
|
||||
# Build and push Docker image with Buildx (don't push on PR)
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
context: .
|
||||
file: docker/Dockerfile.web
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
omnibus:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
@@ -112,14 +122,14 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v2
|
||||
# Login against a Docker registry except on PR
|
||||
# https://github.com/docker/login-action
|
||||
- name: Log into registry ${{ env.REGISTRY }}
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -128,17 +138,18 @@ jobs:
|
||||
# https://github.com/docker/metadata-action
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
tags: |
|
||||
type=ref,enable=true,event=branch,suffix=-omnibus
|
||||
type=ref,enable=true,event=tag,suffix=-omnibus
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
- name: "Generate frontend version information"
|
||||
run: "cd webapp/frontend && ./git.version.sh"
|
||||
# Build and push Docker image with Buildx (don't push on PR)
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
context: .
|
||||
@@ -146,3 +157,5 @@ jobs:
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
@@ -59,6 +59,16 @@ jobs:
|
||||
file "$GITHUB_WORKSPACE/dist/scrutiny-collector-metrics-${GOOS}-${GOARCH}" || true
|
||||
ldd "$GITHUB_WORKSPACE/dist/scrutiny-collector-metrics-${GOOS}-${GOARCH}" || true
|
||||
|
||||
- name: Release Asset - Collector - freebsd-amd64
|
||||
id: upload-release-asset2
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.SCRUTINY_GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ github.event.release.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: './dist/scrutiny-collector-metrics-freebsd-amd64'
|
||||
asset_name: scrutiny-collector-metrics-freebsd-amd64
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Release Asset - Web - freebsd-amd64
|
||||
id: upload-release-asset1
|
||||
@@ -71,13 +81,3 @@ jobs:
|
||||
asset_name: scrutiny-web-freebsd-amd64
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Release Asset - Collector - freebsd-amd64
|
||||
id: upload-release-asset2
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.SCRUTINY_GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ github.event.release.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: './dist/scrutiny-collector-metrics-freebsd-amd64'
|
||||
asset_name: scrutiny-collector-metrics-freebsd-amd64
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
@@ -15,13 +15,15 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{github.event.release.tag_name}}
|
||||
- name: "Generate frontend version information"
|
||||
run: "cd webapp/frontend && ./git.version.sh"
|
||||
- name: Build Frontend
|
||||
run: |
|
||||
cd webapp/frontend
|
||||
npm install -g @angular/cli@9.1.4
|
||||
npm install
|
||||
mkdir -p dist
|
||||
ng build --output-path=dist --deploy-url="/web/" --base-href="/web/" --prod
|
||||
npm run build:prod -- --output-path=dist
|
||||
tar -czf scrutiny-web-frontend.tar.gz dist
|
||||
- name: Upload Frontend Asset
|
||||
id: upload-release-asset3
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
container: techknowlogick/xgo:go-1.13.x
|
||||
container: techknowlogick/xgo:go-1.17.x
|
||||
# Service containers to run with `build` (Required for end-to-end testing)
|
||||
services:
|
||||
influxdb:
|
||||
|
||||
@@ -8,6 +8,7 @@ jobs:
|
||||
build:
|
||||
name: is-sponsor-label
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ false }}
|
||||
steps:
|
||||
- uses: JasonEtco/is-sponsor-label-action@v1.2.0
|
||||
env:
|
||||
|
||||
@@ -64,3 +64,5 @@ scrutiny-*.db
|
||||
scrutiny_test.db
|
||||
scrutiny.yaml
|
||||
coverage.txt
|
||||
/config
|
||||
/influxdb
|
||||
+109
-71
@@ -1,75 +1,109 @@
|
||||
# Contributing
|
||||
|
||||
There are multiple ways to develop on the scrutiny codebase locally. The two most popular are:
|
||||
- Docker Development Container - only requires docker
|
||||
- Run Components Locally - requires smartmontools, golang & nodejs installed locally
|
||||
The Scrutiny repository is a [monorepo](https://en.wikipedia.org/wiki/Monorepo) containing source code for:
|
||||
- Scrutiny Backend Server (API)
|
||||
- Scrutiny Frontend Angular SPA
|
||||
- S.M.A.R.T Collector
|
||||
|
||||
## Docker Development
|
||||
```
|
||||
docker build -f docker/Dockerfile . -t chcr.io/analogj/scrutiny:master-omnibus
|
||||
docker run -it --rm -p 8080:8080 \
|
||||
-v /run/udev:/run/udev:ro \
|
||||
--cap-add SYS_RAWIO \
|
||||
--device=/dev/sda \
|
||||
--device=/dev/sdb \
|
||||
ghcr.io/analogj/scrutiny:master-omnibus
|
||||
/opt/scrutiny/bin/scrutiny-collector-metrics run
|
||||
```
|
||||
Depending on the functionality you are adding, you may need to setup a development environment for 1 or more projects.
|
||||
|
||||
# Modifying the Scrutiny Backend Server (API)
|
||||
|
||||
## Local Development
|
||||
1. install the [Go runtime](https://go.dev/doc/install) (v1.17+)
|
||||
2. download the `scrutiny-web-frontend.tar.gz` for the [latest release](https://github.com/AnalogJ/scrutiny/releases/latest). Extract to a folder named `dist`
|
||||
3. create a `scrutiny.yaml` config file
|
||||
```yaml
|
||||
# config file for local development. store as scrutiny.yaml
|
||||
version: 1
|
||||
|
||||
web:
|
||||
listen:
|
||||
port: 8080
|
||||
host: 0.0.0.0
|
||||
database:
|
||||
# can also set absolute path here
|
||||
location: ./scrutiny.db
|
||||
src:
|
||||
frontend:
|
||||
path: ./dist
|
||||
influxdb:
|
||||
retention_policy: false
|
||||
|
||||
log:
|
||||
file: 'web.log' #absolute or relative paths allowed, eg. web.log
|
||||
level: DEBUG
|
||||
|
||||
### Frontend
|
||||
The frontend is written in Angular.
|
||||
If you're working on the frontend and can use mocked data rather than a real backend, you can use
|
||||
```
|
||||
cd webapp/frontend
|
||||
npm install
|
||||
ng serve --deploy-url="/web/" --base-href="/web/"
|
||||
```
|
||||
```
|
||||
4. start a InfluxDB docker container.
|
||||
```bash
|
||||
docker run -p 8086:8086 --rm influxdb:2.2
|
||||
```
|
||||
5. start the scrutiny web server
|
||||
```bash
|
||||
go mod vendor
|
||||
go run webapp/backend/cmd/scrutiny/scrutiny.go start --config ./scrutiny.yaml
|
||||
```
|
||||
6. open your browser to [http://localhost:8080/web](http://localhost:8080/web)
|
||||
|
||||
However, if you need to also run the backend, and use real data, you'll need to run the following command:
|
||||
```
|
||||
cd webapp/frontend && ng build --watch --output-path=../../dist --prod
|
||||
```
|
||||
# Modifying the Scrutiny Frontend Angular SPA
|
||||
|
||||
> Note: if you do not add `--prod` flag, app will display mocked data for api calls.
|
||||
The frontend is written in Angular. If you're working on the frontend and can use mocked data rather than a real backend, you can follow the instructions below:
|
||||
|
||||
### Backend
|
||||
1. install [NodeJS](https://nodejs.org/en/download/)
|
||||
2. start the Angular Frontend Application
|
||||
```bash
|
||||
cd webapp/frontend
|
||||
npm install
|
||||
npm run start -- --deploy-url="/web/" --base-href="/web/" --port 4200
|
||||
```
|
||||
3. open your browser and visit [http://localhost:4200/web](http://localhost:4200/web)
|
||||
|
||||
If you're using the `ng build` command above to generate your frontend, you'll need to create a custom config file and
|
||||
override the `web.src.frontend.path` value.
|
||||
# Modifying both Scrutiny Backend and Frontend Applications
|
||||
If you're developing a feature that requires changes to the backend and the frontend, or a frontend feature that requires real data,
|
||||
you'll need to follow the steps below:
|
||||
|
||||
```
|
||||
# config file for local development. store as scrutiny.yaml
|
||||
version: 1
|
||||
1. install the [Go runtime](https://go.dev/doc/install) (v1.17+)
|
||||
2. install [NodeJS](https://nodejs.org/en/download/)
|
||||
3. create a `scrutiny.yaml` config file
|
||||
```yaml
|
||||
# config file for local development. store as scrutiny.yaml
|
||||
version: 1
|
||||
|
||||
web:
|
||||
listen:
|
||||
port: 8080
|
||||
host: 0.0.0.0
|
||||
database:
|
||||
# can also set absolute path here
|
||||
location: ./scrutiny.db
|
||||
src:
|
||||
frontend:
|
||||
path: ./dist
|
||||
influxdb:
|
||||
retention_policy: false
|
||||
|
||||
log:
|
||||
file: 'web.log' #absolute or relative paths allowed, eg. web.log
|
||||
level: DEBUG
|
||||
|
||||
web:
|
||||
listen:
|
||||
port: 8080
|
||||
host: 0.0.0.0
|
||||
database:
|
||||
# can also set absolute path here
|
||||
location: ./scrutiny.db
|
||||
src:
|
||||
frontend:
|
||||
path: ./dist
|
||||
influxdb:
|
||||
retention_policy: false
|
||||
|
||||
log:
|
||||
file: 'web.log' #absolute or relative paths allowed, eg. web.log
|
||||
level: DEBUG
|
||||
|
||||
```
|
||||
|
||||
Once you've created a config file, you can pass it to the scrutiny binary during startup.
|
||||
|
||||
```
|
||||
go run webapp/backend/cmd/scrutiny/scrutiny.go start --config ./scrutiny.yaml
|
||||
```
|
||||
|
||||
Now visit http://localhost:8080
|
||||
```
|
||||
4. start a InfluxDB docker container.
|
||||
```bash
|
||||
docker run -p 8086:8086 --rm influxdb:2.2
|
||||
```
|
||||
5. build the Angular Frontend Application
|
||||
```bash
|
||||
cd webapp/frontend
|
||||
npm install
|
||||
npm run build:prod -- --watch --output-path=../../dist
|
||||
# Note: if you do not add `--prod` flag, app will display mocked data for api calls.
|
||||
```
|
||||
6. start the scrutiny web server
|
||||
```bash
|
||||
go mod vendor
|
||||
go run webapp/backend/cmd/scrutiny/scrutiny.go start --config ./scrutiny.yaml
|
||||
```
|
||||
7. open your browser to [http://localhost:8080/web](http://localhost:8080/web)
|
||||
|
||||
|
||||
If you'd like to populate the database with some test data, you can run the following commands:
|
||||
@@ -82,15 +116,6 @@ If you'd like to populate the database with some test data, you can run the fol
|
||||
docker run -p 8086:8086 --rm influxdb:2.2
|
||||
|
||||
|
||||
docker run --rm -p 8086:8086 \
|
||||
-e DOCKER_INFLUXDB_INIT_MODE=setup \
|
||||
-e DOCKER_INFLUXDB_INIT_USERNAME=admin \
|
||||
-e DOCKER_INFLUXDB_INIT_PASSWORD=password12345 \
|
||||
-e DOCKER_INFLUXDB_INIT_ORG=scrutiny \
|
||||
-e DOCKER_INFLUXDB_INIT_BUCKET=metrics \
|
||||
influxdb:2.2
|
||||
|
||||
|
||||
# curl -X POST -H "Content-Type: application/json" -d @webapp/backend/pkg/web/testdata/register-devices-req.json localhost:8080/api/devices/register
|
||||
# curl -X POST -H "Content-Type: application/json" -d @webapp/backend/pkg/models/testdata/smart-ata.json localhost:8080/api/device/0x5000cca264eb01d7/smart
|
||||
# curl -X POST -H "Content-Type: application/json" -d @webapp/backend/pkg/models/testdata/smart-ata-date.json localhost:8080/api/device/0x5000cca264eb01d7/smart
|
||||
@@ -105,14 +130,14 @@ curl localhost:8080/api/summary
|
||||
|
||||
```
|
||||
|
||||
### Collector
|
||||
# Modifying the Collector
|
||||
```
|
||||
brew install smartmontools
|
||||
go run collector/cmd/collector-metrics/collector-metrics.go run --debug
|
||||
```
|
||||
|
||||
|
||||
## Debugging
|
||||
# Debugging
|
||||
|
||||
If you need more verbose logs for debugging, you can use the following environmental variables:
|
||||
|
||||
@@ -131,3 +156,16 @@ Finally, you can copy the files from the scrutiny container to your host using t
|
||||
docker cp scrutiny:/tmp/collector.log collector.log
|
||||
docker cp scrutiny:/tmp/web.log web.log
|
||||
```
|
||||
|
||||
# Docker Development
|
||||
|
||||
```
|
||||
docker build -f docker/Dockerfile . -t chcr.io/analogj/scrutiny:master-omnibus
|
||||
docker run -it --rm -p 8080:8080 \
|
||||
-v /run/udev:/run/udev:ro \
|
||||
--cap-add SYS_RAWIO \
|
||||
--device=/dev/sda \
|
||||
--device=/dev/sdb \
|
||||
ghcr.io/analogj/scrutiny:master-omnibus
|
||||
/opt/scrutiny/bin/scrutiny-collector-metrics run
|
||||
```
|
||||
|
||||
@@ -70,8 +70,10 @@ Scrutiny uses `smartctl --scan` to detect devices/drives.
|
||||
|
||||
If you're using Docker, getting started is as simple as running the following command:
|
||||
|
||||
> See [docker/example.omnibus.docker-compose.yml](./docker/example.omnibus.docker-compose.yml) for a docker-compose file.
|
||||
|
||||
```bash
|
||||
docker run -it --rm -p 8080:8080 \
|
||||
docker run -it --rm -p 8080:8080 -p 8086:8086 \
|
||||
-v `pwd`/scrutiny:/opt/scrutiny/config \
|
||||
-v `pwd`/influxdb2:/opt/scrutiny/influxdb \
|
||||
-v /run/udev:/run/udev:ro \
|
||||
@@ -95,6 +97,8 @@ In addition to the Omnibus image (available under the `latest` tag) there are 2
|
||||
- `ghcr.io/analogj/scrutiny:master-collector` - Contains the Scrutiny data collector, `smartctl` binary and cron-like scheduler. You can run one collector on each server.
|
||||
- `ghcr.io/analogj/scrutiny:master-web` - Contains the Web UI, API and Database. Only one container necessary
|
||||
|
||||
> See [docker/example.hubspoke.docker-compose.yml](./docker/example.hubspoke.docker-compose.yml) for a docker-compose file.
|
||||
|
||||
```bash
|
||||
docker run --rm -p 8086:8086 \
|
||||
-v `pwd`/influxdb2:/var/lib/influxdb2 \
|
||||
@@ -174,7 +178,9 @@ Scrutiny supports sending SMART device failure notifications via the following s
|
||||
- Telegram
|
||||
- Tulip
|
||||
|
||||
Check the `notify.urls` section of [example.scrutiny.yml](example.scrutiny.yaml) for more information and documentation for service specific setup.
|
||||
Check the `notify.urls` section of [example.scrutiny.yml](example.scrutiny.yaml) for examples.
|
||||
|
||||
For more information and troubleshooting, see the [TROUBLESHOOTING_NOTIFICATIONS.md](./docs/TROUBLESHOOTING_NOTIFICATIONS.md) file
|
||||
|
||||
### Testing Notifications
|
||||
|
||||
@@ -233,8 +239,9 @@ scrutiny-collector-metrics run --debug --log-file /tmp/collector.log
|
||||
| amd64 | :white_check_mark: | :white_check_mark: |
|
||||
| arm-5 | :white_check_mark: | |
|
||||
| arm-6 | :white_check_mark: | |
|
||||
| arm-7 | :white_check_mark: | |
|
||||
| arm-7 | :white_check_mark: | web/collector only. see [#236](https://github.com/AnalogJ/scrutiny/issues/236) |
|
||||
| arm64 | :white_check_mark: | :white_check_mark: |
|
||||
| freebsd | collector only. see [#238](https://github.com/AnalogJ/scrutiny/issues/238) | |
|
||||
| macos-amd64 | | :white_check_mark: |
|
||||
| macos-arm64 | | :white_check_mark: |
|
||||
| windows-amd64 | :white_check_mark: | |
|
||||
|
||||
@@ -13,7 +13,7 @@ func DevicePrefix() string {
|
||||
|
||||
func (d *Detect) Start() ([]models.Device, error) {
|
||||
d.Shell = shell.Create()
|
||||
// call the base/common functionality to get a list of devicess
|
||||
// call the base/common functionality to get a list of devices
|
||||
detectedDevices, err := d.SmartctlScan()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package detect
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/analogj/scrutiny/collector/pkg/common/shell"
|
||||
"github.com/analogj/scrutiny/collector/pkg/models"
|
||||
"github.com/jaypipes/ghw"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -22,6 +25,7 @@ func (d *Detect) Start() ([]models.Device, error) {
|
||||
//inflate device info for detected devices.
|
||||
for ndx, _ := range detectedDevices {
|
||||
d.SmartCtlInfo(&detectedDevices[ndx]) //ignore errors.
|
||||
populateUdevInfo(&detectedDevices[ndx]) //ignore errors.
|
||||
}
|
||||
|
||||
return detectedDevices, nil
|
||||
@@ -49,3 +53,51 @@ func (d *Detect) wwnFallback(detectedDevice *models.Device) {
|
||||
//wwn must always be lowercase.
|
||||
detectedDevice.WWN = strings.ToLower(detectedDevice.WWN)
|
||||
}
|
||||
|
||||
// as discussed in
|
||||
// - https://github.com/AnalogJ/scrutiny/issues/225
|
||||
// - https://github.com/jaypipes/ghw/issues/59#issue-361915216
|
||||
// udev exposes its data in a standardized way under /run/udev/data/....
|
||||
func populateUdevInfo(detectedDevice *models.Device) error {
|
||||
// Get device major:minor numbers
|
||||
// `cat /sys/class/block/sda/dev`
|
||||
devNo, err := ioutil.ReadFile(filepath.Join("/sys/class/block/", detectedDevice.DeviceName, "dev"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Look up block device in udev runtime database
|
||||
// `cat /run/udev/data/b8:0`
|
||||
udevID := "b" + strings.TrimSpace(string(devNo))
|
||||
udevBytes, err := ioutil.ReadFile(filepath.Join("/run/udev/data/", udevID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deviceMountPaths := []string{}
|
||||
udevInfo := make(map[string]string)
|
||||
for _, udevLine := range strings.Split(string(udevBytes), "\n") {
|
||||
if strings.HasPrefix(udevLine, "E:") {
|
||||
if s := strings.SplitN(udevLine[2:], "=", 2); len(s) == 2 {
|
||||
udevInfo[s[0]] = s[1]
|
||||
}
|
||||
} else if strings.HasPrefix(udevLine, "S:") {
|
||||
deviceMountPaths = append(deviceMountPaths, udevLine[2:])
|
||||
}
|
||||
}
|
||||
|
||||
//Set additional device information.
|
||||
if deviceLabel, exists := udevInfo["ID_FS_LABEL"]; exists {
|
||||
detectedDevice.DeviceLabel = deviceLabel
|
||||
}
|
||||
if deviceUUID, exists := udevInfo["ID_FS_UUID"]; exists {
|
||||
detectedDevice.DeviceUUID = deviceUUID
|
||||
}
|
||||
if deviceSerialID, exists := udevInfo["ID_SERIAL"]; exists {
|
||||
detectedDevice.DeviceSerialID = fmt.Sprintf("%s-%s", udevInfo["ID_BUS"], deviceSerialID)
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package models
|
||||
|
||||
type Device struct {
|
||||
WWN string `json:"wwn"`
|
||||
HostId string `json:"host_id"`
|
||||
WWN string `json:"wwn"`
|
||||
|
||||
DeviceName string `json:"device_name"`
|
||||
DeviceUUID string `json:"device_uuid"`
|
||||
DeviceSerialID string `json:"device_serial_id"`
|
||||
DeviceLabel string `json:"device_label"`
|
||||
|
||||
Manufacturer string `json:"manufacturer"`
|
||||
ModelName string `json:"model_name"`
|
||||
InterfaceType string `json:"interface_type"`
|
||||
@@ -17,6 +20,10 @@ type Device struct {
|
||||
SmartSupport bool `json:"smart_support"`
|
||||
DeviceProtocol string `json:"device_protocol"` //protocol determines which smart attribute types are available (ATA, NVMe, SCSI)
|
||||
DeviceType string `json:"device_type"` //device type is used for querying with -d/t flag, should only be used by collector.
|
||||
|
||||
// User provided metadata
|
||||
Label string `json:"label"`
|
||||
HostId string `json:"host_id"`
|
||||
}
|
||||
|
||||
type DeviceWrapper struct {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
########
|
||||
FROM golang:1.14.4-buster as backendbuild
|
||||
FROM golang:1.17.10-buster as backendbuild
|
||||
|
||||
WORKDIR /go/src/github.com/analogj/scrutiny
|
||||
|
||||
@@ -22,7 +22,7 @@ COPY webapp/frontend /opt/scrutiny/src
|
||||
RUN npm install -g @angular/cli@9.1.4 && \
|
||||
mkdir -p /scrutiny/dist && \
|
||||
npm install && \
|
||||
ng build --output-path=/opt/scrutiny/dist --prod
|
||||
npm run build:prod -- --output-path=/opt/scrutiny/dist
|
||||
|
||||
|
||||
########
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
########
|
||||
FROM golang:1.14.4-buster as backendbuild
|
||||
FROM golang:1.17.10-buster as backendbuild
|
||||
|
||||
WORKDIR /go/src/github.com/analogj/scrutiny
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
########
|
||||
FROM golang:1.14.4-buster as backendbuild
|
||||
FROM golang:1.17.10-buster as backendbuild
|
||||
|
||||
WORKDIR /go/src/github.com/analogj/scrutiny
|
||||
|
||||
@@ -20,7 +20,7 @@ COPY webapp/frontend /opt/scrutiny/src
|
||||
RUN npm install -g @angular/cli@9.1.4 && \
|
||||
mkdir -p /opt/scrutiny/dist && \
|
||||
npm install && \
|
||||
ng build --output-path=/opt/scrutiny/dist --prod
|
||||
npm run build:prod -- --output-path=/opt/scrutiny/dist
|
||||
|
||||
|
||||
########
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM techknowlogick/xgo:go-1.13.x
|
||||
FROM techknowlogick/xgo:go-1.17.x
|
||||
|
||||
WORKDIR /go/src/github.com/analogj/scrutiny
|
||||
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Cron runs in its own isolated environment (usually using only /etc/environment )
|
||||
# So when the container starts up, we will do a dump of the runtime environment into a .env file that we
|
||||
# will then source into the crontab file (/etc/cron.d/scrutiny.sh)
|
||||
|
||||
printenv | sed 's/^\(.*\)$/export \1/g' > /env.sh
|
||||
# will then source into the crontab file (/etc/cron.d/scrutiny)
|
||||
(set -o posix; export -p) > /env.sh
|
||||
|
||||
# adding ability to customize the cron schedule.
|
||||
COLLECTOR_CRON_SCHEDULE=${COLLECTOR_CRON_SCHEDULE:-"0 0 * * *"}
|
||||
|
||||
# if the cron schedule has been overridden via env variable (eg docker-compose) we should make sure to strip quotes
|
||||
[[ "${COLLECTOR_CRON_SCHEDULE}" == \"*\" || "${COLLECTOR_CRON_SCHEDULE}" == \'*\' ]] && COLLECTOR_CRON_SCHEDULE="${COLLECTOR_CRON_SCHEDULE:1:-1}"
|
||||
|
||||
# replace placeholder with correct value
|
||||
sed -i 's|{COLLECTOR_CRON_SCHEDULE}|'"${COLLECTOR_CRON_SCHEDULE}"'|g' /etc/cron.d/scrutiny
|
||||
|
||||
# now that we have the env start cron in the foreground
|
||||
echo "starting cron"
|
||||
su -c "cron -l 8 -f" root
|
||||
su -c "cron -f -L 15" root
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
version: '2.4'
|
||||
|
||||
services:
|
||||
influxdb:
|
||||
image: influxdb:2.2
|
||||
ports:
|
||||
- '8086:8086'
|
||||
volumes:
|
||||
- './influxdb:/var/lib/influxdb2'
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8086/health"]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 20
|
||||
|
||||
|
||||
web:
|
||||
image: 'ghcr.io/analogj/scrutiny:master-web'
|
||||
ports:
|
||||
- '8080:8080'
|
||||
volumes:
|
||||
- './config:/opt/scrutiny/config'
|
||||
environment:
|
||||
SCRUTINY_WEB_INFLUXDB_HOST: 'influxdb'
|
||||
depends_on:
|
||||
influxdb:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/api/health"]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 20
|
||||
start_period: 10s
|
||||
|
||||
collector:
|
||||
image: 'ghcr.io/analogj/scrutiny:master-collector'
|
||||
cap_add:
|
||||
- SYS_RAWIO
|
||||
volumes:
|
||||
- '/run/udev:/run/udev:ro'
|
||||
environment:
|
||||
COLLECTOR_API_ENDPOINT: 'http://web:8080'
|
||||
depends_on:
|
||||
web:
|
||||
condition: service_healthy
|
||||
devices:
|
||||
- "/dev/sda"
|
||||
- "/dev/sdb"
|
||||
@@ -7,11 +7,12 @@ services:
|
||||
cap_add:
|
||||
- SYS_RAWIO
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "8080:8080" # webapp
|
||||
- "8086:8086" # influxDB admin
|
||||
volumes:
|
||||
- /run/udev:/run/udev:ro
|
||||
- ./config:/opt/scrutiny/config
|
||||
- ./influxdb:/var/lib/influxdb2
|
||||
- ./influxdb:/opt/scrutiny/influxdb
|
||||
devices:
|
||||
- "/dev/sda"
|
||||
- "/dev/sdb"
|
||||
@@ -0,0 +1,17 @@
|
||||
# Ansible Install
|
||||
|
||||
[Zorlin](https://github.com/Zorlin) has developed and now maintains [an Ansible playbook](https://github.com/Zorlin/scrutiny-playbook) which automates the steps involved in manually setting up Scrutiny.
|
||||
|
||||
Using it is simple:
|
||||
|
||||
* Grab a copy of the playbook
|
||||
* Follow the directions in the playbook repository
|
||||
* Run `ansible-playbook site.yml`
|
||||
* Visit http://your-machine:8080 to see your new Scrutiny installation.
|
||||
|
||||
It will automatically pull metrics from machines once a day, at 1am.
|
||||
|
||||
You can see it in action below.
|
||||
|
||||
[](https://asciinema.org/a/493531)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
> See [docker/example.hubspoke.docker-compose.yml](./docker/example.hubspoke.docker-compose.yml) for a docker-compose file.
|
||||
|
||||
+19
-2
@@ -2,12 +2,18 @@
|
||||
|
||||
While the easiest way to get started with [Scrutiny is using Docker](https://github.com/AnalogJ/scrutiny#docker),
|
||||
it is possible to run it manually without much work. You can even mix and match, using Docker for one component and
|
||||
a manual installation for the other.
|
||||
a manual installation for the other. There's also [an installer](INSTALL_ANSIBLE.md) which automates this manual installation procedure.
|
||||
|
||||
Scrutiny is made up of two components: a collector and a webapp/api. Here's how each component can be deployed manually.
|
||||
Scrutiny is made up of three components: an influxdb Database, a collector and a webapp/api. Here's how each component can be deployed manually.
|
||||
|
||||
> Note: the `/opt/scrutiny` directory is not hardcoded, you can use any directory name/path.
|
||||
|
||||
## InfluxDB
|
||||
|
||||
Please follow the official InfluxDB installation guide. Note, you'll need to install v2.2.0+.
|
||||
|
||||
https://docs.influxdata.com/influxdb/v2.2/install/
|
||||
|
||||
## Webapp/API
|
||||
|
||||
### Dependencies
|
||||
@@ -45,6 +51,17 @@ web:
|
||||
# The path to the Scrutiny frontend files (js, css, images) must be specified.
|
||||
# We'll populate it with files in the next section
|
||||
path: /opt/scrutiny/web
|
||||
|
||||
# if you're runnning influxdb on a different host (or using a cloud-provider) you'll need to update the host & port below.
|
||||
# token, org, bucket are unnecessary for a new InfluxDB installation, as Scrutiny will automatically run the InfluxDB setup,
|
||||
# and store the information in the config file. If you 're re-using an existing influxdb installation, you'll need to provide
|
||||
# the `token`
|
||||
influxdb:
|
||||
host: 0.0.0.0
|
||||
port: 8086
|
||||
# token: 'my-token'
|
||||
# org: 'my-org'
|
||||
# bucket: 'bucket'
|
||||
```
|
||||
|
||||
> Note: for a full list of available configuration options, please check the [example.scrutiny.yaml](https://github.com/AnalogJ/scrutiny/blob/master/example.scrutiny.yaml) file.
|
||||
|
||||
@@ -118,6 +118,19 @@ instead of the block device (`/dev/nvme0n1`). See [#209](https://github.com/Anal
|
||||
### Volume Mount All Devices (`/dev`) - Privileged
|
||||
|
||||
|
||||
## Scrutiny detects Failure but SMART Passed?
|
||||
|
||||
There's 2 different mechanisms that Scrutiny uses to detect failures.
|
||||
|
||||
The first is simple SMART failures. If SMART thinks an attribute is in a failed state, Scrutiny will display it as failed as well.
|
||||
|
||||
The second is using BackBlaze failure data: [https://backblaze.com/blog-smart-stats-2014-8.html](https://backblaze.com/blog-smart-stats-2014-8.html)
|
||||
If Scrutiny detects that an attribute corresponds with a high rate of failure using BackBlaze's data, it will also mark that attribute (and disk) as failed (even though SMART may think the device is still healthy).
|
||||
|
||||
This can cause some confusion when comparing Scrutiny's dashboard against other SMART analysis tools.
|
||||
If you hover over the "failed" label beside an attribute, Scrutiny will tell you if the failure was due to SMART or Scrutiny/BackBlaze data.
|
||||
|
||||
|
||||
## Hub & Spoke model, with multiple Hosts.
|
||||
|
||||
When deploying Scrutiny in a hub & spoke model, it can be difficult to determine exactly which node a set of devices are associated with.
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# InfluxDB Troubleshooting
|
||||
|
||||
## Installation
|
||||
InfluxDB is a required dependency for Scrutiny v0.4.0+.
|
||||
|
||||
https://docs.influxdata.com/influxdb/v2.2/install/
|
||||
|
||||
## Persistence
|
||||
|
||||
To ensure that all data is correctly stored, you must also persist the InfluxDB database directory
|
||||
|
||||
- If you're using the Official Scrutiny Omnibus image (`ghcr.io/analogj/scrutiny:master-omnibus`), the path is `/opt/scrutiny/influxdb`
|
||||
- If you're deploying in Hub/Spoke mode with the InfluxDB maintained image (`influxdb:2.2`), the path is `/var/lib/influxdb2`
|
||||
|
||||
If you attempt to restart Scrutiny but you forgot to persist the InfluxDB directory, you will get an error message like follows:
|
||||
|
||||
```
|
||||
scrutiny | time="2022-05-12T22:54:12Z" level=info msg="Trying to connect to scrutiny sqlite db: /opt/scrutiny/config/scrutiny.db\n"
|
||||
scrutiny | time="2022-05-12T22:54:12Z" level=info msg="Successfully connected to scrutiny sqlite db: /opt/scrutiny/config/scrutiny.db\n"
|
||||
scrutiny | ts=2022-05-12T22:54:12.240791Z lvl=info msg=Unauthorized log_id=0aQcVlOW000 error="authorization not found"
|
||||
scrutiny | panic: unauthorized: unauthorized access
|
||||
```
|
||||
|
||||
Unfortunately this may mean that your database is lost, and the previous Scrutiny data is unavailable.
|
||||
You should fix the docker-compose/docker run command that you're using to ensure that your database folder is persisted correctly,
|
||||
then delete the `web.influxdb.token` field in your `scrutiny.yaml` file, and then restart Scrutiny.
|
||||
|
||||
|
||||
## First Start
|
||||
The web/api service will trigger an InfluxDB onboarding process automatically when it first starts. After that, it will store the newly generated influxdb api token in the Scrutiny config file.
|
||||
|
||||
If this Credential is not correctly stored in the scrutiny config file, Scrutiny will fail to start (with an authentication error)
|
||||
|
||||
```
|
||||
scrutiny | time="2022-05-12T22:52:55Z" level=info msg="Successfully connected to scrutiny sqlite db: /opt/scrutiny/config/scrutiny.db\n"
|
||||
scrutiny | ts=2022-05-12T22:52:55.235753Z lvl=error msg="failed to onboard user admin" log_id=0aQcRnc0000 handler=onboard error="onboarding has already been completed" took=0.038ms
|
||||
scrutiny | ts=2022-05-12T22:52:55.235816Z lvl=error msg="api error encountered" log_id=0aQcRnc0000 error="onboarding has already been completed"
|
||||
scrutiny | panic: conflict: onboarding has already been completed
|
||||
```
|
||||
|
||||
You can fix this issue by authenticating to the InfluxDB admin portal (the default credentials are username: `admin`, password: `password12345`),
|
||||
then retrieving the API token, and writing it to your `scrutiny.yaml` config file under the `web.influxdb.token` field:
|
||||
|
||||

|
||||
|
||||
## Upgrading from v0.3.x to v0.4.x
|
||||
|
||||
When upgrading from v0.3.x to v0.4.x, some users have noticed problems such as:
|
||||
|
||||
```
|
||||
2022/05/13 14:38:05 Loading configuration file: /opt/scrutiny/config/scrutiny.yaml
|
||||
time="2022-05-13T14:38:05Z" level=info msg="Trying to connect to scrutiny sqlite db:"
|
||||
time="2022-05-13T14:38:05Z" level=info msg="Successfully connected to scrutiny sqlite db:"
|
||||
panic: a username and password is required for a setup
|
||||
```
|
||||
|
||||
As discussed in [#248](https://github.com/AnalogJ/scrutiny/issues/248) and [#234](https://github.com/AnalogJ/scrutiny/issues/234),
|
||||
this usually related to either:
|
||||
|
||||
- Upgrading from the LSIO Scrutiny image to the Official Scrutiny image, without removing LSIO specific environmental variables
|
||||
- remove the `SCRUTINY_WEB=true` and `SCRUTINY_COLLECTOR=true` environmental variables. They were used by the LSIO image, but are unnecessary and cause issues with the official Scrutiny image.
|
||||
- Updated versions of the [LSIO Scrutiny images are broken](https://github.com/linuxserver/docker-scrutiny/issues/22), as they have not installed InfluxDB which is a required dependency of Scrutiny v0.4.x
|
||||
- You can revert to an earlier version of the LSIO image (`lscr.io/linuxserver/scrutiny:060ac7b8-ls34`), or just change to the official Scrutiny image (`ghcr.io/analogj/scrutiny:master-omnibus`)
|
||||
|
||||
Here's a couple of confirmed working docker-compose files that you may want to look at:
|
||||
|
||||
- https://github.com/AnalogJ/scrutiny/blob/master/docker/example.hubspoke.docker-compose.yml
|
||||
- https://github.com/AnalogJ/scrutiny/blob/master/docker/example.omnibus.docker-compose.yml
|
||||
@@ -0,0 +1,25 @@
|
||||
# Notifications
|
||||
|
||||
As documented in [example.scrutiny.yaml](https://github.com/AnalogJ/scrutiny/blob/master/example.scrutiny.yaml#L59-L75)
|
||||
there are multiple ways to configure notifications for Scrutiny.
|
||||
|
||||
Under the hood we use a library called [Shoutrrr](https://github.com/containrrr/shoutrrr) to send our notifications, and you should use their documentation if you run into
|
||||
any issues: https://containrrr.dev/shoutrrr/services/overview/
|
||||
|
||||
|
||||
# Script Notifications
|
||||
|
||||
While the Shoutrrr library supports many popular providers for sending notifications Scrutiny also supports a "script" based
|
||||
notification system, allowing you to execute a custom script whenever a notification needs to be sent.
|
||||
Data is provided to this script using the following environmental variables:
|
||||
|
||||
```
|
||||
SCRUTINY_SUBJECT - eg. "Scrutiny SMART error (%s) detected on device: %s"
|
||||
SCRUTINY_DATE
|
||||
SCRUTINY_FAILURE_TYPE - EmailTest, SmartFail, ScrutinyFail
|
||||
SCRUTINY_DEVICE_NAME - eg. /dev/sda
|
||||
SCRUTINY_DEVICE_TYPE - ATA/SCSI/NVMe
|
||||
SCRUTINY_DEVICE_SERIAL - eg. WDDJ324KSO
|
||||
SCRUTINY_MESSAGE - eg. "Scrutiny SMART error notification for device: %s\nFailure Type: %s\nDevice Name: %s\nDevice Serial: %s\nDevice Type: %s\nDate: %s"
|
||||
```
|
||||
|
||||
@@ -55,4 +55,52 @@ api:
|
||||
You may also configure these values using the following environmental variables (both are required).
|
||||
|
||||
- `COLLECTOR_API_ENDPOINT=http://localhost:8080/custombasepath`
|
||||
- `SCRUTINY_WEB_LISTEN_BASEPATH=/custombasepath`
|
||||
- `SCRUTINY_WEB_LISTEN_BASEPATH=/custombasepath`
|
||||
|
||||
# Real Examples
|
||||
|
||||
## Caddy
|
||||
|
||||
1. Create a Caddyfile
|
||||
```yaml
|
||||
# Caddyfile
|
||||
:9090
|
||||
|
||||
# The `scrutiny` text in this file must match the service name in the docker-compose file below.
|
||||
# The `/custom/` text is the custom base path scrutiny will be availble on.
|
||||
reverse_proxy /custom/* scrutiny:8080
|
||||
|
||||
```
|
||||
2. Create a `docker-compose.yml` file
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
version: '3.5'
|
||||
|
||||
services:
|
||||
scrutiny:
|
||||
container_name: scrutiny
|
||||
image: ghcr.io/analogj/scrutiny:master-omnibus
|
||||
cap_add:
|
||||
- SYS_RAWIO
|
||||
ports:
|
||||
- "8086:8086" # influxDB admin
|
||||
volumes:
|
||||
- /run/udev:/run/udev:ro
|
||||
- ./config:/opt/scrutiny/config
|
||||
- ./influxdb:/opt/scrutiny/influxdb
|
||||
devices:
|
||||
- "/dev/sda"
|
||||
- "/dev/sdb"
|
||||
environment:
|
||||
- SCRUTINY_WEB_LISTEN_BASEPATH=/custom
|
||||
- COLLECTOR_API_ENDPOINT=http://localhost:8080/custom
|
||||
caddy:
|
||||
image: caddy
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile
|
||||
ports:
|
||||
- "9090:9090"
|
||||
```
|
||||
3. run `docker-compose up`
|
||||
4. visit [http://localhost:9090/custom/web](http://localhost:9090/custom/web) - access the scrutiny container via caddy reverse proxy
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
@@ -72,3 +72,13 @@ devices:
|
||||
#
|
||||
########################################################################################################################
|
||||
|
||||
#collect:
|
||||
# metric:
|
||||
# enable: true
|
||||
# command: '-a -o on -S on'
|
||||
# long:
|
||||
# enable: false
|
||||
# command: ''
|
||||
# short:
|
||||
# enable: false
|
||||
# command: ''
|
||||
|
||||
+6
-17
@@ -34,7 +34,13 @@ web:
|
||||
# the location on the filesystem where scrutiny javascript + css is located
|
||||
frontend:
|
||||
path: /opt/scrutiny/web
|
||||
|
||||
# if you're running influxdb on a different host (or using a cloud-provider) you'll need to update the host & port below.
|
||||
# token, org, bucket are unnecessary for a new InfluxDB installation, as Scrutiny will automatically run the InfluxDB setup,
|
||||
# and store the information in the config file. If you 're re-using an existing influxdb installation, you'll need to provide
|
||||
# the `token`
|
||||
influxdb:
|
||||
# scheme: 'http'
|
||||
host: 0.0.0.0
|
||||
port: 8086
|
||||
# token: 'my-token'
|
||||
@@ -75,12 +81,6 @@ log:
|
||||
#
|
||||
########################################################################################################################
|
||||
|
||||
#disks:
|
||||
# include:
|
||||
# # - /dev/sda
|
||||
# exclude:
|
||||
# # - /dev/sdb
|
||||
|
||||
#limits:
|
||||
# ata:
|
||||
# critical:
|
||||
@@ -95,14 +95,3 @@ log:
|
||||
# critical: true
|
||||
# standard: true
|
||||
|
||||
|
||||
#collect:
|
||||
# metric:
|
||||
# enable: true
|
||||
# command: '-a -o on -S on'
|
||||
# long:
|
||||
# enable: false
|
||||
# command: ''
|
||||
# short:
|
||||
# enable: false
|
||||
# command: ''
|
||||
|
||||
@@ -1,31 +1,83 @@
|
||||
module github.com/analogj/scrutiny
|
||||
|
||||
go 1.13
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/analogj/go-util v0.0.0-20190301173314-5295e364eb14
|
||||
github.com/citilinkru/libudev v1.0.0 // indirect
|
||||
github.com/containrrr/shoutrrr v0.4.4
|
||||
github.com/fatih/color v1.10.0
|
||||
github.com/gin-gonic/gin v1.6.3
|
||||
github.com/go-gormigrate/gormigrate/v2 v2.0.0
|
||||
github.com/golang/mock v1.4.3
|
||||
github.com/google/uuid v1.2.0 // indirect
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.2.3
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.9.0
|
||||
github.com/jaypipes/ghw v0.6.1
|
||||
github.com/jinzhu/gorm v1.9.16
|
||||
github.com/klauspost/compress v1.12.1 // indirect
|
||||
github.com/kvz/logstreamer v0.0.0-20150507115422-a635b98146f0 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.4 // indirect
|
||||
github.com/mitchellh/mapstructure v1.2.2
|
||||
github.com/onsi/ginkgo v1.16.1 // indirect
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/spf13/viper v1.7.0
|
||||
github.com/stretchr/testify v1.5.1
|
||||
github.com/urfave/cli/v2 v2.2.0
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 // indirect
|
||||
gorm.io/driver/sqlite v1.1.3
|
||||
gorm.io/gorm v1.20.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||
github.com/citilinkru/libudev v1.0.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/deepmap/oapi-codegen v1.8.2 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||
github.com/go-playground/locales v0.13.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.2.0 // indirect
|
||||
github.com/golang/protobuf v1.4.2 // indirect
|
||||
github.com/google/uuid v1.2.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
|
||||
github.com/jaypipes/pcidb v0.5.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.1 // indirect
|
||||
github.com/json-iterator/go v1.1.9 // indirect
|
||||
github.com/klauspost/compress v1.12.1 // indirect
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||
github.com/kvz/logstreamer v0.0.0-20150507115422-a635b98146f0 // indirect
|
||||
github.com/leodido/go-urn v1.2.0 // indirect
|
||||
github.com/magiconair/properties v1.8.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.4 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/onsi/ginkgo v1.16.1 // indirect
|
||||
github.com/pelletier/go-toml v1.7.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/spf13/afero v1.2.2 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
github.com/ugorji/go/codec v1.1.7 // indirect
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 // indirect
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
|
||||
golang.org/x/text v0.3.5 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/protobuf v1.23.0 // indirect
|
||||
gopkg.in/ini.v1 v1.55.0 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||
gosrc.io/xmpp v0.5.1 // indirect
|
||||
howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect
|
||||
nhooyr.io/websocket v1.8.7 // indirect
|
||||
)
|
||||
|
||||
@@ -0,0 +1,709 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/agnivade/wasmbrowsertest v0.3.1/go.mod h1:zQt6ZTdl338xxRaMW395qccVE2eQm0SjC/SDz0mPWQI=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/analogj/go-util v0.0.0-20190301173314-5295e364eb14 h1:wsrSjiqQtseStRIoLLxS4C5IEtXkazZVEPDHq8jW7r8=
|
||||
github.com/analogj/go-util v0.0.0-20190301173314-5295e364eb14/go.mod h1:lJQVqFKMV5/oDGYR2bra2OljcF3CvolAoyDRyOA4k4E=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/chromedp/cdproto v0.0.0-20190614062957-d6d2f92b486d/go.mod h1:S8mB5wY3vV+vRIzf39xDXsw3XKYewW9X6rW2aEmkrSw=
|
||||
github.com/chromedp/cdproto v0.0.0-20190621002710-8cbd498dd7a0/go.mod h1:S8mB5wY3vV+vRIzf39xDXsw3XKYewW9X6rW2aEmkrSw=
|
||||
github.com/chromedp/cdproto v0.0.0-20190812224334-39ef923dcb8d/go.mod h1:0YChpVzuLJC5CPr+x3xkHN6Z8KOSXjNbL7qV8Wc4GW0=
|
||||
github.com/chromedp/cdproto v0.0.0-20190926234355-1b4886c6fad6/go.mod h1:0YChpVzuLJC5CPr+x3xkHN6Z8KOSXjNbL7qV8Wc4GW0=
|
||||
github.com/chromedp/chromedp v0.3.1-0.20190619195644-fd957a4d2901/go.mod h1:mJdvfrVn594N9tfiPecUidF6W5jPRKHymqHfzbobPsM=
|
||||
github.com/chromedp/chromedp v0.4.0/go.mod h1:DC3QUn4mJ24dwjcaGQLoZrhm4X/uPHZ6spDbS2uFhm4=
|
||||
github.com/citilinkru/libudev v1.0.0 h1:upErSdhsJGdiKxwxPmvcz43fwJJD9R+y1j8BqU4wHog=
|
||||
github.com/citilinkru/libudev v1.0.0/go.mod h1:yaNdhdtfJMs5flqeXzUOMO0mT9QnyNh/U/jdY4WhA/I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/containrrr/shoutrrr v0.4.4 h1:vHZ4E/76pKVY+Jyn/qhBz3X540Bn8NI5ppPHK4PyILY=
|
||||
github.com/containrrr/shoutrrr v0.4.4/go.mod h1:zqL2BvfC1W4FujrT4b3/ZCLxvD+uoeEpBL7rg9Dqpbg=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU=
|
||||
github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
||||
github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gormigrate/gormigrate/v2 v2.0.0 h1:e2A3Uznk4viUC4UuemuVgsNnvYZyOA8B3awlYk3UioU=
|
||||
github.com/go-gormigrate/gormigrate/v2 v2.0.0/go.mod h1:YuVJ+D/dNt4HWrThTBnjgZuRbt7AuwINeg4q52ZE3Jw=
|
||||
github.com/go-interpreter/wagon v0.5.1-0.20190713202023-55a163980b6c/go.mod h1:5+b/MBYkclRZngKF5s6qrgWxSLgE9F5dFdO1hAueZLc=
|
||||
github.com/go-interpreter/wagon v0.6.0/go.mod h1:5+b/MBYkclRZngKF5s6qrgWxSLgE9F5dFdO1hAueZLc=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
|
||||
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
|
||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190908185732-236ed259b199/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.9.0 h1:1Ejxpt+cpWkadefxd5xvVx7pFgFaafdNp1ItfHzKRW4=
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.9.0/go.mod h1:x7Jo5UHHl+w8wu8UnGiNobDDHygojXwJX4mx7rXGKMk=
|
||||
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU=
|
||||
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
|
||||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
|
||||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
|
||||
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
|
||||
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
|
||||
github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk=
|
||||
github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
|
||||
github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
|
||||
github.com/jackc/pgconn v1.6.4 h1:S7T6cx5o2OqmxdHaXLH1ZeD1SbI8jBznyYE9Ec0RCQ8=
|
||||
github.com/jackc/pgconn v1.6.4/go.mod h1:w2pne1C2tZgP+TvjqLpOigGzNqjBgQW9dUw/4Chex78=
|
||||
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
|
||||
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.2 h1:q1Hsy66zh4vuNsajBUF2PNqfAMMfxU5mk594lPE9vjY=
|
||||
github.com/jackc/pgproto3/v2 v2.0.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
|
||||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
|
||||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
||||
github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0=
|
||||
github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po=
|
||||
github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ=
|
||||
github.com/jackc/pgtype v1.4.2 h1:t+6LWm5eWPLX1H5Se702JSBcirq6uWa4jiG4wV1rAWY=
|
||||
github.com/jackc/pgtype v1.4.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
||||
github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA=
|
||||
github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o=
|
||||
github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg=
|
||||
github.com/jackc/pgx/v4 v4.8.1 h1:SUbCLP2pXvf/Sr/25KsuI4aTxiFYIvpfk4l6aTSdyCw=
|
||||
github.com/jackc/pgx/v4 v4.8.1/go.mod h1:4HOLxrl8wToZJReD04/yB20GDwf4KBYETvlHciCnwW0=
|
||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jarcoal/httpmock v1.0.4 h1:jp+dy/+nonJE4g4xbVtl9QdrUNbn6/3hDT5R4nDIZnA=
|
||||
github.com/jarcoal/httpmock v1.0.4/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||
github.com/jaypipes/ghw v0.6.1 h1:Ewt3mdpiyhWotGyzg1ursV/6SnToGcG4215X6rR2af8=
|
||||
github.com/jaypipes/ghw v0.6.1/go.mod h1:QOXppNRCLGYR1H+hu09FxZPqjNt09bqUZUnOL3Rcero=
|
||||
github.com/jaypipes/pcidb v0.5.0 h1:4W5gZ+G7QxydevI8/MmmKdnIPJpURqJ2JNXTzfLxF5c=
|
||||
github.com/jaypipes/pcidb v0.5.0/go.mod h1:L2RGk04sfRhp5wvHO0gfRAMoLY/F3PKv/nwJeVoho0o=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
|
||||
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
|
||||
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.12.1 h1:/+xsCsk06wE38cyiqOR/o7U2fSftcH72xD+BQXmja/g=
|
||||
github.com/klauspost/compress v1.12.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/knq/sysutil v0.0.0-20181215143952-f05b59f0f307/go.mod h1:BjPj+aVjl9FW/cCGiF3nGh5v+9Gd3VCgBQbod/GlMaQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kvz/logstreamer v0.0.0-20150507115422-a635b98146f0 h1:3tLzEnUizyN9YLWFTT9loC30lSBvh2y70LTDcZOTs1s=
|
||||
github.com/kvz/logstreamer v0.0.0-20150507115422-a635b98146f0/go.mod h1:8/LTPeDLaklcUjgSQBHbhBF1ibKAFxzS5o+H7USfMSA=
|
||||
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190620125010-da37f6c1e481/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||
github.com/mattn/go-sqlite3 v1.14.4 h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI=
|
||||
github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.2.2 h1:dxe5oCinTXiTIcfgmZecdCzPmAJKd46KsCWc35r0TV4=
|
||||
github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.6/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.1 h1:foqVmeWDD6yYpK+Yz3fHyNIxFYNxswxqNFjSKe+vI54=
|
||||
github.com/onsi/ginkgo v1.16.1/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
|
||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
|
||||
github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc/go.mod h1:NoCfSFWosfqMqmmD7hApkirIK9ozpHjxRnRxs1l413A=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4=
|
||||
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
go.coder.com/go-tools v0.0.0-20190317003359-0c6a35b74a16/go.mod h1:iKV5yK9t+J5nG9O3uF6KYdPEz3dyfMyB15MN1rbQ8Qw=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180426230345-b49d69b5da94/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190306220234-b354f8bf4d9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190618155005-516e3c20635f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190927073244-c990c680b611/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ=
|
||||
gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gorm.io/driver/mysql v1.0.1 h1:omJoilUzyrAp0xNoio88lGJCroGdIOen9hq2A/+3ifw=
|
||||
gorm.io/driver/mysql v1.0.1/go.mod h1:KtqSthtg55lFp3S5kUXqlGaelnWpKitn4k1xZTnoiPw=
|
||||
gorm.io/driver/postgres v1.0.0 h1:Yh4jyFQ0a7F+JPU0Gtiam/eKmpT/XFc1FKxotGqc6FM=
|
||||
gorm.io/driver/postgres v1.0.0/go.mod h1:wtMFcOzmuA5QigNsgEIb7O5lhvH1tHAF1RbWmLWV4to=
|
||||
gorm.io/driver/sqlite v1.1.1/go.mod h1:hm2olEcl8Tmsc6eZyxYSeznnsDaMqamBvEXLNtBg4cI=
|
||||
gorm.io/driver/sqlite v1.1.3 h1:BYfdVuZB5He/u9dt4qDpZqiqDJ6KhPqs5QUqsr/Eeuc=
|
||||
gorm.io/driver/sqlite v1.1.3/go.mod h1:AKDgRWk8lcSQSw+9kxCJnX/yySj8G3rdwYlU57cB45c=
|
||||
gorm.io/driver/sqlserver v1.0.2 h1:FzxAlw0/7hntMzSiNfotpYCo9Lz8dqWQGdmCGqIiFGo=
|
||||
gorm.io/driver/sqlserver v1.0.2/go.mod h1:gb0Y9QePGgqjzrVyTQUZeh9zkd5v0iz71cM1B4ZycEY=
|
||||
gorm.io/gorm v1.9.19/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
gorm.io/gorm v1.20.0/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
gorm.io/gorm v1.20.2 h1:bZzSEnq7NDGsrd+n3evOOedDrY5oLM5QPlCjZJUK2ro=
|
||||
gorm.io/gorm v1.20.2/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
gosrc.io/xmpp v0.5.1 h1:Rgrm5s2rt+npGggJH3HakQxQXR8ZZz3+QRzakRQqaq4=
|
||||
gosrc.io/xmpp v0.5.1/go.mod h1:L3NFMqYOxyLz3JGmgFyWf7r9htE91zVGiK40oW4RwdY=
|
||||
gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gotest.tools/gotestsum v0.3.5/go.mod h1:Mnf3e5FUzXbkCfynWBGOwLssY7gTQgCHObK9tMpAriY=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M=
|
||||
howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
|
||||
mvdan.cc/sh v2.6.4+incompatible/go.mod h1:IeeQbZq+x2SUGBensq/jge5lLQbS3XT2ktyp3wrt4x8=
|
||||
nhooyr.io/websocket v1.6.5/go.mod h1:F259lAzPRAH0htX2y3ehpJe09ih1aSHN7udWki1defY=
|
||||
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
|
||||
nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
|
||||
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
+2
-14
@@ -1,18 +1,6 @@
|
||||
---
|
||||
engine_enable_code_mutation: true
|
||||
engine_cmd_compile:
|
||||
- go build -ldflags '-w -extldflags "-static"' -o scrutiny webapp/backend/cmd/scrutiny/scrutiny.go
|
||||
- 'GOOS=linux GOARCH=amd64 go build -ldflags "-X main.goos=linux -X main.goarch=amd64" -o scrutiny-web-linux-amd64 -tags "static" webapp/backend/cmd/scrutiny/scrutiny.go'
|
||||
- 'chmod +x scrutiny-web-linux-amd64'
|
||||
- 'GOOS=linux GOARCH=amd64 go build -ldflags "-X main.goos=linux -X main.goarch=amd64" -o scrutiny-collector-metrics-linux-amd64 -tags "static" collector/cmd/collector-metrics/collector-metrics.go'
|
||||
- 'chmod +x scrutiny-collector-metrics-linux-amd64'
|
||||
mgr_keep_lock_file: true
|
||||
engine_version_metadata_path: 'webapp/backend/pkg/version/version.go'
|
||||
engine_cmd_test: 'go test -v -tags "static" $(go list ./... | grep -v /vendor/)'
|
||||
engine_golang_package_path: 'github.com/analogj/scrutiny'
|
||||
scm_enable_branch_cleanup: true
|
||||
engine_disable_lint: true
|
||||
scm_release_assets:
|
||||
- local_path: scrutiny-web-linux-amd64
|
||||
artifact_name: scrutiny-web-linux-amd64
|
||||
- local_path: scrutiny-collector-metrics-linux-amd64
|
||||
artifact_name: scrutiny-collector-metrics-linux-amd64
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
|
||||
COLLECTOR_CRON_SCHEDULE=${COLLECTOR_CRON_SCHEDULE:-"0 0 * * *"}
|
||||
sed -i 's|{COLLECTOR_CRON_SCHEDULE}|'"${COLLECTOR_CRON_SCHEDULE}"'|g' /etc/cron.d/scrutiny
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
|
||||
# Cron runs in its own isolated environment (usually using only /etc/environment )
|
||||
# So when the container starts up, we will do a dump of the runtime environment into a .env file that we
|
||||
# will then source into the crontab file (/etc/cron.d/scrutiny)
|
||||
(set -o posix; export -p) > /env.sh
|
||||
|
||||
# adding ability to customize the cron schedule.
|
||||
COLLECTOR_CRON_SCHEDULE=${COLLECTOR_CRON_SCHEDULE:-"0 0 * * *"}
|
||||
|
||||
# if the cron schedule has been overridden via env variable (eg docker-compose) we should make sure to strip quotes
|
||||
[[ "${COLLECTOR_CRON_SCHEDULE}" == \"*\" || "${COLLECTOR_CRON_SCHEDULE}" == \'*\' ]] && COLLECTOR_CRON_SCHEDULE="${COLLECTOR_CRON_SCHEDULE:1:-1}"
|
||||
|
||||
# replace placeholder with correct value
|
||||
sed -i 's|{COLLECTOR_CRON_SCHEDULE}|'"${COLLECTOR_CRON_SCHEDULE}"'|g' /etc/cron.d/scrutiny
|
||||
@@ -9,5 +9,5 @@ s6-svc -O /var/run/s6/services/collector-once
|
||||
# wait until scrutiny is "Ready"
|
||||
until $(curl --output /dev/null --silent --head --fail http://localhost:8080/api/health); do echo "scrutiny api not ready" && sleep 5; done
|
||||
|
||||
echo "starting scrutiny collector"
|
||||
echo "starting scrutiny collector (run-once mode. subsequent calls will be triggered via cron service)"
|
||||
/opt/scrutiny/bin/scrutiny-collector-metrics run
|
||||
|
||||
Regular → Executable
+1
-7
@@ -1,10 +1,4 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
|
||||
# Cron runs in its own isolated environment (usually using only /etc/environment )
|
||||
# So when the container starts up, we will do a dump of the runtime environment into a .env file that we
|
||||
# will then source into the crontab file (/etc/cron.d/scrutiny.sh)
|
||||
|
||||
printenv | sed 's/^\(.*\)$/export \1/g' > /env.sh
|
||||
|
||||
echo "starting cron"
|
||||
cron -f
|
||||
cron -f -L 15
|
||||
|
||||
@@ -39,12 +39,14 @@ func (c *configuration) Init() error {
|
||||
|
||||
c.SetDefault("notify.urls", []string{})
|
||||
|
||||
c.SetDefault("web.influxdb.host", "0.0.0.0")
|
||||
c.SetDefault("web.influxdb.scheme", "http")
|
||||
c.SetDefault("web.influxdb.host", "localhost")
|
||||
c.SetDefault("web.influxdb.port", "8086")
|
||||
c.SetDefault("web.influxdb.org", "scrutiny")
|
||||
c.SetDefault("web.influxdb.bucket", "metrics")
|
||||
c.SetDefault("web.influxdb.init_username", "admin")
|
||||
c.SetDefault("web.influxdb.init_password", "password12345")
|
||||
c.SetDefault("web.influxdb.token", "scrutiny-default-admin-token")
|
||||
c.SetDefault("web.influxdb.retention_policy", true)
|
||||
|
||||
//c.SetDefault("disks.include", []string{})
|
||||
|
||||
@@ -19,6 +19,7 @@ type DeviceRepo interface {
|
||||
UpdateDevice(ctx context.Context, wwn string, collectorSmartData collector.SmartInfo) (models.Device, error)
|
||||
UpdateDeviceStatus(ctx context.Context, wwn string, status pkg.DeviceStatus) (models.Device, error)
|
||||
GetDeviceDetails(ctx context.Context, wwn string) (models.Device, error)
|
||||
DeleteDevice(ctx context.Context, wwn string) error
|
||||
|
||||
SaveSmartAttributes(ctx context.Context, wwn string, collectorSmartData collector.SmartInfo) (measurements.Smart, error)
|
||||
GetSmartAttributeHistory(ctx context.Context, wwn string, durationKey string, attributes []string) ([]measurements.Smart, error)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Deprecated: m20220503120000.Device is deprecated, only used by db migrations
|
||||
type Device struct {
|
||||
//GORM attributes, see: http://gorm.io/docs/conventions.html
|
||||
CreatedAt time.Time
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package m20220509170100
|
||||
|
||||
import (
|
||||
"github.com/analogj/scrutiny/webapp/backend/pkg"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Device struct {
|
||||
//GORM attributes, see: http://gorm.io/docs/conventions.html
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt *time.Time
|
||||
|
||||
WWN string `json:"wwn" gorm:"primary_key"`
|
||||
|
||||
DeviceName string `json:"device_name"`
|
||||
DeviceUUID string `json:"device_uuid"`
|
||||
DeviceSerialID string `json:"device_serial_id"`
|
||||
DeviceLabel string `json:"device_label"`
|
||||
|
||||
Manufacturer string `json:"manufacturer"`
|
||||
ModelName string `json:"model_name"`
|
||||
InterfaceType string `json:"interface_type"`
|
||||
InterfaceSpeed string `json:"interface_speed"`
|
||||
SerialNumber string `json:"serial_number"`
|
||||
Firmware string `json:"firmware"`
|
||||
RotationSpeed int `json:"rotational_speed"`
|
||||
Capacity int64 `json:"capacity"`
|
||||
FormFactor string `json:"form_factor"`
|
||||
SmartSupport bool `json:"smart_support"`
|
||||
DeviceProtocol string `json:"device_protocol"` //protocol determines which smart attribute types are available (ATA, NVMe, SCSI)
|
||||
DeviceType string `json:"device_type"` //device type is used for querying with -d/t flag, should only be used by collector.
|
||||
|
||||
// User provided metadata
|
||||
Label string `json:"label"`
|
||||
HostId string `json:"host_id"`
|
||||
|
||||
// Data set by Scrutiny
|
||||
DeviceStatus pkg.DeviceStatus `json:"device_status"`
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/analogj/scrutiny/webapp/backend/pkg/config"
|
||||
"github.com/analogj/scrutiny/webapp/backend/pkg/models"
|
||||
@@ -11,6 +12,9 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -75,36 +79,38 @@ func NewScrutinyRepository(appConfig config.Interface, globalLogger logrus.Field
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Create a new client using an InfluxDB server base URL and an authentication token
|
||||
influxdbUrl := fmt.Sprintf("http://%s:%s", appConfig.GetString("web.influxdb.host"), appConfig.GetString("web.influxdb.port"))
|
||||
influxdbUrl := fmt.Sprintf("%s://%s:%s", appConfig.GetString("web.influxdb.scheme"), appConfig.GetString("web.influxdb.host"), appConfig.GetString("web.influxdb.port"))
|
||||
globalLogger.Debugf("InfluxDB url: %s", influxdbUrl)
|
||||
|
||||
client := influxdb2.NewClient(influxdbUrl, appConfig.GetString("web.influxdb.token"))
|
||||
|
||||
if !appConfig.IsSet("web.influxdb.token") {
|
||||
globalLogger.Debugf("No influxdb token found, running first-time setup...")
|
||||
//if !appConfig.IsSet("web.influxdb.token") {
|
||||
globalLogger.Debugf("Determine Influxdb setup status...")
|
||||
influxSetupComplete, err := InfluxSetupComplete(influxdbUrl)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to check influxdb setup status - %w", err)
|
||||
}
|
||||
|
||||
if !influxSetupComplete {
|
||||
globalLogger.Debugf("Influxdb un-initialized, running first-time setup...")
|
||||
|
||||
// if no token is provided, but we have a valid server, we're going to assume this is the first setup of our server.
|
||||
// we will initialize with a predetermined username & password, that you should change.
|
||||
|
||||
// metrics bucket will have a retention period of 8 days (since it will be down-sampled once a week)
|
||||
// in seconds (60seconds * 60minutes * 24hours * 15 days) = 1_296_000 (see EnsureBucket() function)
|
||||
onboardingResponse, err := client.Setup(
|
||||
_, err := client.SetupWithToken(
|
||||
backgroundContext,
|
||||
appConfig.GetString("web.influxdb.init_username"),
|
||||
appConfig.GetString("web.influxdb.init_password"),
|
||||
appConfig.GetString("web.influxdb.org"),
|
||||
appConfig.GetString("web.influxdb.bucket"),
|
||||
0)
|
||||
0,
|
||||
appConfig.GetString("web.influxdb.token"),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appConfig.Set("web.influxdb.token", *onboardingResponse.Auth.Token)
|
||||
// we should write the config file out here. Ignore failures.
|
||||
err = appConfig.WriteConfig()
|
||||
if err != nil {
|
||||
globalLogger.Infof("ignoring error while writing influxdb info to config: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Use blocking write client for writes to desired bucket
|
||||
@@ -176,6 +182,37 @@ func (sr *scrutinyRepository) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func InfluxSetupComplete(influxEndpoint string) (bool, error) {
|
||||
influxUri, err := url.Parse(influxEndpoint)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
influxUri, err = influxUri.Parse("/api/v2/setup")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
res, err := http.Get(influxUri.String())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
type SetupStatus struct {
|
||||
Allowed bool `json:"allowed"`
|
||||
}
|
||||
var data SetupStatus
|
||||
err = json.Unmarshal(body, &data)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return !data.Allowed, nil
|
||||
}
|
||||
|
||||
func (sr *scrutinyRepository) EnsureBuckets(ctx context.Context, org *domain.Organization) error {
|
||||
|
||||
var mainBucketRetentionRule domain.RetentionRule
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/analogj/scrutiny/webapp/backend/pkg/models"
|
||||
"github.com/analogj/scrutiny/webapp/backend/pkg/models/collector"
|
||||
"gorm.io/gorm/clause"
|
||||
"time"
|
||||
)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -18,7 +19,7 @@ import (
|
||||
func (sr *scrutinyRepository) RegisterDevice(ctx context.Context, dev models.Device) error {
|
||||
if err := sr.gormClient.WithContext(ctx).Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "wwn"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"host_id", "device_name", "device_type"}),
|
||||
DoUpdates: clause.AssignmentColumns([]string{"host_id", "device_name", "device_type", "device_uuid", "device_serial_id", "device_label"}),
|
||||
}).Create(&dev).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -72,3 +73,33 @@ func (sr *scrutinyRepository) GetDeviceDetails(ctx context.Context, wwn string)
|
||||
|
||||
return device, nil
|
||||
}
|
||||
|
||||
func (sr *scrutinyRepository) DeleteDevice(ctx context.Context, wwn string) error {
|
||||
if err := sr.gormClient.WithContext(ctx).Where("wwn = ?", wwn).Delete(&models.Device{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//delete data from influxdb.
|
||||
buckets := []string{
|
||||
sr.appConfig.GetString("web.influxdb.bucket"),
|
||||
fmt.Sprintf("%s_weekly", sr.appConfig.GetString("web.influxdb.bucket")),
|
||||
fmt.Sprintf("%s_monthly", sr.appConfig.GetString("web.influxdb.bucket")),
|
||||
fmt.Sprintf("%s_yearly", sr.appConfig.GetString("web.influxdb.bucket")),
|
||||
}
|
||||
|
||||
for _, bucket := range buckets {
|
||||
sr.logger.Infof("Deleting data for %s in bucket: %s", wwn, bucket)
|
||||
if err := sr.influxClient.DeleteAPI().DeleteWithName(
|
||||
ctx,
|
||||
sr.appConfig.GetString("web.influxdb.org"),
|
||||
bucket,
|
||||
time.Now().AddDate(-10, 0, 0),
|
||||
time.Now(),
|
||||
fmt.Sprintf(`device_wwn="%s"`, wwn),
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,14 +2,18 @@ package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/analogj/scrutiny/webapp/backend/pkg/database/migrations/m20201107210306"
|
||||
"github.com/analogj/scrutiny/webapp/backend/pkg/database/migrations/m20220503120000"
|
||||
"github.com/analogj/scrutiny/webapp/backend/pkg/database/migrations/m20220509170100"
|
||||
"github.com/analogj/scrutiny/webapp/backend/pkg/models"
|
||||
"github.com/analogj/scrutiny/webapp/backend/pkg/models/collector"
|
||||
"github.com/analogj/scrutiny/webapp/backend/pkg/models/measurements"
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"github.com/influxdata/influxdb-client-go/v2/api/http"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -22,9 +26,12 @@ import (
|
||||
|
||||
func (sr *scrutinyRepository) Migrate(ctx context.Context) error {
|
||||
|
||||
sr.logger.Infoln("Database migration starting")
|
||||
sr.logger.Infoln("Database migration starting. Please wait, this process may take a long time....")
|
||||
|
||||
m := gormigrate.New(sr.gormClient, gormigrate.DefaultOptions, []*gormigrate.Migration{
|
||||
gormMigrateOptions := gormigrate.DefaultOptions
|
||||
gormMigrateOptions.UseTransaction = true
|
||||
|
||||
m := gormigrate.New(sr.gormClient, gormMigrateOptions, []*gormigrate.Migration{
|
||||
{
|
||||
ID: "20201107210306", // v0.3.13 (pre-influxdb schema). 9fac3c6308dc6cb6cd5bbc43a68cd93e8fb20b87
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
@@ -38,16 +45,6 @@ func (sr *scrutinyRepository) Migrate(ctx context.Context) error {
|
||||
&m20201107210306.SmartNvmeAttribute{},
|
||||
)
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
return tx.Migrator().DropTable(
|
||||
&m20201107210306.Device{},
|
||||
&m20201107210306.Smart{},
|
||||
&m20201107210306.SmartAtaAttribute{},
|
||||
&m20201107210306.SmartNvmeAttribute{},
|
||||
&m20201107210306.SmartNvmeAttribute{},
|
||||
"self_tests",
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "20220503113100", // backwards compatible - influxdb schema
|
||||
@@ -137,7 +134,7 @@ func (sr *scrutinyRepository) Migrate(ctx context.Context) error {
|
||||
smartTags,
|
||||
smartFields,
|
||||
postSmartResults.Date, ctx)
|
||||
if err != nil {
|
||||
if ignorePastRetentionPolicyError(err) != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -147,7 +144,7 @@ func (sr *scrutinyRepository) Migrate(ctx context.Context) error {
|
||||
tempTags,
|
||||
tempFields,
|
||||
postSmartResults.Date, ctx)
|
||||
if err != nil {
|
||||
if ignorePastRetentionPolicyError(err) != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -166,7 +163,7 @@ func (sr *scrutinyRepository) Migrate(ctx context.Context) error {
|
||||
smartFields,
|
||||
postSmartResults.Date, ctx)
|
||||
|
||||
if err != nil {
|
||||
if ignorePastRetentionPolicyError(err) != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -176,7 +173,7 @@ func (sr *scrutinyRepository) Migrate(ctx context.Context) error {
|
||||
tempTags,
|
||||
tempFields,
|
||||
postSmartResults.Date, ctx)
|
||||
if err != nil {
|
||||
if ignorePastRetentionPolicyError(err) != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -194,7 +191,7 @@ func (sr *scrutinyRepository) Migrate(ctx context.Context) error {
|
||||
smartTags,
|
||||
smartFields,
|
||||
postSmartResults.Date, ctx)
|
||||
if err != nil {
|
||||
if ignorePastRetentionPolicyError(err) != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -204,7 +201,7 @@ func (sr *scrutinyRepository) Migrate(ctx context.Context) error {
|
||||
tempTags,
|
||||
tempFields,
|
||||
postSmartResults.Date, ctx)
|
||||
if err != nil {
|
||||
if ignorePastRetentionPolicyError(err) != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -221,7 +218,7 @@ func (sr *scrutinyRepository) Migrate(ctx context.Context) error {
|
||||
smartTags,
|
||||
smartFields,
|
||||
postSmartResults.Date, ctx)
|
||||
if err != nil {
|
||||
if ignorePastRetentionPolicyError(err) != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -231,7 +228,7 @@ func (sr *scrutinyRepository) Migrate(ctx context.Context) error {
|
||||
tempTags,
|
||||
tempFields,
|
||||
postSmartResults.Date, ctx)
|
||||
if err != nil {
|
||||
if ignorePastRetentionPolicyError(err) != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -257,20 +254,44 @@ func (sr *scrutinyRepository) Migrate(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
//migrate the device database to the current version
|
||||
//migrate the device database
|
||||
return tx.AutoMigrate(m20220503120000.Device{})
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "m20220509170100", // addl udev device data
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
|
||||
//migrate the device database.
|
||||
// adding addl columns (device_label, device_uuid, device_serial_id)
|
||||
return tx.AutoMigrate(m20220509170100.Device{})
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if err := m.Migrate(); err != nil {
|
||||
sr.logger.Errorf("Database migration failed with error: %w", err)
|
||||
sr.logger.Errorf("Database migration failed with error. \n Please open a github issue at https://github.com/AnalogJ/scrutiny and attach a copy of your scrutiny.db file. \n %v", err)
|
||||
return err
|
||||
}
|
||||
sr.logger.Infoln("Database migration completed successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
// helpers
|
||||
|
||||
//When adding data to influxdb, an error may be returned if the data point is outside the range of the retention policy.
|
||||
//This function will ignore retention policy errors, and allow the migration to continue.
|
||||
func ignorePastRetentionPolicyError(err error) error {
|
||||
var influxDbWriteError *http.Error
|
||||
if errors.As(err, &influxDbWriteError) {
|
||||
if influxDbWriteError.StatusCode == 422 {
|
||||
log.Infoln("ignoring error: attempted to writePoint past retention period duration")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
func m20201107210306_FromPreInfluxDBTempCreatePostInfluxDBTemp(preDevice m20201107210306.Device, preSmartResult m20201107210306.Smart) (error, measurements.SmartTemperature) {
|
||||
//extract temperature data for every datapoint
|
||||
|
||||
@@ -21,6 +21,10 @@ type Device struct {
|
||||
WWN string `json:"wwn" gorm:"primary_key"`
|
||||
|
||||
DeviceName string `json:"device_name"`
|
||||
DeviceUUID string `json:"device_uuid"`
|
||||
DeviceSerialID string `json:"device_serial_id"`
|
||||
DeviceLabel string `json:"device_label"`
|
||||
|
||||
Manufacturer string `json:"manufacturer"`
|
||||
ModelName string `json:"model_name"`
|
||||
InterfaceType string `json:"interface_type"`
|
||||
|
||||
@@ -171,7 +171,7 @@ func (sm *Smart) ProcessNvmeSmartInfo(nvmeSmartHealthInformationLog collector.Nv
|
||||
"power_on_hours": (&SmartNvmeAttribute{AttributeId: "power_on_hours", Value: nvmeSmartHealthInformationLog.PowerOnHours, Threshold: -1}).PopulateAttributeStatus(),
|
||||
"unsafe_shutdowns": (&SmartNvmeAttribute{AttributeId: "unsafe_shutdowns", Value: nvmeSmartHealthInformationLog.UnsafeShutdowns, Threshold: -1}).PopulateAttributeStatus(),
|
||||
"media_errors": (&SmartNvmeAttribute{AttributeId: "media_errors", Value: nvmeSmartHealthInformationLog.MediaErrors, Threshold: 0}).PopulateAttributeStatus(),
|
||||
"num_err_log_entries": (&SmartNvmeAttribute{AttributeId: "num_err_log_entries", Value: nvmeSmartHealthInformationLog.NumErrLogEntries, Threshold: 0}).PopulateAttributeStatus(),
|
||||
"num_err_log_entries": (&SmartNvmeAttribute{AttributeId: "num_err_log_entries", Value: nvmeSmartHealthInformationLog.NumErrLogEntries, Threshold: -1}).PopulateAttributeStatus(),
|
||||
"warning_temp_time": (&SmartNvmeAttribute{AttributeId: "warning_temp_time", Value: nvmeSmartHealthInformationLog.WarningTempTime, Threshold: -1}).PopulateAttributeStatus(),
|
||||
"critical_comp_time": (&SmartNvmeAttribute{AttributeId: "critical_comp_time", Value: nvmeSmartHealthInformationLog.CriticalCompTime, Threshold: -1}).PopulateAttributeStatus(),
|
||||
}
|
||||
|
||||
@@ -93,6 +93,8 @@ func (sa *SmartAtaAttribute) PopulateAttributeStatus() *SmartAtaAttribute {
|
||||
//this attribute has previously failed
|
||||
sa.Status = pkg.SmartAttributeStatusFailed
|
||||
sa.StatusReason = "Attribute is failing manufacturer SMART threshold"
|
||||
//if the Smart Status is failed, we should exit early, no need to look at thresholds.
|
||||
return sa
|
||||
|
||||
} else if strings.ToUpper(sa.WhenFailed) == pkg.SmartWhenFailedInThePast {
|
||||
sa.Status = pkg.SmartAttributeStatusWarning
|
||||
|
||||
@@ -381,6 +381,70 @@ func TestFromCollectorSmartInfo_Fail_ScrutinySmart(t *testing.T) {
|
||||
require.Equal(t, 17, len(smartMdl.Attributes))
|
||||
}
|
||||
|
||||
func TestFromCollectorSmartInfo_Fail_ScrutinyNonCriticalFailed(t *testing.T) {
|
||||
//setup
|
||||
smartDataFile, err := os.Open("../testdata/smart-ata-failed-scrutiny.json")
|
||||
require.NoError(t, err)
|
||||
defer smartDataFile.Close()
|
||||
|
||||
var smartJson collector.SmartInfo
|
||||
|
||||
smartDataBytes, err := ioutil.ReadAll(smartDataFile)
|
||||
require.NoError(t, err)
|
||||
err = json.Unmarshal(smartDataBytes, &smartJson)
|
||||
require.NoError(t, err)
|
||||
|
||||
//test
|
||||
smartMdl := measurements.Smart{}
|
||||
err = smartMdl.FromCollectorSmartInfo("WWN-test", smartJson)
|
||||
|
||||
//assert
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "WWN-test", smartMdl.DeviceWWN)
|
||||
require.Equal(t, pkg.DeviceStatusFailedScrutiny, smartMdl.Status)
|
||||
require.Equal(t, int64(pkg.SmartAttributeStatusFailed), smartMdl.Attributes["199"].GetStatus(),
|
||||
"scrutiny should detect that %d failed (status: %d, %s)",
|
||||
smartMdl.Attributes["199"].(*measurements.SmartAtaAttribute).AttributeId,
|
||||
smartMdl.Attributes["199"].GetStatus(), smartMdl.Attributes["199"].(*measurements.SmartAtaAttribute).StatusReason,
|
||||
)
|
||||
|
||||
require.Equal(t, 14, len(smartMdl.Attributes))
|
||||
}
|
||||
|
||||
//TODO: Scrutiny Warn
|
||||
//TODO: Smart + Scrutiny Warn
|
||||
|
||||
func TestFromCollectorSmartInfo_NVMe_Fail_Scrutiny(t *testing.T) {
|
||||
//setup
|
||||
smartDataFile, err := os.Open("../testdata/smart-nvme-failed.json")
|
||||
require.NoError(t, err)
|
||||
defer smartDataFile.Close()
|
||||
|
||||
var smartJson collector.SmartInfo
|
||||
|
||||
smartDataBytes, err := ioutil.ReadAll(smartDataFile)
|
||||
require.NoError(t, err)
|
||||
err = json.Unmarshal(smartDataBytes, &smartJson)
|
||||
require.NoError(t, err)
|
||||
|
||||
//test
|
||||
smartMdl := measurements.Smart{}
|
||||
err = smartMdl.FromCollectorSmartInfo("WWN-test", smartJson)
|
||||
|
||||
//assert
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "WWN-test", smartMdl.DeviceWWN)
|
||||
require.Equal(t, pkg.DeviceStatusFailedScrutiny, smartMdl.Status)
|
||||
require.Equal(t, int64(pkg.SmartAttributeStatusFailed), smartMdl.Attributes["media_errors"].GetStatus(),
|
||||
"scrutiny should detect that %s failed (status: %d, %s)",
|
||||
smartMdl.Attributes["media_errors"].(*measurements.SmartNvmeAttribute).AttributeId,
|
||||
smartMdl.Attributes["media_errors"].GetStatus(),
|
||||
smartMdl.Attributes["media_errors"].(*measurements.SmartNvmeAttribute).StatusReason,
|
||||
)
|
||||
|
||||
require.Equal(t, 16, len(smartMdl.Attributes))
|
||||
}
|
||||
|
||||
func TestFromCollectorSmartInfo_Nvme(t *testing.T) {
|
||||
//setup
|
||||
smartDataFile, err := os.Open("../testdata/smart-nvme.json")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"json_format_version": [
|
||||
1,
|
||||
0
|
||||
],
|
||||
"smartctl": {
|
||||
"version": [
|
||||
7,
|
||||
0
|
||||
],
|
||||
"svn_revision": "4883",
|
||||
"platform_info": "x86_64-linux-5.13.0-40-generic",
|
||||
"build_info": "(local build)",
|
||||
"argv": [
|
||||
"smartctl",
|
||||
"-x",
|
||||
"-j",
|
||||
"/dev/nvme0"
|
||||
],
|
||||
"exit_status": 0
|
||||
},
|
||||
"device": {
|
||||
"name": "/dev/nvme0",
|
||||
"info_name": "/dev/nvme0",
|
||||
"type": "nvme",
|
||||
"protocol": "NVMe"
|
||||
},
|
||||
"model_name": "Samsung SSD 970 EVO 500GB",
|
||||
"serial_number": "S466NX0M776250H",
|
||||
"firmware_version": "2B2QEXE7",
|
||||
"nvme_pci_vendor": {
|
||||
"id": 5197,
|
||||
"subsystem_id": 5197
|
||||
},
|
||||
"nvme_ieee_oui_identifier": 9528,
|
||||
"nvme_total_capacity": 500107862016,
|
||||
"nvme_unallocated_capacity": 0,
|
||||
"nvme_controller_id": 4,
|
||||
"nvme_number_of_namespaces": 1,
|
||||
"nvme_namespaces": [
|
||||
{
|
||||
"id": 1,
|
||||
"size": {
|
||||
"blocks": 976773168,
|
||||
"bytes": 500107862016
|
||||
},
|
||||
"capacity": {
|
||||
"blocks": 976773168,
|
||||
"bytes": 500107862016
|
||||
},
|
||||
"utilization": {
|
||||
"blocks": 327275384,
|
||||
"bytes": 167564996608
|
||||
},
|
||||
"formatted_lba_size": 512,
|
||||
"eui64": {
|
||||
"oui": 9528,
|
||||
"ext_id": 376106710327
|
||||
}
|
||||
}
|
||||
],
|
||||
"user_capacity": {
|
||||
"blocks": 976773168,
|
||||
"bytes": 500107862016
|
||||
},
|
||||
"logical_block_size": 512,
|
||||
"local_time": {
|
||||
"time_t": 1652220188,
|
||||
"asctime": "Tue May 10 22:03:08 2022 UTC"
|
||||
},
|
||||
"smart_status": {
|
||||
"passed": true,
|
||||
"nvme": {
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"nvme_smart_health_information_log": {
|
||||
"critical_warning": 0,
|
||||
"temperature": 35,
|
||||
"available_spare": 99,
|
||||
"available_spare_threshold": 10,
|
||||
"percentage_used": 3,
|
||||
"data_units_read": 17176794,
|
||||
"data_units_written": 65602088,
|
||||
"host_reads": 118020838,
|
||||
"host_writes": 874050000,
|
||||
"controller_busy_time": 7601,
|
||||
"power_cycles": 25,
|
||||
"power_on_hours": 12798,
|
||||
"unsafe_shutdowns": 10,
|
||||
"media_errors": 7,
|
||||
"num_err_log_entries": 62,
|
||||
"warning_temp_time": 0,
|
||||
"critical_comp_time": 0,
|
||||
"temperature_sensors": [
|
||||
35,
|
||||
39
|
||||
]
|
||||
},
|
||||
"temperature": {
|
||||
"current": 35
|
||||
},
|
||||
"power_cycle_count": 25,
|
||||
"power_on_time": {
|
||||
"hours": 12798
|
||||
}
|
||||
}
|
||||
@@ -445,50 +445,6 @@ var AtaMetadata = map[int]AtaAttributeMetadata{
|
||||
Ideal: ObservedThresholdIdealLow,
|
||||
Critical: false,
|
||||
Description: "This attribute indicates the count of full hard disk power on/off cycles.",
|
||||
ObservedThresholds: []ObservedThreshold{
|
||||
{
|
||||
Low: 0,
|
||||
High: 13,
|
||||
AnnualFailureRate: 0.019835987118930823,
|
||||
ErrorInterval: []float64{0.016560870164523494, 0.023569242386797896},
|
||||
},
|
||||
{
|
||||
Low: 13,
|
||||
High: 26,
|
||||
AnnualFailureRate: 0.038210930067894826,
|
||||
ErrorInterval: []float64{0.03353859179329295, 0.0433520775718649},
|
||||
},
|
||||
{
|
||||
Low: 26,
|
||||
High: 39,
|
||||
AnnualFailureRate: 0.11053528307302571,
|
||||
ErrorInterval: []float64{0.09671061589521368, 0.1257816678419765},
|
||||
},
|
||||
{
|
||||
Low: 39,
|
||||
High: 52,
|
||||
AnnualFailureRate: 0.16831189443375036,
|
||||
ErrorInterval: []float64{0.1440976510675928, 0.19543066007594895},
|
||||
},
|
||||
{
|
||||
Low: 52,
|
||||
High: 65,
|
||||
AnnualFailureRate: 0.20630344262550107,
|
||||
ErrorInterval: []float64{0.1693965932069108, 0.2488633537247856},
|
||||
},
|
||||
{
|
||||
Low: 65,
|
||||
High: 78,
|
||||
AnnualFailureRate: 0.1030972634140512,
|
||||
ErrorInterval: []float64{0.06734655535304743, 0.15106137807407605},
|
||||
},
|
||||
{
|
||||
Low: 78,
|
||||
High: 91,
|
||||
AnnualFailureRate: 0.12354840389522469,
|
||||
ErrorInterval: []float64{0.06578432170016109, 0.21127153335749593},
|
||||
},
|
||||
},
|
||||
},
|
||||
13: {
|
||||
ID: 13,
|
||||
|
||||
@@ -2,4 +2,4 @@ package version
|
||||
|
||||
// VERSION is the app-global version string, which will be replaced with a
|
||||
// new value during packaging
|
||||
const VERSION = "0.4.2"
|
||||
const VERSION = "0.4.8"
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/analogj/scrutiny/webapp/backend/pkg/database"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func DeleteDevice(c *gin.Context) {
|
||||
logger := c.MustGet("LOGGER").(logrus.FieldLogger)
|
||||
deviceRepo := c.MustGet("DEVICE_REPOSITORY").(database.DeviceRepo)
|
||||
|
||||
err := deviceRepo.DeleteDevice(c, c.Param("wwn"))
|
||||
if err != nil {
|
||||
logger.Errorln("An error occurred while deleting device", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"success": true})
|
||||
}
|
||||
@@ -47,6 +47,8 @@ func (ae *AppEngine) Setup(logger logrus.FieldLogger) *gin.Engine {
|
||||
api.POST("/device/:wwn/smart", handler.UploadDeviceMetrics) //used by Collector to upload data
|
||||
api.POST("/device/:wwn/selftest", handler.UploadDeviceSelfTests)
|
||||
api.GET("/device/:wwn/details", handler.GetDeviceDetails) //used by Details
|
||||
api.DELETE("/device/:wwn", handler.DeleteDevice) //used by UI to delete device
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ func (suite *ServerTestSuite) TestHealthRoute() {
|
||||
fakeConfig.EXPECT().GetString("web.src.frontend.path").Return(parentPath).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.listen.basepath").Return(suite.Basepath).AnyTimes()
|
||||
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.scheme").Return("http").AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.port").Return("8086").AnyTimes()
|
||||
fakeConfig.EXPECT().IsSet("web.influxdb.token").Return(true).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.token").Return("my-super-secret-auth-token").AnyTimes()
|
||||
@@ -132,6 +133,7 @@ func (suite *ServerTestSuite) TestRegisterDevicesRoute() {
|
||||
fakeConfig.EXPECT().GetString("web.database.location").Return(path.Join(parentPath, "scrutiny_test.db")).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.src.frontend.path").Return(parentPath).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.listen.basepath").Return(suite.Basepath).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.scheme").Return("http").AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.port").Return("8086").AnyTimes()
|
||||
fakeConfig.EXPECT().IsSet("web.influxdb.token").Return(true).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.token").Return("my-super-secret-auth-token").AnyTimes()
|
||||
@@ -171,6 +173,7 @@ func (suite *ServerTestSuite) TestUploadDeviceMetricsRoute() {
|
||||
fakeConfig.EXPECT().GetString("web.database.location").AnyTimes().Return(path.Join(parentPath, "scrutiny_test.db"))
|
||||
fakeConfig.EXPECT().GetString("web.src.frontend.path").AnyTimes().Return(parentPath)
|
||||
fakeConfig.EXPECT().GetString("web.listen.basepath").Return(suite.Basepath).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.scheme").Return("http").AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.port").Return("8086").AnyTimes()
|
||||
fakeConfig.EXPECT().IsSet("web.influxdb.token").Return(true).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.token").Return("my-super-secret-auth-token").AnyTimes()
|
||||
@@ -219,6 +222,7 @@ func (suite *ServerTestSuite) TestPopulateMultiple() {
|
||||
fakeConfig.EXPECT().GetString("web.database.location").AnyTimes().Return(path.Join(parentPath, "scrutiny_test.db"))
|
||||
fakeConfig.EXPECT().GetString("web.src.frontend.path").AnyTimes().Return(parentPath)
|
||||
fakeConfig.EXPECT().GetString("web.listen.basepath").Return(suite.Basepath).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.scheme").Return("http").AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.port").Return("8086").AnyTimes()
|
||||
fakeConfig.EXPECT().IsSet("web.influxdb.token").Return(true).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.token").Return("my-super-secret-auth-token").AnyTimes()
|
||||
@@ -314,6 +318,7 @@ func (suite *ServerTestSuite) TestSendTestNotificationRoute_WebhookFailure() {
|
||||
fakeConfig.EXPECT().GetString("web.database.location").AnyTimes().Return(path.Join(parentPath, "scrutiny_test.db"))
|
||||
fakeConfig.EXPECT().GetString("web.src.frontend.path").AnyTimes().Return(parentPath)
|
||||
fakeConfig.EXPECT().GetString("web.listen.basepath").Return(suite.Basepath).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.scheme").Return("http").AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.port").Return("8086").AnyTimes()
|
||||
fakeConfig.EXPECT().IsSet("web.influxdb.token").Return(true).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.token").Return("my-super-secret-auth-token").AnyTimes()
|
||||
@@ -352,6 +357,7 @@ func (suite *ServerTestSuite) TestSendTestNotificationRoute_ScriptFailure() {
|
||||
fakeConfig.EXPECT().GetString("web.database.location").AnyTimes().Return(path.Join(parentPath, "scrutiny_test.db"))
|
||||
fakeConfig.EXPECT().GetString("web.src.frontend.path").AnyTimes().Return(parentPath)
|
||||
fakeConfig.EXPECT().GetString("web.listen.basepath").Return(suite.Basepath).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.scheme").Return("http").AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.port").Return("8086").AnyTimes()
|
||||
fakeConfig.EXPECT().IsSet("web.influxdb.token").Return(true).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.token").Return("my-super-secret-auth-token").AnyTimes()
|
||||
@@ -390,6 +396,7 @@ func (suite *ServerTestSuite) TestSendTestNotificationRoute_ScriptSuccess() {
|
||||
fakeConfig.EXPECT().GetString("web.database.location").AnyTimes().Return(path.Join(parentPath, "scrutiny_test.db"))
|
||||
fakeConfig.EXPECT().GetString("web.src.frontend.path").AnyTimes().Return(parentPath)
|
||||
fakeConfig.EXPECT().GetString("web.listen.basepath").Return(suite.Basepath).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.scheme").Return("http").AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.port").Return("8086").AnyTimes()
|
||||
fakeConfig.EXPECT().IsSet("web.influxdb.token").Return(true).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.token").Return("my-super-secret-auth-token").AnyTimes()
|
||||
@@ -428,6 +435,7 @@ func (suite *ServerTestSuite) TestSendTestNotificationRoute_ShoutrrrFailure() {
|
||||
fakeConfig.EXPECT().GetString("web.database.location").AnyTimes().Return(path.Join(parentPath, "scrutiny_test.db"))
|
||||
fakeConfig.EXPECT().GetString("web.src.frontend.path").AnyTimes().Return(parentPath)
|
||||
fakeConfig.EXPECT().GetString("web.listen.basepath").Return(suite.Basepath).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.scheme").Return("http").AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.port").Return("8086").AnyTimes()
|
||||
fakeConfig.EXPECT().IsSet("web.influxdb.token").Return(true).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.token").Return("my-super-secret-auth-token").AnyTimes()
|
||||
@@ -465,6 +473,7 @@ func (suite *ServerTestSuite) TestGetDevicesSummaryRoute_Nvme() {
|
||||
fakeConfig.EXPECT().GetString("web.database.location").AnyTimes().Return(path.Join(parentPath, "scrutiny_test.db"))
|
||||
fakeConfig.EXPECT().GetString("web.src.frontend.path").AnyTimes().Return(parentPath)
|
||||
fakeConfig.EXPECT().GetString("web.listen.basepath").Return(suite.Basepath).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.scheme").Return("http").AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.port").Return("8086").AnyTimes()
|
||||
fakeConfig.EXPECT().IsSet("web.influxdb.token").Return(true).AnyTimes()
|
||||
fakeConfig.EXPECT().GetString("web.influxdb.token").Return("my-super-secret-auth-token").AnyTimes()
|
||||
@@ -509,5 +518,5 @@ func (suite *ServerTestSuite) TestGetDevicesSummaryRoute_Nvme() {
|
||||
|
||||
//assert
|
||||
require.Equal(suite.T(), "a4c8e8ed-11a0-4c97-9bba-306440f1b944", deviceSummary.Data.Summary["a4c8e8ed-11a0-4c97-9bba-306440f1b944"].Device.WWN)
|
||||
require.Equal(suite.T(), pkg.DeviceStatusFailedScrutiny, deviceSummary.Data.Summary["a4c8e8ed-11a0-4c97-9bba-306440f1b944"].Device.DeviceStatus)
|
||||
require.Equal(suite.T(), pkg.DeviceStatusPassed, deviceSummary.Data.Summary["a4c8e8ed-11a0-4c97-9bba-306440f1b944"].Device.DeviceStatus)
|
||||
}
|
||||
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ -z "${CI}" ]]; then
|
||||
echo "running locally (not in Github Actions). generating version file from git client"
|
||||
GIT_TAG=`git describe --tags`
|
||||
GIT_BRANCH=`git rev-parse --abbrev-ref HEAD`
|
||||
|
||||
if [[ "$GIT_BRANCH" == "master" ]]; then
|
||||
VERSION_INFO="${GIT_TAG}"
|
||||
else
|
||||
VERSION_INFO="${GIT_BRANCH}#${GIT_TAG}"
|
||||
fi
|
||||
else
|
||||
echo "running in Github Actions, generating version file from environmental variables"
|
||||
# https://docs.github.com/en/actions/learn-github-actions/environment-variables
|
||||
VERSION_INFO="${GITHUB_REF_NAME}"
|
||||
|
||||
if [[ "$GITHUB_REF_TYPE" == "branch" ]]; then
|
||||
VERSION_INFO="${VERSION_INFO}#${GITHUB_SHA::7}"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "writing version file (version: ${VERSION_INFO})"
|
||||
cat <<EOT > src/environments/versions.ts
|
||||
// this file is automatically generated by git.version.ts script
|
||||
export const versionInfo = {
|
||||
version: '${VERSION_INFO}',
|
||||
};
|
||||
EOT
|
||||
@@ -3,6 +3,8 @@ import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import * as _ from 'lodash';
|
||||
import { TREO_APP_CONFIG } from '@treo/services/config/config.constants';
|
||||
|
||||
const SCRUTINY_CONFIG_LOCAL_STORAGE_KEY = 'scrutiny';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
@@ -10,14 +12,22 @@ export class TreoConfigService
|
||||
{
|
||||
// Private
|
||||
private _config: BehaviorSubject<any>;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(@Inject(TREO_APP_CONFIG) config: any)
|
||||
constructor(@Inject(TREO_APP_CONFIG) defaultConfig: any)
|
||||
{
|
||||
let currentScrutinyConfig = defaultConfig
|
||||
|
||||
let localConfigStr = localStorage.getItem(SCRUTINY_CONFIG_LOCAL_STORAGE_KEY)
|
||||
if(localConfigStr){
|
||||
//check localstorage for a value
|
||||
let localConfig = JSON.parse(localConfigStr)
|
||||
currentScrutinyConfig = localConfig
|
||||
}
|
||||
|
||||
// Set the private defaults
|
||||
this._config = new BehaviorSubject(config);
|
||||
this._config = new BehaviorSubject(currentScrutinyConfig);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@@ -27,15 +37,20 @@ export class TreoConfigService
|
||||
/**
|
||||
* Setter and getter for config
|
||||
*/
|
||||
//Setter
|
||||
set config(value: any)
|
||||
{
|
||||
// Merge the new config over to the current config
|
||||
const config = _.merge({}, this._config.getValue(), value);
|
||||
|
||||
//Store the config in localstorage
|
||||
localStorage.setItem(SCRUTINY_CONFIG_LOCAL_STORAGE_KEY, JSON.stringify(config));
|
||||
|
||||
// Execute the observable
|
||||
this._config.next(config);
|
||||
}
|
||||
|
||||
//Getter
|
||||
get config$(): Observable<any>
|
||||
{
|
||||
return this._config.asObservable();
|
||||
|
||||
@@ -11,6 +11,12 @@ export interface AppConfig
|
||||
{
|
||||
theme: Theme;
|
||||
layout: Layout;
|
||||
|
||||
// Dashboard options
|
||||
dashboardDisplay: string;
|
||||
dashboardSort: string;
|
||||
|
||||
temperatureUnit: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -23,6 +29,11 @@ export interface AppConfig
|
||||
*/
|
||||
export const appConfig: AppConfig = {
|
||||
theme : "light",
|
||||
layout: "material"
|
||||
layout: "material",
|
||||
|
||||
dashboardDisplay: "name",
|
||||
dashboardSort: "status",
|
||||
|
||||
temperatureUnit: "celsius",
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ export const summary = {
|
||||
"DeletedAt": null,
|
||||
"wwn": "0x5000c500673e6b5f",
|
||||
"device_name": "sdg",
|
||||
"device_label": "14TB-WD-DRIVE2",
|
||||
"device_uuid": "",
|
||||
"device_serial_id": "ata-ST6000DX000-1H217Z-Z4DXXXXX",
|
||||
"manufacturer": "ATA",
|
||||
"model_name": "ST6000DX000-1H217Z",
|
||||
"interface_type": "SCSI",
|
||||
@@ -35,6 +38,9 @@ export const summary = {
|
||||
"DeletedAt": null,
|
||||
"wwn": "0x5000cca252c859cc",
|
||||
"device_name": "sdd",
|
||||
"device_label": "14TB-WD-DRIVE1",
|
||||
"device_uuid": "806cf4bc-d160-4d96-8ee9-3ab7cf2a2e1f",
|
||||
"device_serial_id": "ata-WDC_WD80EFAX-68LHPN0-7SGLXXXXX",
|
||||
"manufacturer": "ATA",
|
||||
"model_name": "WDC_WD80EFAX-68LHPN0",
|
||||
"interface_type": "SCSI",
|
||||
@@ -68,6 +74,9 @@ export const summary = {
|
||||
"DeletedAt": null,
|
||||
"wwn": "0x5000cca264eb01d7",
|
||||
"device_name": "sdb",
|
||||
"device_label": "14TB-WD-DRIVE5",
|
||||
"device_uuid": "8125ec6d-a7e4-4950-ac84-72d6a4d67128",
|
||||
"device_serial_id": "ata-WDC_WD140EDFZ-11A0VA0-9RK1XXXXX",
|
||||
"manufacturer": "ATA",
|
||||
"model_name": "WDC_WD140EDFZ-11A0VA0",
|
||||
"interface_type": "SCSI",
|
||||
@@ -101,6 +110,9 @@ export const summary = {
|
||||
"DeletedAt": null,
|
||||
"wwn": "0x5000cca264ebc248",
|
||||
"device_name": "sde",
|
||||
"device_label": "14TB-WD-DRIVE3",
|
||||
"device_uuid": "9eb60cde-d6d0-4172-b520-b241a6a5477f",
|
||||
"device_serial_id": "ata-WDC_WD140EDFZ-11A0VA0-9RK3XXXXX",
|
||||
"manufacturer": "ATA",
|
||||
"model_name": "WDC_WD140EDFZ-11A0VA0",
|
||||
"interface_type": "SCSI",
|
||||
@@ -125,6 +137,9 @@ export const summary = {
|
||||
"DeletedAt": null,
|
||||
"wwn": "0x5000cca264ec3183",
|
||||
"device_name": "sdc",
|
||||
"device_label": "14TB-WD-DRIVE6",
|
||||
"device_uuid": "e1378723-7861-49b9-8e01-0bd063f0ecdd",
|
||||
"device_serial_id": "ata-WDC_WD140EDFZ-11A0VA0-9RK4XXXXX",
|
||||
"manufacturer": "ATA",
|
||||
"model_name": "WDC_WD140EDFZ-11A0VA0",
|
||||
"interface_type": "SCSI",
|
||||
@@ -138,7 +153,7 @@ export const summary = {
|
||||
"device_protocol": "",
|
||||
"device_type": "",
|
||||
"label": "",
|
||||
"host_id": "",
|
||||
"host_id": "custom host id",
|
||||
"device_status": 1
|
||||
},
|
||||
"smart": {
|
||||
@@ -542,6 +557,9 @@ export const summary = {
|
||||
"DeletedAt": null,
|
||||
"wwn": "0x50014ee20b2a72a9",
|
||||
"device_name": "sdf",
|
||||
"device_label": "8.0TB-WD-4",
|
||||
"device_uuid": "fc684dcc-aa2f-44f3-a958-d302dc7dd46d",
|
||||
"device_serial_id": "ata-WDC_WD60EFRX-68MYMN1-WXL1HXXXXX",
|
||||
"manufacturer": "ATA",
|
||||
"model_name": "WDC_WD60EFRX-68MYMN1",
|
||||
"interface_type": "SCSI",
|
||||
@@ -566,6 +584,9 @@ export const summary = {
|
||||
"DeletedAt": null,
|
||||
"wwn": "0x5002538e40a22954",
|
||||
"device_name": "sda",
|
||||
"device_label": "",
|
||||
"device_uuid": "",
|
||||
"device_serial_id": "ata-Samsung_SSD_860_EVO_500GB-S3YZNB0KBXXXXXX",
|
||||
"manufacturer": "ATA",
|
||||
"model_name": "Samsung_SSD_860_EVO_500GB",
|
||||
"interface_type": "SCSI",
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
<h2 mat-dialog-title>Delete {{data.title}}?</h2>
|
||||
<mat-dialog-content>This will delete all data associated with this device (including all historical data).</mat-dialog-content>
|
||||
<mat-dialog-actions>
|
||||
<button mat-button mat-dialog-close>Cancel</button>
|
||||
<!-- The mat-dialog-close directive optionally accepts a value as a result for the dialog. -->
|
||||
<button class="red-600" mat-button (click)="onDeleteClick()">
|
||||
<mat-icon class="icon-size-20 mr-3"
|
||||
[svgIcon]="'delete_forever'"></mat-icon>
|
||||
Delete</button>
|
||||
</mat-dialog-actions>
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DashboardDeviceDeleteDialogComponent } from './dashboard-device-delete-dialog.component';
|
||||
|
||||
describe('DashboardDeviceDeleteDialogComponent', () => {
|
||||
let component: DashboardDeviceDeleteDialogComponent;
|
||||
let fixture: ComponentFixture<DashboardDeviceDeleteDialogComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DashboardDeviceDeleteDialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DashboardDeviceDeleteDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import { Component, OnInit, Inject } from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
||||
import {DashboardDeviceDeleteDialogService} from "./dashboard-device-delete-dialog.service";
|
||||
import {Subject} from "rxjs";
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard-device-delete-dialog',
|
||||
templateUrl: './dashboard-device-delete-dialog.component.html',
|
||||
styleUrls: ['./dashboard-device-delete-dialog.component.scss']
|
||||
})
|
||||
export class DashboardDeviceDeleteDialogComponent implements OnInit {
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<DashboardDeviceDeleteDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: {wwn: string, title: string},
|
||||
private _deleteService: DashboardDeviceDeleteDialogService,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
onDeleteClick(): void {
|
||||
this._deleteService.deleteDevice(this.data.wwn)
|
||||
.subscribe((data) => {
|
||||
this.dialogRef.close(data);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { Overlay } from '@angular/cdk/overlay';
|
||||
import { MAT_AUTOCOMPLETE_SCROLL_STRATEGY, MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { SharedModule } from 'app/shared/shared.module';
|
||||
import {DashboardDeviceDeleteDialogComponent} from 'app/layout/common/dashboard-device-delete-dialog/dashboard-device-delete-dialog.component'
|
||||
import { MatButtonToggleModule} from "@angular/material/button-toggle";
|
||||
import {MatTabsModule} from "@angular/material/tabs";
|
||||
import {MatSliderModule} from "@angular/material/slider";
|
||||
import {MatSlideToggleModule} from "@angular/material/slide-toggle";
|
||||
import {MatTooltipModule} from "@angular/material/tooltip";
|
||||
import {dashboardRoutes} from "../../../modules/dashboard/dashboard.routing";
|
||||
import {MatDividerModule} from "@angular/material/divider";
|
||||
import {MatMenuModule} from "@angular/material/menu";
|
||||
import {MatProgressBarModule} from "@angular/material/progress-bar";
|
||||
import {MatSortModule} from "@angular/material/sort";
|
||||
import {MatTableModule} from "@angular/material/table";
|
||||
import {NgApexchartsModule} from "ng-apexcharts";
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
DashboardDeviceDeleteDialogComponent
|
||||
],
|
||||
imports : [
|
||||
RouterModule.forChild([]),
|
||||
RouterModule.forChild(dashboardRoutes),
|
||||
MatButtonModule,
|
||||
MatDividerModule,
|
||||
MatTooltipModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
MatProgressBarModule,
|
||||
MatSortModule,
|
||||
MatTableModule,
|
||||
NgApexchartsModule,
|
||||
SharedModule,
|
||||
MatDialogModule
|
||||
],
|
||||
exports : [
|
||||
DashboardDeviceDeleteDialogComponent,
|
||||
],
|
||||
providers : []
|
||||
})
|
||||
export class DashboardDeviceDeleteDialogModule
|
||||
{
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { getBasePath } from 'app/app.routing';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DashboardDeviceDeleteDialogService
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param {HttpClient} _httpClient
|
||||
*/
|
||||
constructor(
|
||||
private _httpClient: HttpClient
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Public methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
deleteDevice(wwn: string): Observable<any>
|
||||
{
|
||||
return this._httpClient.delete( `${getBasePath()}/api/device/${wwn}`, {});
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
<div [ngClass]="{ 'border-green': deviceSummary.device.device_status == 0 && deviceSummary.smart,
|
||||
'border-red': deviceSummary.device.device_status != 0 }"
|
||||
class="relative flex flex-col flex-auto p-6 pr-3 pb-3 bg-card rounded border-l-4 shadow-md overflow-hidden">
|
||||
<div class="absolute bottom-0 right-0 w-24 h-24 -m-6">
|
||||
<mat-icon class="icon-size-96 opacity-12 text-green"
|
||||
*ngIf="deviceSummary.device.device_status == 0 && deviceSummary.smart"
|
||||
[svgIcon]="'heroicons_outline:check-circle'"></mat-icon>
|
||||
<mat-icon class="icon-size-96 opacity-12 text-red"
|
||||
*ngIf="deviceSummary.device.device_status != 0"
|
||||
[svgIcon]="'heroicons_outline:exclamation-circle'"></mat-icon>
|
||||
<mat-icon class="icon-size-96 opacity-12 text-yellow"
|
||||
*ngIf="!deviceSummary.smart"
|
||||
[svgIcon]="'heroicons_outline:question-mark-circle'"></mat-icon>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="flex flex-col">
|
||||
<a [routerLink]="'/device/'+ deviceSummary.device.wwn"
|
||||
class="font-bold text-md text-secondary uppercase tracking-wider">{{deviceSummary.device | deviceTitle:config.dashboardDisplay}}</a>
|
||||
<div [ngClass]="classDeviceLastUpdatedOn(deviceSummary)" class="font-medium text-sm" *ngIf="deviceSummary.smart">
|
||||
Last Updated on {{deviceSummary.smart.collector_date | date:'MMMM dd, yyyy - HH:mm' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-auto" *ngIf="deviceSummary.device">
|
||||
<button mat-icon-button
|
||||
[matMenuTriggerFor]="previousStatementMenu">
|
||||
<mat-icon [svgIcon]="'more_vert'"></mat-icon>
|
||||
</button>
|
||||
<mat-menu #previousStatementMenu="matMenu">
|
||||
<a mat-menu-item [routerLink]="'/device/'+ deviceSummary.device.wwn">
|
||||
<span class="flex items-center">
|
||||
<mat-icon class="icon-size-20 mr-3"
|
||||
[svgIcon]="'assessment'"></mat-icon>
|
||||
<span>View Details</span>
|
||||
</span>
|
||||
</a>
|
||||
<a mat-menu-item (click)="openDeleteDialog()">
|
||||
<span class="flex items-center">
|
||||
<mat-icon class="icon-size-20 mr-3"
|
||||
[svgIcon]="'delete_forever'"></mat-icon>
|
||||
<span>Delete Device</span>
|
||||
</span>
|
||||
</a>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row flex-wrap mt-4 -mx-6">
|
||||
<div class="flex flex-col mx-6 my-3 xs:w-full">
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">Status</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none" *ngIf="deviceSummary.smart?.collector_date; else unknownStatus">{{ deviceStatusString(deviceSummary.device.device_status) | titlecase}}</div>
|
||||
<ng-template #unknownStatus><div class="mt-2 font-medium text-3xl leading-none">No Data</div></ng-template>
|
||||
</div>
|
||||
<div class="flex flex-col mx-6 my-3 xs:w-full">
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">Temperature</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none" *ngIf="deviceSummary.smart?.collector_date; else unknownTemp">{{ deviceSummary.smart?.temp | temperature:config.temperatureUnit:true }}</div>
|
||||
<ng-template #unknownTemp><div class="mt-2 font-medium text-3xl leading-none">--</div></ng-template>
|
||||
</div>
|
||||
<div class="flex flex-col mx-6 my-3 xs:w-full">
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">Capacity</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none">{{ deviceSummary.device.capacity | fileSize}}</div>
|
||||
</div>
|
||||
<div class="flex flex-col mx-6 my-3 xs:w-full">
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">Powered On</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none" *ngIf="deviceSummary.smart?.power_on_hours; else unknownPoweredOn">{{ humanizeDuration(deviceSummary.smart?.power_on_hours * 60 * 60 * 1000, { round: true, largest: 1, units: ['y', 'd', 'h'] }) }}</div>
|
||||
<ng-template #unknownPoweredOn><div class="mt-2 font-medium text-3xl leading-none">--</div></ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DashboardDeviceComponent } from './dashboard-device.component';
|
||||
|
||||
describe('DashboardDeviceComponent', () => {
|
||||
let component: DashboardDeviceComponent;
|
||||
let fixture: ComponentFixture<DashboardDeviceComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DashboardDeviceComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DashboardDeviceComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
import { Component, Input, Output, OnInit, EventEmitter} from '@angular/core';
|
||||
import * as moment from "moment";
|
||||
import {takeUntil} from "rxjs/operators";
|
||||
import {AppConfig} from "app/core/config/app.config";
|
||||
import {TreoConfigService} from "@treo/services/config";
|
||||
import {Subject} from "rxjs";
|
||||
import humanizeDuration from 'humanize-duration'
|
||||
import {MatDialog} from '@angular/material/dialog';
|
||||
import {DashboardDeviceDeleteDialogComponent} from "app/layout/common/dashboard-device-delete-dialog/dashboard-device-delete-dialog.component";
|
||||
import {DeviceTitlePipe} from "app/shared/device-title.pipe";
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard-device',
|
||||
templateUrl: './dashboard-device.component.html',
|
||||
styleUrls: ['./dashboard-device.component.scss']
|
||||
})
|
||||
export class DashboardDeviceComponent implements OnInit {
|
||||
@Input() deviceSummary: any;
|
||||
@Input() deviceWWN: string;
|
||||
@Output() deviceDeleted = new EventEmitter<string>();
|
||||
|
||||
config: AppConfig;
|
||||
|
||||
private _unsubscribeAll: Subject<any>;
|
||||
|
||||
constructor(
|
||||
private _configService: TreoConfigService,
|
||||
public dialog: MatDialog,
|
||||
) {
|
||||
// Set the private defaults
|
||||
this._unsubscribeAll = new Subject();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
// Subscribe to config changes
|
||||
this._configService.config$
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((config: AppConfig) => {
|
||||
this.config = config;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Public methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
classDeviceLastUpdatedOn(deviceSummary){
|
||||
if (deviceSummary.device.device_status !== 0) {
|
||||
return 'text-red' // if the device has failed, always highlight in red
|
||||
} else if(deviceSummary.device.device_status === 0 && deviceSummary.smart){
|
||||
if(moment().subtract(14, 'd').isBefore(deviceSummary.smart.collector_date)){
|
||||
// this device was updated in the last 2 weeks.
|
||||
return 'text-green'
|
||||
} else if(moment().subtract(1, 'm').isBefore(deviceSummary.smart.collector_date)){
|
||||
// this device was updated in the last month
|
||||
return 'text-yellow'
|
||||
} else{
|
||||
// last updated more than a month ago.
|
||||
return 'text-red'
|
||||
}
|
||||
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
deviceStatusString(deviceStatus){
|
||||
if(deviceStatus == 0){
|
||||
return "passed"
|
||||
} else {
|
||||
return "failed"
|
||||
}
|
||||
}
|
||||
|
||||
readonly humanizeDuration = humanizeDuration;
|
||||
|
||||
|
||||
|
||||
openDeleteDialog(): void {
|
||||
const dialogRef = this.dialog.open(DashboardDeviceDeleteDialogComponent, {
|
||||
// width: '250px',
|
||||
data: {wwn: this.deviceWWN, title: DeviceTitlePipe.deviceTitleWithFallback(this.deviceSummary.device, this.config.dashboardDisplay)}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
console.log('The dialog was closed', result);
|
||||
if(result.success){
|
||||
this.deviceDeleted.emit(this.deviceWWN)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { Overlay } from '@angular/cdk/overlay';
|
||||
import { MAT_AUTOCOMPLETE_SCROLL_STRATEGY, MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { SharedModule } from 'app/shared/shared.module';
|
||||
import {DashboardDeviceComponent} from 'app/layout/common/dashboard-device/dashboard-device.component'
|
||||
import { MatDialogModule } from "@angular/material/dialog";
|
||||
import { MatButtonToggleModule} from "@angular/material/button-toggle";
|
||||
import {MatTabsModule} from "@angular/material/tabs";
|
||||
import {MatSliderModule} from "@angular/material/slider";
|
||||
import {MatSlideToggleModule} from "@angular/material/slide-toggle";
|
||||
import {MatTooltipModule} from "@angular/material/tooltip";
|
||||
import {dashboardRoutes} from "../../../modules/dashboard/dashboard.routing";
|
||||
import {MatDividerModule} from "@angular/material/divider";
|
||||
import {MatMenuModule} from "@angular/material/menu";
|
||||
import {MatProgressBarModule} from "@angular/material/progress-bar";
|
||||
import {MatSortModule} from "@angular/material/sort";
|
||||
import {MatTableModule} from "@angular/material/table";
|
||||
import {NgApexchartsModule} from "ng-apexcharts";
|
||||
import {DashboardDeviceDeleteDialogModule} from "../dashboard-device-delete-dialog/dashboard-device-delete-dialog.module";
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
DashboardDeviceComponent
|
||||
],
|
||||
imports : [
|
||||
RouterModule.forChild([]),
|
||||
RouterModule.forChild(dashboardRoutes),
|
||||
MatButtonModule,
|
||||
MatDividerModule,
|
||||
MatTooltipModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
MatProgressBarModule,
|
||||
MatSortModule,
|
||||
MatTableModule,
|
||||
NgApexchartsModule,
|
||||
SharedModule,
|
||||
DashboardDeviceDeleteDialogModule
|
||||
],
|
||||
exports : [
|
||||
DashboardDeviceComponent,
|
||||
],
|
||||
providers : []
|
||||
})
|
||||
export class DashboardDeviceModule
|
||||
{
|
||||
}
|
||||
+43
-22
@@ -1,77 +1,98 @@
|
||||
<h2 mat-dialog-title>Scrutiny Settings</h2>
|
||||
<mat-dialog-content class="mat-typography">
|
||||
|
||||
<form class="flex flex-col p-8 pb-0 overflow-hidden">
|
||||
<div class="flex flex-col gt-xs:flex-row">
|
||||
<mat-form-field class="flex-auto gt-xs:pr-3">
|
||||
<mat-label>Sort By</mat-label>
|
||||
<mat-select [value]="'status'">
|
||||
<mat-option value="status">Status</mat-option>
|
||||
<mat-option value="name" disabled>Name</mat-option>
|
||||
<mat-option value="label" disabled>Label</mat-option>
|
||||
<div class="flex flex-col p-8 pb-0 overflow-hidden">
|
||||
<div class="flex flex-col mt-5 gt-md:flex-row">
|
||||
<mat-form-field class="flex-auto gt-xs:pr-3 gt-md:pr-3">
|
||||
<mat-label>Display Title</mat-label>
|
||||
<mat-select [(ngModel)]="dashboardDisplay">
|
||||
<mat-option value="name">Name</mat-option>
|
||||
<mat-option value="serial_id">Serial ID</mat-option>
|
||||
<mat-option value="uuid">UUID</mat-option>
|
||||
<mat-option value="label">Label</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-auto gt-xs:pr-3 gt-md:pl-3">
|
||||
<mat-label>Sort By</mat-label>
|
||||
<mat-select [(ngModel)]="dashboardSort">
|
||||
<mat-option value="status">Status</mat-option>
|
||||
<mat-option value="title">Title</mat-option>
|
||||
<mat-option value="age">Age</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col mt-5 gt-md:flex-row">
|
||||
<mat-form-field class="flex-auto gt-xs:pr-3 gt-md:pr-3">
|
||||
<mat-label>Temperature Display Unit</mat-label>
|
||||
<mat-select [(ngModel)]="temperatureUnit">
|
||||
<mat-option value="celsius">Celsius</mat-option>
|
||||
<mat-option value="fahrenheit">Fahrenheit</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<mat-tab-group mat-align-tabs="start">
|
||||
<mat-tab label="Ata">
|
||||
|
||||
<div class="flex flex-col mt-5 gt-md:flex-row">
|
||||
<div matTooltip="not yet implemented" class="gray-200 flex flex-col mt-5 gt-md:flex-row">
|
||||
<mat-form-field class="flex-auto gt-md:pr-3">
|
||||
<mat-label>Critical Error Threshold</mat-label>
|
||||
<input matInput [value]="'10%'">
|
||||
<input disabled matInput [value]="'10%'">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-auto gt-md:pl-3">
|
||||
<mat-label>Critical Warning Threshold</mat-label>
|
||||
<input matInput>
|
||||
<input disabled matInput>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gt-md:flex-row">
|
||||
<div matTooltip="not yet implemented" class="gray-200 flex flex-col gt-md:flex-row">
|
||||
<mat-form-field class="flex-auto gt-md:pr-3">
|
||||
<mat-label>Error Threshold</mat-label>
|
||||
<input matInput [value]="'20%'">
|
||||
<input disabled matInput [value]="'20%'">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-auto gt-md:pl-3">
|
||||
<mat-label>Warning Threshold</mat-label>
|
||||
<input matInput [value]="'10%'">
|
||||
<input disabled matInput [value]="'10%'">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
</mat-tab>
|
||||
<mat-tab label="NVMe">
|
||||
|
||||
<div class="flex flex-col mt-5 gt-md:flex-row">
|
||||
<div matTooltip="not yet implemented" class="gray-200 flex flex-col mt-5 gt-md:flex-row">
|
||||
<mat-form-field class="flex-auto gt-md:pr-3">
|
||||
<mat-label>Critical Error Threshold</mat-label>
|
||||
<input matInput [value]="'enabled'">
|
||||
<input disabled matInput [value]="'enabled'">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-auto gt-md:pl-3">
|
||||
<mat-label>Critical Warning Threshold</mat-label>
|
||||
<input matInput>
|
||||
<input disabled matInput>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
</mat-tab>
|
||||
<mat-tab label="SCSI">
|
||||
<div class="flex flex-col mt-5 gt-md:flex-row">
|
||||
<div matTooltip="not yet implemented" class="gray-200 flex flex-col mt-5 gt-md:flex-row">
|
||||
<mat-form-field class="flex-auto gt-md:pr-3">
|
||||
<mat-label>Critical Error Threshold</mat-label>
|
||||
<input matInput [value]="'enabled'">
|
||||
<input disabled matInput [value]="'enabled'">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-auto gt-md:pl-3">
|
||||
<mat-label>Critical Warning Threshold</mat-label>
|
||||
<input matInput>
|
||||
<input disabled matInput>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button mat-dialog-close>Cancel</button>
|
||||
<button mat-button matTooltip="not yet implemented" [mat-dialog-close]="true" cdkFocusInitial>Save</button>
|
||||
<button mat-button mat-dialog-close (click)="saveSettings()" cdkFocusInitial>Save</button>
|
||||
</mat-dialog-actions>
|
||||
|
||||
+39
-2
@@ -1,4 +1,8 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {AppConfig} from 'app/core/config/app.config';
|
||||
import { TreoConfigService } from '@treo/services/config';
|
||||
import {Subject} from "rxjs";
|
||||
import {takeUntil} from "rxjs/operators";
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard-settings',
|
||||
@@ -7,11 +11,44 @@ import { Component, OnInit } from '@angular/core';
|
||||
})
|
||||
export class DashboardSettingsComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
dashboardDisplay: string;
|
||||
dashboardSort: string;
|
||||
temperatureUnit: string
|
||||
|
||||
// Private
|
||||
private _unsubscribeAll: Subject<any>;
|
||||
|
||||
constructor(
|
||||
private _configService: TreoConfigService,
|
||||
) {
|
||||
// Set the private defaults
|
||||
this._unsubscribeAll = new Subject();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
// Subscribe to config changes
|
||||
this._configService.config$
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((config: AppConfig) => {
|
||||
|
||||
// Store the config
|
||||
this.dashboardDisplay = config.dashboardDisplay;
|
||||
this.dashboardSort = config.dashboardSort;
|
||||
this.temperatureUnit = config.temperatureUnit;
|
||||
});
|
||||
}
|
||||
formatLabel(value: number) {
|
||||
|
||||
saveSettings(): void {
|
||||
const newSettings = {
|
||||
dashboardDisplay: this.dashboardDisplay,
|
||||
dashboardSort: this.dashboardSort,
|
||||
temperatureUnit: this.temperatureUnit,
|
||||
}
|
||||
this._configService.config = newSettings
|
||||
console.log(`Saved Settings: ${JSON.stringify(newSettings)}`)
|
||||
}
|
||||
|
||||
formatLabel(value: number): number {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
<!-- Spacer -->
|
||||
<div class="spacer"></div>
|
||||
|
||||
<code>{{appVersion}}</code>
|
||||
|
||||
<!-- Shortcuts -->
|
||||
<!-- <shortcuts [shortcuts]="data.shortcuts"></shortcuts>-->
|
||||
@@ -48,6 +48,7 @@
|
||||
<!-- <notifications [notifications]="data.notifications"></notifications>-->
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { TreoMediaWatcherService } from '@treo/services/media-watcher';
|
||||
import { TreoNavigationService } from '@treo/components/navigation';
|
||||
import {versionInfo} from 'environments/versions';
|
||||
|
||||
@Component({
|
||||
selector : 'material-layout',
|
||||
@@ -13,6 +14,7 @@ import { TreoNavigationService } from '@treo/components/navigation';
|
||||
})
|
||||
export class MaterialLayoutComponent implements OnInit, OnDestroy
|
||||
{
|
||||
appVersion: string;
|
||||
data: any;
|
||||
isScreenSmall: boolean;
|
||||
|
||||
@@ -46,6 +48,8 @@ export class MaterialLayoutComponent implements OnInit, OnDestroy
|
||||
// Set the defaults
|
||||
this.fixedHeader = false;
|
||||
this.fixedFooter = false;
|
||||
|
||||
this.appVersion = versionInfo.version
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -47,71 +47,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap w-full">
|
||||
<div *ngFor="let summary of data.data.summary | keyvalue" class="flex gt-sm:w-1/2 min-w-80 p-4">
|
||||
<div [ngClass]="{ 'border-green': summary.value.device.device_status == 0 && summary.value.smart,
|
||||
'border-red': summary.value.device.device_status != 0 }"
|
||||
class="relative flex flex-col flex-auto p-6 pr-3 pb-3 bg-card rounded border-l-4 shadow-md overflow-hidden">
|
||||
<div class="absolute bottom-0 right-0 w-24 h-24 -m-6">
|
||||
<mat-icon class="icon-size-96 opacity-12 text-green"
|
||||
*ngIf="summary.value.device.device_status == 0 && summary.value.smart"
|
||||
[svgIcon]="'heroicons_outline:check-circle'"></mat-icon>
|
||||
<mat-icon class="icon-size-96 opacity-12 text-red"
|
||||
*ngIf="summary.value.device.device_status != 0"
|
||||
[svgIcon]="'heroicons_outline:exclamation-circle'"></mat-icon>
|
||||
<mat-icon class="icon-size-96 opacity-12 text-yellow"
|
||||
*ngIf="!summary.value.smart"
|
||||
[svgIcon]="'heroicons_outline:question-mark-circle'"></mat-icon>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="flex flex-col">
|
||||
<a [routerLink]="'/device/'+ summary.value.device.wwn"
|
||||
class="font-bold text-md text-secondary uppercase tracking-wider">{{deviceTitle(summary.value.device)}}</a>
|
||||
<div [ngClass]="classDeviceLastUpdatedOn(summary.value)" class="font-medium text-sm" *ngIf="summary.value.smart">
|
||||
Last Updated on {{summary.value.smart.collector_date | date:'MMMM dd, yyyy - HH:mm' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-auto" *ngIf="summary.value.device">
|
||||
<button mat-icon-button
|
||||
[matMenuTriggerFor]="previousStatementMenu">
|
||||
<mat-icon [svgIcon]="'more_vert'"></mat-icon>
|
||||
</button>
|
||||
<mat-menu #previousStatementMenu="matMenu">
|
||||
<a mat-menu-item [routerLink]="'/device/'+ summary.value.device.wwn">
|
||||
<span class="flex items-center">
|
||||
<mat-icon class="icon-size-20 mr-3"
|
||||
[svgIcon]="'payment'"></mat-icon>
|
||||
<span>View Details</span>
|
||||
</span>
|
||||
</a>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row flex-wrap mt-4 -mx-6">
|
||||
<div class="flex flex-col mx-6 my-3 xs:w-full">
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">Status</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none" *ngIf="summary.value.smart?.collector_date; else unknownStatus">{{ deviceStatusString(summary.value.device.device_status) | titlecase}}</div>
|
||||
<ng-template #unknownStatus><div class="mt-2 font-medium text-3xl leading-none">No Data</div></ng-template>
|
||||
</div>
|
||||
<div class="flex flex-col mx-6 my-3 xs:w-full">
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">Temperature</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none" *ngIf="summary.value.smart?.collector_date; else unknownTemp">{{ summary.value.smart?.temp }}°C</div>
|
||||
<ng-template #unknownTemp><div class="mt-2 font-medium text-3xl leading-none">--</div></ng-template>
|
||||
</div>
|
||||
<div class="flex flex-col mx-6 my-3 xs:w-full">
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">Capacity</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none">{{ summary.value.device.capacity | fileSize}}</div>
|
||||
</div>
|
||||
<div class="flex flex-col mx-6 my-3 xs:w-full">
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">Powered On</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none" *ngIf="summary.value.smart?.power_on_hours; else unknownPoweredOn">{{ humanizeDuration(summary.value.smart?.power_on_hours * 60 * 60 * 1000, { round: true, largest: 1, units: ['y', 'd', 'h'] }) }}</div>
|
||||
<ng-template #unknownPoweredOn><div class="mt-2 font-medium text-3xl leading-none">--</div></ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap w-full" *ngFor="let hostId of hostGroups | keyvalue">
|
||||
<h3 class="ml-4" *ngIf="hostId.key">{{hostId.key}}</h3>
|
||||
<div class="flex flex-wrap w-full">
|
||||
<app-dashboard-device (deviceDeleted)="onDeviceDeleted($event)" class="flex gt-sm:w-1/2 min-w-80 p-4" *ngFor="let deviceSummary of (deviceSummariesForHostGroup(hostId.value) | deviceSort:config.dashboardSort:config.dashboardDisplay )" [deviceWWN]="deviceSummary.device.wwn" [deviceSummary]="deviceSummary"></app-dashboard-device>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Drive Temperatures -->
|
||||
<div class="flex flex-auto w-full min-w-80 h-90 p-4">
|
||||
<div class="flex flex-col flex-auto bg-card shadow-md rounded overflow-hidden">
|
||||
@@ -123,22 +67,22 @@
|
||||
</div>
|
||||
<div>
|
||||
<button class="h-8 min-h-8 px-2"
|
||||
matTooltip="not yet implemented"
|
||||
mat-button
|
||||
[matMenuTriggerFor]="tempRangeMenu">
|
||||
<span class="font-medium text-sm text-hint">1 week</span>
|
||||
<span class="font-medium text-sm text-hint">{{tempDurationKey}}</span>
|
||||
</button>
|
||||
<mat-menu #tempRangeMenu="matMenu">
|
||||
<button mat-menu-item>1 month</button>
|
||||
<button mat-menu-item>12 months</button>
|
||||
<button mat-menu-item>all time</button>
|
||||
<button (click)="changeSummaryTempDuration('forever')" mat-menu-item>forever</button>
|
||||
<button (click)="changeSummaryTempDuration('year')" mat-menu-item>year</button>
|
||||
<button (click)="changeSummaryTempDuration('month')" mat-menu-item>month</button>
|
||||
<button (click)="changeSummaryTempDuration('week')" mat-menu-item>week</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="flex flex-col flex-auto">
|
||||
<apx-chart *ngIf="temperatureOptions" class="flex-auto w-full h-full"
|
||||
<apx-chart #tempChart *ngIf="temperatureOptions" class="flex-auto w-full h-full"
|
||||
[chart]="temperatureOptions.chart"
|
||||
[colors]="temperatureOptions.colors"
|
||||
[fill]="temperatureOptions.fill"
|
||||
@@ -167,6 +111,4 @@
|
||||
<code>scrutiny-collector-metrics run</code>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</ng-template>
|
||||
|
||||
@@ -3,12 +3,15 @@ import { MatSort } from '@angular/material/sort';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { ApexOptions } from 'ng-apexcharts';
|
||||
import {ApexOptions, ChartComponent} from 'ng-apexcharts';
|
||||
import { DashboardService } from 'app/modules/dashboard/dashboard.service';
|
||||
import * as moment from "moment";
|
||||
import {MatDialog} from '@angular/material/dialog';
|
||||
import { DashboardSettingsComponent } from 'app/layout/common/dashboard-settings/dashboard-settings.component';
|
||||
import humanizeDuration from 'humanize-duration'
|
||||
import {AppConfig} from "app/core/config/app.config";
|
||||
import {TreoConfigService} from "@treo/services/config";
|
||||
import {Router} from "@angular/router";
|
||||
import {TemperaturePipe} from "app/shared/temperature.pipe";
|
||||
import {DeviceTitlePipe} from "app/shared/device-title.pipe";
|
||||
|
||||
@Component({
|
||||
selector : 'example',
|
||||
@@ -20,10 +23,14 @@ import humanizeDuration from 'humanize-duration'
|
||||
export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
{
|
||||
data: any;
|
||||
hostGroups: { [hostId: string]: string[] } = {}
|
||||
temperatureOptions: ApexOptions;
|
||||
tempDurationKey: string = "forever"
|
||||
config: AppConfig;
|
||||
|
||||
// Private
|
||||
private _unsubscribeAll: Subject<any>;
|
||||
@ViewChild("tempChart", { static: false }) tempChart: ChartComponent;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -32,7 +39,9 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
*/
|
||||
constructor(
|
||||
private _smartService: DashboardService,
|
||||
public dialog: MatDialog
|
||||
private _configService: TreoConfigService,
|
||||
public dialog: MatDialog,
|
||||
private router: Router,
|
||||
)
|
||||
{
|
||||
// Set the private defaults
|
||||
@@ -49,6 +58,28 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
|
||||
// Subscribe to config changes
|
||||
this._configService.config$
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((config: AppConfig) => {
|
||||
|
||||
//check if the old config and the new config do not match.
|
||||
let oldConfig = JSON.stringify(this.config)
|
||||
let newConfig = JSON.stringify(config)
|
||||
|
||||
if(oldConfig != newConfig){
|
||||
console.log(`Configuration updated: ${newConfig} vs ${oldConfig}`)
|
||||
// Store the config
|
||||
this.config = config;
|
||||
|
||||
if(oldConfig){
|
||||
console.log("reloading component...")
|
||||
this.refreshComponent()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Get the data
|
||||
this._smartService.data$
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
@@ -57,6 +88,15 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
// Store the data
|
||||
this.data = data;
|
||||
|
||||
//generate group data.
|
||||
for(let wwn in this.data.data.summary){
|
||||
let hostid = this.data.data.summary[wwn].device.host_id
|
||||
let hostDeviceList = this.hostGroups[hostid] || []
|
||||
hostDeviceList.push(wwn)
|
||||
this.hostGroups[hostid] = hostDeviceList
|
||||
}
|
||||
console.log(this.hostGroups)
|
||||
|
||||
// Prepare the chart data
|
||||
this._prepareChartData();
|
||||
});
|
||||
@@ -81,6 +121,14 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Private methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
private refreshComponent(){
|
||||
|
||||
let currentUrl = this.router.url;
|
||||
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
|
||||
this.router.onSameUrlNavigation = 'reload';
|
||||
this.router.navigate([currentUrl]);
|
||||
}
|
||||
|
||||
private _deviceDataTemperatureSeries() {
|
||||
var deviceTemperatureSeries = []
|
||||
|
||||
@@ -91,8 +139,11 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
if (!deviceSummary.temp_history){
|
||||
continue
|
||||
}
|
||||
|
||||
let deviceName = DeviceTitlePipe.deviceTitleWithFallback(deviceSummary.device, this.config.dashboardDisplay)
|
||||
|
||||
var deviceSeriesMetadata = {
|
||||
name: `/dev/${deviceSummary.device.device_name}`,
|
||||
name: deviceName,
|
||||
data: []
|
||||
}
|
||||
|
||||
@@ -100,7 +151,7 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
let newDate = new Date(tempHistory.date);
|
||||
deviceSeriesMetadata.data.push({
|
||||
x: newDate,
|
||||
y: tempHistory.temp
|
||||
y: TemperaturePipe.formatTemperature(tempHistory.temp, this.config.temperatureUnit, false)
|
||||
})
|
||||
}
|
||||
deviceTemperatureSeries.push(deviceSeriesMetadata)
|
||||
@@ -149,8 +200,9 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
format: 'MMM dd, yyyy HH:mm:ss'
|
||||
},
|
||||
y : {
|
||||
|
||||
formatter: (value) => {
|
||||
return value + '°C';
|
||||
return TemperaturePipe.formatTemperature(value, this.config.temperatureUnit, true) as string;
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -164,6 +216,16 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
// @ Public methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
deviceSummariesForHostGroup(hostGroupWWNs: string[]) {
|
||||
let deviceSummaries = []
|
||||
for(let wwn of hostGroupWWNs){
|
||||
if(this.data.data.summary[wwn]){
|
||||
deviceSummaries.push(this.data.data.summary[wwn])
|
||||
}
|
||||
}
|
||||
return deviceSummaries
|
||||
}
|
||||
|
||||
openDialog() {
|
||||
const dialogRef = this.dialog.open(DashboardSettingsComponent);
|
||||
|
||||
@@ -172,48 +234,33 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
});
|
||||
}
|
||||
|
||||
deviceTitle(disk){
|
||||
let title = []
|
||||
|
||||
if (disk.host_id) title.push(disk.host_id)
|
||||
|
||||
title.push(`/dev/${disk.device_name}`)
|
||||
|
||||
if (disk.device_type && disk.device_type != 'scsi' && disk.device_type != 'ata'){
|
||||
title.push(disk.device_type)
|
||||
}
|
||||
|
||||
title.push(disk.model_name)
|
||||
|
||||
return title.join(' - ')
|
||||
onDeviceDeleted(wwn: string) {
|
||||
delete this.data.data.summary[wwn] // remove the device from the summary list.
|
||||
}
|
||||
|
||||
deviceStatusString(deviceStatus){
|
||||
if(deviceStatus == 0){
|
||||
return "passed"
|
||||
} else {
|
||||
return "failed"
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
classDeviceLastUpdatedOn(deviceSummary){
|
||||
if (deviceSummary.device.device_status !== 0) {
|
||||
return 'text-red' // if the device has failed, always highlight in red
|
||||
} else if(deviceSummary.device.device_status === 0 && deviceSummary.smart){
|
||||
if(moment().subtract(14, 'd').isBefore(deviceSummary.smart.collector_date)){
|
||||
// this device was updated in the last 2 weeks.
|
||||
return 'text-green'
|
||||
} else if(moment().subtract(1, 'm').isBefore(deviceSummary.smart.collector_date)){
|
||||
// this device was updated in the last month
|
||||
return 'text-yellow'
|
||||
} else{
|
||||
// last updated more than a month ago.
|
||||
return 'text-red'
|
||||
}
|
||||
DURATION_KEY_WEEK = "week"
|
||||
DURATION_KEY_MONTH = "month"
|
||||
DURATION_KEY_YEAR = "year"
|
||||
DURATION_KEY_FOREVER = "forever"
|
||||
*/
|
||||
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
changeSummaryTempDuration(durationKey: string){
|
||||
this.tempDurationKey = durationKey
|
||||
|
||||
this._smartService.getSummaryTempData(durationKey)
|
||||
.subscribe((data) => {
|
||||
|
||||
// given a list of device temp history, override the data in the "summary" object.
|
||||
for(const wwn in this.data.data.summary) {
|
||||
// console.log(`Updating ${wwn}, length: ${this.data.data.summary[wwn].temp_history.length}`)
|
||||
this.data.data.summary[wwn].temp_history = data.data.temp_history[wwn] || []
|
||||
}
|
||||
|
||||
// Prepare the chart series data
|
||||
this.tempChart.updateSeries(this._deviceDataTemperatureSeries())
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -227,6 +274,4 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
return item.id || index;
|
||||
}
|
||||
|
||||
readonly humanizeDuration = humanizeDuration;
|
||||
|
||||
}
|
||||
|
||||
@@ -13,12 +13,13 @@ import { MatTableModule } from '@angular/material/table';
|
||||
import { NgApexchartsModule } from 'ng-apexcharts';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip'
|
||||
import { DashboardSettingsModule } from "app/layout/common/dashboard-settings/dashboard-settings.module";
|
||||
import { DashboardDeviceModule } from "app/layout/common/dashboard-device/dashboard-device.module";
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
DashboardComponent
|
||||
],
|
||||
imports : [
|
||||
imports: [
|
||||
RouterModule.forChild(dashboardRoutes),
|
||||
MatButtonModule,
|
||||
MatDividerModule,
|
||||
@@ -30,7 +31,8 @@ import { DashboardSettingsModule } from "app/layout/common/dashboard-settings/da
|
||||
MatTableModule,
|
||||
NgApexchartsModule,
|
||||
SharedModule,
|
||||
DashboardSettingsModule
|
||||
DashboardSettingsModule,
|
||||
DashboardDeviceModule
|
||||
]
|
||||
})
|
||||
export class DashboardModule
|
||||
|
||||
@@ -31,6 +31,6 @@ export class DashboardResolver implements Resolve<any>
|
||||
*/
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any>
|
||||
{
|
||||
return this._dashboardService.getData();
|
||||
return this._dashboardService.getSummaryData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ export class DashboardService
|
||||
/**
|
||||
* Get data
|
||||
*/
|
||||
getData(): Observable<any>
|
||||
getSummaryData(): Observable<any>
|
||||
{
|
||||
return this._httpClient.get(getBasePath() + '/api/summary').pipe(
|
||||
tap((response: any) => {
|
||||
@@ -52,4 +52,14 @@ export class DashboardService
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
getSummaryTempData(durationKey: string): Observable<any>
|
||||
{
|
||||
let params = {}
|
||||
if(durationKey){
|
||||
params["duration_key"] = durationKey
|
||||
}
|
||||
|
||||
return this._httpClient.get(getBasePath() + '/api/summary/temp', {params: params});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<div class="flex items-center justify-between w-full my-4 px-4 xs:pr-0">
|
||||
<div class="mr-6">
|
||||
<h2 class="m-0">Drive Details</h2>
|
||||
<h2 class="m-0">Drive Details - {{device | deviceTitle:config.dashboardDisplay}} </h2>
|
||||
<div class="text-secondary tracking-tight">Dive into S.M.A.R.T data</div>
|
||||
</div>
|
||||
<!-- Action buttons -->
|
||||
@@ -51,11 +51,8 @@
|
||||
|
||||
<!-- Card -->
|
||||
<div class="flex flex-auto w-1/4 p-4 lt-md:w-full">
|
||||
<treo-card class="flex flex-auto p-4 pt-6 flex-col flex-auto filter-list">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-2xl font-semibold leading-tight">/dev/{{device?.device_name}}</div>
|
||||
</div>
|
||||
<div class="flex flex-col my-2 grid grid-cols-2">
|
||||
<treo-card class="flex flex-auto p-4 flex-col flex-auto filter-list">
|
||||
<div class="flex flex-col grid grid-cols-2">
|
||||
<div *ngIf="device" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>
|
||||
<span class="inline-flex items-center font-bold text-xs px-2 py-2px rounded-full tracking-wide uppercase"
|
||||
@@ -64,7 +61,7 @@
|
||||
<span class="w-2 h-2 rounded-full mr-2"
|
||||
[ngClass]="{'bg-red': device?.device_status != 0,
|
||||
'bg-green': device?.device_status == 0}"></span>
|
||||
<span class="pr-2px leading-relaxed whitespace-no-wrap">{{device?.device_status == 0 ? 'passed' : 'failed'}}</span>
|
||||
<span class="pr-2px leading-relaxed whitespace-no-wrap">{{device?.device_status | deviceStatus}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-secondary text-md">Status</div>
|
||||
@@ -119,7 +116,7 @@
|
||||
<div class="text-secondary text-md">Powered On</div>
|
||||
</div>
|
||||
<div class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{smart_results[0]?.temp}}°C</div>
|
||||
<div>{{smart_results[0]?.temp | temperature:config.temperatureUnit:true}}</div>
|
||||
<div class="text-secondary text-md">Temperature</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,8 @@ import {fadeOut} from "../../../@treo/animations/fade";
|
||||
import {DetailSettingsComponent} from "app/layout/common/detail-settings/detail-settings.component";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import humanizeDuration from 'humanize-duration';
|
||||
import {TreoConfigService} from "../../../@treo/services/config";
|
||||
import {AppConfig} from "../../core/config/app.config";
|
||||
|
||||
@Component({
|
||||
selector: 'detail',
|
||||
@@ -18,6 +20,8 @@ import humanizeDuration from 'humanize-duration';
|
||||
|
||||
export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
config: AppConfig;
|
||||
|
||||
onlyCritical: boolean = true;
|
||||
// data: any;
|
||||
|
||||
@@ -43,7 +47,9 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
*/
|
||||
constructor(
|
||||
private _detailService: DetailService,
|
||||
public dialog: MatDialog
|
||||
public dialog: MatDialog,
|
||||
private _configService: TreoConfigService,
|
||||
|
||||
|
||||
)
|
||||
{
|
||||
@@ -65,6 +71,14 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
// Subscribe to config changes
|
||||
this._configService.config$
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((config: AppConfig) => {
|
||||
|
||||
this.config = config;
|
||||
});
|
||||
|
||||
// Get the data
|
||||
this._detailService.data$
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
@@ -111,9 +125,9 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
if(attribute_status == 0){
|
||||
return "passed"
|
||||
} else if (attribute_status == 1){
|
||||
return "warn"
|
||||
} else if (attribute_status == 2){
|
||||
return "failed"
|
||||
} else if (attribute_status == 2){
|
||||
return "warn"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,33 +1,70 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import {DeviceTitlePipe} from "./device-title.pipe";
|
||||
|
||||
@Pipe({
|
||||
name: 'deviceSort'
|
||||
})
|
||||
export class DeviceSortPipe implements PipeTransform {
|
||||
|
||||
numericalStatus(device): number {
|
||||
if(!device.smart_results[0]){
|
||||
return 0
|
||||
} else if (device.smart_results[0].smart_status == 'passed'){
|
||||
return 1
|
||||
} else {
|
||||
return -1
|
||||
statusCompareFn(a: any, b: any) {
|
||||
function deviceStatus(deviceSummary): number {
|
||||
if(!deviceSummary.smart){
|
||||
return 0
|
||||
} else if (deviceSummary.device.device_status == 0){
|
||||
return 1
|
||||
} else {
|
||||
return deviceSummary.device.device_status * -1 // will return range from -1, -2, -3
|
||||
}
|
||||
}
|
||||
|
||||
let left = deviceStatus(a)
|
||||
let right = deviceStatus(b)
|
||||
|
||||
return left - right;
|
||||
}
|
||||
|
||||
titleCompareFn(dashboardDisplay: string) {
|
||||
return function (a: any, b: any){
|
||||
let _dashboardDisplay = dashboardDisplay
|
||||
let left = DeviceTitlePipe.deviceTitleForType(a.device, _dashboardDisplay) || DeviceTitlePipe.deviceTitleForType(a.device, 'name')
|
||||
let right = DeviceTitlePipe.deviceTitleForType(b.device, _dashboardDisplay) || DeviceTitlePipe.deviceTitleForType(b.device, 'name')
|
||||
|
||||
if( left < right )
|
||||
return -1;
|
||||
|
||||
if( left > right )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ageCompareFn(a: any, b: any) {
|
||||
const left = a.smart?.power_on_hours
|
||||
const right = b.smart?.power_on_hours
|
||||
|
||||
transform(devices: Array<unknown>, ...args: unknown[]): Array<unknown> {
|
||||
//failed, unknown/empty, passed
|
||||
devices.sort((a: any, b: any) => {
|
||||
|
||||
let left = this.numericalStatus(a)
|
||||
let right = this.numericalStatus(b)
|
||||
|
||||
return left - right;
|
||||
});
|
||||
return left - right;
|
||||
}
|
||||
|
||||
|
||||
return devices;
|
||||
transform(deviceSummaries: Array<unknown>, sortBy = 'status', dashboardDisplay = 'name'): Array<unknown> {
|
||||
let compareFn: any
|
||||
switch (sortBy) {
|
||||
case 'status':
|
||||
compareFn = this.statusCompareFn
|
||||
break;
|
||||
case 'title':
|
||||
compareFn = this.titleCompareFn(dashboardDisplay)
|
||||
break;
|
||||
case 'age':
|
||||
compareFn = this.ageCompareFn
|
||||
break;
|
||||
}
|
||||
|
||||
// failed, unknown/empty, passed
|
||||
deviceSummaries.sort(compareFn);
|
||||
|
||||
return deviceSummaries;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { DeviceStatusPipe } from './device-status.pipe';
|
||||
|
||||
describe('DeviceStatusPipe', () => {
|
||||
it('create an instance', () => {
|
||||
const pipe = new DeviceStatusPipe();
|
||||
expect(pipe).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
@Pipe({
|
||||
name: 'deviceStatus'
|
||||
})
|
||||
export class DeviceStatusPipe implements PipeTransform {
|
||||
|
||||
transform(deviceStatusFlag: number): string {
|
||||
if(deviceStatusFlag === 0){
|
||||
return 'passed'
|
||||
} else if(deviceStatusFlag === 3){
|
||||
return 'failed: both'
|
||||
} else if(deviceStatusFlag === 2) {
|
||||
return 'failed: scrutiny'
|
||||
} else if(deviceStatusFlag === 1) {
|
||||
return 'failed: smart'
|
||||
}
|
||||
return 'unknown'
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { DeviceTitlePipe } from './device-title.pipe';
|
||||
|
||||
describe('DeviceTitlePipe', () => {
|
||||
it('create an instance', () => {
|
||||
const pipe = new DeviceTitlePipe();
|
||||
expect(pipe).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
@Pipe({
|
||||
name: 'deviceTitle'
|
||||
})
|
||||
export class DeviceTitlePipe implements PipeTransform {
|
||||
|
||||
static deviceTitleForType(device: any, titleType: string): string {
|
||||
const titleParts = []
|
||||
switch(titleType){
|
||||
case 'name':
|
||||
titleParts.push(`/dev/${device.device_name}`)
|
||||
if (device.device_type && device.device_type !== 'scsi' && device.device_type !== 'ata'){
|
||||
titleParts.push(device.device_type)
|
||||
}
|
||||
titleParts.push(device.model_name)
|
||||
|
||||
break;
|
||||
case 'serial_id':
|
||||
if(!device.device_serial_id) return ''
|
||||
titleParts.push(`/by-id/${device.device_serial_id}`)
|
||||
break;
|
||||
case 'uuid':
|
||||
if(!device.device_uuid) return ''
|
||||
titleParts.push(`/by-uuid/${device.device_uuid}`)
|
||||
break;
|
||||
case 'label':
|
||||
if(device.label){
|
||||
titleParts.push(device.label)
|
||||
} else if(device.device_label){
|
||||
titleParts.push(`/by-label/${device.device_label}`)
|
||||
}
|
||||
break;
|
||||
}
|
||||
return titleParts.join(' - ')
|
||||
}
|
||||
|
||||
static deviceTitleWithFallback(device, titleType: string): string {
|
||||
console.log(`Displaying Device ${device.wwn} with: ${titleType}`)
|
||||
const titleParts = []
|
||||
if (device.host_id) titleParts.push(device.host_id)
|
||||
|
||||
// add device identifier (fallback to generated device name)
|
||||
titleParts.push(DeviceTitlePipe.deviceTitleForType(device, titleType) || DeviceTitlePipe.deviceTitleForType(device, 'name'))
|
||||
|
||||
return titleParts.join(' - ')
|
||||
}
|
||||
|
||||
|
||||
transform(device: any, titleType: string = 'name'): string {
|
||||
return DeviceTitlePipe.deviceTitleWithFallback(device, titleType)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,19 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import {FileSizePipe} from "./file-size.pipe";
|
||||
import {FileSizePipe} from './file-size.pipe';
|
||||
import { DeviceSortPipe } from './device-sort.pipe';
|
||||
import { TemperaturePipe } from './temperature.pipe';
|
||||
import { DeviceTitlePipe } from './device-title.pipe';
|
||||
import { DeviceStatusPipe } from './device-status.pipe';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
FileSizePipe,
|
||||
DeviceSortPipe
|
||||
DeviceSortPipe,
|
||||
TemperaturePipe,
|
||||
DeviceTitlePipe,
|
||||
DeviceStatusPipe
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
@@ -19,7 +25,10 @@ import { DeviceSortPipe } from './device-sort.pipe';
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
FileSizePipe,
|
||||
DeviceSortPipe
|
||||
DeviceSortPipe,
|
||||
DeviceTitlePipe,
|
||||
DeviceStatusPipe,
|
||||
TemperaturePipe
|
||||
]
|
||||
})
|
||||
export class SharedModule
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { TemperaturePipe } from './temperature.pipe';
|
||||
|
||||
describe('TemperaturePipe', () => {
|
||||
it('create an instance', () => {
|
||||
const pipe = new TemperaturePipe();
|
||||
expect(pipe).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import {formatNumber} from "@angular/common";
|
||||
|
||||
@Pipe({
|
||||
name: 'temperature'
|
||||
})
|
||||
export class TemperaturePipe implements PipeTransform {
|
||||
static celsiusToFahrenheit(celsiusTemp: number): number {
|
||||
return celsiusTemp * 9.0 / 5.0 + 32;
|
||||
}
|
||||
static formatTemperature(celsiusTemp: number, unit: string, includeUnits: boolean): number|string {
|
||||
let convertedTemp
|
||||
let convertedUnitSuffix
|
||||
switch (unit) {
|
||||
case 'celsius':
|
||||
convertedTemp = celsiusTemp
|
||||
convertedUnitSuffix = '°C'
|
||||
break
|
||||
case 'fahrenheit':
|
||||
convertedTemp = TemperaturePipe.celsiusToFahrenheit(celsiusTemp)
|
||||
convertedUnitSuffix = '°F'
|
||||
break
|
||||
}
|
||||
if(includeUnits){
|
||||
return formatNumber(convertedTemp, 'en-US') + convertedUnitSuffix
|
||||
} else {
|
||||
return formatNumber(convertedTemp, 'en-US',)
|
||||
}
|
||||
}
|
||||
|
||||
transform(celsiusTemp: number, unit = 'celsius', includeUnits = false): number|string {
|
||||
return TemperaturePipe.formatTemperature(celsiusTemp, unit, includeUnits)
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,329 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<defs >
|
||||
<font id="IBMPlexMono" horiz-adv-x="600" ><font-face
|
||||
font-family="IBM Plex Mono Medium"
|
||||
units-per-em="1000"
|
||||
panose-1="2 11 6 9 5 2 3 0 2 3"
|
||||
ascent="1025"
|
||||
descent="-275"
|
||||
alphabetic="0" />
|
||||
<glyph unicode=" " glyph-name="space" />
|
||||
<glyph unicode="!" glyph-name="exclam" d="M281 237L240 495V698H360V495L319 237H281ZM300 -10Q254 -10 235 9T216 57V81Q216 110 235 129T300 148Q346 148 365 129T384 81V57Q384 28 365 9T300 -10Z" />
|
||||
<glyph unicode=""" glyph-name="quotedbl" d="M408 442V740H508V442H408ZM349 442V740H449V442H349Z" />
|
||||
<glyph unicode="#" glyph-name="numbersign" d="M135 207H13V291H150L170 407H50V491H185L222 698H313L190 0H99L135 207ZM410 698H501L465 491H587V407H450L430 291H550V207H415L378 0H287L410 698Z" />
|
||||
<glyph unicode="$" glyph-name="dollar" d="M268 -11Q188 -5 133 26T43 105L115 174Q149 133 187 111T273 83V312L250 316Q200 325 165 343T108 387T76 444T66 512Q66 597 119 647T268 708V811H352V708Q418 701 466 675T549 604L476 538Q452 569 421 588T347 612V400L374
|
||||
396Q424 387 459 369T516 326T549 268T559 200Q559 114 506 59T352 -8V-113H268V-11ZM172 515Q172 473 195 450T273 414V614Q172 602 172 515ZM453 195Q453 240 429 263T347 298V84Q399 92 426 120T453 195Z" />
|
||||
<glyph unicode="%" glyph-name="percent" d="M167 348Q98 348 57 394T15 529Q15 617 56 663T167 710Q236 710 277 664T319 529Q319 441 278 395T167 348ZM167 416Q200 416 218 439T236 505V553Q236 595 218 618T167 642Q134 642 116 619T98 553V505Q98 463 116
|
||||
440T167 416ZM499 698H589L432 398H343L499 698ZM168 300H257L101 0H11L168 300ZM433 -12Q364 -12 323 34T281 169Q281 257 322 303T433 350Q502 350 543 304T585 169Q585 81 544 35T433 -12ZM433 56Q466 56 484 79T502 145V193Q502 235 484 258T433 282Q400 282
|
||||
382 259T364 193V145Q364 103 382 80T433 56Z" />
|
||||
<glyph unicode="&" glyph-name="ampersand" d="M213 -12Q167 -12 131 3T71 46T33 108T20 185Q20 242 48 294T145 383Q115 422 98 459T80 538Q80 576 94 607T134 662T193 697T267 710Q302 710 331 700T382 674T420 638T443 596L362 554Q350 585 325 604T265
|
||||
624Q227 624 204 601T180 540V533Q180 518 184 504T197 474T220 439T256 392L332 298L395 215H400Q407 252 409 300T412 390H569V305H496Q490 263 483 228T458 150L583 0H462L378 100H372Q361 49 320 19T213 -12ZM241 77Q275 77 302 90T347 133L192 324Q154 297
|
||||
140 265T126 195V186Q126 135 157 106T241 77Z" />
|
||||
<glyph unicode="'" glyph-name="quotesingle" d="M250 442V740H350V442H250Z" />
|
||||
<glyph unicode="(" glyph-name="parenleft" d="M192 311Q192 384 208 451T253 577T320 681T400 760H509Q464 728 424 685T354 590T306 480T288 357V265Q288 201 306 143T354 32T424 -63T509 -138H400Q358 -107 320 -60T254 45T209 170T192 311Z" />
|
||||
<glyph unicode=")" glyph-name="parenright" d="M408 311Q408 238 392 171T347 45T280 -60T200 -138H91Q136 -106 176 -63T246 32T294 142T312 265V357Q312 421 294 479T246 590T176 685T91 760H200Q242 728 280 682T346 577T391 452T408 311Z" />
|
||||
<glyph unicode="*" glyph-name="asterisk" d="M182 48L105 101L225 263L38 326L66 412L252 349V549H348V349L534 412L562 326L375 263L495 101L418 48L300 210L182 48Z" />
|
||||
<glyph unicode="+" glyph-name="plus" d="M251 62V261H62V350H251V549H349V350H538V261H349V62H251Z" />
|
||||
<glyph unicode="," glyph-name="comma" d="M244 152H399L275 -145H190L244 152Z" />
|
||||
<glyph unicode="-" glyph-name="hyphen" d="M149 250V359H451V250H149Z" />
|
||||
<glyph unicode="." glyph-name="period" d="M300 -10Q252 -10 233 10T213 59V85Q213 114 232 134T300 154Q348 154 367 134T387 85V59Q387 30 368 10T300 -10Z" />
|
||||
<glyph unicode="/" glyph-name="slash" d="M83 -138L420 760H517L180 -138H83Z" />
|
||||
<glyph unicode="0" glyph-name="zero" d="M300 -12Q234 -12 186 12T106 83T59 196T44 349Q44 434 59 501T105 615T185 685T300 710Q366 710 414 686T494 615T541 502T556 349Q556 263 541 196T495 83T415 13T300 -12ZM300 80Q376 80 408 136T441 289V409Q441 505
|
||||
409 561T300 618Q262 618 235 604T191 562T167 496T159 409V289Q159 241 166 203T191 137T235 95T300 80ZM300 290Q265 290 252 304T238 338V360Q238 380 251 394T300 408Q335 408 348 394T362 360V338Q362 318 349 304T300 290Z" />
|
||||
<glyph unicode="1" glyph-name="one" d="M88 0V93H284V616H276L114 443L45 505L223 698H396V93H565V0H88Z" />
|
||||
<glyph unicode="2" glyph-name="two" d="M545 0H63V107L291 306Q345 354 374 397T404 488V499Q404 554 374 583T287 613Q229 613 198 582T152 503L54 540Q64 573 83 603T131 658T201 696T295 710Q349 710 391 695T463 652T507 588T522 505Q522 463 510 428T475
|
||||
360T421 297T353 237L184 95H545V0Z" />
|
||||
<glyph unicode="3" glyph-name="three" d="M271 410Q338 410 370 438T403 510V517Q403 565 372 590T287 616Q236 616 201 593T141 530L65 595Q81 618 102 639T150 675T212 700T291 710Q340 710 382 698T455 663T503 606T520 530Q520 497 510 470T481 423T437 389T384
|
||||
370V365Q414 359 441 346T489 311T522 260T534 192Q534 146 516 109T465 44T384 3T279 -12Q230 -12 193 -2T126 26T76 66T38 113L121 177Q147 135 182 109T280 82Q346 82 381 112T416 197V205Q416 259 380 287T274 316H199V410H271Z" />
|
||||
<glyph unicode="4" glyph-name="four" d="M362 0V136H30V232L322 698H469V224H567V136H469V0H362ZM125 224H362V595H356L125 224Z" />
|
||||
<glyph unicode="5" glyph-name="five" d="M511 601H194L176 353H184Q208 394 242 418T335 443Q380 443 418 428T485 385T530 317T547 225Q547 173 530 130T481 55T402 6T295 -12Q248 -12 212 -2T147 26T97 66T60 113L142 177Q155 157 169 140T202 109T243 89T297
|
||||
82Q362 82 396 117T430 214V222Q430 283 396 317T297 351Q250 351 223 334T176 296L83 309L109 698H511V601Z" />
|
||||
<glyph unicode="6" glyph-name="six" d="M302 -12Q243 -12 197 7T119 61T70 147T53 260Q53 336 76 403T136 526T218 625T307 698H457Q397 655 349 615T266 533T206 445T169 341L176 339Q187 360 202 378T237 411T283 433T342 441Q387 441 425 426T491 383T534
|
||||
314T550 224Q550 172 533 129T483 54T404 6T302 -12ZM301 78Q365 78 400 112T435 210V220Q435 283 400 317T301 352Q238 352 203 318T168 220V210Q168 147 203 113T301 78Z" />
|
||||
<glyph unicode="7" glyph-name="seven" d="M169 0L428 605H156V476H59V698H540V600L288 0H169Z" />
|
||||
<glyph unicode="8" glyph-name="eight" d="M300 -12Q238 -12 191 3T112 46T64 110T47 191Q47 261 86 303T188 362V370Q134 389 101 430T68 531Q68 612 128 661T300 710Q411 710 471 661T532 531Q532 471 499 430T412 370V362Q475 345 514 303T553 191Q553 147
|
||||
537 110T488 46T409 4T300 -12ZM300 77Q366 77 401 106T437 188V209Q437 262 402 291T300 320Q234 320 199 291T163 209V188Q163 135 198 106T300 77ZM300 406Q360 406 391 432T423 507V520Q423 568 392 594T300 621Q240 621 209 595T177 520V507Q177 459 208 433T300
|
||||
406Z" />
|
||||
<glyph unicode="9" glyph-name="nine" d="M547 438Q547 362 524 295T464 172T382 72T293 0H143Q203 43 251 83T334 165T394 253T431 357L424 359Q413 338 398 320T363 287T317 265T258 257Q213 257 175 272T109 315T66 384T50 474Q50 526 67 569T117 644T196 692T298
|
||||
710Q356 710 402 691T481 637T530 551T547 438ZM299 346Q362 346 397 380T432 478V488Q432 551 397 585T299 620Q235 620 200 586T165 488V478Q165 415 200 381T299 346Z" />
|
||||
<glyph unicode=":" glyph-name="colon" d="M300 -10Q252 -10 233 10T213 59V85Q213 114 232 134T300 154Q348 154 367 134T387 85V59Q387 30 368 10T300 -10ZM300 362Q252 362 233 382T213 431V457Q213 486 232 506T300 526Q348 526 367 506T387 457V431Q387 402
|
||||
368 382T300 362Z" />
|
||||
<glyph unicode=";" glyph-name="semicolon" d="M244 152H399L275 -145H190L244 152ZM300 362Q252 362 233 382T213 431V457Q213 486 232 506T300 526Q348 526 367 506T387 457V431Q387 402 368 382T300 362Z" />
|
||||
<glyph unicode="<" glyph-name="less" d="M85 253V357L515 598V492L184 309V301L515 119V12L85 253Z" />
|
||||
<glyph unicode="=" glyph-name="equal" d="M62 367V456H538V367H62ZM62 155V244H538V155H62Z" />
|
||||
<glyph unicode=">" glyph-name="greater" d="M85 118L416 301V309L85 491V598L515 357V253L85 12V118Z" />
|
||||
<glyph unicode="?" glyph-name="question" d="M226 223V378Q307 381 354 410T401 503V517Q401 567 372 591T293 615Q241 615 209 586T165 511L70 549Q79 580 97 609T143 661T209 696T297 710Q347 710 387 696T457 657T501 595T517 514Q517 469 501 434T459 374T400
|
||||
333T331 311V223H226ZM281 -10Q235 -10 216 9T197 57V81Q197 110 216 129T281 148Q327 148 346 129T365 81V57Q365 28 346 9T281 -10Z" />
|
||||
<glyph unicode="@" glyph-name="at" d="M451 -112H335Q256 -112 202 -87T115 -10T67 120T52 302Q52 417 68 495T116 621T194 689T301 710Q363 710 407 691T481 639T523 561T537 463V91H451V150H445Q434 119 411 100T347 80Q288 80 253 131T218 294Q218 405 253
|
||||
456T347 508Q388 508 411 488T445 438H451V463Q451 633 305 633Q264 633 233 619T182 571T152 486T142 358V229Q142 171 151 123T182 39T241 -15T335 -35H451V-112ZM381 150Q413 150 432 168T451 220V368Q451 402 432 420T381 438Q346 438 327 414T308 326V262Q308
|
||||
199 327 175T381 150Z" />
|
||||
<glyph unicode="A" glyph-name="A" d="M462 0L409 186H187L134 0H20L224 698H377L581 0H462ZM302 585H294L208 279H388L302 585Z" />
|
||||
<glyph unicode="B" glyph-name="B" d="M83 698H324Q419 698 471 649T524 515Q524 454 494 418T413 367V362Q474 348 511 309T548 197Q548 154 534 118T494 56T432 15T351 0H83V698ZM317 86Q373 86 403 109T433 183V219Q433 270 403 293T317 316H193V86H317ZM301
|
||||
398Q354 398 381 418T409 487V523Q409 571 382 591T301 612H193V398H301Z" />
|
||||
<glyph unicode="C" glyph-name="C" d="M320 -12Q187 -12 123 82T58 349Q58 522 122 616T320 710Q371 710 408 697T473 660T518 605T549 537L448 503Q440 527 430 548T405 584T370 608T319 617Q245 617 211 561T177 408V290Q177 194 211 138T319 81Q349 81 369
|
||||
90T405 114T430 150T448 195L549 161Q537 125 519 94T473 39T409 2T320 -12Z" />
|
||||
<glyph unicode="D" glyph-name="D" d="M82 698H290Q424 698 488 609T553 349Q553 178 489 89T290 0H82V698ZM283 92Q360 92 397 143T435 291V407Q435 503 398 554T283 606H193V92H283Z" />
|
||||
<glyph unicode="E" glyph-name="E" d="M86 0V698H523V604H198V401H511V307H198V94H523V0H86Z" />
|
||||
<glyph unicode="F" glyph-name="F" d="M86 0V698H535V604H198V401H504V307H198V0H86Z" />
|
||||
<glyph unicode="G" glyph-name="G" d="M430 96H423Q414 75 402 56T371 21T326 -3T266 -12Q157 -12 102 81T47 344Q47 522 110 616T303 710Q354 710 392 696T458 659T503 604T532 537L431 503Q423 526 413 546T389 583T354 608T304 617Q231 617 199 561T166 408V297Q166
|
||||
249 173 209T196 141T239 96T304 80Q365 80 397 116T430 210V273H295V357H532V0H430V96Z" />
|
||||
<glyph unicode="H" glyph-name="H" d="M416 307H184V0H72V698H184V401H416V698H528V0H416V307Z" />
|
||||
<glyph unicode="I" glyph-name="I" d="M80 0V85H244V613H80V698H520V613H356V85H520V0H80Z" />
|
||||
<glyph unicode="J" glyph-name="J" d="M493 698V187Q493 142 478 105T434 42T365 2T276 -12Q184 -12 130 34T59 161L165 183Q174 140 199 111T277 82Q326 82 353 111T381 202V604H138V698H493Z" />
|
||||
<glyph unicode="K" glyph-name="K" d="M274 321L190 216V0H78V698H190V364H195L280 480L451 698H580L350 404L589 0H461L274 321Z" />
|
||||
<glyph unicode="L" glyph-name="L" d="M108 0V698H220V94H538V0H108Z" />
|
||||
<glyph unicode="M" glyph-name="M" d="M445 334L448 544H440L300 185L160 544H152L155 334V0H56V698H193L300 421H307L415 698H544V0H445V334Z" />
|
||||
<glyph unicode="N" glyph-name="N" d="M179 537H170V0H72V698H216L421 161H430V698H528V0H384L179 537Z" />
|
||||
<glyph unicode="O" glyph-name="O" d="M300 -12Q234 -12 186 12T106 83T59 196T44 349Q44 434 59 501T105 615T185 685T300 710Q366 710 414 686T494 615T541 502T556 349Q556 263 541 196T495 83T415 13T300 -12ZM300 81Q375 81 406 137T437 291V408Q437 504
|
||||
406 560T300 617Q225 617 194 561T163 408V290Q163 194 194 138T300 81Z" />
|
||||
<glyph unicode="P" glyph-name="P" d="M84 0V698H345Q445 698 497 642T550 488Q550 390 498 334T345 278H196V0H84ZM196 371H328Q432 371 432 467V510Q432 605 328 605H196V371Z" />
|
||||
<glyph unicode="Q" glyph-name="Q" d="M506 -175H378Q310 -175 280 -140T250 -46V-8Q197 1 158 29T94 102T56 210T44 349Q44 434 59 501T105 615T185 685T300 710Q366 710 414 686T494 615T541 502T556 349Q556 195 506 102T350 -8V-91H506V-175ZM300 81Q375 81
|
||||
406 137T437 291V408Q437 504 406 560T300 617Q225 617 194 561T163 408V290Q163 194 194 138T300 81Z" />
|
||||
<glyph unicode="R" glyph-name="R" d="M195 0H84V698H345Q445 698 497 642T550 488Q550 408 511 356T399 292L560 0H436L288 282H195V0ZM329 372Q433 372 433 467V510Q433 605 329 605H195V372H329Z" />
|
||||
<glyph unicode="S" glyph-name="S" d="M294 -12Q203 -12 141 20T39 105L111 174Q151 126 196 104T298 81Q364 81 399 111T435 197Q435 242 409 266T320 302L244 314Q194 322 160 340T105 384T75 441T65 508Q65 607 129 658T305 710Q388 710 446 684T541 609L471
|
||||
539Q442 574 403 595T305 617Q243 617 211 591T178 513Q178 470 203 446T294 410L368 397Q462 380 505 329T548 203Q548 155 532 115T483 47T403 4T294 -12Z" />
|
||||
<glyph unicode="T" glyph-name="T" d="M356 604V0H244V604H25V698H575V604H356Z" />
|
||||
<glyph unicode="U" glyph-name="U" d="M181 698V269Q181 226 183 191T198 132T234 94T300 81Q342 81 366 94T402 131T416 191T419 269V698H531V289Q531 214 523 158T489 64T419 7T300 -12Q227 -12 182 7T111 63T78 157T69 289V698H181Z" />
|
||||
<glyph unicode="V" glyph-name="V" d="M222 0L25 698H146L238 346L299 109H305L366 346L459 698H575L378 0H222Z" />
|
||||
<glyph unicode="W" glyph-name="W" d="M75 0L25 698H123L148 292L159 113H167L246 529H357L436 113H444L455 292L481 698H575L525 0H375L304 404H296L225 0H75Z" />
|
||||
<glyph unicode="X" glyph-name="X" d="M582 0H455L376 138L302 270H296L220 138L138 0H19L233 358L32 698H159L230 573L302 444H307L379 573L453 698H572L370 358L582 0Z" />
|
||||
<glyph unicode="Y" glyph-name="Y" d="M244 0V263L12 698H137L226 524L298 375H304L377 524L466 698H588L356 263V0H244Z" />
|
||||
<glyph unicode="Z" glyph-name="Z" d="M552 0H48V99L415 604H62V698H538V599L171 94H552V0Z" />
|
||||
<glyph unicode="[" glyph-name="bracketleft" d="M207 -138V760H506V682H297V-60H506V-138H207Z" />
|
||||
<glyph unicode="\" glyph-name="backslash" d="M420 -138L83 760H180L517 -138H420Z" />
|
||||
<glyph unicode="]" glyph-name="bracketright" d="M393 760V-138H94V-60H303V682H94V760H393Z" />
|
||||
<glyph unicode="^" glyph-name="asciicircum" d="M475 267L301 601H294L120 267L37 307L241 698H359L563 307L475 267Z" />
|
||||
<glyph unicode="_" glyph-name="underscore" d="M60 -179V-85H540V-179H60Z" />
|
||||
<glyph unicode="`" glyph-name="grave" d="M171 745L265 791L356 611L289 579L171 745Z" />
|
||||
<glyph unicode="a" glyph-name="a" d="M492 0Q445 0 422 24T393 87H388Q373 40 334 14T233 -12Q154 -12 107 29T60 144Q60 219 115 258T286 298H385V338Q385 443 274 443Q224 443 193 424T141 372L76 425Q98 467 150 497T284 528Q382 528 438 481T494 345V86H559V0H492ZM264
|
||||
68Q317 68 351 92T385 154V229H288Q170 229 170 158V138Q170 103 195 86T264 68Z" />
|
||||
<glyph unicode="b" glyph-name="b" d="M79 740H188V428H194Q217 475 255 501T350 528Q441 528 495 460T549 258Q549 124 495 56T350 -12Q293 -12 255 14T194 88H188V0H79V740ZM305 77Q367 77 400 115T434 216V300Q434 363 401 401T305 439Q281 439 260 433T223
|
||||
415T198 386T188 344V172Q188 148 197 131T223 101T260 83T305 77Z" />
|
||||
<glyph unicode="c" glyph-name="c" d="M319 -12Q261 -12 216 7T139 61T91 146T74 258Q74 320 90 370T138 455T215 509T318 528Q398 528 446 494T519 406L434 360Q420 396 392 417T318 438Q256 438 222 401T188 301V215Q188 154 222 116T320 78Q368 78 398 100T447
|
||||
160L527 111Q502 57 451 23T319 -12Z" />
|
||||
<glyph unicode="d" glyph-name="d" d="M412 88H406Q383 41 345 15T250 -12Q159 -12 105 56T51 258Q51 392 105 460T250 528Q307 528 345 502T406 428H412V740H521V0H412V88ZM295 77Q319 77 340 83T377 101T402 130T412 172V344Q412 368 403 385T377 415T340 433T295
|
||||
439Q233 439 200 401T166 300V216Q166 153 199 115T295 77Z" />
|
||||
<glyph unicode="e" glyph-name="e" d="M311 -12Q252 -12 205 7T126 61T77 145T60 257Q60 319 77 369T126 454T203 509T303 528Q357 528 401 510T476 457T523 376T540 272V231H170V214Q170 153 208 115T313 76Q363 76 398 97T456 155L524 95Q498 50 445 19T311
|
||||
-12ZM303 445Q274 445 250 435T208 407T180 363T170 308V301H429V311Q429 372 395 408T303 445Z" />
|
||||
<glyph unicode="f" glyph-name="f" d="M78 88H243V428H68V516H243V609Q243 667 275 703T375 740H549V652H352V516H549V428H352V88H526V0H78V88Z" />
|
||||
<glyph unicode="g" glyph-name="g" d="M570 -56Q570 -136 503 -174T299 -212Q232 -212 187 -204T113 -179T72 -140T59 -88Q59 -46 82 -23T149 12V22Q123 32 108 50T92 97Q92 135 118 154T185 184V189Q138 211 112 251T86 347Q86 388 101 421T143 478T209 515T296
|
||||
528Q350 528 393 511V528Q393 558 410 578T462 598H556V512H436V488Q470 465 488 430T506 347Q506 306 491 273T449 216T383 180T296 167Q262 167 232 173Q214 168 196 156T178 123Q178 99 201 93T258 87H374Q478 87 524 48T570 -56ZM468 -63Q468 -37 447 -22T371
|
||||
-6H192Q154 -24 154 -64Q154 -93 178 -114T260 -135H341Q403 -135 435 -117T468 -63ZM296 242Q349 242 374 267T399 334V361Q399 403 374 428T296 453Q243 453 218 428T193 361V334Q193 292 218 267T296 242Z" />
|
||||
<glyph unicode="h" glyph-name="h" d="M84 740H193V428H198Q206 448 218 466T249 498T291 520T347 528Q425 528 473 477T521 332V0H412V316Q412 439 305 439Q284 439 264 434T228 417T203 389T193 350V0H84V740Z" />
|
||||
<glyph unicode="i" glyph-name="i" d="M332 610Q290 610 274 627T257 669V690Q257 715 273 732T331 749Q373 749 389 732T406 690V669Q406 644 390 627T332 610ZM101 88H277V428H101V516H386V88H551V0H101V88Z" />
|
||||
<glyph unicode="j" glyph-name="j" d="M98 -112H326V428H92V516H435V-69Q435 -127 403 -163T302 -200H98V-112ZM381 610Q339 610 323 627T306 669V690Q306 715 322 732T380 749Q422 749 438 732T455 690V669Q455 644 439 627T381 610Z" />
|
||||
<glyph unicode="k" glyph-name="k" d="M88 740H197V293H202L283 376L428 516H557L348 313L580 0H449L269 251L197 184V0H88V740Z" />
|
||||
<glyph unicode="l" glyph-name="l" d="M75 88H246V652H75V740H355V88H526V0H75V88Z" />
|
||||
<glyph unicode="m" glyph-name="m" d="M44 0V516H137V449H142Q154 482 176 505T241 528Q282 528 304 506T333 444H337Q351 479 376 503T448 528Q508 528 531 486T555 363V0H462V349Q462 403 449 423T407 444Q381 444 364 427T346 374V0H253V349Q253 403 241 423T199
|
||||
444Q172 444 155 427T137 374V0H44Z" />
|
||||
<glyph unicode="n" glyph-name="n" d="M84 0V516H193V428H198Q206 448 218 466T249 498T291 520T347 528Q425 528 473 477T521 332V0H412V316Q412 439 305 439Q284 439 264 434T228 417T203 389T193 350V0H84Z" />
|
||||
<glyph unicode="o" glyph-name="o" d="M300 -12Q243 -12 198 7T121 61T72 146T55 258Q55 320 72 370T120 455T197 509T300 528Q357 528 402 509T479 455T528 370T545 258Q545 196 528 146T480 61T403 7T300 -12ZM300 74Q360 74 395 110T431 219V297Q431 369 396
|
||||
405T300 442Q240 442 205 406T169 297V219Q169 147 204 111T300 74Z" />
|
||||
<glyph unicode="p" glyph-name="p" d="M79 516H188V428H194Q217 475 255 501T350 528Q441 528 495 460T549 258Q549 124 495 56T350 -12Q293 -12 255 14T194 88H188V-200H79V516ZM305 77Q367 77 400 115T434 216V300Q434 363 401 401T305 439Q281 439 260 433T223
|
||||
415T198 386T188 344V172Q188 148 197 131T223 101T260 83T305 77Z" />
|
||||
<glyph unicode="q" glyph-name="q" d="M412 88H406Q383 41 345 15T250 -12Q159 -12 105 56T51 258Q51 392 105 460T250 528Q307 528 345 502T406 428H412V516H521V-200H412V88ZM295 77Q319 77 340 83T377 101T402 130T412 172V344Q412 368 403 385T377 415T340
|
||||
433T295 439Q233 439 200 401T166 300V216Q166 153 199 115T295 77Z" />
|
||||
<glyph unicode="r" glyph-name="r" d="M76 88H213V428H76V516H322V379H328Q335 406 348 431T381 474T430 504T498 516H560V412H458Q398 412 360 377T322 281V88H509V0H76V88Z" />
|
||||
<glyph unicode="s" glyph-name="s" d="M301 -12Q217 -12 157 15T59 87L126 147Q160 110 202 91T303 71Q356 71 388 89T421 145Q421 161 415 172T398 190T373 201T342 207L260 220Q230 224 199 233T144 258T104 301T88 367Q88 446 148 487T308 528Q380 528 432
|
||||
507T520 447L459 383Q439 406 402 425T304 445Q195 445 195 376Q195 343 218 331T274 314L356 301Q387 296 417 288T472 264T512 221T528 155Q528 77 468 33T301 -12Z" />
|
||||
<glyph unicode="t" glyph-name="t" d="M331 0Q263 0 231 36T199 131V428H40V516H153Q182 516 194 527T206 569V698H308V516H528V428H308V88H528V0H331Z" />
|
||||
<glyph unicode="u" glyph-name="u" d="M407 88H402Q394 68 382 50T351 18T309 -4T253 -12Q175 -12 127 39T79 184V516H188V200Q188 77 295 77Q316 77 336 82T372 99T397 126T407 166V516H516V0H407V88Z" />
|
||||
<glyph unicode="v" glyph-name="v" d="M233 0L48 516H161L232 298L299 91H305L372 298L443 516H552L367 0H233Z" />
|
||||
<glyph unicode="w" glyph-name="w" d="M20 516H113L163 82H172L249 516H355L431 82H440L491 516H580L508 0H374L305 400H296L226 0H92L20 516Z" />
|
||||
<glyph unicode="x" glyph-name="x" d="M45 0L237 262L53 516H180L248 418L302 340H308L361 418L429 516H547L362 266L556 0H428L351 111L298 187H292L240 111L164 0H45Z" />
|
||||
<glyph unicode="y" glyph-name="y" d="M451 516H561L311 -100Q291 -150 259 -175T165 -200H78V-112H200L247 7L39 516H153L235 300L299 123H305L369 300L451 516Z" />
|
||||
<glyph unicode="z" glyph-name="z" d="M77 0V96L391 428H88V516H513V420L199 88H523V0H77Z" />
|
||||
<glyph unicode="{" glyph-name="braceleft" d="M324 -138Q271 -138 247 -112T222 -45V10Q222 36 227 56T240 91T259 119T278 142Q295 162 301 176T308 207Q308 272 183 272H100V350H183Q308 350 308 415Q308 431 302 445T278 480Q269 491 259 503T241 531T228
|
||||
566T222 612V667Q222 707 246 733T324 760H500V682H312V618Q312 598 315 584T323 557T336 535T352 515Q369 494 384 470T399 414Q399 372 370 347T286 314V308Q340 301 369 276T399 208Q399 176 384 152T352 107Q344 97 337 87T324 65T315 39T312 4V-60H500V-138H324Z"
|
||||
/>
|
||||
<glyph unicode="|" glyph-name="bar" d="M253 -138V760H347V-138H253Z" />
|
||||
<glyph unicode="}" glyph-name="braceright" d="M276 760Q329 760 353 734T378 667V612Q378 586 373 566T359 531T341 504T322 480Q305 460 299 446T292 415Q292 350 417 350H500V272H417Q292 272 292 207Q292 191 298 177T322 142Q331 130 341 118T359 91T373
|
||||
56T378 10V-45Q378 -85 354 -111T276 -138H100V-60H288V4Q288 44 276 65T248 107Q231 128 216 152T201 208Q201 250 230 275T314 308V314Q260 321 231 346T201 414Q201 446 216 470T248 515Q264 535 276 556T288 618V682H100V760H276Z" />
|
||||
<glyph unicode="~" glyph-name="asciitilde" d="M408 225Q377 225 350 235T293 260Q267 273 244 283T198 294Q171 294 155 276T125 225L45 256Q59 313 96 349T192 385Q223 385 250 375T307 350Q333 337 356 327T402 316Q429 316 445 334T475 385L555 354Q541 297
|
||||
504 261T408 225Z" />
|
||||
<glyph unicode=" " glyph-name="uni00A0" />
|
||||
<glyph unicode="¡" glyph-name="exclamdown" d="M240 -182V21L281 279H319L360 21V-182H240ZM300 368Q254 368 235 387T216 435V459Q216 488 235 507T300 526Q346 526 365 507T384 459V435Q384 406 365 387T300 368Z" />
|
||||
<glyph unicode="¢" glyph-name="cent" d="M270 -114V-8Q176 7 125 77T74 258Q74 368 125 438T270 524V630H354V526Q417 518 457 486T519 406L437 362Q426 391 404 411T350 438V77Q385 84 410 105T450 158L527 111Q505 63 463 31T354 -10V-114H270ZM183 215Q183
|
||||
164 206 128T275 80V436Q230 424 207 388T183 301V215Z" />
|
||||
<glyph unicode="£" glyph-name="sterling" d="M72 0V118Q114 135 134 167T154 245Q154 262 151 279H49V365H125Q113 397 103 429T93 501Q93 547 110 585T158 652T234 695T333 710Q411 710 465 681T554 600L476 535Q450 571 417 592T332 613Q275 613 241 583T207
|
||||
488Q207 453 216 424T236 365H426V279H262Q263 272 263 266T264 253Q264 224 257 201T238 160T212 129T183 107V100H544V0H72Z" />
|
||||
<glyph unicode="¥" glyph-name="yen" d="M67 87H247V241H67V328H192L13 698H132L298 328H305L471 698H587L408 328H533V241H353V87H533V0H67V87Z" />
|
||||
<glyph unicode="¦" glyph-name="brokenbar" d="M253 401V760H347V401H253ZM253 -138V221H347V-138H253Z" />
|
||||
<glyph unicode="§" glyph-name="section" d="M497 3Q497 -35 482 -66T439 -119T373 -152T287 -164Q239 -164 191 -150T104 -101L162 -32Q187 -55 218 -67T288 -80Q339 -80 368 -59T398 0Q398 33 373 52T300 85L230 105Q146 128 110 168T74 258Q74 304 102
|
||||
340T185 398V408Q145 433 127 467T108 543Q108 581 123 612T166 664T232 698T318 710Q366 710 414 696T501 647L443 578Q418 601 387 613T317 626Q266 626 237 605T207 546Q207 513 232 494T305 461L375 441Q459 418 495 378T531 288Q531 242 503 206T420 148V138Q460
|
||||
113 478 79T497 3ZM433 258Q433 294 410 318T329 358L260 376Q251 378 243 381T227 387Q201 367 187 343T172 288Q172 252 195 228T276 188L345 170Q354 168 362 165T378 159Q404 179 418 203T433 258Z" />
|
||||
<glyph unicode="¨" glyph-name="dieresis" d="M200 607Q163 607 148 622T133 660V679Q133 702 148 717T200 732Q237 732 252 717T267 679V660Q267 637 252 622T200 607ZM400 607Q363 607 348 622T333 660V679Q333 702 348 717T400 732Q437 732 452 717T467
|
||||
679V660Q467 637 452 622T400 607Z" />
|
||||
<glyph unicode="©" glyph-name="copyright" d="M300 18Q237 18 183 41T88 107T24 211T0 349Q0 425 23 486T87 591T182 657T300 680Q363 680 417 657T512 591T576 487T600 349Q600 272 577 211T513 107T418 41T300 18ZM300 73Q351 73 394 92T469 144T519 223T537
|
||||
319V379Q537 430 519 475T470 553T395 606T300 625Q249 625 206 606T131 554T81 475T63 379V319Q63 268 81 223T130 145T205 92T300 73ZM307 163Q229 163 185 213T140 349Q140 434 185 484T307 535Q361 535 394 510T444 445L378 410Q367 434 351 448T308 462Q273
|
||||
462 253 440T233 380V317Q233 281 252 259T309 236Q338 236 355 251T385 289L450 253Q433 215 399 189T307 163Z" />
|
||||
<glyph unicode="ª" glyph-name="ordfeminine" d="M429 350Q397 350 380 365T361 407H357Q346 379 319 361T246 342Q192 342 163 369T133 445Q133 499 173 525T288 552H355V575Q355 648 283 648Q249 648 227 634T192 599L144 640Q160 668 196 689T290 710Q358
|
||||
710 396 677T435 579V414H474V350H429ZM288 501Q252 501 233 490T213 456V444Q213 421 228 411T270 400Q305 400 330 415T355 460V501H288Z" />
|
||||
<glyph unicode="«" glyph-name="guillemotleft" d="M528 47L324 219V321L528 493L561 420L421 270L561 120L528 47ZM508 47L304 219V321L508 493L541 420L401 270L541 120L508 47Z" />
|
||||
<glyph unicode="¬" glyph-name="logicalnot" d="M431 68V261H62V350H522V68H431Z" />
|
||||
<glyph unicode="­" glyph-name="uni00AD" d="M149 250V359H451V250H149Z" />
|
||||
<glyph unicode="®" glyph-name="registered" d="M300 346Q262 346 229 360T170 398T131 455T117 528Q117 567 131 600T170 658T228 696T300 710Q338 710 371 696T429 658T468 601T483 528Q483 489 469 456T430 398T372 360T300 346ZM300 387Q329 387 353
|
||||
396T396 423T424 464T435 518V538Q435 568 425 592T396 633T354 659T300 669Q271 669 247 660T204 633T176 592T165 538V518Q165 488 175 464T204 423T246 397T300 387ZM273 436H227V621H315Q347 621 363 605T379 561Q379 541 370 528T343 507L386 436H335L299
|
||||
499H273V436ZM304 533Q330 533 330 555V563Q330 585 304 585H273V533H304Z" />
|
||||
<glyph unicode="¯" glyph-name="overscore" d="M155 710H445V628H155V710Z" />
|
||||
<glyph unicode="°" glyph-name="degree" d="M300 354Q262 354 230 367T173 405T136 461T122 532Q122 570 135 602T173 659T229 696T300 710Q337 710 369 697T426 659T464 603T478 532Q478 494 464 462T426 405T370 368T300 354ZM300 431Q343 431 369 460T395
|
||||
532Q395 575 369 604T300 633Q257 633 231 604T205 532Q205 489 231 460T300 431Z" />
|
||||
<glyph unicode="±" glyph-name="plusminus" d="M251 164V350H62V439H251V625H349V439H538V350H349V164H251ZM62 0V89H538V0H62Z" />
|
||||
<glyph unicode="²" glyph-name="twosuperior" d="M443 329H164V399L285 495Q318 521 333 541T349 586V590Q349 614 334 626T293 638Q263 638 248 623T225 585L156 611Q170 649 204 676T300 704Q364 704 399 673T434 593Q434 570 426 550T404 513T371 481T331
|
||||
450L250 393H443V329Z" />
|
||||
<glyph unicode="³" glyph-name="threesuperior" d="M283 551Q317 551 332 563T348 594V598Q348 618 333 630T292 642Q240 642 210 598L159 642Q180 670 211 687T294 704Q357 704 394 678T432 606Q432 571 410 550T355 523V520Q390 514 414 492T438 432Q438
|
||||
382 398 353T290 323Q231 323 198 344T146 393L205 437Q218 414 237 400T290 385Q322 385 338 398T355 436V440Q355 465 337 476T285 487H246V551H283Z" />
|
||||
<glyph unicode="´" glyph-name="acute" d="M311 579L244 611L335 791L429 745L311 579Z" />
|
||||
<glyph unicode="µ" glyph-name="mu" d="M84 -200V516H193V204Q193 77 297 77Q318 77 338 82T373 99T397 126T407 166V516H516V0H407V88H402Q394 68 384 50T357 18T320 -4T272 -12Q241 -12 219 -1T181 36H176L193 -69V-200H84Z" />
|
||||
<glyph unicode="¶" glyph-name="paragraph" d="M260 246Q213 246 173 263T101 310T53 381T35 472Q35 521 52 562T101 634T172 681T260 698H524V-149H432V612H352V-149H260V246Z" />
|
||||
<glyph unicode="·" glyph-name="middot" d="M300 222Q252 222 233 242T213 291V317Q213 346 232 366T300 386Q348 386 367 366T387 317V291Q387 262 368 242T300 222Z" />
|
||||
<glyph unicode="¸" glyph-name="cedilla" d="M313 -209Q268 -209 242 -195T203 -167L245 -120Q254 -131 269 -139T308 -148Q327 -148 339 -141T352 -119Q352 -107 338 -96T281 -79L256 -76L276 24H333L316 -58L320 -62Q331 -59 341 -57T363 -55Q392 -55 412
|
||||
-71T433 -123Q433 -146 423 -162T397 -188T359 -204T313 -209Z" />
|
||||
<glyph unicode="¹" glyph-name="onesuperior" d="M181 329V391H283V628L189 581L158 637L278 698H362V391H453V329H181Z" />
|
||||
<glyph unicode="º" glyph-name="ordmasculine" d="M300 342Q221 342 176 391T131 526Q131 612 176 661T300 710Q379 710 424 661T469 526Q469 440 424 391T300 342ZM300 405Q341 405 362 430T384 497V555Q384 597 363 622T300 647Q259 647 238 622T216 555V497Q216
|
||||
455 237 430T300 405Z" />
|
||||
<glyph unicode="»" glyph-name="guillemotright" d="M60 120L200 270L60 420L93 493L297 321V219L93 47L60 120ZM296 120L436 270L296 420L329 493L533 321V219L329 47L296 120Z" />
|
||||
<glyph unicode="¼" glyph-name="onequarter" d="M39 421H129V636L45 593L18 643L124 698H202V421H282V363H39V421ZM504 698H589L424 398H339L504 698ZM176 300H261L96 0H11L176 300ZM471 64H313V129L450 335H541V117H587V64H541V0H471V64ZM471 117V269H467L365
|
||||
117H471Z" />
|
||||
<glyph unicode="½" glyph-name="onehalf" d="M39 421H129V636L45 593L18 643L124 698H202V421H282V363H39V421ZM504 698H589L424 398H339L504 698ZM176 300H261L96 0H11L176 300ZM326 65L436 151Q466 175 478 194T491 237V241Q491 259 478 270T443 281Q418
|
||||
281 404 267T380 230L318 254Q324 271 334 286T359 314T397 333T448 341Q507 341 538 313T569 242Q569 221 562 204T541 170T510 138T472 108L405 58H578V0H326V65Z" />
|
||||
<glyph unicode="¾" glyph-name="threequarters" d="M146 357Q92 357 62 378T15 426L69 463Q80 442 98 428T145 414Q172 414 186 426T201 458V465Q201 486 184 497T136 508H105V563H138Q168 563 182 574T196 601V609Q196 626 183 636T146 647Q99 647 71 606L25
|
||||
646Q45 673 73 688T147 704Q204 704 238 680T272 615Q272 583 252 564T202 539V535Q235 530 256 511T278 456Q278 411 242 384T146 357ZM504 698H589L424 398H339L504 698ZM176 300H261L96 0H11L176 300ZM471 64H313V129L450 335H541V117H587V64H541V0H471V64ZM471
|
||||
117V269H467L365 117H471Z" />
|
||||
<glyph unicode="¿" glyph-name="questiondown" d="M303 -194Q253 -194 213 -180T143 -141T99 -79T83 2Q83 47 99 82T141 142T200 183T269 205V293H374V138Q293 135 246 106T199 13V-1Q199 -51 228 -75T307 -99Q359 -99 391 -70T435 5L530 -33Q521 -65 503
|
||||
-94T457 -145T391 -180T303 -194ZM319 368Q273 368 254 387T235 435V459Q235 488 254 507T319 526Q365 526 384 507T403 459V435Q403 406 384 387T319 368Z" />
|
||||
<glyph unicode="À" glyph-name="Agrave" d="M462 0L409 186H187L134 0H20L224 698H377L581 0H462ZM302 585H294L208 279H388L302 585ZM171 915L265 961L356 781L289 749L171 915Z" />
|
||||
<glyph unicode="Á" glyph-name="Aacute" d="M462 0L409 186H187L134 0H20L224 698H377L581 0H462ZM302 585H294L208 279H388L302 585ZM311 749L244 781L335 961L429 915L311 749Z" />
|
||||
<glyph unicode="Â" glyph-name="Acircumflex" d="M462 0L409 186H187L134 0H20L224 698H377L581 0H462ZM302 585H294L208 279H388L302 585ZM355 944L475 794L417 752L299 868L180 752L125 794L245 944H355Z" />
|
||||
<glyph unicode="Ã" glyph-name="Atilde" d="M462 0L409 186H187L134 0H20L224 698H377L581 0H462ZM302 585H294L208 279H388L302 585ZM374 774Q349 774 331 781T296 797Q273 808 256 814T222 820Q205 820 192 814T164 794L123 846Q138 869 163 886T226 903Q251
|
||||
903 269 896T304 880Q327 869 344 863T378 857Q395 857 408 863T436 883L477 831Q462 808 437 791T374 774Z" />
|
||||
<glyph unicode="Ä" glyph-name="Adieresis" d="M462 0L409 186H187L134 0H20L224 698H377L581 0H462ZM302 585H294L208 279H388L302 585ZM200 777Q163 777 148 792T133 830V849Q133 872 148 887T200 902Q237 902 252 887T267 849V830Q267 807 252 792T200
|
||||
777ZM400 777Q363 777 348 792T333 830V849Q333 872 348 887T400 902Q437 902 452 887T467 849V830Q467 807 452 792T400 777Z" />
|
||||
<glyph unicode="Å" glyph-name="Aring" d="M462 0L409 186H187L134 0H20L224 698H377L581 0H462ZM302 585H294L208 279H388L302 585ZM300 735Q273 735 249 744T208 770T181 810T171 861Q171 889 181 912T208 952T249 978T300 988Q327 988 351 979T392 952T419
|
||||
912T429 861Q429 834 419 811T392 771T351 745T300 735ZM300 795Q355 795 355 848V875Q355 928 300 928Q245 928 245 875V848Q245 795 300 795Z" />
|
||||
<glyph unicode="Æ" glyph-name="AE" d="M298 187H166L120 0H10L196 698H565V611H403V397H554V310H403V87H565V0H298V187ZM271 620L186 274H298V620H271Z" />
|
||||
<glyph unicode="Ç" glyph-name="Ccedilla" d="M319 617Q245 617 211 561T177 408V290Q177 242 185 204T211 138T255 96T319 81Q349 81 369 90T405 114T430 150T448 195L549 161Q537 126 520 95T476 41T415 4T331 -12L322 -58L326 -62Q337 -59 347 -57T368
|
||||
-55Q398 -55 418 -71T439 -123Q439 -146 429 -162T403 -188T365 -204T319 -209Q273 -209 247 -195T209 -167L251 -120Q260 -131 275 -139T314 -148Q333 -148 345 -141T358 -119Q358 -107 344 -96T287 -79L262 -76L275 -9Q164 7 111 98T58 349Q58 522 122 616T320
|
||||
710Q371 710 408 697T473 660T518 605T549 537L448 503Q440 527 430 548T405 584T370 608T319 617Z" />
|
||||
<glyph unicode="È" glyph-name="Egrave" d="M175 915L269 961L360 781L293 749L175 915ZM86 0V698H523V604H198V401H511V307H198V94H523V0H86Z" />
|
||||
<glyph unicode="É" glyph-name="Eacute" d="M86 0V698H523V604H198V401H511V307H198V94H523V0H86ZM315 749L248 781L339 961L433 915L315 749Z" />
|
||||
<glyph unicode="Ê" glyph-name="Ecircumflex" d="M359 944L479 794L421 752L303 868L184 752L129 794L249 944H359ZM86 0V698H523V604H198V401H511V307H198V94H523V0H86Z" />
|
||||
<glyph unicode="Ë" glyph-name="Edieresis" d="M86 0V698H523V604H198V401H511V307H198V94H523V0H86ZM204 777Q167 777 152 792T137 830V849Q137 872 152 887T204 902Q241 902 256 887T271 849V830Q271 807 256 792T204 777ZM404 777Q367 777 352 792T337
|
||||
830V849Q337 872 352 887T404 902Q441 902 456 887T471 849V830Q471 807 456 792T404 777Z" />
|
||||
<glyph unicode="Ì" glyph-name="Igrave" d="M80 0V85H244V613H80V698H520V613H356V85H520V0H80ZM171 915L265 961L356 781L289 749L171 915Z" />
|
||||
<glyph unicode="Í" glyph-name="Iacute" d="M80 0V85H244V613H80V698H520V613H356V85H520V0H80ZM311 749L244 781L335 961L429 915L311 749Z" />
|
||||
<glyph unicode="Î" glyph-name="Icircumflex" d="M80 0V85H244V613H80V698H520V613H356V85H520V0H80ZM355 944L475 794L417 752L299 868L180 752L125 794L245 944H355Z" />
|
||||
<glyph unicode="Ï" glyph-name="Idieresis" d="M80 0V85H244V613H80V698H520V613H356V85H520V0H80ZM200 777Q163 777 148 792T133 830V849Q133 872 148 887T200 902Q237 902 252 887T267 849V830Q267 807 252 792T200 777ZM400 777Q363 777 348 792T333 830V849Q333
|
||||
872 348 887T400 902Q437 902 452 887T467 849V830Q467 807 452 792T400 777Z" />
|
||||
<glyph unicode="Ð" glyph-name="Eth" d="M88 326H17V411H88V698H290Q424 698 488 609T553 349Q553 178 489 89T290 0H88V326ZM283 92Q360 92 397 143T435 291V407Q435 503 398 554T283 606H199V408H327V328H199V92H283Z" />
|
||||
<glyph unicode="Ñ" glyph-name="Ntilde" d="M374 774Q349 774 331 781T296 797Q273 808 256 814T222 820Q205 820 192 814T164 794L123 846Q138 869 163 886T226 903Q251 903 269 896T304 880Q327 869 344 863T378 857Q395 857 408 863T436 883L477 831Q462
|
||||
808 437 791T374 774ZM179 537H170V0H72V698H216L421 161H430V698H528V0H384L179 537Z" />
|
||||
<glyph unicode="Ò" glyph-name="Ograve" d="M171 915L265 961L356 781L289 749L171 915ZM300 -12Q234 -12 186 12T106 83T59 196T44 349Q44 434 59 501T105 615T185 685T300 710Q366 710 414 686T494 615T541 502T556 349Q556 263 541 196T495 83T415 13T300
|
||||
-12ZM300 81Q375 81 406 137T437 291V408Q437 504 406 560T300 617Q225 617 194 561T163 408V290Q163 194 194 138T300 81Z" />
|
||||
<glyph unicode="Ó" glyph-name="Oacute" d="M311 749L244 781L335 961L429 915L311 749ZM300 -12Q234 -12 186 12T106 83T59 196T44 349Q44 434 59 501T105 615T185 685T300 710Q366 710 414 686T494 615T541 502T556 349Q556 263 541 196T495 83T415 13T300
|
||||
-12ZM300 81Q375 81 406 137T437 291V408Q437 504 406 560T300 617Q225 617 194 561T163 408V290Q163 194 194 138T300 81Z" />
|
||||
<glyph unicode="Ô" glyph-name="Ocircumflex" d="M355 944L475 794L417 752L299 868L180 752L125 794L245 944H355ZM300 -12Q234 -12 186 12T106 83T59 196T44 349Q44 434 59 501T105 615T185 685T300 710Q366 710 414 686T494 615T541 502T556 349Q556 263
|
||||
541 196T495 83T415 13T300 -12ZM300 81Q375 81 406 137T437 291V408Q437 504 406 560T300 617Q225 617 194 561T163 408V290Q163 194 194 138T300 81Z" />
|
||||
<glyph unicode="Õ" glyph-name="Otilde" d="M300 -12Q234 -12 186 12T106 83T59 196T44 349Q44 434 59 501T105 615T185 685T300 710Q366 710 414 686T494 615T541 502T556 349Q556 263 541 196T495 83T415 13T300 -12ZM300 81Q375 81 406 137T437 291V408Q437
|
||||
504 406 560T300 617Q225 617 194 561T163 408V290Q163 194 194 138T300 81ZM374 774Q349 774 331 781T296 797Q273 808 256 814T222 820Q205 820 192 814T164 794L123 846Q138 869 163 886T226 903Q251 903 269 896T304 880Q327 869 344 863T378 857Q395 857 408
|
||||
863T436 883L477 831Q462 808 437 791T374 774Z" />
|
||||
<glyph unicode="Ö" glyph-name="Odieresis" d="M300 -12Q234 -12 186 12T106 83T59 196T44 349Q44 434 59 501T105 615T185 685T300 710Q366 710 414 686T494 615T541 502T556 349Q556 263 541 196T495 83T415 13T300 -12ZM300 81Q375 81 406 137T437 291V408Q437
|
||||
504 406 560T300 617Q225 617 194 561T163 408V290Q163 194 194 138T300 81ZM200 777Q163 777 148 792T133 830V849Q133 872 148 887T200 902Q237 902 252 887T267 849V830Q267 807 252 792T200 777ZM400 777Q363 777 348 792T333 830V849Q333 872 348 887T400
|
||||
902Q437 902 452 887T467 849V830Q467 807 452 792T400 777Z" />
|
||||
<glyph unicode="×" glyph-name="multiply" d="M300 241L145 85L80 150L236 305L80 460L145 525L300 369L455 525L520 460L364 305L520 150L455 85L300 241Z" />
|
||||
<glyph unicode="Ø" glyph-name="Oslash" d="M300 -12Q213 -12 159 29L110 -53L35 -10L98 94Q70 140 57 204T44 349Q44 434 59 501T105 615T185 685T300 710Q387 710 441 669L490 751L565 708L502 603Q530 557 543 494T556 349Q556 263 541 196T495 83T415
|
||||
13T300 -12ZM163 290Q163 266 164 245T171 203L392 580Q358 617 300 617Q225 617 194 561T163 408V290ZM300 81Q375 81 406 137T437 290V408Q437 432 436 453T429 495L208 118Q242 81 300 81Z" />
|
||||
<glyph unicode="Ù" glyph-name="Ugrave" d="M171 915L265 961L356 781L289 749L171 915ZM181 698V269Q181 226 183 191T198 132T234 94T300 81Q342 81 366 94T402 131T416 191T419 269V698H531V289Q531 214 523 158T489 64T419 7T300 -12Q227 -12 182 7T111
|
||||
63T78 157T69 289V698H181Z" />
|
||||
<glyph unicode="Ú" glyph-name="Uacute" d="M181 698V269Q181 226 183 191T198 132T234 94T300 81Q342 81 366 94T402 131T416 191T419 269V698H531V289Q531 214 523 158T489 64T419 7T300 -12Q227 -12 182 7T111 63T78 157T69 289V698H181ZM311 749L244
|
||||
781L335 961L429 915L311 749Z" />
|
||||
<glyph unicode="Û" glyph-name="Ucircumflex" d="M355 944L475 794L417 752L299 868L180 752L125 794L245 944H355ZM181 698V269Q181 226 183 191T198 132T234 94T300 81Q342 81 366 94T402 131T416 191T419 269V698H531V289Q531 214 523 158T489 64T419
|
||||
7T300 -12Q227 -12 182 7T111 63T78 157T69 289V698H181Z" />
|
||||
<glyph unicode="Ü" glyph-name="Udieresis" d="M181 698V269Q181 226 183 191T198 132T234 94T300 81Q342 81 366 94T402 131T416 191T419 269V698H531V289Q531 214 523 158T489 64T419 7T300 -12Q227 -12 182 7T111 63T78 157T69 289V698H181ZM200 777Q163
|
||||
777 148 792T133 830V849Q133 872 148 887T200 902Q237 902 252 887T267 849V830Q267 807 252 792T200 777ZM400 777Q363 777 348 792T333 830V849Q333 872 348 887T400 902Q437 902 452 887T467 849V830Q467 807 452 792T400 777Z" />
|
||||
<glyph unicode="Ý" glyph-name="Yacute" d="M244 0V263L12 698H137L226 524L298 375H304L377 524L466 698H588L356 263V0H244ZM311 749L244 781L335 961L429 915L311 749Z" />
|
||||
<glyph unicode="Þ" glyph-name="Thorn" d="M84 0V698H196V563H343Q443 563 495 507T548 354Q548 258 496 202T343 146H196V0H84ZM196 239H327Q432 239 432 333V376Q432 470 327 470H196V239Z" />
|
||||
<glyph unicode="ß" glyph-name="germandbls" d="M84 0V609Q84 667 116 703T217 740H363V654H191V516H531V426L373 212Q467 202 520 154T573 15Q573 -90 502 -145T311 -200H245V-114H307Q385 -114 423 -86T461 3V27Q461 87 421 112T294 138H275V224L427 430H191V0H84Z"
|
||||
/>
|
||||
<glyph unicode="à" glyph-name="agrave" d="M492 0Q445 0 422 24T393 87H388Q373 40 334 14T233 -12Q154 -12 107 29T60 144Q60 219 115 258T286 298H385V338Q385 443 274 443Q224 443 193 424T141 372L76 425Q98 467 150 497T284 528Q382 528 438 481T494
|
||||
345V86H559V0H492ZM264 68Q317 68 351 92T385 154V229H288Q170 229 170 158V138Q170 103 195 86T264 68ZM415 745L509 791L600 611L533 579L415 745Z" />
|
||||
<glyph unicode="á" glyph-name="aacute" d="M492 0Q445 0 422 24T393 87H388Q373 40 334 14T233 -12Q154 -12 107 29T60 144Q60 219 115 258T286 298H385V338Q385 443 274 443Q224 443 193 424T141 372L76 425Q98 467 150 497T284 528Q382 528 438 481T494
|
||||
345V86H559V0H492ZM264 68Q317 68 351 92T385 154V229H288Q170 229 170 158V138Q170 103 195 86T264 68ZM555 579L488 611L579 791L673 745L555 579Z" />
|
||||
<glyph unicode="â" glyph-name="acircumflex" d="M492 0Q445 0 422 24T393 87H388Q373 40 334 14T233 -12Q154 -12 107 29T60 144Q60 219 115 258T286 298H385V338Q385 443 274 443Q224 443 193 424T141 372L76 425Q98 467 150 497T284 528Q382 528 438 481T494
|
||||
345V86H559V0H492ZM264 68Q317 68 351 92T385 154V229H288Q170 229 170 158V138Q170 103 195 86T264 68ZM599 774L719 624L661 582L543 698L424 582L369 624L489 774H599Z" />
|
||||
<glyph unicode="ã" glyph-name="atilde" d="M492 0Q445 0 422 24T393 87H388Q373 40 334 14T233 -12Q154 -12 107 29T60 144Q60 219 115 258T286 298H385V338Q385 443 274 443Q224 443 193 424T141 372L76 425Q98 467 150 497T284 528Q382 528 438 481T494
|
||||
345V86H559V0H492ZM264 68Q317 68 351 92T385 154V229H288Q170 229 170 158V138Q170 103 195 86T264 68ZM618 604Q593 604 575 611T540 627Q517 638 500 644T466 650Q449 650 436 644T408 624L367 676Q382 699 407 716T470 733Q495 733 513 726T548 710Q571 699
|
||||
588 693T622 687Q639 687 652 693T680 713L721 661Q706 638 681 621T618 604Z" />
|
||||
<glyph unicode="ä" glyph-name="adieresis" d="M492 0Q445 0 422 24T393 87H388Q373 40 334 14T233 -12Q154 -12 107 29T60 144Q60 219 115 258T286 298H385V338Q385 443 274 443Q224 443 193 424T141 372L76 425Q98 467 150 497T284 528Q382 528 438 481T494
|
||||
345V86H559V0H492ZM264 68Q317 68 351 92T385 154V229H288Q170 229 170 158V138Q170 103 195 86T264 68ZM444 607Q407 607 392 622T377 660V679Q377 702 392 717T444 732Q481 732 496 717T511 679V660Q511 637 496 622T444 607ZM644 607Q607 607 592 622T577 660V679Q577
|
||||
702 592 717T644 732Q681 732 696 717T711 679V660Q711 637 696 622T644 607Z" />
|
||||
<glyph unicode="å" glyph-name="aring" d="M492 0Q445 0 422 24T393 87H388Q373 40 334 14T233 -12Q154 -12 107 29T60 144Q60 219 115 258T286 298H385V338Q385 443 274 443Q224 443 193 424T141 372L76 425Q98 467 150 497T284 528Q382 528 438 481T494
|
||||
345V86H559V0H492ZM264 68Q317 68 351 92T385 154V229H288Q170 229 170 158V138Q170 103 195 86T264 68ZM544 565Q517 565 493 574T452 600T425 640T415 691Q415 719 425 742T452 782T493 808T544 818Q571 818 595 809T636 782T663 742T673 691Q673 664 663 641T636
|
||||
601T595 575T544 565ZM544 625Q599 625 599 678V705Q599 758 544 758Q489 758 489 705V678Q489 625 544 625Z" />
|
||||
<glyph unicode="æ" glyph-name="ae" d="M139 -12Q83 -12 45 26T7 139Q7 219 53 259T187 299H241V354Q241 407 223 430T169 454Q136 454 118 434T88 380L18 413Q35 464 73 496T171 528Q216 528 247 509T295 452H299Q319 493 350 510T421 528Q499 528 541 467T583
|
||||
294V234H333V213Q333 147 355 107T419 66Q453 66 471 90T501 147L576 120Q568 94 555 71T523 29T477 -1T418 -12Q367 -12 328 17T268 103H264Q253 43 220 16T139 -12ZM161 62Q203 62 222 91T241 165V234H198Q150 234 125 215T99 154V137Q99 102 113 82T161 62ZM416
|
||||
456Q375 456 354 426T333 338V299H498V338Q498 395 477 425T416 456Z" />
|
||||
<glyph unicode="ç" glyph-name="ccedilla" d="M318 528Q398 528 446 494T519 406L434 360Q420 396 392 417T318 438Q256 438 222 401T188 301V215Q188 154 222 116T320 78Q368 78 398 100T447 160L527 111Q503 57 455 24T328 -12L318 -58L322 -62Q333 -59
|
||||
343 -57T365 -55Q394 -55 414 -71T435 -123Q435 -146 425 -162T399 -188T361 -204T315 -209Q270 -209 244 -195T206 -167L247 -120Q256 -131 271 -139T310 -148Q329 -148 341 -141T354 -119Q354 -107 341 -96T283 -79L258 -76L272 -8Q178 6 126 77T74 258Q74 320
|
||||
90 370T138 455T215 509T318 528Z" />
|
||||
<glyph unicode="è" glyph-name="egrave" d="M311 -12Q252 -12 205 7T126 61T77 145T60 257Q60 319 77 369T126 454T203 509T303 528Q357 528 401 510T476 457T523 376T540 272V231H170V214Q170 153 208 115T313 76Q363 76 398 97T456 155L524 95Q498 50 445
|
||||
19T311 -12ZM303 445Q274 445 250 435T208 407T180 363T170 308V301H429V311Q429 372 395 408T303 445ZM172 745L266 791L357 611L290 579L172 745Z" />
|
||||
<glyph unicode="é" glyph-name="eacute" d="M312 579L245 611L336 791L430 745L312 579ZM311 -12Q252 -12 205 7T126 61T77 145T60 257Q60 319 77 369T126 454T203 509T303 528Q357 528 401 510T476 457T523 376T540 272V231H170V214Q170 153 208 115T313
|
||||
76Q363 76 398 97T456 155L524 95Q498 50 445 19T311 -12ZM303 445Q274 445 250 435T208 407T180 363T170 308V301H429V311Q429 372 395 408T303 445Z" />
|
||||
<glyph unicode="ê" glyph-name="ecircumflex" d="M356 774L476 624L418 582L300 698L181 582L126 624L246 774H356ZM311 -12Q252 -12 205 7T126 61T77 145T60 257Q60 319 77 369T126 454T203 509T303 528Q357 528 401 510T476 457T523 376T540 272V231H170V214Q170
|
||||
153 208 115T313 76Q363 76 398 97T456 155L524 95Q498 50 445 19T311 -12ZM303 445Q274 445 250 435T208 407T180 363T170 308V301H429V311Q429 372 395 408T303 445Z" />
|
||||
<glyph unicode="ë" glyph-name="edieresis" d="M201 607Q164 607 149 622T134 660V679Q134 702 149 717T201 732Q238 732 253 717T268 679V660Q268 637 253 622T201 607ZM401 607Q364 607 349 622T334 660V679Q334 702 349 717T401 732Q438 732 453 717T468
|
||||
679V660Q468 637 453 622T401 607ZM311 -12Q252 -12 205 7T126 61T77 145T60 257Q60 319 77 369T126 454T203 509T303 528Q357 528 401 510T476 457T523 376T540 272V231H170V214Q170 153 208 115T313 76Q363 76 398 97T456 155L524 95Q498 50 445 19T311 -12ZM303
|
||||
445Q274 445 250 435T208 407T180 363T170 308V301H429V311Q429 372 395 408T303 445Z" />
|
||||
<glyph unicode="ì" glyph-name="igrave" d="M101 88H277V428H101V516H386V88H551V0H101V88ZM203 745L297 791L388 611L321 579L203 745Z" />
|
||||
<glyph unicode="í" glyph-name="iacute" d="M343 579L276 611L367 791L461 745L343 579ZM101 88H277V428H101V516H386V88H551V0H101V88Z" />
|
||||
<glyph unicode="î" glyph-name="icircumflex" d="M387 774L507 624L449 582L331 698L212 582L157 624L277 774H387ZM101 88H277V428H101V516H386V88H551V0H101V88Z" />
|
||||
<glyph unicode="ï" glyph-name="idieresis" d="M232 607Q195 607 180 622T165 660V679Q165 702 180 717T232 732Q269 732 284 717T299 679V660Q299 637 284 622T232 607ZM432 607Q395 607 380 622T365 660V679Q365 702 380 717T432 732Q469 732 484 717T499
|
||||
679V660Q499 637 484 622T432 607ZM101 88H277V428H101V516H386V88H551V0H101V88Z" />
|
||||
<glyph unicode="ð" glyph-name="eth" d="M469 702L387 648Q419 616 447 577T498 491T532 389T545 271Q545 199 528 146T480 57T403 5T303 -12Q244 -12 198 6T121 58T72 140T55 249Q55 307 70 353T113 433T179 484T264 502Q324 502 363 475T426 406L432 409Q412
|
||||
464 380 510T306 597L210 534L167 585L254 642Q220 670 183 694T103 740H271Q286 730 302 719T336 694L426 753L469 702ZM301 74Q361 74 396 109T432 213V276Q432 345 396 380T300 415Q240 415 205 380T169 276V213Q169 144 205 109T301 74Z" />
|
||||
<glyph unicode="ñ" glyph-name="ntilde" d="M84 0V516H193V428H198Q206 448 218 466T249 498T291 520T347 528Q425 528 473 477T521 332V0H412V316Q412 439 305 439Q284 439 264 434T228 417T203 389T193 350V0H84ZM376 604Q351 604 333 611T298 627Q275
|
||||
638 258 644T224 650Q207 650 194 644T166 624L125 676Q140 699 165 716T228 733Q253 733 271 726T306 710Q329 699 346 693T380 687Q397 687 410 693T438 713L479 661Q464 638 439 621T376 604Z" />
|
||||
<glyph unicode="ò" glyph-name="ograve" d="M300 -12Q243 -12 198 7T121 61T72 146T55 258Q55 320 72 370T120 455T197 509T300 528Q357 528 402 509T479 455T528 370T545 258Q545 196 528 146T480 61T403 7T300 -12ZM300 74Q360 74 395 110T431 219V297Q431
|
||||
369 396 405T300 442Q240 442 205 406T169 297V219Q169 147 204 111T300 74ZM171 745L265 791L356 611L289 579L171 745Z" />
|
||||
<glyph unicode="ó" glyph-name="oacute" d="M311 579L244 611L335 791L429 745L311 579ZM300 -12Q243 -12 198 7T121 61T72 146T55 258Q55 320 72 370T120 455T197 509T300 528Q357 528 402 509T479 455T528 370T545 258Q545 196 528 146T480 61T403 7T300
|
||||
-12ZM300 74Q360 74 395 110T431 219V297Q431 369 396 405T300 442Q240 442 205 406T169 297V219Q169 147 204 111T300 74Z" />
|
||||
<glyph unicode="ô" glyph-name="ocircumflex" d="M355 774L475 624L417 582L299 698L180 582L125 624L245 774H355ZM300 -12Q243 -12 198 7T121 61T72 146T55 258Q55 320 72 370T120 455T197 509T300 528Q357 528 402 509T479 455T528 370T545 258Q545 196
|
||||
528 146T480 61T403 7T300 -12ZM300 74Q360 74 395 110T431 219V297Q431 369 396 405T300 442Q240 442 205 406T169 297V219Q169 147 204 111T300 74Z" />
|
||||
<glyph unicode="õ" glyph-name="otilde" d="M300 -12Q243 -12 198 7T121 61T72 146T55 258Q55 320 72 370T120 455T197 509T300 528Q357 528 402 509T479 455T528 370T545 258Q545 196 528 146T480 61T403 7T300 -12ZM300 74Q360 74 395 110T431 219V297Q431
|
||||
369 396 405T300 442Q240 442 205 406T169 297V219Q169 147 204 111T300 74ZM374 604Q349 604 331 611T296 627Q273 638 256 644T222 650Q205 650 192 644T164 624L123 676Q138 699 163 716T226 733Q251 733 269 726T304 710Q327 699 344 693T378 687Q395 687 408
|
||||
693T436 713L477 661Q462 638 437 621T374 604Z" />
|
||||
<glyph unicode="ö" glyph-name="odieresis" d="M200 607Q163 607 148 622T133 660V679Q133 702 148 717T200 732Q237 732 252 717T267 679V660Q267 637 252 622T200 607ZM400 607Q363 607 348 622T333 660V679Q333 702 348 717T400 732Q437 732 452 717T467
|
||||
679V660Q467 637 452 622T400 607ZM300 -12Q243 -12 198 7T121 61T72 146T55 258Q55 320 72 370T120 455T197 509T300 528Q357 528 402 509T479 455T528 370T545 258Q545 196 528 146T480 61T403 7T300 -12ZM300 74Q360 74 395 110T431 219V297Q431 369 396 405T300
|
||||
442Q240 442 205 406T169 297V219Q169 147 204 111T300 74Z" />
|
||||
<glyph unicode="÷" glyph-name="divide" d="M62 261V350H538V261H62ZM300 42Q260 42 244 58T227 99V122Q227 146 243 162T300 179Q340 179 356 163T373 122V99Q373 75 357 59T300 42ZM300 432Q260 432 244 448T227 489V512Q227 536 243 552T300 569Q340 569
|
||||
356 553T373 512V489Q373 465 357 449T300 432Z" />
|
||||
<glyph unicode="ø" glyph-name="oslash" d="M37 -3L105 81Q55 149 55 258Q55 320 72 370T120 455T197 509T300 528Q384 528 441 488L503 564L563 519L495 435Q545 367 545 258Q545 196 528 146T480 61T403 7T300 -12Q216 -12 159 28L97 -48L37 -3ZM300 442Q240
|
||||
442 205 406T169 297V223Q169 206 170 190T177 161L385 415Q353 442 300 442ZM300 74Q360 74 395 110T431 219V293Q431 310 430 326T423 355L215 101Q231 87 252 81T300 74Z" />
|
||||
<glyph unicode="ù" glyph-name="ugrave" d="M407 88H402Q394 68 382 50T351 18T309 -4T253 -12Q175 -12 127 39T79 184V516H188V200Q188 77 295 77Q316 77 336 82T372 99T397 126T407 166V516H516V0H407V88ZM426 745L520 791L611 611L544 579L426 745Z" />
|
||||
<glyph unicode="ú" glyph-name="uacute" d="M566 579L499 611L590 791L684 745L566 579ZM407 88H402Q394 68 382 50T351 18T309 -4T253 -12Q175 -12 127 39T79 184V516H188V200Q188 77 295 77Q316 77 336 82T372 99T397 126T407 166V516H516V0H407V88Z" />
|
||||
<glyph unicode="û" glyph-name="ucircumflex" d="M610 774L730 624L672 582L554 698L435 582L380 624L500 774H610ZM407 88H402Q394 68 382 50T351 18T309 -4T253 -12Q175 -12 127 39T79 184V516H188V200Q188 77 295 77Q316 77 336 82T372 99T397 126T407
|
||||
166V516H516V0H407V88Z" />
|
||||
<glyph unicode="ü" glyph-name="udieresis" d="M455 607Q418 607 403 622T388 660V679Q388 702 403 717T455 732Q492 732 507 717T522 679V660Q522 637 507 622T455 607ZM655 607Q618 607 603 622T588 660V679Q588 702 603 717T655 732Q692 732 707 717T722
|
||||
679V660Q722 637 707 622T655 607ZM407 88H402Q394 68 382 50T351 18T309 -4T253 -12Q175 -12 127 39T79 184V516H188V200Q188 77 295 77Q316 77 336 82T372 99T397 126T407 166V516H516V0H407V88Z" />
|
||||
<glyph unicode="ý" glyph-name="yacute" d="M451 516H561L311 -100Q291 -150 259 -175T165 -200H78V-112H200L247 7L39 516H153L235 300L299 123H305L369 300L451 516ZM312 579L245 611L336 791L430 745L312 579Z" />
|
||||
<glyph unicode="þ" glyph-name="thorn" d="M79 740H188V428H194Q217 475 255 501T350 528Q441 528 495 460T549 258Q549 124 495 56T350 -12Q293 -12 255 14T194 88H188V-200H79V740ZM305 77Q367 77 400 115T434 216V300Q434 363 401 401T305 439Q281 439
|
||||
260 433T223 415T198 386T188 344V172Q188 148 197 131T223 101T260 83T305 77Z" />
|
||||
<glyph unicode="ÿ" glyph-name="ydieresis" d="M451 516H561L311 -100Q291 -150 259 -175T165 -200H78V-112H200L247 7L39 516H153L235 300L299 123H305L369 300L451 516ZM201 607Q164 607 149 622T134 660V679Q134 702 149 717T201 732Q238 732 253 717T268
|
||||
679V660Q268 637 253 622T201 607ZM401 607Q364 607 349 622T334 660V679Q334 702 349 717T401 732Q438 732 453 717T468 679V660Q468 637 453 622T401 607Z" />
|
||||
<glyph unicode="–" glyph-name="endash" d="M60 257V351H540V257H60Z" />
|
||||
<glyph unicode="—" glyph-name="emdash" d="M0 257V351H600V257H0Z" />
|
||||
<glyph unicode="‘" glyph-name="quoteleft" d="M306 740H390L336 442H181L306 740Z" />
|
||||
<glyph unicode="’" glyph-name="quoteright" d="M264 740H419L294 442H210L264 740Z" />
|
||||
<glyph unicode="‚" glyph-name="quotesinglbase" d="M244 152H399L275 -145H190L244 152Z" />
|
||||
<glyph unicode="“" glyph-name="quotedblleft" d="M443 740H527L473 442H318L443 740ZM433 740H517L463 442H308L433 740Z" />
|
||||
<glyph unicode="”" glyph-name="quotedblright" d="M401 740H556L431 442H347L401 740ZM391 740H546L421 442H337L391 740Z" />
|
||||
<glyph unicode="„" glyph-name="quotedblbase" d="M393 152H548L424 -145H339L393 152ZM383 152H538L414 -145H329L383 152Z" />
|
||||
<glyph unicode="•" glyph-name="bullet" d="M300 173Q226 173 196 206T165 289V319Q165 344 172 365T195 401T237 426T300 435Q337 435 363 426T405 402T428 365T435 319V289Q435 239 405 206T300 173Z" />
|
||||
<glyph unicode="‹" glyph-name="guilsinglleft" d="M375 47L171 219V321L375 493L408 420L268 270L408 120L375 47Z" />
|
||||
<glyph unicode="›" glyph-name="guilsinglright" d="M192 120L332 270L192 420L225 493L429 321V219L225 47L192 120Z" />
|
||||
</font>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 51 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,327 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<defs >
|
||||
<font id="IBMPlexMono" horiz-adv-x="600" ><font-face
|
||||
font-family="IBM Plex Mono SemiBold"
|
||||
units-per-em="1000"
|
||||
panose-1="2 11 7 9 5 2 3 0 2 3"
|
||||
ascent="1025"
|
||||
descent="-275"
|
||||
alphabetic="0" />
|
||||
<glyph unicode=" " glyph-name="space" />
|
||||
<glyph unicode="!" glyph-name="exclam" d="M279 240L230 495V698H370V495L321 240H279ZM300 -11Q250 -11 230 10T209 61V89Q209 119 229 140T300 161Q350 161 370 140T391 89V61Q391 31 371 10T300 -11Z" />
|
||||
<glyph unicode=""" glyph-name="quotedbl" d="M394 428V740H510V428H394ZM347 428V740H463V428H347Z" />
|
||||
<glyph unicode="#" glyph-name="numbersign" d="M126 201H11V297H144L161 401H49V497H179L214 698H318L195 0H91L126 201ZM405 698H509L474 497H589V401H456L439 297H551V201H421L386 0H282L405 698Z" />
|
||||
<glyph unicode="$" glyph-name="dollar" d="M261 -11Q183 -5 128 24T37 101L116 182Q182 108 268 98V305L245 309Q196 318 161 336T103 380T70 438T59 507Q59 592 111 644T261 707V811H359V708Q424 700 470 675T549 610L470 529Q424 584 352 596V406L377 402Q475
|
||||
384 519 333T563 206Q563 121 511 65T359 -7V-113H261V-11ZM182 511Q182 474 202 454T268 423V599Q182 587 182 511ZM441 198Q441 238 420 258T352 289V99Q397 107 419 132T441 198Z" />
|
||||
<glyph unicode="%" glyph-name="percent" d="M166 344Q94 344 53 392T12 527Q12 614 53 662T166 710Q238 710 279 662T320 527Q320 440 279 392T166 344ZM166 421Q198 421 212 443T227 504V550Q227 588 213 610T166 633Q134 633 120 611T105 550V504Q105 466 119
|
||||
444T166 421ZM492 698H593L439 398H339L492 698ZM161 300H261L108 0H7L161 300ZM434 -12Q362 -12 321 36T280 171Q280 258 321 306T434 354Q506 354 547 306T588 171Q588 84 547 36T434 -12ZM434 65Q466 65 480 87T495 148V194Q495 232 481 254T434 277Q402 277
|
||||
388 255T373 194V148Q373 110 387 88T434 65Z" />
|
||||
<glyph unicode="&" glyph-name="ampersand" d="M210 -12Q163 -12 128 4T67 47T30 110T17 187Q17 247 46 297T139 382Q107 424 91 459T74 536Q74 574 88 606T128 661T189 697T265 710Q301 710 331 700T384 674T424 636T448 591L357 543Q346 575 322 593T265
|
||||
612Q230 612 209 591T188 538V532Q188 517 192 504T205 475T230 439T268 391L334 307L390 229H396Q399 247 401 268T404 311T406 355T407 396H574V299H503Q497 262 489 228T463 154L591 0H452L370 99H363Q354 48 314 18T210 -12ZM242 89Q271 89 295 100T334 137L192
|
||||
315Q160 289 149 260T138 197V192Q138 142 166 116T242 89Z" />
|
||||
<glyph unicode="'" glyph-name="quotesingle" d="M242 428V740H358V428H242Z" />
|
||||
<glyph unicode="(" glyph-name="parenleft" d="M183 311Q183 384 199 451T244 577T311 681T391 760H519Q474 728 433 685T361 591T312 481T293 359V263Q293 200 311 142T361 32T433 -63T519 -138H391Q349 -107 311 -60T245 45T200 170T183 311Z" />
|
||||
<glyph unicode=")" glyph-name="parenright" d="M417 311Q417 238 401 171T356 45T289 -60T209 -138H81Q126 -106 167 -63T239 31T288 141T307 263V359Q307 422 289 480T239 590T167 685T81 760H209Q251 728 289 682T355 577T400 452T417 311Z" />
|
||||
<glyph unicode="*" glyph-name="asterisk" d="M186 44L96 105L213 261L34 322L67 422L244 360V549H356V360L533 422L566 322L387 261L504 105L414 44L300 200L186 44Z" />
|
||||
<glyph unicode="+" glyph-name="plus" d="M244 62V254H62V357H244V549H356V357H538V254H356V62H244Z" />
|
||||
<glyph unicode="," glyph-name="comma" d="M236 163H408L277 -148H180L236 163Z" />
|
||||
<glyph unicode="-" glyph-name="hyphen" d="M145 242V367H455V242H145Z" />
|
||||
<glyph unicode="." glyph-name="period" d="M300 -11Q248 -11 226 11T204 65V95Q204 127 226 149T300 171Q352 171 374 149T396 95V65Q396 33 374 11T300 -11Z" />
|
||||
<glyph unicode="/" glyph-name="slash" d="M78 -138L407 760H522L193 -138H78Z" />
|
||||
<glyph unicode="0" glyph-name="zero" d="M300 -12Q232 -12 182 12T100 83T52 196T36 349Q36 434 51 501T99 615T182 685T300 710Q436 710 500 615T564 349Q564 178 500 83T300 -12ZM300 93Q372 93 401 144T431 287V411Q431 502 402 553T300 605Q228 605 199 554T169
|
||||
411V287Q169 196 198 145T300 93ZM300 290Q265 290 252 304T238 338V360Q238 380 251 394T300 408Q335 408 348 394T362 360V338Q362 318 349 304T300 290Z" />
|
||||
<glyph unicode="1" glyph-name="one" d="M91 0V107H283V603H274L122 423L40 492L213 698H414V107H572V0H91Z" />
|
||||
<glyph unicode="2" glyph-name="two" d="M550 0H58V122L282 313Q338 361 365 400T392 485V495Q392 545 364 571T286 597Q231 597 202 567T160 493L46 536Q57 570 77 601T128 657T201 695T297 710Q353 710 396 695T470 652T515 586T531 503Q531 460 518 424T480
|
||||
356T424 293T353 233L201 110H550V0Z" />
|
||||
<glyph unicode="3" glyph-name="three" d="M272 416Q335 416 364 441T394 504V511Q394 554 366 578T287 602Q239 602 203 580T141 518L56 594Q74 618 96 639T147 676T211 701T291 710Q344 710 388 698T464 661T513 604T531 528Q531 495 520 468T491 421T448 388T395
|
||||
369V364Q426 358 453 345T500 310T532 260T544 193Q544 147 525 109T472 44T389 3T280 -12Q230 -12 191 -2T122 27T70 68T31 117L128 192Q153 150 187 123T282 96Q342 96 374 123T407 200V208Q407 256 372 281T273 307H203V416H272Z" />
|
||||
<glyph unicode="4" glyph-name="four" d="M351 0V135H28V247L313 698H476V237H570V135H476V0H351ZM135 237H351V570H343L135 237Z" />
|
||||
<glyph unicode="5" glyph-name="five" d="M518 584H198L181 350H189Q201 372 215 390T247 422T289 442T344 449Q388 449 427 434T495 391T540 322T557 229Q557 177 540 133T489 57T407 6T295 -12Q246 -12 208 -2T140 27T89 68T51 117L146 192Q158 172 172 155T205
|
||||
124T245 104T297 96Q357 96 388 128T420 218V226Q420 281 388 312T298 343Q254 343 227 327T182 291L75 306L101 698H518V584Z" />
|
||||
<glyph unicode="6" glyph-name="six" d="M303 -12Q242 -12 195 7T114 62T64 148T46 262Q46 337 69 403T128 525T210 625T300 698H478Q415 654 366 614T280 531T219 444T182 344L190 342Q200 362 214 380T247 413T292 436T352 445Q396 445 434 430T499 387T543
|
||||
318T559 228Q559 175 541 131T490 55T409 6T303 -12ZM302 91Q362 91 393 122T424 212V224Q424 282 393 313T302 344Q245 344 213 313T181 224V212Q181 154 212 123T302 91Z" />
|
||||
<glyph unicode="7" glyph-name="seven" d="M167 0L416 591H167V463H55V698H546V584L305 0H167Z" />
|
||||
<glyph unicode="8" glyph-name="eight" d="M300 -12Q238 -12 190 3T109 46T59 110T42 191Q42 260 80 302T182 361V369Q128 388 96 428T63 529Q63 569 79 602T125 660T199 697T300 710Q357 710 401 697T475 660T521 603T537 529Q537 468 505 428T418 369V361Q481
|
||||
344 519 302T558 191Q558 147 541 110T491 46T410 4T300 -12ZM300 90Q359 90 390 116T422 190V210Q422 258 391 284T300 311Q240 311 209 285T178 210V190Q178 143 209 117T300 90ZM300 408Q355 408 384 433T413 502V516Q413 559 384 583T300 608Q245 608 216 584T187
|
||||
516V502Q187 458 216 433T300 408Z" />
|
||||
<glyph unicode="9" glyph-name="nine" d="M554 436Q554 361 531 295T472 173T390 73T300 0H122Q185 44 234 84T320 167T381 254T418 354L410 356Q400 336 386 317T353 284T308 262T248 253Q204 253 166 268T100 311T57 380T41 470Q41 523 59 567T110 643T191 692T297
|
||||
710Q358 710 405 691T486 636T536 550T554 436ZM298 354Q355 354 387 385T419 474V486Q419 544 388 575T298 607Q238 607 207 576T176 486V474Q176 416 207 385T298 354Z" />
|
||||
<glyph unicode=":" glyph-name="colon" d="M300 -11Q248 -11 226 11T204 65V95Q204 127 226 149T300 171Q352 171 374 149T396 95V65Q396 33 374 11T300 -11ZM300 344Q248 344 226 366T204 420V450Q204 482 226 504T300 526Q352 526 374 504T396 450V420Q396 388
|
||||
374 366T300 344Z" />
|
||||
<glyph unicode=";" glyph-name="semicolon" d="M236 163H408L277 -148H180L236 163ZM300 344Q248 344 226 366T204 420V450Q204 482 226 504T300 526Q352 526 374 504T396 450V420Q396 388 374 366T300 344Z" />
|
||||
<glyph unicode="<" glyph-name="less" d="M85 245V365L515 601V479L201 309V301L515 131V9L85 245Z" />
|
||||
<glyph unicode="=" glyph-name="equal" d="M62 364V467H538V364H62ZM62 143V246H538V143H62Z" />
|
||||
<glyph unicode=">" glyph-name="greater" d="M85 131L399 301V309L85 479V601L515 365V245L85 9V131Z" />
|
||||
<glyph unicode="?" glyph-name="question" d="M217 228V382Q295 385 340 411T386 498V512Q386 557 359 578T290 600Q243 600 214 574T174 505L66 549Q75 580 93 609T138 660T204 696T294 710Q345 710 387 696T459 655T505 592T522 510Q522 466 507 432T467 372T408
|
||||
330T339 308V228H217ZM281 -11Q231 -11 211 10T190 61V89Q190 119 210 140T281 161Q331 161 351 140T372 89V61Q372 31 352 10T281 -11Z" />
|
||||
<glyph unicode="@" glyph-name="at" d="M449 -112H338Q257 -112 201 -87T111 -9T61 120T45 303Q45 418 62 496T111 621T191 689T301 710Q364 710 410 691T486 639T530 561T545 463V91H449V151H442Q431 117 408 99T346 80Q287 80 253 131T219 294Q219 405 253 456T346
|
||||
508Q384 508 407 489T442 437H449V463Q449 548 412 586T306 624Q267 624 237 611T187 566T157 484T146 358V229Q146 171 155 124T187 44T247 -8T338 -26H449V-112ZM385 157Q415 157 432 174T449 222V366Q449 397 432 414T385 431Q353 431 337 408T320 326V262Q320
|
||||
203 336 180T385 157Z" />
|
||||
<glyph unicode="A" glyph-name="A" d="M449 0L400 177H193L145 0H13L209 698H391L588 0H449ZM301 569H293L216 284H378L301 569Z" />
|
||||
<glyph unicode="B" glyph-name="B" d="M80 698H323Q422 698 475 649T529 514Q529 454 500 418T416 366V361Q479 346 515 307T552 195Q552 151 538 116T497 54T433 14T348 0H80V698ZM308 95Q363 95 390 115T418 186V219Q418 268 391 288T308 309H208V95H308ZM291
|
||||
400Q344 400 369 419T395 485V518Q395 565 370 584T291 603H208V400H291Z" />
|
||||
<glyph unicode="C" glyph-name="C" d="M318 -12Q181 -12 116 82T50 349Q50 521 115 615T318 710Q370 710 409 696T478 658T526 599T556 523L436 489Q429 513 420 534T398 570T364 594T316 603Q248 603 219 551T189 409V289Q189 199 218 147T316 95Q344 95 364
|
||||
103T397 127T420 164T436 209L556 175Q545 134 526 100T478 41T410 2T318 -12Z" />
|
||||
<glyph unicode="D" glyph-name="D" d="M73 698H290Q426 698 492 608T559 349Q559 179 493 90T290 0H73V698ZM281 105Q353 105 387 152T422 289V410Q422 499 388 546T281 593H202V105H281Z" />
|
||||
<glyph unicode="E" glyph-name="E" d="M83 0V698H524V590H214V408H513V300H214V108H524V0H83Z" />
|
||||
<glyph unicode="F" glyph-name="F" d="M83 0V698H539V590H214V408H507V300H214V0H83Z" />
|
||||
<glyph unicode="G" glyph-name="G" d="M421 97H413Q404 76 391 56T359 21T315 -3T256 -12Q150 -12 96 81T41 344Q41 522 105 616T302 710Q354 710 393 696T461 657T508 598T538 523L418 489Q411 511 403 532T381 568T348 593T301 603Q236 603 208 551T180 409V297Q180
|
||||
252 186 215T208 150T247 109T307 94Q363 94 392 127T421 213V270H294V365H538V0H421V97Z" />
|
||||
<glyph unicode="H" glyph-name="H" d="M402 300H198V0H67V698H198V408H402V698H533V0H402V300Z" />
|
||||
<glyph unicode="I" glyph-name="I" d="M78 0V98H235V600H78V698H522V600H365V98H522V0H78Z" />
|
||||
<glyph unicode="J" glyph-name="J" d="M502 698V191Q502 144 486 107T441 43T370 3T277 -12Q178 -12 122 38T49 171L172 197Q181 153 204 125T277 96Q322 96 346 122T370 206V590H134V698H502Z" />
|
||||
<glyph unicode="K" glyph-name="K" d="M277 306L204 210V0H73V698H204V384H210L291 500L438 698H586L367 404L596 0H448L277 306Z" />
|
||||
<glyph unicode="L" glyph-name="L" d="M100 0V698H231V108H540V0H100Z" />
|
||||
<glyph unicode="M" glyph-name="M" d="M438 323L444 525H435L300 166L165 525H156L162 323V0H48V698H204L301 441H308L406 698H552V0H438V323Z" />
|
||||
<glyph unicode="N" glyph-name="N" d="M189 501H179V0H67V698H228L411 197H421V698H533V0H372L189 501Z" />
|
||||
<glyph unicode="O" glyph-name="O" d="M300 -12Q232 -12 182 12T100 83T52 196T36 349Q36 434 51 501T99 615T182 685T300 710Q436 710 500 615T564 349Q564 178 500 83T300 -12ZM300 95Q335 95 359 108T397 147T418 208T425 290V409Q425 499 398 551T300 603Q230
|
||||
603 203 551T175 409V289Q175 199 202 147T300 95Z" />
|
||||
<glyph unicode="P" glyph-name="P" d="M80 0V698H345Q447 698 501 640T555 482Q555 382 501 324T345 266H211V0H80ZM211 373H318Q371 373 394 394T417 463V501Q417 548 394 569T318 591H211V373Z" />
|
||||
<glyph unicode="Q" glyph-name="Q" d="M516 -183H381Q307 -183 275 -146T243 -46V-7Q136 12 86 104T36 349Q36 434 51 501T99 615T182 685T300 710Q436 710 500 615T564 349Q564 196 514 104T357 -7V-88H516V-183ZM300 95Q335 95 359 108T397 147T418 208T425
|
||||
290V409Q425 499 398 551T300 603Q230 603 203 551T175 409V289Q175 199 202 147T300 95Z" />
|
||||
<glyph unicode="R" glyph-name="R" d="M211 0H80V698H345Q447 698 501 640T555 482Q555 405 520 353T418 286L567 0H423L290 271H211V0ZM318 373Q371 373 394 394T417 463V501Q417 548 394 569T318 591H211V373H318Z" />
|
||||
<glyph unicode="S" glyph-name="S" d="M292 -12Q202 -12 139 19T35 101L114 183Q153 138 198 117T296 95Q356 95 388 122T420 200Q420 242 396 263T315 294L241 306Q144 323 103 376T62 503Q62 603 127 656T307 710Q389 710 448 684T544 613L467 531Q439 564 400
|
||||
583T308 603Q194 603 194 509Q194 469 218 448T300 417L373 404Q464 387 508 337T552 209Q552 160 535 120T485 50T404 4T292 -12Z" />
|
||||
<glyph unicode="T" glyph-name="T" d="M365 590V0H235V590H25V698H575V590H365Z" />
|
||||
<glyph unicode="U" glyph-name="U" d="M193 698V263Q193 224 195 193T208 141T240 107T300 95Q338 95 359 107T391 140T404 193T407 263V698H538V283Q538 209 529 154T494 62T422 7T300 -12Q225 -12 179 6T106 62T71 154T62 283V698H193Z" />
|
||||
<glyph unicode="V" glyph-name="V" d="M208 0L17 698H161L248 345L299 125H306L358 345L446 698H583L392 0H208Z" />
|
||||
<glyph unicode="W" glyph-name="W" d="M65 0L18 698H131L153 296L162 130H171L241 537H363L433 130H442L451 296L473 698H582L535 0H366L304 395H296L234 0H65Z" />
|
||||
<glyph unicode="X" glyph-name="X" d="M586 0H438L362 139L301 261H293L230 139L152 0H14L219 360L27 698H176L240 580L301 459H308L370 580L437 698H575L382 358L586 0Z" />
|
||||
<glyph unicode="Y" glyph-name="Y" d="M235 0V255L8 698H154L235 530L298 387H305L369 530L451 698H592L365 255V0H235Z" />
|
||||
<glyph unicode="Z" glyph-name="Z" d="M552 0H48V115L395 590H60V698H539V583L193 108H552V0Z" />
|
||||
<glyph unicode="[" glyph-name="bracketleft" d="M195 -138V760H506V672H299V-50H506V-138H195Z" />
|
||||
<glyph unicode="\" glyph-name="backslash" d="M407 -138L78 760H193L522 -138H407Z" />
|
||||
<glyph unicode="]" glyph-name="bracketright" d="M405 760V-138H94V-50H301V672H94V760H405Z" />
|
||||
<glyph unicode="^" glyph-name="asciicircum" d="M466 253L302 582H293L129 253L32 300L232 698H368L568 300L466 253Z" />
|
||||
<glyph unicode="_" glyph-name="underscore" d="M60 -185V-78H540V-185H60Z" />
|
||||
<glyph unicode="`" glyph-name="grave" d="M161 745L269 799L364 612L287 575L161 745Z" />
|
||||
<glyph unicode="a" glyph-name="a" d="M490 0Q443 0 418 23T387 89H382Q368 41 327 15T226 -12Q148 -12 102 29T56 143Q56 299 285 299H376V333Q376 382 352 407T274 432Q225 432 195 413T144 364L71 426Q95 469 148 498T287 528Q389 528 446 481T504 339V96H565V0H490ZM269
|
||||
76Q315 76 345 97T376 156V225H288Q183 225 183 159V139Q183 108 206 92T269 76Z" />
|
||||
<glyph unicode="b" glyph-name="b" d="M69 740H197V425H204Q225 472 261 500T358 528Q402 528 438 512T501 462T541 377T555 258Q555 190 541 139T501 55T439 5T358 -12Q298 -12 262 16T204 91H197V0H69V740ZM304 90Q360 90 390 124T421 217V299Q421 358 391 392T304
|
||||
426Q260 426 229 405T197 339V177Q197 133 228 112T304 90Z" />
|
||||
<glyph unicode="c" glyph-name="c" d="M320 -12Q261 -12 214 7T135 61T85 146T67 258Q67 320 84 370T134 455T213 509T319 528Q401 528 451 494T527 404L428 350Q414 383 389 403T319 424Q262 424 232 391T201 301V215Q201 159 231 126T321 92Q367 92 394 113T439
|
||||
169L535 112Q509 57 457 23T320 -12Z" />
|
||||
<glyph unicode="d" glyph-name="d" d="M403 91H396Q375 44 339 16T242 -12Q198 -12 162 4T99 54T59 139T45 258Q45 394 99 461T242 528Q302 528 338 500T396 425H403V740H531V0H403V91ZM296 90Q318 90 337 95T371 111T394 138T403 177V339Q403 361 395 377T372
|
||||
404T338 420T296 426Q240 426 210 392T179 299V217Q179 158 209 124T296 90Z" />
|
||||
<glyph unicode="e" glyph-name="e" d="M312 -12Q250 -12 202 7T122 61T72 145T55 257Q55 320 72 370T122 455T199 509T302 528Q358 528 403 510T479 457T528 375T545 269V227H183V214Q183 158 218 124T316 89Q364 89 398 108T456 160L529 87Q501 46 448 17T312
|
||||
-12ZM303 434Q249 434 216 400T183 310V303H417V312Q417 368 387 401T303 434Z" />
|
||||
<glyph unicode="f" glyph-name="f" d="M75 101H233V415H65V516H233V600Q233 631 241 656T268 700T313 729T378 740H552V639H361V516H552V415H361V101H529V0H75V101Z" />
|
||||
<glyph unicode="g" glyph-name="g" d="M576 -54Q576 -135 509 -173T298 -212Q228 -212 181 -204T106 -179T65 -141T53 -90Q53 -47 78 -24T148 10V18Q118 28 101 46T83 96Q83 134 108 153T176 182V187Q130 209 104 249T78 346Q78 389 93 422T137 479T206 515T295
|
||||
528Q347 528 389 514V536Q389 566 408 586T463 606H556V510H434V493Q472 470 492 434T513 346Q513 303 498 269T454 212T385 177T295 164Q275 164 257 165T221 172Q207 167 194 156T181 127Q181 103 204 98T259 92H376Q430 92 468 82T530 52T565 5T576 -54ZM456
|
||||
-63Q456 -40 438 -27T369 -13H191Q161 -30 161 -63Q161 -90 183 -108T260 -126H343Q456 -126 456 -63ZM295 248Q344 248 367 271T390 333V359Q390 397 367 420T295 444Q247 444 224 421T201 359V333Q201 295 224 272T295 248Z" />
|
||||
<glyph unicode="h" glyph-name="h" d="M75 740H203V425H208Q225 467 260 497T359 528Q435 528 482 478T530 333V0H402V315Q402 427 305 427Q285 427 267 422T235 407T212 381T203 345V0H75V740Z" />
|
||||
<glyph unicode="i" glyph-name="i" d="M332 596Q287 596 269 615T250 661V685Q250 712 268 731T332 750Q377 750 395 731T414 685V661Q414 634 396 615T332 596ZM98 101H268V415H98V516H396V101H554V0H98V101Z" />
|
||||
<glyph unicode="j" glyph-name="j" d="M95 -99H308V415H91V516H436V-60Q436 -122 401 -161T292 -200H95V-99ZM373 596Q328 596 310 615T291 661V685Q291 712 309 731T373 750Q418 750 436 731T455 685V661Q455 634 437 615T373 596Z" />
|
||||
<glyph unicode="k" glyph-name="k" d="M77 740H205V306H211L286 388L413 516H562L357 313L584 0H431L266 240L205 182V0H77V740Z" />
|
||||
<glyph unicode="l" glyph-name="l" d="M72 101H236V639H72V740H364V101H529V0H72V101Z" />
|
||||
<glyph unicode="m" glyph-name="m" d="M37 0V516H143V445H149Q161 479 183 503T247 528Q286 528 309 506T339 442H344Q357 477 382 502T455 528Q512 528 537 487T562 366V0H457V351Q457 396 445 414T407 432Q384 432 369 417T353 371V0H247V351Q247 396 235 414T198
|
||||
432Q174 432 159 417T143 371V0H37Z" />
|
||||
<glyph unicode="n" glyph-name="n" d="M75 0V516H203V425H208Q225 467 260 497T359 528Q435 528 482 478T530 333V0H402V315Q402 427 305 427Q285 427 267 422T235 407T212 381T203 345V0H75Z" />
|
||||
<glyph unicode="o" glyph-name="o" d="M300 -12Q241 -12 195 7T116 61T66 146T48 258Q48 320 65 370T115 455T194 509T300 528Q358 528 405 509T484 455T534 370T552 258Q552 196 535 146T485 61T405 7T300 -12ZM300 86Q355 86 387 119T419 218V298Q419 363 387
|
||||
396T300 430Q245 430 213 397T181 298V218Q181 153 213 120T300 86Z" />
|
||||
<glyph unicode="p" glyph-name="p" d="M69 516H197V425H204Q225 472 261 500T358 528Q402 528 438 512T501 462T541 377T555 258Q555 190 541 139T501 55T439 5T358 -12Q298 -12 262 16T204 91H197V-200H69V516ZM304 90Q360 90 390 124T421 217V299Q421 358 391
|
||||
392T304 426Q260 426 229 405T197 339V177Q197 133 228 112T304 90Z" />
|
||||
<glyph unicode="q" glyph-name="q" d="M403 91H396Q375 44 339 16T242 -12Q198 -12 162 4T99 54T59 139T45 258Q45 394 99 461T242 528Q302 528 338 500T396 425H403V516H531V-200H403V91ZM296 90Q318 90 337 95T371 111T394 138T403 177V339Q403 361 395 377T372
|
||||
404T338 420T296 426Q240 426 210 392T179 299V217Q179 158 209 124T296 90Z" />
|
||||
<glyph unicode="r" glyph-name="r" d="M75 101H203V415H75V516H331V375H339Q346 402 358 427T390 472T438 504T505 516H561V396H455Q397 396 364 362T331 275V101H510V0H75V101Z" />
|
||||
<glyph unicode="s" glyph-name="s" d="M298 -12Q213 -12 151 14T54 86L129 154Q161 119 202 100T299 81Q347 81 376 97T405 146Q405 174 386 184T334 199L251 212Q219 217 189 226T135 253T97 296T83 361Q83 442 143 485T310 528Q385 528 437 507T524 448L457
|
||||
374Q435 398 399 416T306 435Q208 435 208 374Q208 346 228 336T280 320L362 307Q395 302 425 293T479 266T517 223T531 159Q531 79 470 34T298 -12Z" />
|
||||
<glyph unicode="t" glyph-name="t" d="M335 0Q261 0 226 39T191 140V415H41V516H143Q174 516 187 528T200 573V698H319V516H529V415H319V101H529V0H335Z" />
|
||||
<glyph unicode="u" glyph-name="u" d="M397 91H392Q375 49 340 19T241 -12Q165 -12 118 38T70 183V516H198V201Q198 89 295 89Q314 89 332 94T365 109T388 135T397 171V516H525V0H397V91Z" />
|
||||
<glyph unicode="v" glyph-name="v" d="M223 0L38 516H172L241 297L299 107H306L364 297L433 516H562L377 0H223Z" />
|
||||
<glyph unicode="w" glyph-name="w" d="M14 516H121L165 90H174L244 516H361L430 90H439L484 516H586L520 0H365L305 379H296L235 0H80L14 516Z" />
|
||||
<glyph unicode="x" glyph-name="x" d="M34 0L227 262L45 516H192L254 425L302 353H309L357 425L419 516H555L373 268L566 0H418L347 104L298 177H291L242 104L171 0H34Z" />
|
||||
<glyph unicode="y" glyph-name="y" d="M441 516H571L324 -92Q303 -145 268 -172T169 -200H75V-99H198L237 5L29 516H165L244 300L299 136H306L361 300L441 516Z" />
|
||||
<glyph unicode="z" glyph-name="z" d="M72 0V109L372 415H82V516H518V407L218 101H528V0H72Z" />
|
||||
<glyph unicode="{" glyph-name="braceleft" d="M327 -138Q267 -138 240 -110T213 -38V12Q213 38 218 57T232 92T250 119T269 142Q286 162 292 176T299 207Q299 267 183 267H96V355H183Q299 355 299 415Q299 431 293 445T269 480Q260 491 250 503T232 530T219 564T213
|
||||
610V660Q213 704 240 732T327 760H504V672H317V616Q317 577 329 556T357 515Q374 494 389 470T404 414Q404 372 375 347T289 314V308Q346 301 375 276T404 208Q404 176 389 152T357 107Q341 87 329 66T317 6V-50H504V-138H327Z" />
|
||||
<glyph unicode="|" glyph-name="bar" d="M245 -138V760H355V-138H245Z" />
|
||||
<glyph unicode="}" glyph-name="braceright" d="M273 760Q333 760 360 732T387 660V610Q387 584 382 565T368 530T350 503T331 480Q314 460 308 446T301 415Q301 355 417 355H504V267H417Q301 267 301 207Q301 191 307 177T331 142Q340 131 350 119T368 92T381
|
||||
58T387 12V-38Q387 -82 360 -110T273 -138H96V-50H283V6Q283 45 271 66T243 107Q226 128 211 152T196 208Q196 250 225 275T311 308V314Q254 321 225 346T196 414Q196 446 211 470T243 515Q259 535 271 556T283 616V672H96V760H273Z" />
|
||||
<glyph unicode="~" glyph-name="asciitilde" d="M409 218Q380 218 352 227T291 253Q265 266 244 276T202 286Q176 286 161 268T133 218L41 252Q56 314 94 353T191 392Q220 392 248 383T309 357Q335 344 356 334T398 324Q424 324 439 342T467 392L559 358Q544 296
|
||||
506 257T409 218Z" />
|
||||
<glyph unicode=" " glyph-name="uni00A0" />
|
||||
<glyph unicode="¡" glyph-name="exclamdown" d="M230 -182V21L279 276H321L370 21V-182H230ZM300 355Q250 355 230 376T209 427V455Q209 485 229 506T300 527Q350 527 370 506T391 455V427Q391 397 371 376T300 355Z" />
|
||||
<glyph unicode="¢" glyph-name="cent" d="M264 -114V-7Q170 9 119 79T67 258Q67 367 118 437T264 523V630H363V525Q426 517 465 485T527 404L433 353Q422 378 403 397T356 425V90Q387 98 408 118T444 165L535 112Q512 64 470 32T363 -9V-114H264ZM192 215Q192
|
||||
170 212 138T272 93V423Q233 411 213 379T192 301V215Z" />
|
||||
<glyph unicode="£" glyph-name="sterling" d="M71 0V127Q154 162 154 251Q154 257 154 263T152 274H48V372H121Q109 401 100 432T90 502Q90 548 107 586T157 652T234 695T334 710Q412 710 465 682T556 602L468 524Q443 557 413 577T336 597Q284 597 254 569T223
|
||||
484Q223 452 231 425T251 372H434V274H281Q283 266 283 257Q283 230 276 209T257 170T231 141T203 122V114H548V0H71Z" />
|
||||
<glyph unicode="¥" glyph-name="yen" d="M62 100H238V231H62V331H176L7 698H144L298 331H306L460 698H593L424 331H538V231H362V100H538V0H62V100Z" />
|
||||
<glyph unicode="¦" glyph-name="brokenbar" d="M245 401V760H355V401H245ZM245 -138V221H355V-138H245Z" />
|
||||
<glyph unicode="§" glyph-name="section" d="M504 3Q504 -36 488 -68T444 -122T376 -157T288 -170Q238 -170 188 -155T96 -102L162 -24Q187 -49 219 -62T289 -76Q337 -76 364 -56T392 -1Q392 29 369 46T299 76L225 97Q182 109 153 125T105 160T78 202T70
|
||||
248Q70 293 97 328T180 387V400Q139 426 121 460T102 537Q102 577 117 609T161 663T230 698T318 710Q368 710 418 695T510 643L444 564Q418 589 387 602T317 616Q269 616 242 596T214 542Q214 512 237 494T307 464L381 443Q424 431 453 415T501 380T528 338T536
|
||||
292Q536 247 509 212T426 153V140Q467 114 485 80T504 3ZM426 255Q426 286 406 309T332 346L260 366Q251 368 243 371T227 377Q204 357 192 335T180 285Q180 254 200 231T274 194L346 174Q355 172 363 169T379 163Q402 183 414 205T426 255Z" />
|
||||
<glyph unicode="¨" glyph-name="dieresis" d="M195 599Q154 599 138 616T122 657V679Q122 703 138 720T195 737Q236 737 252 720T268 679V657Q268 633 252 616T195 599ZM405 599Q364 599 348 616T332 657V679Q332 703 348 720T405 737Q446 737 462 720T478
|
||||
679V657Q478 633 462 616T405 599Z" />
|
||||
<glyph unicode="©" glyph-name="copyright" d="M300 18Q237 18 183 41T88 107T24 211T0 349Q0 425 23 486T87 591T182 657T300 680Q363 680 417 657T512 591T576 487T600 349Q600 272 577 211T513 107T418 41T300 18ZM300 73Q351 73 394 92T469 144T519 223T537
|
||||
319V379Q537 430 519 475T470 553T395 606T300 625Q249 625 206 606T131 554T81 475T63 379V319Q63 268 81 223T130 145T205 92T300 73ZM308 158Q227 158 180 210T133 349Q133 392 145 427T181 488T237 526T308 540Q365 540 400 513T453 444L378 405Q367 429 351
|
||||
443T309 457Q277 457 259 437T240 383V315Q240 282 258 262T310 241Q339 241 356 255T385 293L459 254Q442 215 406 187T308 158Z" />
|
||||
<glyph unicode="ª" glyph-name="ordfeminine" d="M429 345Q364 345 358 406H354Q344 374 316 356T244 337Q190 337 160 365T129 443Q129 498 169 525T288 552H350V572Q350 607 334 624T282 641Q248 641 227 628T192 594L140 640Q157 669 194 689T291 710Q362
|
||||
710 402 676T442 576V414H481V345H429ZM289 498Q219 498 219 454V441Q219 421 234 411T275 400Q306 400 328 414T350 456V498H289Z" />
|
||||
<glyph unicode="«" glyph-name="guillemotleft" d="M523 43L321 213V329L523 499L562 415L427 271L562 127L523 43ZM507 43L305 213V329L507 499L546 415L411 271L546 127L507 43Z" />
|
||||
<glyph unicode="¬" glyph-name="logicalnot" d="M416 61V254H62V357H522V61H416Z" />
|
||||
<glyph unicode="­" glyph-name="uni00AD" d="M145 242V367H455V242H145Z" />
|
||||
<glyph unicode="®" glyph-name="registered" d="M300 346Q262 346 229 360T170 398T131 455T117 528Q117 567 131 600T170 658T228 696T300 710Q338 710 371 696T429 658T468 601T483 528Q483 489 469 456T430 398T372 360T300 346ZM300 387Q329 387 353
|
||||
396T396 423T424 464T435 518V538Q435 568 425 592T396 633T354 659T300 669Q271 669 247 660T204 633T176 592T165 538V518Q165 488 175 464T204 423T246 397T300 387ZM275 436H225V621H315Q349 621 365 604T382 560Q382 520 347 504L388 436H333L299 495H275V436ZM303
|
||||
532Q329 532 329 553V561Q329 582 303 582H275V532H303Z" />
|
||||
<glyph unicode="¯" glyph-name="overscore" d="M151 714H449V622H151V714Z" />
|
||||
<glyph unicode="°" glyph-name="degree" d="M300 344Q261 344 228 358T170 396T131 454T117 527Q117 566 131 599T170 657T228 696T300 710Q339 710 372 696T430 658T469 600T483 527Q483 488 469 455T430 397T372 358T300 344ZM300 430Q342 430 366 457T391
|
||||
527Q391 569 367 596T300 624Q258 624 234 597T209 527Q209 485 233 458T300 430Z" />
|
||||
<glyph unicode="±" glyph-name="plusminus" d="M244 174V350H62V453H244V629H356V453H538V350H356V174H244ZM62 0V104H538V0H62Z" />
|
||||
<glyph unicode="²" glyph-name="twosuperior" d="M446 329H163V408L278 497Q313 524 328 542T343 585V587Q343 610 328 619T293 628Q266 628 252 614T232 579L153 609Q167 648 203 676T302 704Q368 704 404 673T440 592Q440 568 431 548T407 510T373 477T331
|
||||
448L261 402H446V329Z" />
|
||||
<glyph unicode="³" glyph-name="threesuperior" d="M284 554Q315 554 328 565T342 592V596Q342 613 329 623T292 634Q268 634 247 623T210 590L154 642Q178 671 210 687T294 704Q360 704 399 677T438 605Q438 570 416 549T361 523V519Q398 513 421 491T444
|
||||
432Q444 382 402 353T291 323Q260 323 237 329T196 344T165 367T142 395L209 446Q221 423 240 408T291 393Q319 393 334 405T349 437V440Q349 463 332 472T284 482H248V554H284Z" />
|
||||
<glyph unicode="´" glyph-name="acute" d="M313 575L236 612L331 799L439 745L313 575Z" />
|
||||
<glyph unicode="µ" glyph-name="mu" d="M75 -200V516H203V208Q203 89 297 89Q316 89 334 94T366 109T388 135T397 171V516H525V0H397V91H392Q385 71 375 52T349 19T314 -3T268 -12Q242 -12 222 -2T185 33H180L203 -86V-200H75Z" />
|
||||
<glyph unicode="¶" glyph-name="paragraph" d="M253 246Q206 246 166 263T94 310T46 381T28 472Q28 521 45 562T94 634T165 681T253 698H538V-149H432V597H359V-149H253V246Z" />
|
||||
<glyph unicode="·" glyph-name="middot" d="M300 213Q248 213 226 235T204 289V319Q204 351 226 373T300 395Q352 395 374 373T396 319V289Q396 257 374 235T300 213Z" />
|
||||
<glyph unicode="¸" glyph-name="cedilla" d="M313 -210Q265 -210 237 -196T197 -167L241 -116Q250 -128 266 -136T305 -145Q324 -145 336 -139T349 -118Q349 -106 335 -95T276 -78L253 -75L274 27H336L318 -57L322 -61Q333 -58 345 -56T368 -54Q397 -54 418
|
||||
-70T439 -122Q439 -146 429 -163T401 -190T361 -205T313 -210Z" />
|
||||
<glyph unicode="¹" glyph-name="onesuperior" d="M184 329V399H282V617L195 576L161 639L277 698H372V399H458V329H184Z" />
|
||||
<glyph unicode="º" glyph-name="ordmasculine" d="M300 338Q218 338 172 387T125 524Q125 611 171 660T300 710Q382 710 428 661T475 524Q475 437 429 388T300 338ZM300 408Q338 408 358 431T379 495V553Q379 594 359 617T300 640Q262 640 242 617T221 553V495Q221
|
||||
454 241 431T300 408Z" />
|
||||
<glyph unicode="»" glyph-name="guillemotright" d="M55 127L190 271L55 415L94 499L296 329V213L94 43L55 127ZM295 127L430 271L295 415L334 499L536 329V213L334 43L295 127Z" />
|
||||
<glyph unicode="¼" glyph-name="onequarter" d="M38 426H126V631L45 590L16 644L120 698H206V426H283V363H38V426ZM500 698H594L425 398H331L500 698ZM175 300H269L100 0H6L175 300ZM467 64H312V133L446 335H543V120H588V64H543V0H467V64ZM467 120V260H462L369
|
||||
120H467Z" />
|
||||
<glyph unicode="½" glyph-name="onehalf" d="M38 426H126V631L45 590L16 644L120 698H206V426H283V363H38V426ZM500 698H594L425 398H331L500 698ZM175 300H269L100 0H6L175 300ZM324 70L432 153Q464 178 476 196T488 237V240Q488 257 476 266T443 276Q419
|
||||
276 405 263T382 227L315 253Q321 270 331 286T357 314T395 333T448 341Q508 341 540 312T573 241Q573 220 566 203T545 169T513 138T472 107L412 63H580V0H324V70Z" />
|
||||
<glyph unicode="¾" glyph-name="threequarters" d="M147 357Q92 357 61 378T13 425L71 464Q82 444 99 431T146 418Q198 418 198 458V465Q198 485 181 495T136 506H106V564H138Q167 564 180 574T194 601V609Q194 623 182 633T147 643Q124 643 105 633T71 602L22
|
||||
646Q44 673 72 688T147 704Q207 704 242 680T277 614Q277 582 257 563T207 538V534Q241 529 262 510T283 456Q283 411 246 384T147 357ZM500 698H594L425 398H331L500 698ZM175 300H269L100 0H6L175 300ZM467 64H312V133L446 335H543V120H588V64H543V0H467V64ZM467
|
||||
120V260H462L369 120H467Z" />
|
||||
<glyph unicode="¿" glyph-name="questiondown" d="M306 -194Q255 -194 213 -180T141 -139T95 -76T78 6Q78 50 93 84T133 144T192 186T261 208V288H383V134Q305 131 260 105T214 18V4Q214 -41 241 -62T310 -84Q357 -84 386 -58T426 11L534 -33Q525 -64 507
|
||||
-93T462 -144T396 -180T306 -194ZM319 355Q269 355 249 376T228 427V455Q228 485 248 506T319 527Q369 527 389 506T410 455V427Q410 397 390 376T319 355Z" />
|
||||
<glyph unicode="À" glyph-name="Agrave" d="M449 0L400 177H193L145 0H13L209 698H391L588 0H449ZM301 569H293L216 284H378L301 569ZM161 915L269 969L364 782L287 745L161 915Z" />
|
||||
<glyph unicode="Á" glyph-name="Aacute" d="M449 0L400 177H193L145 0H13L209 698H391L588 0H449ZM301 569H293L216 284H378L301 569ZM313 745L236 782L331 969L439 915L313 745Z" />
|
||||
<glyph unicode="Â" glyph-name="Acircumflex" d="M449 0L400 177H193L145 0H13L209 698H391L588 0H449ZM301 569H293L216 284H378L301 569ZM358 950L484 795L418 746L298 861L178 746L116 795L242 950H358Z" />
|
||||
<glyph unicode="Ã" glyph-name="Atilde" d="M449 0L400 177H193L145 0H13L209 698H391L588 0H449ZM301 569H293L216 284H378L301 569ZM375 768Q351 768 333 775T297 790Q275 800 257 806T222 812Q205 812 192 806T163 787L117 846Q134 872 160 889T225 907Q249
|
||||
907 267 900T303 885Q325 875 343 869T378 863Q395 863 408 869T437 888L483 829Q466 803 440 786T375 768Z" />
|
||||
<glyph unicode="Ä" glyph-name="Adieresis" d="M449 0L400 177H193L145 0H13L209 698H391L588 0H449ZM301 569H293L216 284H378L301 569ZM195 769Q154 769 138 786T122 827V849Q122 873 138 890T195 907Q236 907 252 890T268 849V827Q268 803 252 786T195
|
||||
769ZM405 769Q364 769 348 786T332 827V849Q332 873 348 890T405 907Q446 907 462 890T478 849V827Q478 803 462 786T405 769Z" />
|
||||
<glyph unicode="Å" glyph-name="Aring" d="M449 0L400 177H193L145 0H13L209 698H391L588 0H449ZM301 569H293L216 284H378L301 569ZM300 726Q271 726 246 736T202 764T173 806T162 861Q162 890 172 915T201 958T245 986T300 996Q329 996 354 986T398 958T427
|
||||
916T438 861Q438 832 428 807T399 764T355 736T300 726ZM300 793Q326 793 339 807T353 845V877Q353 929 300 929Q274 929 261 915T247 877V845Q247 793 300 793Z" />
|
||||
<glyph unicode="Æ" glyph-name="AE" d="M289 178H170L131 0H3L176 698H568V599H410V403H558V304H410V99H568V0H289V178ZM264 607L191 276H289V607H264Z" />
|
||||
<glyph unicode="Ç" glyph-name="Ccedilla" d="M316 603Q248 603 219 551T189 409V289Q189 200 218 148T316 95Q344 95 364 103T397 127T420 164T436 209L556 175Q545 135 527 102T481 44T418 5T332 -12L323 -57L327 -61Q338 -58 349 -56T372 -54Q402 -54
|
||||
423 -70T444 -122Q444 -146 434 -163T406 -190T365 -205T318 -210Q269 -210 242 -196T201 -167L245 -116Q255 -128 271 -136T310 -145Q329 -145 341 -139T354 -118Q354 -106 340 -95T281 -78L258 -75L271 -9Q158 7 104 99T50 349Q50 521 115 615T318 710Q370 710
|
||||
409 696T478 658T526 599T556 523L436 489Q429 513 420 534T398 570T364 594T316 603Z" />
|
||||
<glyph unicode="È" glyph-name="Egrave" d="M164 915L272 969L367 782L290 745L164 915ZM83 0V698H524V590H214V408H513V300H214V108H524V0H83Z" />
|
||||
<glyph unicode="É" glyph-name="Eacute" d="M83 0V698H524V590H214V408H513V300H214V108H524V0H83ZM316 745L239 782L334 969L442 915L316 745Z" />
|
||||
<glyph unicode="Ê" glyph-name="Ecircumflex" d="M361 950L487 795L421 746L301 861L181 746L119 795L245 950H361ZM83 0V698H524V590H214V408H513V300H214V108H524V0H83Z" />
|
||||
<glyph unicode="Ë" glyph-name="Edieresis" d="M83 0V698H524V590H214V408H513V300H214V108H524V0H83ZM198 769Q157 769 141 786T125 827V849Q125 873 141 890T198 907Q239 907 255 890T271 849V827Q271 803 255 786T198 769ZM408 769Q367 769 351 786T335
|
||||
827V849Q335 873 351 890T408 907Q449 907 465 890T481 849V827Q481 803 465 786T408 769Z" />
|
||||
<glyph unicode="Ì" glyph-name="Igrave" d="M78 0V98H235V600H78V698H522V600H365V98H522V0H78ZM161 915L269 969L364 782L287 745L161 915Z" />
|
||||
<glyph unicode="Í" glyph-name="Iacute" d="M78 0V98H235V600H78V698H522V600H365V98H522V0H78ZM313 745L236 782L331 969L439 915L313 745Z" />
|
||||
<glyph unicode="Î" glyph-name="Icircumflex" d="M78 0V98H235V600H78V698H522V600H365V98H522V0H78ZM358 950L484 795L418 746L298 861L178 746L116 795L242 950H358Z" />
|
||||
<glyph unicode="Ï" glyph-name="Idieresis" d="M78 0V98H235V600H78V698H522V600H365V98H522V0H78ZM195 769Q154 769 138 786T122 827V849Q122 873 138 890T195 907Q236 907 252 890T268 849V827Q268 803 252 786T195 769ZM405 769Q364 769 348 786T332 827V849Q332
|
||||
873 348 890T405 907Q446 907 462 890T478 849V827Q478 803 462 786T405 769Z" />
|
||||
<glyph unicode="Ð" glyph-name="Eth" d="M79 319H14V418H79V698H290Q426 698 492 608T559 349Q559 179 493 90T290 0H79V319ZM281 105Q353 105 387 152T422 289V410Q422 499 388 546T281 593H208V414H327V322H208V105H281Z" />
|
||||
<glyph unicode="Ñ" glyph-name="Ntilde" d="M375 768Q351 768 333 775T297 790Q275 800 257 806T222 812Q205 812 192 806T163 787L117 846Q134 872 160 889T225 907Q249 907 267 900T303 885Q325 875 343 869T378 863Q395 863 408 869T437 888L483 829Q466
|
||||
803 440 786T375 768ZM189 501H179V0H67V698H228L411 197H421V698H533V0H372L189 501Z" />
|
||||
<glyph unicode="Ò" glyph-name="Ograve" d="M161 915L269 969L364 782L287 745L161 915ZM300 -12Q232 -12 182 12T100 83T52 196T36 349Q36 434 51 501T99 615T182 685T300 710Q436 710 500 615T564 349Q564 178 500 83T300 -12ZM300 95Q335 95 359 108T397
|
||||
147T418 208T425 290V409Q425 499 398 551T300 603Q230 603 203 551T175 409V289Q175 199 202 147T300 95Z" />
|
||||
<glyph unicode="Ó" glyph-name="Oacute" d="M313 745L236 782L331 969L439 915L313 745ZM300 -12Q232 -12 182 12T100 83T52 196T36 349Q36 434 51 501T99 615T182 685T300 710Q436 710 500 615T564 349Q564 178 500 83T300 -12ZM300 95Q335 95 359 108T397
|
||||
147T418 208T425 290V409Q425 499 398 551T300 603Q230 603 203 551T175 409V289Q175 199 202 147T300 95Z" />
|
||||
<glyph unicode="Ô" glyph-name="Ocircumflex" d="M358 950L484 795L418 746L298 861L178 746L116 795L242 950H358ZM300 -12Q232 -12 182 12T100 83T52 196T36 349Q36 434 51 501T99 615T182 685T300 710Q436 710 500 615T564 349Q564 178 500 83T300 -12ZM300
|
||||
95Q335 95 359 108T397 147T418 208T425 290V409Q425 499 398 551T300 603Q230 603 203 551T175 409V289Q175 199 202 147T300 95Z" />
|
||||
<glyph unicode="Õ" glyph-name="Otilde" d="M300 -12Q232 -12 182 12T100 83T52 196T36 349Q36 434 51 501T99 615T182 685T300 710Q436 710 500 615T564 349Q564 178 500 83T300 -12ZM300 95Q335 95 359 108T397 147T418 208T425 290V409Q425 499 398 551T300
|
||||
603Q230 603 203 551T175 409V289Q175 199 202 147T300 95ZM375 768Q351 768 333 775T297 790Q275 800 257 806T222 812Q205 812 192 806T163 787L117 846Q134 872 160 889T225 907Q249 907 267 900T303 885Q325 875 343 869T378 863Q395 863 408 869T437 888L483
|
||||
829Q466 803 440 786T375 768Z" />
|
||||
<glyph unicode="Ö" glyph-name="Odieresis" d="M300 -12Q232 -12 182 12T100 83T52 196T36 349Q36 434 51 501T99 615T182 685T300 710Q436 710 500 615T564 349Q564 178 500 83T300 -12ZM300 95Q335 95 359 108T397 147T418 208T425 290V409Q425 499 398
|
||||
551T300 603Q230 603 203 551T175 409V289Q175 199 202 147T300 95ZM195 769Q154 769 138 786T122 827V849Q122 873 138 890T195 907Q236 907 252 890T268 849V827Q268 803 252 786T195 769ZM405 769Q364 769 348 786T332 827V849Q332 873 348 890T405 907Q446
|
||||
907 462 890T478 849V827Q478 803 462 786T405 769Z" />
|
||||
<glyph unicode="×" glyph-name="multiply" d="M300 231L150 80L75 155L226 305L75 455L150 530L300 379L450 530L525 455L374 305L525 155L450 80L300 231Z" />
|
||||
<glyph unicode="Ø" glyph-name="Oslash" d="M300 -12Q217 -12 162 24L111 -59L27 -11L92 94Q63 140 50 204T36 349Q36 434 51 501T99 615T182 685T300 710Q382 710 438 674L489 757L573 709L508 604Q537 558 550 494T564 349Q564 178 500 83T300 -12ZM175
|
||||
289Q175 272 176 256T180 225L382 573Q352 603 300 603Q230 603 203 551T175 409V289ZM300 95Q370 95 397 147T425 289V409Q425 426 424 442T420 473L218 125Q248 95 300 95Z" />
|
||||
<glyph unicode="Ù" glyph-name="Ugrave" d="M161 915L269 969L364 782L287 745L161 915ZM193 698V263Q193 224 195 193T208 141T240 107T300 95Q338 95 359 107T391 140T404 193T407 263V698H538V283Q538 209 529 154T494 62T422 7T300 -12Q225 -12 179 6T106
|
||||
62T71 154T62 283V698H193Z" />
|
||||
<glyph unicode="Ú" glyph-name="Uacute" d="M193 698V263Q193 224 195 193T208 141T240 107T300 95Q338 95 359 107T391 140T404 193T407 263V698H538V283Q538 209 529 154T494 62T422 7T300 -12Q225 -12 179 6T106 62T71 154T62 283V698H193ZM313 745L236
|
||||
782L331 969L439 915L313 745Z" />
|
||||
<glyph unicode="Û" glyph-name="Ucircumflex" d="M358 950L484 795L418 746L298 861L178 746L116 795L242 950H358ZM193 698V263Q193 224 195 193T208 141T240 107T300 95Q338 95 359 107T391 140T404 193T407 263V698H538V283Q538 209 529 154T494 62T422
|
||||
7T300 -12Q225 -12 179 6T106 62T71 154T62 283V698H193Z" />
|
||||
<glyph unicode="Ü" glyph-name="Udieresis" d="M193 698V263Q193 224 195 193T208 141T240 107T300 95Q338 95 359 107T391 140T404 193T407 263V698H538V283Q538 209 529 154T494 62T422 7T300 -12Q225 -12 179 6T106 62T71 154T62 283V698H193ZM195 769Q154
|
||||
769 138 786T122 827V849Q122 873 138 890T195 907Q236 907 252 890T268 849V827Q268 803 252 786T195 769ZM405 769Q364 769 348 786T332 827V849Q332 873 348 890T405 907Q446 907 462 890T478 849V827Q478 803 462 786T405 769Z" />
|
||||
<glyph unicode="Ý" glyph-name="Yacute" d="M235 0V255L8 698H154L235 530L298 387H305L369 530L451 698H592L365 255V0H235ZM313 745L236 782L331 969L439 915L313 745Z" />
|
||||
<glyph unicode="Þ" glyph-name="Thorn" d="M80 0V698H211V570H342Q393 570 432 555T497 511T537 443T551 354Q551 256 498 198T342 140H211V0H80ZM211 246H316Q369 246 392 267T415 336V373Q415 420 392 441T316 463H211V246Z" />
|
||||
<glyph unicode="ß" glyph-name="germandbls" d="M72 0V600Q72 631 80 656T107 700T152 729T217 740H369V642H197V516H535V418L387 212Q475 200 524 152T573 15Q573 -90 502 -145T311 -200H245V-102H305Q376 -102 409 -77T443 3V27Q443 81 408 105T295 129H274V227L412
|
||||
418H197V0H72Z" />
|
||||
<glyph unicode="à" glyph-name="agrave" d="M490 0Q443 0 418 23T387 89H382Q368 41 327 15T226 -12Q148 -12 102 29T56 143Q56 299 285 299H376V333Q376 382 352 407T274 432Q225 432 195 413T144 364L71 426Q95 469 148 498T287 528Q389 528 446 481T504
|
||||
339V96H565V0H490ZM269 76Q315 76 345 97T376 156V225H288Q183 225 183 159V139Q183 108 206 92T269 76ZM408 745L516 799L611 612L534 575L408 745Z" />
|
||||
<glyph unicode="á" glyph-name="aacute" d="M490 0Q443 0 418 23T387 89H382Q368 41 327 15T226 -12Q148 -12 102 29T56 143Q56 299 285 299H376V333Q376 382 352 407T274 432Q225 432 195 413T144 364L71 426Q95 469 148 498T287 528Q389 528 446 481T504
|
||||
339V96H565V0H490ZM269 76Q315 76 345 97T376 156V225H288Q183 225 183 159V139Q183 108 206 92T269 76ZM560 575L483 612L578 799L686 745L560 575Z" />
|
||||
<glyph unicode="â" glyph-name="acircumflex" d="M490 0Q443 0 418 23T387 89H382Q368 41 327 15T226 -12Q148 -12 102 29T56 143Q56 299 285 299H376V333Q376 382 352 407T274 432Q225 432 195 413T144 364L71 426Q95 469 148 498T287 528Q389 528 446 481T504
|
||||
339V96H565V0H490ZM269 76Q315 76 345 97T376 156V225H288Q183 225 183 159V139Q183 108 206 92T269 76ZM605 780L731 625L665 576L545 691L425 576L363 625L489 780H605Z" />
|
||||
<glyph unicode="ã" glyph-name="atilde" d="M490 0Q443 0 418 23T387 89H382Q368 41 327 15T226 -12Q148 -12 102 29T56 143Q56 299 285 299H376V333Q376 382 352 407T274 432Q225 432 195 413T144 364L71 426Q95 469 148 498T287 528Q389 528 446 481T504
|
||||
339V96H565V0H490ZM269 76Q315 76 345 97T376 156V225H288Q183 225 183 159V139Q183 108 206 92T269 76ZM622 598Q598 598 580 605T544 620Q522 630 504 636T469 642Q452 642 439 636T410 617L364 676Q381 702 407 719T472 737Q496 737 514 730T550 715Q572 705
|
||||
590 699T625 693Q642 693 655 699T684 718L730 659Q713 633 687 616T622 598Z" />
|
||||
<glyph unicode="ä" glyph-name="adieresis" d="M490 0Q443 0 418 23T387 89H382Q368 41 327 15T226 -12Q148 -12 102 29T56 143Q56 299 285 299H376V333Q376 382 352 407T274 432Q225 432 195 413T144 364L71 426Q95 469 148 498T287 528Q389 528 446 481T504
|
||||
339V96H565V0H490ZM269 76Q315 76 345 97T376 156V225H288Q183 225 183 159V139Q183 108 206 92T269 76ZM442 599Q401 599 385 616T369 657V679Q369 703 385 720T442 737Q483 737 499 720T515 679V657Q515 633 499 616T442 599ZM652 599Q611 599 595 616T579 657V679Q579
|
||||
703 595 720T652 737Q693 737 709 720T725 679V657Q725 633 709 616T652 599Z" />
|
||||
<glyph unicode="å" glyph-name="aring" d="M490 0Q443 0 418 23T387 89H382Q368 41 327 15T226 -12Q148 -12 102 29T56 143Q56 299 285 299H376V333Q376 382 352 407T274 432Q225 432 195 413T144 364L71 426Q95 469 148 498T287 528Q389 528 446 481T504
|
||||
339V96H565V0H490ZM269 76Q315 76 345 97T376 156V225H288Q183 225 183 159V139Q183 108 206 92T269 76ZM547 556Q518 556 493 566T449 594T420 636T409 691Q409 720 419 745T448 788T492 816T547 826Q576 826 601 816T645 788T674 746T685 691Q685 662 675 637T646
|
||||
594T602 566T547 556ZM547 623Q573 623 586 637T600 675V707Q600 759 547 759Q521 759 508 745T494 707V675Q494 623 547 623Z" />
|
||||
<glyph unicode="æ" glyph-name="ae" d="M138 -12Q82 -12 44 26T6 140Q6 220 52 261T187 302H233V358Q233 445 169 445Q138 445 123 426T96 374L16 407Q32 465 71 496T169 528Q215 528 246 509T294 454H298Q339 528 419 528Q496 528 539 467T583 296V231H339V213Q339
|
||||
151 359 113T418 75Q449 75 465 98T491 152L577 125Q569 98 556 73T524 29T478 -1T418 -12Q366 -12 325 16T265 104H261Q250 44 218 16T138 -12ZM165 70Q202 70 217 97T233 172V231H198Q156 231 133 213T109 156V138Q109 106 122 88T165 70ZM413 447Q376 447 358
|
||||
419T339 343V302H487V343Q487 391 469 419T413 447Z" />
|
||||
<glyph unicode="ç" glyph-name="ccedilla" d="M319 528Q401 528 451 494T527 404L428 350Q414 383 389 403T319 424Q262 424 232 391T201 301V215Q201 159 231 126T321 92Q367 92 394 113T439 169L535 112Q509 58 459 24T329 -12L320 -57L324 -61Q335 -58
|
||||
346 -56T369 -54Q399 -54 420 -70T441 -122Q441 -146 431 -163T403 -190T362 -205T315 -210Q267 -210 239 -196T199 -167L242 -116Q252 -128 268 -136T307 -145Q326 -145 338 -139T351 -118Q351 -106 337 -95T278 -78L255 -75L269 -8Q173 7 120 77T67 258Q67 320
|
||||
84 370T134 455T213 509T319 528Z" />
|
||||
<glyph unicode="è" glyph-name="egrave" d="M312 -12Q250 -12 202 7T122 61T72 145T55 257Q55 320 72 370T122 455T199 509T302 528Q358 528 403 510T479 457T528 375T545 269V227H183V214Q183 158 218 124T316 89Q364 89 398 108T456 160L529 87Q501 46
|
||||
448 17T312 -12ZM303 434Q249 434 216 400T183 310V303H417V312Q417 368 387 401T303 434ZM162 745L270 799L365 612L288 575L162 745Z" />
|
||||
<glyph unicode="é" glyph-name="eacute" d="M314 575L237 612L332 799L440 745L314 575ZM312 -12Q250 -12 202 7T122 61T72 145T55 257Q55 320 72 370T122 455T199 509T302 528Q358 528 403 510T479 457T528 375T545 269V227H183V214Q183 158 218 124T316
|
||||
89Q364 89 398 108T456 160L529 87Q501 46 448 17T312 -12ZM303 434Q249 434 216 400T183 310V303H417V312Q417 368 387 401T303 434Z" />
|
||||
<glyph unicode="ê" glyph-name="ecircumflex" d="M359 780L485 625L419 576L299 691L179 576L117 625L243 780H359ZM312 -12Q250 -12 202 7T122 61T72 145T55 257Q55 320 72 370T122 455T199 509T302 528Q358 528 403 510T479 457T528 375T545 269V227H183V214Q183
|
||||
158 218 124T316 89Q364 89 398 108T456 160L529 87Q501 46 448 17T312 -12ZM303 434Q249 434 216 400T183 310V303H417V312Q417 368 387 401T303 434Z" />
|
||||
<glyph unicode="ë" glyph-name="edieresis" d="M196 599Q155 599 139 616T123 657V679Q123 703 139 720T196 737Q237 737 253 720T269 679V657Q269 633 253 616T196 599ZM406 599Q365 599 349 616T333 657V679Q333 703 349 720T406 737Q447 737 463 720T479
|
||||
679V657Q479 633 463 616T406 599ZM312 -12Q250 -12 202 7T122 61T72 145T55 257Q55 320 72 370T122 455T199 509T302 528Q358 528 403 510T479 457T528 375T545 269V227H183V214Q183 158 218 124T316 89Q364 89 398 108T456 160L529 87Q501 46 448 17T312 -12ZM303
|
||||
434Q249 434 216 400T183 310V303H417V312Q417 368 387 401T303 434Z" />
|
||||
<glyph unicode="ì" glyph-name="igrave" d="M98 101H268V415H98V516H396V101H554V0H98V101ZM193 745L301 799L396 612L319 575L193 745Z" />
|
||||
<glyph unicode="í" glyph-name="iacute" d="M345 575L268 612L363 799L471 745L345 575ZM98 101H268V415H98V516H396V101H554V0H98V101Z" />
|
||||
<glyph unicode="î" glyph-name="icircumflex" d="M390 780L516 625L450 576L330 691L210 576L148 625L274 780H390ZM98 101H268V415H98V516H396V101H554V0H98V101Z" />
|
||||
<glyph unicode="ï" glyph-name="idieresis" d="M227 599Q186 599 170 616T154 657V679Q154 703 170 720T227 737Q268 737 284 720T300 679V657Q300 633 284 616T227 599ZM437 599Q396 599 380 616T364 657V679Q364 703 380 720T437 737Q478 737 494 720T510
|
||||
679V657Q510 633 494 616T437 599ZM98 101H268V415H98V516H396V101H554V0H98V101Z" />
|
||||
<glyph unicode="ð" glyph-name="eth" d="M476 698L397 648Q429 616 457 577T507 491T540 390T553 274Q553 200 535 146T484 57T405 5T303 -12Q243 -12 196 6T116 59T66 141T48 251Q48 308 62 354T104 433T169 483T253 501Q311 501 350 475T413 405L420 409Q403
|
||||
460 373 504T300 590L206 531L159 586L244 639Q209 668 170 692T87 740H284Q298 731 312 721T342 698L429 753L476 698ZM301 86Q356 86 388 119T421 215V274Q421 337 389 370T301 403Q246 403 214 370T181 274V215Q181 152 213 119T301 86Z" />
|
||||
<glyph unicode="ñ" glyph-name="ntilde" d="M75 0V516H203V425H208Q225 467 260 497T359 528Q435 528 482 478T530 333V0H402V315Q402 427 305 427Q285 427 267 422T235 407T212 381T203 345V0H75ZM377 598Q353 598 335 605T299 620Q277 630 259 636T224
|
||||
642Q207 642 194 636T165 617L119 676Q136 702 162 719T227 737Q251 737 269 730T305 715Q327 705 345 699T380 693Q397 693 410 699T439 718L485 659Q468 633 442 616T377 598Z" />
|
||||
<glyph unicode="ò" glyph-name="ograve" d="M300 -12Q241 -12 195 7T116 61T66 146T48 258Q48 320 65 370T115 455T194 509T300 528Q358 528 405 509T484 455T534 370T552 258Q552 196 535 146T485 61T405 7T300 -12ZM300 86Q355 86 387 119T419 218V298Q419
|
||||
363 387 396T300 430Q245 430 213 397T181 298V218Q181 153 213 120T300 86ZM161 745L269 799L364 612L287 575L161 745Z" />
|
||||
<glyph unicode="ó" glyph-name="oacute" d="M313 575L236 612L331 799L439 745L313 575ZM300 -12Q241 -12 195 7T116 61T66 146T48 258Q48 320 65 370T115 455T194 509T300 528Q358 528 405 509T484 455T534 370T552 258Q552 196 535 146T485 61T405 7T300
|
||||
-12ZM300 86Q355 86 387 119T419 218V298Q419 363 387 396T300 430Q245 430 213 397T181 298V218Q181 153 213 120T300 86Z" />
|
||||
<glyph unicode="ô" glyph-name="ocircumflex" d="M358 780L484 625L418 576L298 691L178 576L116 625L242 780H358ZM300 -12Q241 -12 195 7T116 61T66 146T48 258Q48 320 65 370T115 455T194 509T300 528Q358 528 405 509T484 455T534 370T552 258Q552 196
|
||||
535 146T485 61T405 7T300 -12ZM300 86Q355 86 387 119T419 218V298Q419 363 387 396T300 430Q245 430 213 397T181 298V218Q181 153 213 120T300 86Z" />
|
||||
<glyph unicode="õ" glyph-name="otilde" d="M300 -12Q241 -12 195 7T116 61T66 146T48 258Q48 320 65 370T115 455T194 509T300 528Q358 528 405 509T484 455T534 370T552 258Q552 196 535 146T485 61T405 7T300 -12ZM300 86Q355 86 387 119T419 218V298Q419
|
||||
363 387 396T300 430Q245 430 213 397T181 298V218Q181 153 213 120T300 86ZM375 598Q351 598 333 605T297 620Q275 630 257 636T222 642Q205 642 192 636T163 617L117 676Q134 702 160 719T225 737Q249 737 267 730T303 715Q325 705 343 699T378 693Q395 693 408
|
||||
699T437 718L483 659Q466 633 440 616T375 598Z" />
|
||||
<glyph unicode="ö" glyph-name="odieresis" d="M195 599Q154 599 138 616T122 657V679Q122 703 138 720T195 737Q236 737 252 720T268 679V657Q268 633 252 616T195 599ZM405 599Q364 599 348 616T332 657V679Q332 703 348 720T405 737Q446 737 462 720T478
|
||||
679V657Q478 633 462 616T405 599ZM300 -12Q241 -12 195 7T116 61T66 146T48 258Q48 320 65 370T115 455T194 509T300 528Q358 528 405 509T484 455T534 370T552 258Q552 196 535 146T485 61T405 7T300 -12ZM300 86Q355 86 387 119T419 218V298Q419 363 387 396T300
|
||||
430Q245 430 213 397T181 298V218Q181 153 213 120T300 86Z" />
|
||||
<glyph unicode="÷" glyph-name="divide" d="M62 254V357H538V254H62ZM300 36Q256 36 238 54T220 99V122Q220 148 238 166T300 185Q344 185 362 167T380 122V99Q380 72 362 54T300 36ZM300 426Q256 426 238 444T220 489V512Q220 538 238 556T300 575Q344 575
|
||||
362 557T380 512V489Q380 463 362 445T300 426Z" />
|
||||
<glyph unicode="ø" glyph-name="oslash" d="M30 -1L99 82Q48 149 48 258Q48 320 65 370T115 455T194 509T300 528Q340 528 374 519T436 493L499 569L570 517L501 434Q552 366 552 258Q552 196 535 146T485 61T405 7T300 -12Q260 -12 226 -3T164 23L101 -53L30
|
||||
-1ZM300 430Q245 430 213 397T181 298V224Q181 213 182 201T186 180L373 408Q359 419 341 424T300 430ZM300 86Q355 86 387 119T419 218V292Q419 303 418 315T414 336L227 108Q241 97 259 92T300 86Z" />
|
||||
<glyph unicode="ù" glyph-name="ugrave" d="M397 91H392Q375 49 340 19T241 -12Q165 -12 118 38T70 183V516H198V201Q198 89 295 89Q314 89 332 94T365 109T388 135T397 171V516H525V0H397V91ZM416 745L524 799L619 612L542 575L416 745Z" />
|
||||
<glyph unicode="ú" glyph-name="uacute" d="M568 575L491 612L586 799L694 745L568 575ZM397 91H392Q375 49 340 19T241 -12Q165 -12 118 38T70 183V516H198V201Q198 89 295 89Q314 89 332 94T365 109T388 135T397 171V516H525V0H397V91Z" />
|
||||
<glyph unicode="û" glyph-name="ucircumflex" d="M613 780L739 625L673 576L553 691L433 576L371 625L497 780H613ZM397 91H392Q375 49 340 19T241 -12Q165 -12 118 38T70 183V516H198V201Q198 89 295 89Q314 89 332 94T365 109T388 135T397 171V516H525V0H397V91Z" />
|
||||
<glyph unicode="ü" glyph-name="udieresis" d="M450 599Q409 599 393 616T377 657V679Q377 703 393 720T450 737Q491 737 507 720T523 679V657Q523 633 507 616T450 599ZM660 599Q619 599 603 616T587 657V679Q587 703 603 720T660 737Q701 737 717 720T733
|
||||
679V657Q733 633 717 616T660 599ZM397 91H392Q375 49 340 19T241 -12Q165 -12 118 38T70 183V516H198V201Q198 89 295 89Q314 89 332 94T365 109T388 135T397 171V516H525V0H397V91Z" />
|
||||
<glyph unicode="ý" glyph-name="yacute" d="M441 516H571L324 -92Q303 -145 268 -172T169 -200H75V-99H198L237 5L29 516H165L244 300L299 136H306L361 300L441 516ZM314 575L237 612L332 799L440 745L314 575Z" />
|
||||
<glyph unicode="þ" glyph-name="thorn" d="M69 740H197V425H204Q225 472 261 500T358 528Q402 528 438 512T501 462T541 377T555 258Q555 190 541 139T501 55T439 5T358 -12Q298 -12 262 16T204 91H197V-200H69V740ZM304 90Q360 90 390 124T421 217V299Q421
|
||||
358 391 392T304 426Q260 426 229 405T197 339V177Q197 133 228 112T304 90Z" />
|
||||
<glyph unicode="ÿ" glyph-name="ydieresis" d="M441 516H571L324 -92Q303 -145 268 -172T169 -200H75V-99H198L237 5L29 516H165L244 300L299 136H306L361 300L441 516ZM196 599Q155 599 139 616T123 657V679Q123 703 139 720T196 737Q237 737 253 720T269
|
||||
679V657Q269 633 253 616T196 599ZM406 599Q365 599 349 616T333 657V679Q333 703 349 720T406 737Q447 737 463 720T479 679V657Q479 633 463 616T406 599Z" />
|
||||
<glyph unicode="–" glyph-name="endash" d="M60 251V358H540V251H60Z" />
|
||||
<glyph unicode="—" glyph-name="emdash" d="M0 251V358H600V251H0Z" />
|
||||
<glyph unicode="‘" glyph-name="quoteleft" d="M303 740H399L344 428H172L303 740Z" />
|
||||
<glyph unicode="’" glyph-name="quoteright" d="M256 740H428L297 428H201L256 740Z" />
|
||||
<glyph unicode="‚" glyph-name="quotesinglbase" d="M236 163H408L277 -148H180L236 163Z" />
|
||||
<glyph unicode="“" glyph-name="quotedblleft" d="M436 740H532L477 428H305L436 740ZM431 740H527L472 428H300L431 740Z" />
|
||||
<glyph unicode="”" glyph-name="quotedblright" d="M389 740H561L430 428H334L389 740ZM384 740H556L425 428H329L384 740Z" />
|
||||
<glyph unicode="„" glyph-name="quotedblbase" d="M377 163H549L418 -148H321L377 163ZM372 163H544L413 -148H316L372 163Z" />
|
||||
<glyph unicode="•" glyph-name="bullet" d="M300 165Q260 165 233 174T188 200T164 239T156 288V320Q156 346 163 368T188 407T232 433T300 443Q340 443 367 434T412 408T436 369T444 320V288Q444 235 412 200T300 165Z" />
|
||||
<glyph unicode="‹" glyph-name="guilsinglleft" d="M374 43L172 213V329L374 499L413 415L278 271L413 127L374 43Z" />
|
||||
<glyph unicode="›" glyph-name="guilsinglright" d="M187 127L322 271L187 415L226 499L428 329V213L226 43L187 127Z" />
|
||||
</font>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 51 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,325 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<defs >
|
||||
<font id="IBMPlexMono" horiz-adv-x="600" ><font-face
|
||||
font-family="IBM Plex Mono"
|
||||
units-per-em="1000"
|
||||
panose-1="2 11 8 9 5 2 3 0 2 3"
|
||||
ascent="1025"
|
||||
descent="-275"
|
||||
alphabetic="0" />
|
||||
<glyph unicode=" " glyph-name="space" />
|
||||
<glyph unicode="!" glyph-name="exclam" d="M276 243L219 495V698H381V495L324 243H276ZM300 -12Q246 -12 224 11T202 66V98Q202 129 224 152T300 175Q353 175 375 152T398 98V66Q398 34 376 11T300 -12Z" />
|
||||
<glyph unicode=""" glyph-name="quotedbl" d="M378 414V740H510V414H378ZM347 414V740H479V414H347Z" />
|
||||
<glyph unicode="#" glyph-name="numbersign" d="M117 194H9V304H137L152 394H47V504H172L206 698H323L200 0H83L117 194ZM400 698H517L483 504H591V394H463L448 304H553V194H428L394 0H277L400 698Z" />
|
||||
<glyph unicode="$" glyph-name="dollar" d="M253 -10Q178 -4 122 23T30 96L117 191Q149 157 185 138T263 113V297L240 301Q144 318 98 371T52 502Q52 587 104 640T253 706V811H367V707Q430 699 474 675T549 616L463 520Q421 566 357 580V413L380 409Q476 391 522
|
||||
340T568 212Q568 171 555 135T516 71T453 24T367 -5V-113H253V-10ZM193 507Q193 475 209 459T263 432V583Q226 577 210 558T193 507ZM428 202Q428 236 411 253T357 279V114Q393 122 410 144T428 202Z" />
|
||||
<glyph unicode="%" glyph-name="percent" d="M165 338Q90 338 49 387T8 524Q8 611 49 660T165 710Q240 710 281 661T322 524Q322 437 281 388T165 338ZM165 425Q194 425 205 446T217 502V546Q217 581 206 602T165 623Q136 623 125 602T113 546V502Q113 467 124
|
||||
446T165 425ZM485 698H598L447 398H334L485 698ZM153 300H266L115 0H2L153 300ZM436 -12Q361 -12 320 37T279 174Q279 261 320 310T436 360Q511 360 552 311T593 174Q593 87 552 38T436 -12ZM436 75Q465 75 476 96T488 152V196Q488 231 477 252T436 273Q407 273
|
||||
396 252T384 196V152Q384 117 395 96T436 75Z" />
|
||||
<glyph unicode="&" glyph-name="ampersand" d="M207 -12Q160 -12 124 4T64 48T27 112T14 190Q14 253 44 300T132 381Q100 426 84 461T67 534Q67 571 81 603T122 659T184 696T262 710Q299 710 331 700T387 672T428 633T453 586L351 531Q340 563 317 581T264
|
||||
600Q234 600 216 582T197 535V530Q197 516 201 504T215 476T240 440T280 389L337 317L385 243H391Q394 260 396 280T399 322T401 364T402 402H580V292H510Q505 260 495 227T469 158L599 0H441L361 97H354Q347 46 308 17T207 -12ZM244 101Q267 101 287 109T321 141L192
|
||||
305Q166 280 158 255T150 200V198Q150 150 175 126T244 101Z" />
|
||||
<glyph unicode="'" glyph-name="quotesingle" d="M234 414V740H366V414H234Z" />
|
||||
<glyph unicode="(" glyph-name="parenleft" d="M174 311Q174 384 190 451T235 577T302 681T382 760H530Q483 728 441 686T368 592T317 483T298 362V260Q298 197 317 139T367 30T441 -63T530 -138H382Q340 -107 302 -60T236 45T191 170T174 311Z" />
|
||||
<glyph unicode=")" glyph-name="parenright" d="M426 311Q426 238 410 171T365 45T298 -60T218 -138H70Q116 -106 158 -64T232 30T283 139T302 260V362Q302 425 283 483T233 592T159 685T70 760H218Q260 728 298 682T364 577T409 452T426 311Z" />
|
||||
<glyph unicode="*" glyph-name="asterisk" d="M191 60L87 129L201 279L30 337L69 452L236 391V568H364V391L531 452L570 337L399 279L513 129L409 60L300 209L191 60Z" />
|
||||
<glyph unicode="+" glyph-name="plus" d="M236 62V246H62V364H236V548H364V364H538V246H364V62H236Z" />
|
||||
<glyph unicode="," glyph-name="comma" d="M227 174H417L280 -151H170L227 174Z" />
|
||||
<glyph unicode="-" glyph-name="hyphen" d="M140 234V376H460V234H140Z" />
|
||||
<glyph unicode="." glyph-name="period" d="M300 -12Q244 -12 220 12T195 71V106Q195 140 219 164T300 189Q356 189 380 165T405 106V71Q405 37 381 13T300 -12Z" />
|
||||
<glyph unicode="/" glyph-name="slash" d="M73 -138L394 760H527L206 -138H73Z" />
|
||||
<glyph unicode="0" glyph-name="zero" d="M300 -12Q160 -12 94 83T27 349Q27 520 93 615T300 710Q440 710 506 615T573 349Q573 178 507 83T300 -12ZM300 106Q367 106 393 153T420 284V414Q420 498 394 545T300 592Q233 592 207 545T180 414V284Q180 200 206 153T300
|
||||
106ZM300 290Q265 290 252 304T238 338V360Q238 380 251 394T300 408Q335 408 348 394T362 360V338Q362 318 349 304T300 290Z" />
|
||||
<glyph unicode="1" glyph-name="one" d="M94 0V121H282V589H273L131 403L35 478L202 698H432V121H580V0H94Z" />
|
||||
<glyph unicode="2" glyph-name="two" d="M555 0H53V137L273 320Q330 369 355 405T380 481V491Q380 535 354 557T284 580Q234 580 207 551T169 482L38 532Q50 568 71 600T124 657T200 695T299 710Q356 710 401 694T477 650T524 584T540 500Q540 456 526 420T486
|
||||
351T426 289T352 229L219 126H555V0Z" />
|
||||
<glyph unicode="3" glyph-name="three" d="M273 422Q331 422 357 444T384 498V505Q384 543 359 565T286 588Q243 588 206 567T142 505L47 593Q67 619 91 640T144 677T209 701T292 710Q349 710 395 697T473 660T524 601T542 525Q542 492 531 465T502 418T459 386T406
|
||||
368V362Q470 351 512 309T555 194Q555 147 536 109T481 44T395 3T282 -12Q229 -12 189 -1T117 28T64 71T24 122L135 208Q158 165 192 138T285 110Q339 110 368 135T397 204V211Q397 254 364 275T272 297H207V422H273Z" />
|
||||
<glyph unicode="4" glyph-name="four" d="M339 0V134H25V262L303 698H483V250H573V134H483V0H339ZM146 250H339V543H330L146 250Z" />
|
||||
<glyph unicode="5" glyph-name="five" d="M525 567H202L186 346H195Q206 370 220 390T253 425T297 448T354 456Q397 456 435 441T503 398T550 328T567 234Q567 181 549 136T497 58T411 7T295 -12Q244 -12 204 -1T134 28T81 71T42 122L151 208Q163 188 176 170T207
|
||||
139T246 118T296 110Q352 110 380 140T409 222V230Q409 279 380 307T300 335Q258 335 231 319T189 286L66 303L92 698H525V567Z" />
|
||||
<glyph unicode="6" glyph-name="six" d="M304 -12Q241 -12 192 7T108 63T56 151T38 265Q38 338 61 403T120 524T202 624T293 698H500Q435 653 384 612T294 529T231 443T195 348L204 345Q213 365 226 384T258 417T302 441T362 450Q406 450 444 435T509 391T553
|
||||
322T569 232Q569 179 550 134T497 57T413 6T304 -12ZM303 105Q357 105 385 133T413 214V228Q413 280 385 307T303 335Q252 335 223 308T194 228V214Q194 162 221 134T303 105Z" />
|
||||
<glyph unicode="7" glyph-name="seven" d="M164 0L404 576H178V449H51V698H553V568L322 0H164Z" />
|
||||
<glyph unicode="8" glyph-name="eight" d="M300 -12Q237 -12 188 3T105 46T54 110T36 192Q36 260 75 301T175 360V368Q123 387 90 426T57 526Q57 566 73 600T120 658T196 696T300 710Q358 710 403 697T480 659T527 600T543 526Q543 465 510 426T425 368V360Q486
|
||||
343 525 302T564 192Q564 148 547 111T495 46T412 4T300 -12ZM300 103Q352 103 379 127T407 192V212Q407 254 380 277T300 301Q247 301 220 278T193 212V192Q193 151 220 127T300 103ZM300 411Q350 411 376 434T402 496V511Q402 550 376 572T300 595Q251 595 225
|
||||
573T198 511V496Q198 457 224 434T300 411Z" />
|
||||
<glyph unicode="9" glyph-name="nine" d="M562 433Q562 359 539 294T480 174T398 74T307 0H100Q165 45 216 86T306 169T369 255T405 350L396 353Q387 333 374 314T342 281T298 257T238 248Q194 248 156 263T91 307T47 376T31 466Q31 519 50 564T103 641T187 692T296
|
||||
710Q359 710 408 691T492 635T544 547T562 433ZM297 363Q348 363 377 390T406 470V484Q406 536 379 564T297 593Q243 593 215 565T187 484V470Q187 418 215 391T297 363Z" />
|
||||
<glyph unicode=":" glyph-name="colon" d="M300 -12Q244 -12 220 12T195 71V106Q195 140 219 164T300 189Q356 189 380 165T405 106V71Q405 37 381 13T300 -12ZM300 327Q244 327 220 351T195 410V445Q195 479 219 503T300 528Q356 528 380 504T405 445V410Q405
|
||||
376 381 352T300 327Z" />
|
||||
<glyph unicode=";" glyph-name="semicolon" d="M227 174H417L280 -151H170L227 174ZM300 327Q244 327 220 351T195 410V445Q195 479 219 503T300 528Q356 528 380 504T405 445V410Q405 376 381 352T300 327Z" />
|
||||
<glyph unicode="<" glyph-name="less" d="M85 236V374L515 604V466L218 309V301L515 144V6L85 236Z" />
|
||||
<glyph unicode="=" glyph-name="equal" d="M62 361V479H538V361H62ZM62 131V249H538V131H62Z" />
|
||||
<glyph unicode=">" glyph-name="greater" d="M85 144L382 301V309L85 466V604L515 374V236L85 6V144Z" />
|
||||
<glyph unicode="?" glyph-name="question" d="M208 233V386Q283 389 327 412T371 492V506Q371 548 347 566T286 584Q245 584 219 561T183 499L61 550Q70 580 87 608T133 659T200 696T291 710Q344 710 387 695T462 653T510 588T527 505Q527 463 513 429T474 369T417
|
||||
327T348 305V233H208ZM280 -12Q227 -12 205 11T182 66V98Q182 130 204 152T280 175Q333 175 356 152T379 98V66Q379 34 357 11T280 -12Z" />
|
||||
<glyph unicode="@" glyph-name="at" d="M446 -113H341Q258 -113 200 -87T106 -9T54 121T38 305Q38 419 55 496T106 621T189 689T301 710Q366 710 413 691T492 639T538 560T553 463V91H446V152H439Q428 115 404 97T345 79Q286 79 254 130T221 294Q221 406 253 457T345
|
||||
509Q380 509 404 491T439 436H446V463Q446 505 436 534T408 581T364 607T307 615Q270 615 241 603T192 562T161 483T150 358V229Q150 171 160 125T194 48T253 0T341 -17H446V-113ZM389 165Q417 165 431 181T446 224V364Q446 391 432 407T389 423Q362 423 348 403T333
|
||||
327V261Q333 205 347 185T389 165Z" />
|
||||
<glyph unicode="A" glyph-name="A" d="M435 0L391 168H200L157 0H5L194 698H406L595 0H435ZM300 553H292L224 289H368L300 553Z" />
|
||||
<glyph unicode="B" glyph-name="B" d="M77 698H322Q425 698 479 648T534 512Q534 452 505 417T420 365V359Q485 343 520 303T556 192Q556 104 501 52T345 0H77V698ZM299 105Q353 105 378 123T403 189V218Q403 266 378 284T299 302H223V105H299ZM280 402Q333 402
|
||||
357 419T381 483V513Q381 559 357 576T280 593H223V402H280Z" />
|
||||
<glyph unicode="C" glyph-name="C" d="M316 -12Q176 -12 109 82T41 349Q41 521 108 615T316 710Q370 710 411 696T483 655T532 592T563 509L423 475Q417 500 409 521T389 557T358 580T313 589Q252 589 227 542T201 410V288Q201 204 226 157T313 109Q365 109 388
|
||||
141T423 223L563 189Q552 143 533 106T483 43T412 2T316 -12Z" />
|
||||
<glyph unicode="D" glyph-name="D" d="M64 698H289Q430 698 498 608T566 349Q566 180 498 90T289 0H64V698ZM279 118Q346 118 377 161T408 286V413Q408 494 377 537T279 580H212V118H279Z" />
|
||||
<glyph unicode="E" glyph-name="E" d="M80 0V698H526V575H230V415H516V292H230V123H526V0H80Z" />
|
||||
<glyph unicode="F" glyph-name="F" d="M80 0V698H543V575H230V415H510V292H230V0H80Z" />
|
||||
<glyph unicode="G" glyph-name="G" d="M411 99H402Q393 77 380 57T348 22T304 -3T246 -12Q195 -12 156 12T89 82T49 194T35 343Q35 521 100 615T301 710Q355 710 396 696T466 655T515 591T545 509L405 475Q399 497 392 517T372 554T342 579T298 589Q241 589 218
|
||||
542T194 410V296Q194 211 219 160T310 109Q361 109 386 139T411 216V267H292V373H545V0H411V99Z" />
|
||||
<glyph unicode="H" glyph-name="H" d="M388 292H212V0H61V698H212V415H388V698H539V0H388V292Z" />
|
||||
<glyph unicode="I" glyph-name="I" d="M75 0V111H225V587H75V698H525V587H375V111H525V0H75Z" />
|
||||
<glyph unicode="J" glyph-name="J" d="M511 698V195Q511 148 495 110T448 44T374 3T278 -12Q171 -12 113 41T38 182L180 211Q188 166 210 138T278 110Q316 110 337 134T359 210V575H129V698H511Z" />
|
||||
<glyph unicode="K" glyph-name="K" d="M280 291L218 204V0H68V698H218V406H226L302 522L425 698H593L384 403L603 0H434L280 291Z" />
|
||||
<glyph unicode="L" glyph-name="L" d="M92 0V698H243V123H543V0H92Z" />
|
||||
<glyph unicode="M" glyph-name="M" d="M431 311L439 506H430L300 147L170 506H161L169 311V0H39V698H216L302 463H310L396 698H561V0H431V311Z" />
|
||||
<glyph unicode="N" glyph-name="N" d="M200 464H189V0H61V698H241L400 234H411V698H539V0H359L200 464Z" />
|
||||
<glyph unicode="O" glyph-name="O" d="M300 -12Q160 -12 94 83T27 349Q27 520 93 615T300 710Q440 710 506 615T573 349Q573 178 507 83T300 -12ZM300 109Q364 109 388 156T413 289V410Q413 494 389 541T300 589Q236 589 212 542T187 410V288Q187 204 211 157T300 109Z" />
|
||||
<glyph unicode="P" glyph-name="P" d="M76 0V698H346Q397 698 437 683T504 638T546 568T560 476Q560 425 546 384T505 314T437 270T346 254H227V0H76ZM227 375H308Q361 375 381 395T402 461V491Q402 537 382 557T308 577H227V375Z" />
|
||||
<glyph unicode="Q" glyph-name="Q" d="M526 -191H384Q303 -191 269 -152T235 -47V-6Q128 15 78 106T27 349Q27 520 93 615T300 710Q440 710 506 615T573 349Q573 198 523 107T365 -6V-84H526V-191ZM300 109Q364 109 388 156T413 289V410Q413 494 389 541T300 589Q236
|
||||
589 212 542T187 410V288Q187 204 211 157T300 109Z" />
|
||||
<glyph unicode="R" glyph-name="R" d="M224 0H76V698H346Q397 698 437 683T504 638T546 568T560 476Q560 402 528 349T437 279L574 0H410L293 259H224V0ZM310 375Q363 375 383 395T404 461V491Q404 537 384 557T310 577H224V375H310Z" />
|
||||
<glyph unicode="S" glyph-name="S" d="M289 -12Q201 -12 136 17T31 96L118 192Q156 150 201 130T294 110Q348 110 376 134T404 203Q404 240 383 259T310 286L237 298Q143 314 101 367T59 498Q59 599 125 654T310 710Q391 710 451 685T548 617L463 522Q435 553
|
||||
397 570T311 588Q210 588 210 505Q210 469 232 451T306 424L379 411Q464 396 510 347T556 215Q556 166 539 125T488 53T405 5T289 -12Z" />
|
||||
<glyph unicode="T" glyph-name="T" d="M375 575V0H225V575H24V698H576V575H375Z" />
|
||||
<glyph unicode="U" glyph-name="U" d="M205 698V256Q205 223 207 196T219 149T248 120T300 109Q333 109 352 119T380 149T392 195T395 256V698H545V276Q545 204 536 150T499 60T424 6T300 -12Q224 -12 176 6T101 60T65 150T55 276V698H205Z" />
|
||||
<glyph unicode="V" glyph-name="V" d="M194 0L9 698H176L258 343L299 142H307L349 343L432 698H591L406 0H194Z" />
|
||||
<glyph unicode="W" glyph-name="W" d="M54 0L11 698H140L160 280L166 148H175L235 546H370L430 148H439L445 276L465 698H589L546 0H356L305 385H295L244 0H54Z" />
|
||||
<glyph unicode="X" glyph-name="X" d="M591 0H420L348 139L299 249H290L240 139L166 0H9L205 361L22 698H193L250 587L301 475H309L361 587L421 698H578L395 359L591 0Z" />
|
||||
<glyph unicode="Y" glyph-name="Y" d="M225 0V247L4 698H171L245 536L299 399H307L361 536L435 698H596L375 247V0H225Z" />
|
||||
<glyph unicode="Z" glyph-name="Z" d="M551 0H48V131L373 575H58V698H541V567L216 123H551V0Z" />
|
||||
<glyph unicode="[" glyph-name="bracketleft" d="M183 -138V760H507V661H302V-39H507V-138H183Z" />
|
||||
<glyph unicode="\" glyph-name="backslash" d="M394 -138L73 760H206L527 -138H394Z" />
|
||||
<glyph unicode="]" glyph-name="bracketright" d="M417 760V-138H93V-39H298V661H93V760H417Z" />
|
||||
<glyph unicode="^" glyph-name="asciicircum" d="M456 239L303 562H291L138 239L27 293L222 698H379L573 293L456 239Z" />
|
||||
<glyph unicode="_" glyph-name="underscore" d="M60 -192V-71H540V-192H60Z" />
|
||||
<glyph unicode="`" glyph-name="grave" d="M150 746L273 807L372 613L284 570L150 746Z" />
|
||||
<glyph unicode="a" glyph-name="a" d="M487 0Q441 0 413 23T380 91H375Q361 40 320 14T218 -12Q143 -12 98 28T52 142Q52 223 111 262T284 301H367V327Q367 373 346 396T273 420Q226 420 197 402T147 355L66 427Q92 471 147 499T290 528Q396 528 455 480T515 333V107H572V0H487ZM274
|
||||
85Q313 85 340 104T367 159V221H288Q197 221 197 160V140Q197 113 218 99T274 85Z" />
|
||||
<glyph unicode="b" glyph-name="b" d="M59 740H207V422H214Q233 468 269 498T367 528Q410 528 445 512T506 463T546 379T561 258Q561 188 547 137T507 53T446 4T367 -12Q305 -12 269 17T214 94H207V0H59V740ZM303 103Q353 103 380 133T407 218V298Q407 352 380
|
||||
382T303 413Q264 413 236 394T207 334V182Q207 141 235 122T303 103Z" />
|
||||
<glyph unicode="c" glyph-name="c" d="M321 -12Q260 -12 212 6T130 60T78 145T60 258Q60 321 78 371T129 456T211 509T320 528Q405 528 456 494T535 402L421 340Q407 370 385 390T320 410Q269 410 242 381T214 300V216Q214 165 241 136T322 106Q365 106 389 126T431
|
||||
178L543 114Q515 57 462 23T321 -12Z" />
|
||||
<glyph unicode="d" glyph-name="d" d="M393 94H386Q366 47 331 18T233 -12Q190 -12 155 4T94 53T54 137T39 258Q39 328 53 379T93 463T154 512T233 528Q264 528 288 520T330 498T362 465T386 422H393V740H541V0H393V94ZM297 103Q336 103 364 122T393 182V334Q393
|
||||
375 365 394T297 413Q247 413 220 383T193 298V218Q193 164 220 134T297 103Z" />
|
||||
<glyph unicode="e" glyph-name="e" d="M314 -12Q184 -12 117 60T50 256Q50 319 67 369T117 455T196 509T301 528Q359 528 405 510T483 457T532 375T550 266V222H197V213Q197 163 228 133T319 102Q365 102 398 119T455 166L535 79Q505 42 451 15T314 -12ZM302 422Q254
|
||||
422 226 393T197 313V305H405V313Q405 364 378 393T302 422Z" />
|
||||
<glyph unicode="f" glyph-name="f" d="M71 115H223V401H61V516H223V591Q223 657 261 698T381 740H556V625H371V516H556V401H371V115H533V0H71V115Z" />
|
||||
<glyph unicode="g" glyph-name="g" d="M583 -52Q583 -134 514 -173T297 -212Q223 -212 175 -204T99 -179T59 -141T47 -93Q47 -49 73 -27T146 8V14Q113 24 94 42T74 95Q74 133 99 151T167 179V185Q121 207 96 247T70 344Q70 389 86 423T131 481T202 516T294 528Q343
|
||||
528 385 517V545Q385 575 406 595T464 615H555V507H431V498Q473 476 496 438T520 344Q520 299 504 265T458 208T387 172T294 160Q271 160 250 162T210 170Q199 164 192 155T184 132Q184 120 190 113T206 103T231 98T260 97H378Q433 97 472 86T536 55T572 8T583
|
||||
-52ZM443 -63Q443 -43 427 -32T366 -20H189Q169 -37 169 -62Q169 -86 189 -101T259 -117H346Q397 -117 420 -103T443 -63ZM294 254Q339 254 359 276T380 332V356Q380 390 360 412T294 434Q250 434 230 412T210 356V332Q210 298 230 276T294 254Z" />
|
||||
<glyph unicode="h" glyph-name="h" d="M65 740H213V422H219Q228 444 241 463T272 496T315 519T371 528Q408 528 439 516T492 478T526 417T539 334V0H391V314Q391 414 304 414Q287 414 271 410T241 396T221 372T213 339V0H65V740Z" />
|
||||
<glyph unicode="i" glyph-name="i" d="M332 582Q282 582 263 602T243 652V681Q243 711 262 731T332 751Q382 751 401 731T421 681V652Q421 623 402 603T332 582ZM94 115H258V401H94V516H406V115H558V0H94V115Z" />
|
||||
<glyph unicode="j" glyph-name="j" d="M92 -85H290V401H90V516H438V-51Q438 -116 399 -158T281 -200H92V-85ZM364 582Q314 582 295 602T275 652V681Q275 711 294 731T364 751Q413 751 433 731T453 681V652Q453 623 433 603T364 582Z" />
|
||||
<glyph unicode="k" glyph-name="k" d="M65 740H213V320H220L289 401L397 516H567L367 312L588 0H412L262 228L213 179V0H65V740Z" />
|
||||
<glyph unicode="l" glyph-name="l" d="M68 115H226V625H68V740H374V115H532V0H68V115Z" />
|
||||
<glyph unicode="m" glyph-name="m" d="M30 0V516H149V440H156Q168 476 190 502T254 528Q329 528 346 440H352Q358 458 367 474T389 502T420 521T462 528Q570 528 570 369V0H451V354Q451 390 439 404T406 419Q387 419 374 407T360 368V0H240V354Q240 390 229 404T197
|
||||
419Q177 419 163 407T149 368V0H30Z" />
|
||||
<glyph unicode="n" glyph-name="n" d="M65 0V516H213V422H219Q228 444 241 463T272 496T315 519T371 528Q408 528 439 516T492 478T526 417T539 334V0H391V314Q391 414 304 414Q287 414 271 410T241 396T221 372T213 339V0H65Z" />
|
||||
<glyph unicode="o" glyph-name="o" d="M300 -12Q240 -12 192 6T111 60T59 145T41 258Q41 321 59 371T110 456T192 509T300 528Q360 528 408 510T489 456T541 371T559 258Q559 195 541 145T490 60T408 7T300 -12ZM300 98Q350 98 378 129T406 217V299Q406 356 378
|
||||
387T300 418Q250 418 222 387T194 299V217Q194 160 222 129T300 98Z" />
|
||||
<glyph unicode="p" glyph-name="p" d="M59 516H207V422H214Q233 468 269 498T367 528Q410 528 445 512T506 463T546 379T561 258Q561 188 547 137T507 53T446 4T367 -12Q305 -12 269 17T214 94H207V-200H59V516ZM303 103Q353 103 380 133T407 218V298Q407 352
|
||||
380 382T303 413Q264 413 236 394T207 334V182Q207 141 235 122T303 103Z" />
|
||||
<glyph unicode="q" glyph-name="q" d="M393 94H386Q366 47 331 18T233 -12Q190 -12 155 4T94 53T54 137T39 258Q39 328 53 379T93 463T154 512T233 528Q264 528 288 520T330 498T362 465T386 422H393V516H541V-200H393V94ZM297 103Q336 103 364 122T393 182V334Q393
|
||||
375 365 394T297 413Q247 413 220 383T193 298V218Q193 164 220 134T297 103Z" />
|
||||
<glyph unicode="r" glyph-name="r" d="M74 115H193V401H74V516H341V370H348Q355 398 367 424T399 471T447 504T513 516H562V380H452Q397 380 369 348T341 268V115H511V0H74V115Z" />
|
||||
<glyph unicode="s" glyph-name="s" d="M294 -12Q208 -12 145 14T49 85L132 162Q162 129 202 111T295 92Q339 92 364 105T389 147Q389 169 372 177T325 191L242 204Q207 209 177 219T125 248T90 292T77 355Q77 436 139 482T313 528Q389 528 442 508T528 449L454
|
||||
365Q431 390 395 407T308 424Q222 424 222 372Q222 349 239 341T286 327L368 314Q403 309 433 299T485 270T521 226T534 163Q534 82 472 35T294 -12Z" />
|
||||
<glyph unicode="t" glyph-name="t" d="M340 0Q260 0 221 42T182 149V401H42V516H133Q166 516 180 529T194 577V698H330V516H531V401H330V115H531V0H340Z" />
|
||||
<glyph unicode="u" glyph-name="u" d="M387 94H381Q364 50 328 19T229 -12Q192 -12 161 0T108 38T74 99T61 182V516H209V202Q209 102 296 102Q313 102 329 106T358 120T379 144T387 177V516H535V0H387V94Z" />
|
||||
<glyph unicode="v" glyph-name="v" d="M212 0L27 516H183L250 295L299 123H307L356 295L423 516H573L388 0H212Z" />
|
||||
<glyph unicode="w" glyph-name="w" d="M7 516H130L167 98H177L238 516H368L428 98H438L476 516H593L532 0H356L305 356H295L244 0H68L7 516Z" />
|
||||
<glyph unicode="x" glyph-name="x" d="M23 0L216 262L36 516H205L260 433L302 366H310L353 433L409 516H564L384 270L577 0H407L342 97L297 166H289L245 97L179 0H23Z" />
|
||||
<glyph unicode="y" glyph-name="y" d="M430 516H581L338 -83Q315 -140 277 -170T173 -200H71V-85H195L227 3L19 516H178L253 299L300 149H308L353 299L430 516Z" />
|
||||
<glyph unicode="z" glyph-name="z" d="M66 0V123L353 401H76V516H524V393L237 115H534V0H66Z" />
|
||||
<glyph unicode="{" glyph-name="braceleft" d="M330 -138Q262 -138 233 -108T204 -30V15Q204 40 209 59T223 93T241 119T260 142Q277 162 283 176T290 207Q290 233 263 247T182 261H92V361H182Q236 361 263 375T290 415Q290 431 284 445T260 480Q251 490 241 502T223
|
||||
529T210 563T204 607V652Q204 699 233 729T330 760H508V661H323V613Q323 575 335 555T363 515Q380 494 395 470T410 414Q410 372 381 347T292 315V307Q352 300 381 275T410 208Q410 176 395 152T363 107Q348 87 336 67T323 9V-39H508V-138H330Z" />
|
||||
<glyph unicode="|" glyph-name="bar" d="M237 -138V760H363V-138H237Z" />
|
||||
<glyph unicode="}" glyph-name="braceright" d="M270 760Q338 760 367 730T396 652V607Q396 582 391 563T377 529T359 502T340 480Q323 460 317 446T310 415Q310 389 337 375T418 361H508V261H418Q364 261 337 247T310 207Q310 191 316 177T340 142Q349 131 359
|
||||
120T377 93T390 59T396 15V-30Q396 -77 367 -107T270 -138H92V-39H277V9Q277 47 265 67T237 107Q220 128 205 152T190 208Q190 250 219 275T308 307V315Q248 322 219 347T190 414Q190 446 205 470T237 515Q252 535 264 555T277 613V661H92V760H270Z" />
|
||||
<glyph unicode="~" glyph-name="asciitilde" d="M409 210Q377 210 349 221T290 247Q264 260 245 268T207 277Q183 277 169 261T142 210L36 248Q52 316 91 358T191 400Q223 400 251 389T310 363Q336 350 355 342T393 333Q417 333 431 349T458 400L564 362Q548 294
|
||||
509 252T409 210Z" />
|
||||
<glyph unicode=" " glyph-name="uni00A0" />
|
||||
<glyph unicode="¡" glyph-name="exclamdown" d="M219 -182V21L276 273H324L381 21V-182H219ZM300 341Q247 341 225 363T202 418V450Q202 482 224 505T300 528Q354 528 376 505T398 450V418Q398 386 376 364T300 341Z" />
|
||||
<glyph unicode="¢" glyph-name="cent" d="M258 -114V-6Q164 11 112 80T60 258Q60 367 112 436T258 522V630H372V524Q434 514 473 482T535 402L428 344Q418 365 402 383T363 411V104Q389 113 407 131T438 173L543 114Q520 66 478 34T372 -8V-114H258ZM202
|
||||
216Q202 177 218 149T268 106V410Q236 397 219 369T202 300V216Z" />
|
||||
<glyph unicode="£" glyph-name="sterling" d="M69 0V136Q109 153 131 184T154 257Q154 265 153 269H46V379H117Q105 407 96 437T86 504Q86 550 104 588T154 653T233 695T335 710Q411 710 466 683T559 605L460 512Q437 542 410 561T340 581Q293 581 266 555T239
|
||||
480Q239 452 247 428T267 379H442V269H302V262Q302 236 295 216T277 181T251 155T224 137V128H553V0H69Z" />
|
||||
<glyph unicode="¥" glyph-name="yen" d="M56 113H229V221H56V334H160L0 698H156L297 334H307L449 698H600L441 334H544V221H371V113H544V0H56V113Z" />
|
||||
<glyph unicode="¦" glyph-name="brokenbar" d="M237 401V760H363V401H237ZM237 -138V221H363V-138H237Z" />
|
||||
<glyph unicode="§" glyph-name="section" d="M511 3Q511 -38 495 -71T449 -127T379 -163T289 -176Q237 -176 185 -160T88 -104L161 -16Q187 -42 219 -56T290 -71Q334 -71 360 -53T386 -3Q386 24 365 39T297 67L219 88Q176 100 147 116T99 152T73 194T65 238Q65
|
||||
281 91 316T175 375V391Q133 417 115 453T96 531Q96 572 112 605T158 661T228 697T318 710Q370 710 422 694T519 638L446 550Q420 576 388 590T317 605Q273 605 247 587T221 537Q221 510 242 495T310 467L388 446Q431 434 460 418T508 382T534 340T542 296Q542
|
||||
253 516 218T432 159V143Q474 117 492 81T511 3ZM419 252Q419 278 403 299T336 334L259 355Q250 357 242 360T226 366Q208 346 198 326T188 282Q188 256 204 235T271 200L348 179Q357 177 365 174T381 168Q399 188 409 208T419 252Z" />
|
||||
<glyph unicode="¨" glyph-name="dieresis" d="M190 591Q145 591 128 609T110 654V680Q110 706 127 724T190 742Q235 742 253 724T271 680V654Q271 628 253 610T190 591ZM410 591Q365 591 347 609T329 654V680Q329 706 347 724T410 742Q455 742 472 724T490
|
||||
680V654Q490 628 473 610T410 591Z" />
|
||||
<glyph unicode="©" glyph-name="copyright" d="M300 18Q237 18 183 41T88 107T24 211T0 349Q0 425 23 486T87 591T182 657T300 680Q363 680 417 657T512 591T576 487T600 349Q600 272 577 211T513 107T418 41T300 18ZM300 73Q351 73 394 92T469 144T519 223T537
|
||||
319V379Q537 430 519 475T470 553T395 606T300 625Q249 625 206 606T131 554T81 475T63 379V319Q63 268 81 223T130 145T205 92T300 73ZM309 153Q267 153 233 167T175 206T138 268T125 348Q125 393 138 429T176 491T234 531T309 545Q371 545 408 517T463 443L378
|
||||
400Q368 423 353 437T311 452Q281 452 264 434T247 386V313Q247 284 264 265T312 246Q340 246 356 261T384 298L469 255Q460 235 447 217T415 184T369 162T309 153Z" />
|
||||
<glyph unicode="ª" glyph-name="ordfeminine" d="M429 340Q397 340 378 356T355 404H351Q341 369 312 351T241 332Q188 332 157 360T125 440Q125 497 166 524T287 551H345V569Q345 601 330 617T280 634Q247 634 227 622T191 589L135 639Q153 670 192 690T292
|
||||
710Q366 710 407 676T449 573V415H489V340H429ZM290 495Q226 495 226 452V438Q226 419 240 410T280 400Q308 400 326 413T345 452V495H290Z" />
|
||||
<glyph unicode="«" glyph-name="guillemotleft" d="M516 38L316 206V338L516 506L561 410L431 272L561 133L516 38ZM506 38L306 206V338L506 506L551 410L421 272L551 133L506 38Z" />
|
||||
<glyph unicode="¬" glyph-name="logicalnot" d="M401 54V246H62V364H522V54H401Z" />
|
||||
<glyph unicode="­" glyph-name="uni00AD" d="M140 234V376H460V234H140Z" />
|
||||
<glyph unicode="®" glyph-name="registered" d="M300 346Q262 346 229 360T170 398T131 455T117 528Q117 567 131 600T170 658T228 696T300 710Q338 710 371 696T429 658T468 601T483 528Q483 489 469 456T430 398T372 360T300 346ZM300 387Q329 387 353
|
||||
396T396 423T424 464T435 518V538Q435 568 425 592T396 633T354 659T300 669Q271 669 247 660T204 633T176 592T165 538V518Q165 488 175 464T204 423T246 397T300 387ZM278 436H222V621H314Q352 621 369 603T386 558Q386 517 352 501L391 436H330L300 490H278V436ZM302
|
||||
531Q328 531 328 551V558Q328 578 302 578H278V531H302Z" />
|
||||
<glyph unicode="¯" glyph-name="overscore" d="M147 718H453V615H147V718Z" />
|
||||
<glyph unicode="°" glyph-name="degree" d="M300 334Q260 334 226 348T167 388T127 447T112 522Q112 562 126 596T166 656T226 695T300 710Q340 710 374 696T433 656T473 597T488 522Q488 482 474 448T434 388T374 349T300 334ZM300 429Q339 429 362 456T386
|
||||
522Q386 561 363 588T300 615Q261 615 238 588T214 522Q214 483 237 456T300 429Z" />
|
||||
<glyph unicode="±" glyph-name="plusminus" d="M236 184V350H62V468H236V634H364V468H538V350H364V184H236ZM62 0V119H538V0H62Z" />
|
||||
<glyph unicode="²" glyph-name="twosuperior" d="M450 329H161V417L279 507Q297 521 308 530T325 548T334 565T337 583V584Q337 601 325 609T294 618Q271 618 258 606T239 573L150 606Q164 648 202 676T304 704Q370 704 408 672T446 591Q446 566 437 545T413
|
||||
506T377 473T332 445L273 412H450V329Z" />
|
||||
<glyph unicode="³" glyph-name="threesuperior" d="M285 558Q312 558 324 567T336 589V593Q336 606 325 615T291 625Q270 625 249 614T211 582L149 641Q175 672 208 688T294 704Q365 704 404 676T444 603Q444 568 422 547T368 522V518Q406 512 428 490T450
|
||||
433Q450 382 407 353T293 323Q228 323 193 345T138 398L214 456Q225 433 244 418T293 402Q316 402 329 411T343 438V440Q343 460 326 468T282 476H251V558H285Z" />
|
||||
<glyph unicode="´" glyph-name="acute" d="M316 570L228 613L327 807L450 746L316 570Z" />
|
||||
<glyph unicode="µ" glyph-name="mu" d="M65 -200V516H213V212Q213 102 298 102Q315 102 331 106T359 120T379 144T387 177V516H535V0H387V94H381Q375 74 365 55T340 21T306 -3T263 -12Q243 -12 225 -4T190 30H184L213 -103V-200H65Z" />
|
||||
<glyph unicode="¶" glyph-name="paragraph" d="M245 246Q198 246 158 263T86 310T38 381T20 472Q20 521 37 562T86 634T157 681T245 698H552V-149H433V582H364V-149H245V246Z" />
|
||||
<glyph unicode="·" glyph-name="middot" d="M300 204Q244 204 220 228T195 287V322Q195 356 219 380T300 405Q356 405 380 381T405 322V287Q405 253 381 229T300 204Z" />
|
||||
<glyph unicode="¸" glyph-name="cedilla" d="M314 -212Q262 -212 233 -198T190 -168L236 -112Q246 -124 262 -132T302 -141Q321 -141 333 -135T346 -116Q346 -110 343 -104T332 -93T309 -83T271 -76L250 -74L272 30H339L321 -55L325 -59Q337 -56 349 -54T373
|
||||
-52Q403 -52 424 -68T446 -121Q446 -147 435 -164T406 -192T363 -207T314 -212Z" />
|
||||
<glyph unicode="¹" glyph-name="onesuperior" d="M188 329V408H281V606L202 570L164 642L276 698H382V408H463V329H188Z" />
|
||||
<glyph unicode="º" glyph-name="ordmasculine" d="M300 332Q215 332 167 382T119 521Q119 609 167 659T300 710Q385 710 433 660T481 521Q481 433 433 383T300 332ZM300 409Q335 409 354 430T374 492V550Q374 590 355 611T300 633Q265 633 246 612T226 550V492Q226
|
||||
452 245 431T300 409Z" />
|
||||
<glyph unicode="»" glyph-name="guillemotright" d="M50 133L180 272L50 410L95 506L295 338V206L95 38L50 133ZM296 133L426 272L296 410L341 506L541 338V206L341 38L296 133Z" />
|
||||
<glyph unicode="¼" glyph-name="onequarter" d="M37 432H122V626L46 587L14 645L116 698H210V432H285V363H37V432ZM496 698H599L426 398H323L496 698ZM174 300H277L104 0H1L174 300ZM462 63H311V137L442 335H546V124H590V63H546V0H462V63ZM462 124V250H457L373
|
||||
124H462Z" />
|
||||
<glyph unicode="½" glyph-name="onehalf" d="M37 432H122V626L46 587L14 645L116 698H210V432H285V363H37V432ZM496 698H599L426 398H323L496 698ZM174 300H277L104 0H1L174 300ZM321 75L427 155Q462 182 473 198T485 236V238Q485 253 474 262T443 271Q422
|
||||
271 408 259T385 224L312 252Q318 269 328 284T354 313T393 333T447 341Q506 341 542 313T578 239Q578 200 549 168T473 106L419 69H583V0H321V75Z" />
|
||||
<glyph unicode="¾" glyph-name="threequarters" d="M149 357Q92 357 60 377T11 423L74 465Q85 446 102 435T147 423Q195 423 195 457V465Q195 484 178 493T135 503H108V566H139Q167 566 179 576T191 600V608Q191 621 180 629T148 638Q102 638 70 597L18 647Q42
|
||||
674 71 689T148 704Q211 704 247 679T283 613Q283 581 262 561T212 537V533Q247 528 268 509T289 457Q289 411 251 384T149 357ZM496 698H599L426 398H323L496 698ZM174 300H277L104 0H1L174 300ZM462 63H311V137L442 335H546V124H590V63H546V0H462V63ZM462 124V250H457L373
|
||||
124H462Z" />
|
||||
<glyph unicode="¿" glyph-name="questiondown" d="M309 -194Q256 -194 213 -179T138 -137T90 -72T73 11Q73 53 87 87T126 147T183 189T252 211V283H392V130Q317 127 273 104T229 24V10Q229 -32 253 -50T314 -68Q355 -68 381 -45T417 17L539 -34Q530 -64 513
|
||||
-93T467 -144T400 -180T309 -194ZM320 341Q267 341 244 363T221 418V450Q221 482 243 505T320 528Q373 528 395 505T418 450V418Q418 386 396 364T320 341Z" />
|
||||
<glyph unicode="À" glyph-name="Agrave" d="M435 0L391 168H200L157 0H5L194 698H406L595 0H435ZM300 553H292L224 289H368L300 553ZM150 916L273 977L372 783L284 740L150 916Z" />
|
||||
<glyph unicode="Á" glyph-name="Aacute" d="M435 0L391 168H200L157 0H5L194 698H406L595 0H435ZM300 553H292L224 289H368L300 553ZM316 740L228 783L327 977L450 916L316 740Z" />
|
||||
<glyph unicode="Â" glyph-name="Acircumflex" d="M435 0L391 168H200L157 0H5L194 698H406L595 0H435ZM300 553H292L224 289H368L300 553ZM362 956L494 797L419 739L298 854L177 739L106 797L238 956H362Z" />
|
||||
<glyph unicode="Ã" glyph-name="Atilde" d="M435 0L391 168H200L157 0H5L194 698H406L595 0H435ZM300 553H292L224 289H368L300 553ZM376 762Q353 762 336 768T299 782Q277 791 259 797T221 804Q204 804 191 798T162 779L110 847Q128 874 156 892T224 911Q247
|
||||
911 264 905T301 891Q323 882 341 876T379 869Q396 869 409 875T438 894L490 826Q472 799 444 781T376 762Z" />
|
||||
<glyph unicode="Ä" glyph-name="Adieresis" d="M435 0L391 168H200L157 0H5L194 698H406L595 0H435ZM300 553H292L224 289H368L300 553ZM190 761Q145 761 128 779T110 824V850Q110 876 127 894T190 912Q235 912 253 894T271 850V824Q271 798 253 780T190
|
||||
761ZM410 761Q365 761 347 779T329 824V850Q329 876 347 894T410 912Q455 912 472 894T490 850V824Q490 798 473 780T410 761Z" />
|
||||
<glyph unicode="Å" glyph-name="Aring" d="M435 0L391 168H200L157 0H5L194 698H406L595 0H435ZM300 553H292L224 289H368L300 553ZM300 719Q269 719 242 729T195 759T164 804T152 862Q152 893 163 919T195 964T242 994T300 1005Q331 1005 358 995T405 965T436
|
||||
920T448 862Q448 831 437 805T405 760T358 730T300 719ZM300 794Q325 794 338 808T351 845V879Q351 903 338 916T300 930Q275 930 262 916T249 879V845Q249 821 262 808T300 794Z" />
|
||||
<glyph unicode="Æ" glyph-name="AE" d="M279 168H175L142 0H-4L155 698H572V587H417V409H562V298H417V111H572V0H279V168ZM257 594L197 279H279V594H257Z" />
|
||||
<glyph unicode="Ç" glyph-name="Ccedilla" d="M313 589Q252 589 227 542T201 410V288Q201 204 226 157T313 109Q365 109 388 141T423 223L563 189Q543 101 488 48T333 -11L324 -55L328 -59Q340 -56 352 -54T376 -52Q406 -52 427 -68T449 -121Q449 -147 438
|
||||
-164T409 -192T366 -207T317 -212Q265 -212 236 -198T193 -168L239 -112Q249 -124 265 -132T305 -141Q324 -141 336 -135T349 -116Q349 -110 346 -104T335 -93T312 -83T274 -76L253 -74L267 -8Q151 8 96 100T41 349Q41 521 108 615T316 710Q370 710 411 696T483
|
||||
655T532 592T563 509L423 475Q417 500 409 521T389 557T358 580T313 589Z" />
|
||||
<glyph unicode="È" glyph-name="Egrave" d="M80 0V698H526V575H230V415H516V292H230V123H526V0H80ZM153 916L276 977L375 783L287 740L153 916Z" />
|
||||
<glyph unicode="É" glyph-name="Eacute" d="M80 0V698H526V575H230V415H516V292H230V123H526V0H80ZM319 740L231 783L330 977L453 916L319 740Z" />
|
||||
<glyph unicode="Ê" glyph-name="Ecircumflex" d="M80 0V698H526V575H230V415H516V292H230V123H526V0H80ZM365 956L497 797L422 739L301 854L180 739L109 797L241 956H365Z" />
|
||||
<glyph unicode="Ë" glyph-name="Edieresis" d="M80 0V698H526V575H230V415H516V292H230V123H526V0H80ZM193 761Q148 761 131 779T113 824V850Q113 876 130 894T193 912Q238 912 256 894T274 850V824Q274 798 256 780T193 761ZM413 761Q368 761 350 779T332
|
||||
824V850Q332 876 350 894T413 912Q458 912 475 894T493 850V824Q493 798 476 780T413 761Z" />
|
||||
<glyph unicode="Ì" glyph-name="Igrave" d="M75 0V111H225V587H75V698H525V587H375V111H525V0H75ZM150 916L273 977L372 783L284 740L150 916Z" />
|
||||
<glyph unicode="Í" glyph-name="Iacute" d="M75 0V111H225V587H75V698H525V587H375V111H525V0H75ZM316 740L228 783L327 977L450 916L316 740Z" />
|
||||
<glyph unicode="Î" glyph-name="Icircumflex" d="M75 0V111H225V587H75V698H525V587H375V111H525V0H75ZM362 956L494 797L419 739L298 854L177 739L106 797L238 956H362Z" />
|
||||
<glyph unicode="Ï" glyph-name="Idieresis" d="M75 0V111H225V587H75V698H525V587H375V111H525V0H75ZM190 761Q145 761 128 779T110 824V850Q110 876 127 894T190 912Q235 912 253 894T271 850V824Q271 798 253 780T190 761ZM410 761Q365 761 347 779T329
|
||||
824V850Q329 876 347 894T410 912Q455 912 472 894T490 850V824Q490 798 473 780T410 761Z" />
|
||||
<glyph unicode="Ð" glyph-name="Eth" d="M69 311H10V425H69V698H289Q430 698 498 608T566 349Q566 180 498 90T289 0H69V311ZM279 118Q346 118 377 161T408 286V413Q408 494 377 537T279 580H217V420H327V316H217V118H279Z" />
|
||||
<glyph unicode="Ñ" glyph-name="Ntilde" d="M200 464H189V0H61V698H241L400 234H411V698H539V0H359L200 464ZM376 762Q353 762 336 768T299 782Q277 791 259 797T221 804Q204 804 191 798T162 779L110 847Q128 874 156 892T224 911Q247 911 264 905T301 891Q323
|
||||
882 341 876T379 869Q396 869 409 875T438 894L490 826Q472 799 444 781T376 762Z" />
|
||||
<glyph unicode="Ò" glyph-name="Ograve" d="M300 -12Q160 -12 94 83T27 349Q27 520 93 615T300 710Q440 710 506 615T573 349Q573 178 507 83T300 -12ZM300 109Q364 109 388 156T413 289V410Q413 494 389 541T300 589Q236 589 212 542T187 410V288Q187 204
|
||||
211 157T300 109ZM150 916L273 977L372 783L284 740L150 916Z" />
|
||||
<glyph unicode="Ó" glyph-name="Oacute" d="M300 -12Q160 -12 94 83T27 349Q27 520 93 615T300 710Q440 710 506 615T573 349Q573 178 507 83T300 -12ZM300 109Q364 109 388 156T413 289V410Q413 494 389 541T300 589Q236 589 212 542T187 410V288Q187 204
|
||||
211 157T300 109ZM316 740L228 783L327 977L450 916L316 740Z" />
|
||||
<glyph unicode="Ô" glyph-name="Ocircumflex" d="M300 -12Q160 -12 94 83T27 349Q27 520 93 615T300 710Q440 710 506 615T573 349Q573 178 507 83T300 -12ZM300 109Q364 109 388 156T413 289V410Q413 494 389 541T300 589Q236 589 212 542T187 410V288Q187
|
||||
204 211 157T300 109ZM362 956L494 797L419 739L298 854L177 739L106 797L238 956H362Z" />
|
||||
<glyph unicode="Õ" glyph-name="Otilde" d="M300 -12Q160 -12 94 83T27 349Q27 520 93 615T300 710Q440 710 506 615T573 349Q573 178 507 83T300 -12ZM300 109Q364 109 388 156T413 289V410Q413 494 389 541T300 589Q236 589 212 542T187 410V288Q187 204
|
||||
211 157T300 109ZM376 762Q353 762 336 768T299 782Q277 791 259 797T221 804Q204 804 191 798T162 779L110 847Q128 874 156 892T224 911Q247 911 264 905T301 891Q323 882 341 876T379 869Q396 869 409 875T438 894L490 826Q472 799 444 781T376 762Z" />
|
||||
<glyph unicode="Ö" glyph-name="Odieresis" d="M300 -12Q160 -12 94 83T27 349Q27 520 93 615T300 710Q440 710 506 615T573 349Q573 178 507 83T300 -12ZM300 109Q364 109 388 156T413 289V410Q413 494 389 541T300 589Q236 589 212 542T187 410V288Q187
|
||||
204 211 157T300 109ZM190 761Q145 761 128 779T110 824V850Q110 876 127 894T190 912Q235 912 253 894T271 850V824Q271 798 253 780T190 761ZM410 761Q365 761 347 779T329 824V850Q329 876 347 894T410 912Q455 912 472 894T490 850V824Q490 798 473 780T410
|
||||
761Z" />
|
||||
<glyph unicode="×" glyph-name="multiply" d="M300 220L155 75L70 160L215 305L70 450L155 535L300 390L445 535L530 450L385 305L530 160L445 75L300 220Z" />
|
||||
<glyph unicode="Ø" glyph-name="Oslash" d="M300 -12Q221 -12 166 19L113 -66L19 -12L85 95Q27 186 27 349Q27 520 93 615T300 710Q379 710 434 679L487 764L581 710L515 603Q573 512 573 349Q573 178 507 83T300 -12ZM187 288Q187 277 187 268T189 249L371
|
||||
565Q345 589 300 589Q236 589 212 542T187 410V288ZM300 109Q364 109 388 156T413 288V410Q413 421 413 429T411 449L229 133Q254 109 300 109Z" />
|
||||
<glyph unicode="Ù" glyph-name="Ugrave" d="M205 698V256Q205 223 207 196T219 149T248 120T300 109Q333 109 352 119T380 149T392 195T395 256V698H545V276Q545 204 536 150T499 60T424 6T300 -12Q224 -12 176 6T101 60T65 150T55 276V698H205ZM150 916L273
|
||||
977L372 783L284 740L150 916Z" />
|
||||
<glyph unicode="Ú" glyph-name="Uacute" d="M205 698V256Q205 223 207 196T219 149T248 120T300 109Q333 109 352 119T380 149T392 195T395 256V698H545V276Q545 204 536 150T499 60T424 6T300 -12Q224 -12 176 6T101 60T65 150T55 276V698H205ZM316 740L228
|
||||
783L327 977L450 916L316 740Z" />
|
||||
<glyph unicode="Û" glyph-name="Ucircumflex" d="M205 698V256Q205 223 207 196T219 149T248 120T300 109Q333 109 352 119T380 149T392 195T395 256V698H545V276Q545 204 536 150T499 60T424 6T300 -12Q224 -12 176 6T101 60T65 150T55 276V698H205ZM362
|
||||
956L494 797L419 739L298 854L177 739L106 797L238 956H362Z" />
|
||||
<glyph unicode="Ü" glyph-name="Udieresis" d="M205 698V256Q205 223 207 196T219 149T248 120T300 109Q333 109 352 119T380 149T392 195T395 256V698H545V276Q545 204 536 150T499 60T424 6T300 -12Q224 -12 176 6T101 60T65 150T55 276V698H205ZM190 761Q145
|
||||
761 128 779T110 824V850Q110 876 127 894T190 912Q235 912 253 894T271 850V824Q271 798 253 780T190 761ZM410 761Q365 761 347 779T329 824V850Q329 876 347 894T410 912Q455 912 472 894T490 850V824Q490 798 473 780T410 761Z" />
|
||||
<glyph unicode="Ý" glyph-name="Yacute" d="M225 0V247L4 698H171L245 536L299 399H307L361 536L435 698H596L375 247V0H225ZM316 740L228 783L327 977L450 916L316 740Z" />
|
||||
<glyph unicode="Þ" glyph-name="Thorn" d="M76 0V698H227V577H341Q393 577 433 561T500 516T541 446T555 355Q555 305 541 264T500 194T433 149T341 133H227V0H76ZM227 254H304Q357 254 377 274T398 340V370Q398 416 378 436T304 456H227V254Z" />
|
||||
<glyph unicode="ß" glyph-name="germandbls" d="M60 0V591Q60 657 98 698T218 740H376V629H204V516H540V410L401 213Q482 198 528 150T574 16Q574 -91 503 -145T312 -200H246V-89H303Q366 -89 395 -67T425 3V26Q425 75 394 97T297 119H273V230L396 405H204V0H60Z" />
|
||||
<glyph unicode="à" glyph-name="agrave" d="M487 0Q441 0 413 23T380 91H375Q361 40 320 14T218 -12Q143 -12 98 28T52 142Q52 223 111 262T284 301H367V327Q367 373 346 396T273 420Q226 420 197 402T147 355L66 427Q92 471 147 499T290 528Q396 528 455
|
||||
480T515 333V107H572V0H487ZM274 85Q313 85 340 104T367 159V221H288Q197 221 197 160V140Q197 113 218 99T274 85ZM399 746L522 807L621 613L533 570L399 746Z" />
|
||||
<glyph unicode="á" glyph-name="aacute" d="M487 0Q441 0 413 23T380 91H375Q361 40 320 14T218 -12Q143 -12 98 28T52 142Q52 223 111 262T284 301H367V327Q367 373 346 396T273 420Q226 420 197 402T147 355L66 427Q92 471 147 499T290 528Q396 528 455
|
||||
480T515 333V107H572V0H487ZM274 85Q313 85 340 104T367 159V221H288Q197 221 197 160V140Q197 113 218 99T274 85ZM565 570L477 613L576 807L699 746L565 570Z" />
|
||||
<glyph unicode="â" glyph-name="acircumflex" d="M487 0Q441 0 413 23T380 91H375Q361 40 320 14T218 -12Q143 -12 98 28T52 142Q52 223 111 262T284 301H367V327Q367 373 346 396T273 420Q226 420 197 402T147 355L66 427Q92 471 147 499T290 528Q396 528
|
||||
455 480T515 333V107H572V0H487ZM274 85Q313 85 340 104T367 159V221H288Q197 221 197 160V140Q197 113 218 99T274 85ZM611 786L743 627L668 569L547 684L426 569L355 627L487 786H611Z" />
|
||||
<glyph unicode="ã" glyph-name="atilde" d="M487 0Q441 0 413 23T380 91H375Q361 40 320 14T218 -12Q143 -12 98 28T52 142Q52 223 111 262T284 301H367V327Q367 373 346 396T273 420Q226 420 197 402T147 355L66 427Q92 471 147 499T290 528Q396 528 455
|
||||
480T515 333V107H572V0H487ZM274 85Q313 85 340 104T367 159V221H288Q197 221 197 160V140Q197 113 218 99T274 85ZM625 592Q602 592 585 598T548 612Q526 621 508 627T470 634Q453 634 440 628T411 609L359 677Q377 704 405 722T473 741Q496 741 513 735T550 721Q572
|
||||
712 590 706T628 699Q645 699 658 705T687 724L739 656Q721 629 693 611T625 592Z" />
|
||||
<glyph unicode="ä" glyph-name="adieresis" d="M487 0Q441 0 413 23T380 91H375Q361 40 320 14T218 -12Q143 -12 98 28T52 142Q52 223 111 262T284 301H367V327Q367 373 346 396T273 420Q226 420 197 402T147 355L66 427Q92 471 147 499T290 528Q396 528
|
||||
455 480T515 333V107H572V0H487ZM274 85Q313 85 340 104T367 159V221H288Q197 221 197 160V140Q197 113 218 99T274 85ZM439 591Q394 591 377 609T359 654V680Q359 706 376 724T439 742Q484 742 502 724T520 680V654Q520 628 502 610T439 591ZM659 591Q614 591
|
||||
596 609T578 654V680Q578 706 596 724T659 742Q704 742 721 724T739 680V654Q739 628 722 610T659 591Z" />
|
||||
<glyph unicode="å" glyph-name="aring" d="M487 0Q441 0 413 23T380 91H375Q361 40 320 14T218 -12Q143 -12 98 28T52 142Q52 223 111 262T284 301H367V327Q367 373 346 396T273 420Q226 420 197 402T147 355L66 427Q92 471 147 499T290 528Q396 528 455
|
||||
480T515 333V107H572V0H487ZM274 85Q313 85 340 104T367 159V221H288Q197 221 197 160V140Q197 113 218 99T274 85ZM549 549Q518 549 491 559T444 589T413 634T401 692Q401 723 412 749T444 794T491 824T549 835Q580 835 607 825T654 795T685 750T697 692Q697 661
|
||||
686 635T654 590T607 560T549 549ZM549 624Q574 624 587 638T600 675V709Q600 733 587 746T549 760Q524 760 511 746T498 709V675Q498 651 511 638T549 624Z" />
|
||||
<glyph unicode="æ" glyph-name="ae" d="M137 -12Q109 -12 85 -3T42 26T14 74T4 141Q4 222 51 263T186 305H226V348Q226 436 167 436Q141 436 128 418T105 368L13 401Q30 466 70 497T168 528Q214 528 245 509T293 455H297Q339 528 416 528Q454 528 485 511T538
|
||||
463T572 388T584 289V228H345V213Q345 155 363 120T417 84Q445 84 459 105T481 156L578 129Q570 100 558 74T526 29T480 -1T419 -12Q366 -12 323 15T262 105H258Q249 44 217 16T137 -12ZM169 78Q201 78 213 104T226 179V228H197Q160 228 140 210T120 157V138Q120
|
||||
110 132 94T169 78ZM410 438Q377 438 361 409T345 337V305H475V337Q475 379 459 408T410 438Z" />
|
||||
<glyph unicode="ç" glyph-name="ccedilla" d="M320 528Q405 528 456 494T535 402L421 340Q407 370 385 390T320 410Q269 410 242 381T214 300V216Q214 165 241 136T322 106Q365 106 389 126T431 178L543 114Q516 59 465 25T331 -12L322 -55L326 -59Q338 -56
|
||||
350 -54T374 -52Q404 -52 425 -68T447 -121Q447 -147 436 -164T407 -192T364 -207T315 -212Q263 -212 234 -198T191 -168L237 -112Q247 -124 263 -132T303 -141Q322 -141 334 -135T347 -116Q347 -110 344 -104T333 -93T310 -83T272 -76L251 -74L265 -7Q168 9 114
|
||||
78T60 258Q60 321 78 371T129 456T211 509T320 528Z" />
|
||||
<glyph unicode="è" glyph-name="egrave" d="M314 -12Q184 -12 117 60T50 256Q50 319 67 369T117 455T196 509T301 528Q359 528 405 510T483 457T532 375T550 266V222H197V213Q197 163 228 133T319 102Q365 102 398 119T455 166L535 79Q505 42 451 15T314
|
||||
-12ZM302 422Q254 422 226 393T197 313V305H405V313Q405 364 378 393T302 422ZM151 746L274 807L373 613L285 570L151 746Z" />
|
||||
<glyph unicode="é" glyph-name="eacute" d="M314 -12Q184 -12 117 60T50 256Q50 319 67 369T117 455T196 509T301 528Q359 528 405 510T483 457T532 375T550 266V222H197V213Q197 163 228 133T319 102Q365 102 398 119T455 166L535 79Q505 42 451 15T314
|
||||
-12ZM302 422Q254 422 226 393T197 313V305H405V313Q405 364 378 393T302 422ZM317 570L229 613L328 807L451 746L317 570Z" />
|
||||
<glyph unicode="ê" glyph-name="ecircumflex" d="M314 -12Q184 -12 117 60T50 256Q50 319 67 369T117 455T196 509T301 528Q359 528 405 510T483 457T532 375T550 266V222H197V213Q197 163 228 133T319 102Q365 102 398 119T455 166L535 79Q505 42 451 15T314
|
||||
-12ZM302 422Q254 422 226 393T197 313V305H405V313Q405 364 378 393T302 422ZM363 786L495 627L420 569L299 684L178 569L107 627L239 786H363Z" />
|
||||
<glyph unicode="ë" glyph-name="edieresis" d="M314 -12Q184 -12 117 60T50 256Q50 319 67 369T117 455T196 509T301 528Q359 528 405 510T483 457T532 375T550 266V222H197V213Q197 163 228 133T319 102Q365 102 398 119T455 166L535 79Q505 42 451 15T314
|
||||
-12ZM302 422Q254 422 226 393T197 313V305H405V313Q405 364 378 393T302 422ZM191 591Q146 591 129 609T111 654V680Q111 706 128 724T191 742Q236 742 254 724T272 680V654Q272 628 254 610T191 591ZM411 591Q366 591 348 609T330 654V680Q330 706 348 724T411
|
||||
742Q456 742 473 724T491 680V654Q491 628 474 610T411 591Z" />
|
||||
<glyph unicode="ì" glyph-name="igrave" d="M94 115H258V401H94V516H406V115H558V0H94V115ZM182 746L305 807L404 613L316 570L182 746Z" />
|
||||
<glyph unicode="í" glyph-name="iacute" d="M94 115H258V401H94V516H406V115H558V0H94V115ZM348 570L260 613L359 807L482 746L348 570Z" />
|
||||
<glyph unicode="î" glyph-name="icircumflex" d="M94 115H258V401H94V516H406V115H558V0H94V115ZM394 786L526 627L451 569L330 684L209 569L138 627L270 786H394Z" />
|
||||
<glyph unicode="ï" glyph-name="idieresis" d="M94 115H258V401H94V516H406V115H558V0H94V115ZM222 591Q177 591 160 609T142 654V680Q142 706 159 724T222 742Q267 742 285 724T303 680V654Q303 628 285 610T222 591ZM442 591Q397 591 379 609T361 654V680Q361
|
||||
706 379 724T442 742Q487 742 504 724T522 680V654Q522 628 505 610T442 591Z" />
|
||||
<glyph unicode="ð" glyph-name="eth" d="M483 693L408 649Q441 616 469 577T517 491T549 392T561 278Q561 202 543 147T490 57T409 5T303 -12Q241 -12 192 6T110 59T58 142T40 253Q40 309 54 354T95 432T159 482T242 500Q299 500 337 475T399 404L408 408Q394
|
||||
454 365 497T294 582L202 528L151 588L233 636Q197 665 157 691T71 740H297Q310 732 322 723T348 703L433 753L483 693ZM302 98Q352 98 380 129T408 217V273Q408 330 379 359T301 388Q250 388 222 358T193 271V217Q193 160 222 129T302 98Z" />
|
||||
<glyph unicode="ñ" glyph-name="ntilde" d="M65 0V516H213V422H219Q228 444 241 463T272 496T315 519T371 528Q408 528 439 516T492 478T526 417T539 334V0H391V314Q391 414 304 414Q287 414 271 410T241 396T221 372T213 339V0H65ZM378 592Q355 592 338
|
||||
598T301 612Q279 621 261 627T223 634Q206 634 193 628T164 609L112 677Q130 704 158 722T226 741Q249 741 266 735T303 721Q325 712 343 706T381 699Q398 699 411 705T440 724L492 656Q474 629 446 611T378 592Z" />
|
||||
<glyph unicode="ò" glyph-name="ograve" d="M300 -12Q240 -12 192 6T111 60T59 145T41 258Q41 321 59 371T110 456T192 509T300 528Q360 528 408 510T489 456T541 371T559 258Q559 195 541 145T490 60T408 7T300 -12ZM300 98Q350 98 378 129T406 217V299Q406
|
||||
356 378 387T300 418Q250 418 222 387T194 299V217Q194 160 222 129T300 98ZM150 746L273 807L372 613L284 570L150 746Z" />
|
||||
<glyph unicode="ó" glyph-name="oacute" d="M300 -12Q240 -12 192 6T111 60T59 145T41 258Q41 321 59 371T110 456T192 509T300 528Q360 528 408 510T489 456T541 371T559 258Q559 195 541 145T490 60T408 7T300 -12ZM300 98Q350 98 378 129T406 217V299Q406
|
||||
356 378 387T300 418Q250 418 222 387T194 299V217Q194 160 222 129T300 98ZM316 570L228 613L327 807L450 746L316 570Z" />
|
||||
<glyph unicode="ô" glyph-name="ocircumflex" d="M300 -12Q240 -12 192 6T111 60T59 145T41 258Q41 321 59 371T110 456T192 509T300 528Q360 528 408 510T489 456T541 371T559 258Q559 195 541 145T490 60T408 7T300 -12ZM300 98Q350 98 378 129T406 217V299Q406
|
||||
356 378 387T300 418Q250 418 222 387T194 299V217Q194 160 222 129T300 98ZM362 786L494 627L419 569L298 684L177 569L106 627L238 786H362Z" />
|
||||
<glyph unicode="õ" glyph-name="otilde" d="M300 -12Q240 -12 192 6T111 60T59 145T41 258Q41 321 59 371T110 456T192 509T300 528Q360 528 408 510T489 456T541 371T559 258Q559 195 541 145T490 60T408 7T300 -12ZM300 98Q350 98 378 129T406 217V299Q406
|
||||
356 378 387T300 418Q250 418 222 387T194 299V217Q194 160 222 129T300 98ZM376 592Q353 592 336 598T299 612Q277 621 259 627T221 634Q204 634 191 628T162 609L110 677Q128 704 156 722T224 741Q247 741 264 735T301 721Q323 712 341 706T379 699Q396 699 409
|
||||
705T438 724L490 656Q472 629 444 611T376 592Z" />
|
||||
<glyph unicode="ö" glyph-name="odieresis" d="M300 -12Q240 -12 192 6T111 60T59 145T41 258Q41 321 59 371T110 456T192 509T300 528Q360 528 408 510T489 456T541 371T559 258Q559 195 541 145T490 60T408 7T300 -12ZM300 98Q350 98 378 129T406 217V299Q406
|
||||
356 378 387T300 418Q250 418 222 387T194 299V217Q194 160 222 129T300 98ZM190 591Q145 591 128 609T110 654V680Q110 706 127 724T190 742Q235 742 253 724T271 680V654Q271 628 253 610T190 591ZM410 591Q365 591 347 609T329 654V680Q329 706 347 724T410
|
||||
742Q455 742 472 724T490 680V654Q490 628 473 610T410 591Z" />
|
||||
<glyph unicode="÷" glyph-name="divide" d="M62 246V364H538V246H62ZM300 29Q252 29 232 49T212 98V122Q212 151 232 171T300 191Q348 191 368 171T388 122V98Q388 69 368 49T300 29ZM300 419Q252 419 232 439T212 488V512Q212 541 232 561T300 581Q348 581
|
||||
368 561T388 512V488Q388 459 368 439T300 419Z" />
|
||||
<glyph unicode="ø" glyph-name="oslash" d="M23 1L92 84Q41 151 41 258Q41 321 59 371T110 456T192 509T300 528Q338 528 371 520T431 498L495 575L577 515L508 432Q559 364 559 258Q559 195 541 145T490 60T408 7T300 -12Q262 -12 229 -4T169 18L105 -59L23
|
||||
1ZM300 418Q250 418 222 387T194 299V225Q194 219 194 212T196 200L361 401Q336 418 300 418ZM300 98Q350 98 378 129T406 217V291Q406 297 406 304T404 316L239 115Q264 98 300 98Z" />
|
||||
<glyph unicode="ù" glyph-name="ugrave" d="M387 94H381Q364 50 328 19T229 -12Q192 -12 161 0T108 38T74 99T61 182V516H209V202Q209 102 296 102Q313 102 329 106T358 120T379 144T387 177V516H535V0H387V94ZM405 746L528 807L627 613L539 570L405 746Z" />
|
||||
<glyph unicode="ú" glyph-name="uacute" d="M387 94H381Q364 50 328 19T229 -12Q192 -12 161 0T108 38T74 99T61 182V516H209V202Q209 102 296 102Q313 102 329 106T358 120T379 144T387 177V516H535V0H387V94ZM571 570L483 613L582 807L705 746L571 570Z" />
|
||||
<glyph unicode="û" glyph-name="ucircumflex" d="M387 94H381Q364 50 328 19T229 -12Q192 -12 161 0T108 38T74 99T61 182V516H209V202Q209 102 296 102Q313 102 329 106T358 120T379 144T387 177V516H535V0H387V94ZM617 786L749 627L674 569L553 684L432
|
||||
569L361 627L493 786H617Z" />
|
||||
<glyph unicode="ü" glyph-name="udieresis" d="M387 94H381Q364 50 328 19T229 -12Q192 -12 161 0T108 38T74 99T61 182V516H209V202Q209 102 296 102Q313 102 329 106T358 120T379 144T387 177V516H535V0H387V94ZM445 591Q400 591 383 609T365 654V680Q365
|
||||
706 382 724T445 742Q490 742 508 724T526 680V654Q526 628 508 610T445 591ZM665 591Q620 591 602 609T584 654V680Q584 706 602 724T665 742Q710 742 727 724T745 680V654Q745 628 728 610T665 591Z" />
|
||||
<glyph unicode="ý" glyph-name="yacute" d="M430 516H581L338 -83Q315 -140 277 -170T173 -200H71V-85H195L227 3L19 516H178L253 299L300 149H308L353 299L430 516ZM319 570L231 613L330 807L453 746L319 570Z" />
|
||||
<glyph unicode="þ" glyph-name="thorn" d="M59 740H207V422H214Q233 468 269 498T367 528Q410 528 445 512T506 463T546 379T561 258Q561 188 547 137T507 53T446 4T367 -12Q305 -12 269 17T214 94H207V-200H59V740ZM303 103Q353 103 380 133T407 218V298Q407
|
||||
352 380 382T303 413Q264 413 236 394T207 334V182Q207 141 235 122T303 103Z" />
|
||||
<glyph unicode="ÿ" glyph-name="ydieresis" d="M430 516H581L338 -83Q315 -140 277 -170T173 -200H71V-85H195L227 3L19 516H178L253 299L300 149H308L353 299L430 516ZM193 591Q148 591 131 609T113 654V680Q113 706 130 724T193 742Q238 742 256 724T274
|
||||
680V654Q274 628 256 610T193 591ZM413 591Q368 591 350 609T332 654V680Q332 706 350 724T413 742Q458 742 475 724T493 680V654Q493 628 476 610T413 591Z" />
|
||||
<glyph unicode="–" glyph-name="endash" d="M60 244V365H540V244H60Z" />
|
||||
<glyph unicode="—" glyph-name="emdash" d="M0 244V365H600V244H0Z" />
|
||||
<glyph unicode="‘" glyph-name="quoteleft" d="M300 740H409L352 414H162L300 740Z" />
|
||||
<glyph unicode="’" glyph-name="quoteright" d="M248 740H438L300 414H191L248 740Z" />
|
||||
<glyph unicode="‚" glyph-name="quotesinglbase" d="M227 174H417L280 -151H170L227 174Z" />
|
||||
<glyph unicode="“" glyph-name="quotedblleft" d="M172 740H281L224 414H34L172 740ZM430 740H539L482 414H292L430 740Z" />
|
||||
<glyph unicode="”" glyph-name="quotedblright" d="M120 740H310L172 414H63L120 740ZM378 740H568L430 414H321L378 740Z" />
|
||||
<glyph unicode="„" glyph-name="quotedblbase" d="M358 174H548L411 -151H301L358 174ZM360 174H550L413 -151H303L360 174Z" />
|
||||
<glyph unicode="•" glyph-name="bullet" d="M300 156Q258 156 229 166T181 193T154 235T146 287V321Q146 349 154 373T180 414T228 442T300 452Q342 452 371 442T419 415T446 373T454 321V287Q454 259 446 235T420 194T372 166T300 156Z" />
|
||||
<glyph unicode="‹" glyph-name="guilsinglleft" d="M373 38L173 206V338L373 506L418 410L288 272L418 133L373 38Z" />
|
||||
<glyph unicode="›" glyph-name="guilsinglright" d="M182 133L312 272L182 410L227 506L427 338V206L227 38L182 133Z" />
|
||||
</font>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 51 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user