Changeset - ae4b90efb55a
[Not reviewed]
default
0 3 6
drewp@bigasterisk.com - 8 months ago 2024-05-20 08:28:12
drewp@bigasterisk.com
start calibration tool
9 files changed with 481 insertions and 8 deletions:
0 comments (0 inline, 0 general)
package.json
Show inline comments
 
{
 
  "name": "light9",
 
  "version": "1.0.0",
 
  "repository": "...",
 
  "license": "MIT",
 
  "description": "see makefile for build commands",
 
  "main": "index.js",
 
  "directories": {
 
    "test": "test"
 
  },
 
  "dependencies": {
 
    "@material/mwc-button": "^0.27.0",
 
    "@material/mwc-dialog": "^0.27.0",
 
    "@material/mwc-slider": "^0.27.0",
 
    "@material/mwc-textfield": "^0.27.0",
 
    "@microsoft/fast-components": "^2.30.6",
 
    "@types/async": "^3.2.24",
 
    "@types/d3": "^7.4.3",
 
    "@types/debug": "^4.1.12",
 
    "@types/fpsmeter": "^0.3.34",
 
    "@types/n3": "^1.16.4",
 
    "@types/node": "^20.12.11",
 
    "@types/reconnectingwebsocket": "^1.0.10",
 
    "@types/underscore": "^1.11.15",
 
    "async": "^3.2.5",
 
    "avro-js": "^1.11.3",
 
    "d3": "^7.9.0",
 
    "debug": "^4.3.4",
 
    "echarts": "^5.5.0",
 
    "flexlayout-react": "^0.7.15",
 
    "fpsmeter": "^0.3.1",
 
    "immutable": "^4.3.5",
 
    "knockout": "^3.5.1",
 
    "lit": "^2.8.0",
 
    "n3": "^1.17.3",
 
    "onecolor": "^4.1.0",
 
    "parse-prometheus-text-format": "^1.1.1",
 
    "react": "^18.3.1",
 
    "react-dom": "^18.3.1",
 
    "reconnectingwebsocket": "^1.0.0",
 
    "sub-events": "^1.9.0",
 
    "sylvester": "^0.0.21",
 
    "typescript": "^5.4.5",
 
    "underscore": "^1.13.6",
 
    "vite": "^4.5.3",
 
    "vite-plugin-rewrite-all": "^1.0.2",
 
    "vitest": "^0.31.4"
 
  },
 
  "devDependencies": {
 
    "@types/react": "^18.3.2",
 
    "@types/react-dom": "^18.3.0",
 
    "vite-plugin-node-polyfills": "^0.21.0"
 
  }
 
}
pnpm-lock.yaml
Show inline comments
 
lockfileVersion: '6.0'
 

	
 
settings:
 
  autoInstallPeers: true
 
  excludeLinksFromLockfile: false
 

	
 
dependencies:
 
  '@material/mwc-button':
 
    specifier: ^0.27.0
 
    version: 0.27.0
 
  '@material/mwc-dialog':
 
    specifier: ^0.27.0
 
    version: 0.27.0
 
  '@material/mwc-slider':
 
    specifier: ^0.27.0
 
    version: 0.27.0
 
  '@material/mwc-textfield':
 
    specifier: ^0.27.0
 
    version: 0.27.0
 
  '@microsoft/fast-components':
 
    specifier: ^2.30.6
 
    version: 2.30.6
 
  '@types/async':
 
    specifier: ^3.2.24
 
    version: 3.2.24
 
  '@types/d3':
 
    specifier: ^7.4.3
 
    version: 7.4.3
 
  '@types/debug':
 
    specifier: ^4.1.12
 
    version: 4.1.12
 
  '@types/fpsmeter':
 
    specifier: ^0.3.34
 
    version: 0.3.34
 
  '@types/n3':
 
    specifier: ^1.16.4
 
    version: 1.16.4
 
  '@types/node':
 
    specifier: ^20.12.11
 
    version: 20.12.11
 
  '@types/reconnectingwebsocket':
 
    specifier: ^1.0.10
 
    version: 1.0.10
 
  '@types/underscore':
 
    specifier: ^1.11.15
 
    version: 1.11.15
 
  async:
 
    specifier: ^3.2.5
 
    version: 3.2.5
 
  avro-js:
 
    specifier: ^1.11.3
 
    version: 1.11.3
 
  avsc:
 
    specifier: ^5.7.7
 
    version: 5.7.7
 
  d3:
 
    specifier: ^7.9.0
 
    version: 7.9.0
 
  debug:
 
    specifier: ^4.3.4
 
    version: 4.3.4
 
  echarts:
 
    specifier: ^5.5.0
 
    version: 5.5.0
 
  flexlayout-react:
 
    specifier: ^0.7.15
 
    version: 0.7.15(react-dom@18.3.1)(react@18.3.1)
 
  fpsmeter:
 
    specifier: ^0.3.1
 
    version: 0.3.1
 
  immutable:
 
    specifier: ^4.3.5
 
    version: 4.3.5
 
  knockout:
 
    specifier: ^3.5.1
 
    version: 3.5.1
 
  lit:
 
    specifier: ^2.8.0
 
    version: 2.8.0
 
  n3:
 
    specifier: ^1.17.3
 
    version: 1.17.3
 
  onecolor:
 
    specifier: ^4.1.0
 
    version: 4.1.0
 
  parse-prometheus-text-format:
 
    specifier: ^1.1.1
 
    version: 1.1.1
 
  react:
 
    specifier: ^18.3.1
 
    version: 18.3.1
 
  react-dom:
 
    specifier: ^18.3.1
 
    version: 18.3.1(react@18.3.1)
 
  reconnectingwebsocket:
 
    specifier: ^1.0.0
 
    version: 1.0.0
 
  sub-events:
 
    specifier: ^1.9.0
 
    version: 1.9.0
 
  sylvester:
 
    specifier: ^0.0.21
 
    version: 0.0.21
 
  typescript:
 
    specifier: ^5.4.5
 
    version: 5.4.5
 
  underscore:
 
    specifier: ^1.13.6
 
    version: 1.13.6
 
  vite:
 
    specifier: ^4.5.3
 
    version: 4.5.3(@types/node@20.12.11)
 
  vite-plugin-rewrite-all:
 
    specifier: ^1.0.2
 
    version: 1.0.2(vite@4.5.3)
 
  vitest:
 
    specifier: ^0.31.4
 
    version: 0.31.4
 

	
 
devDependencies:
 
  '@types/react':
 
    specifier: ^18.3.2
 
    version: 18.3.2
 
  '@types/react-dom':
 
    specifier: ^18.3.0
 
    version: 18.3.0
 
  vite-plugin-node-polyfills:
 
    specifier: ^0.21.0
 
    version: 0.21.0(vite@4.5.3)
 

	
 
packages:
 

	
 
  /@esbuild/android-arm64@0.18.20:
 
    resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
 
    engines: {node: '>=12'}
 
    cpu: [arm64]
 
    os: [android]
 
    requiresBuild: true
 
    optional: true
 

	
 
  /@esbuild/android-arm@0.18.20:
 
    resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==}
 
    engines: {node: '>=12'}
 
    cpu: [arm]
 
    os: [android]
 
    requiresBuild: true
 
    optional: true
 

	
 
  /@esbuild/android-x64@0.18.20:
 
    resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==}
 
    engines: {node: '>=12'}
 
    cpu: [x64]
 
    os: [android]
 
    requiresBuild: true
 
    optional: true
 

	
 
  /@esbuild/darwin-arm64@0.18.20:
 
    resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==}
 
    engines: {node: '>=12'}
 
    cpu: [arm64]
 
@@ -993,197 +993,192 @@ packages:
 
    dependencies:
 
      '@vitest/utils': 0.31.4
 
      concordance: 5.0.4
 
      p-limit: 4.0.0
 
      pathe: 1.1.2
 
    dev: false
 

	
 
  /@vitest/snapshot@0.31.4:
 
    resolution: {integrity: sha512-LemvNumL3NdWSmfVAMpXILGyaXPkZbG5tyl6+RQSdcHnTj6hvA49UAI8jzez9oQyE/FWLKRSNqTGzsHuk89LRA==}
 
    dependencies:
 
      magic-string: 0.30.10
 
      pathe: 1.1.2
 
      pretty-format: 27.5.1
 
    dev: false
 

	
 
  /@vitest/spy@0.31.4:
 
    resolution: {integrity: sha512-3ei5ZH1s3aqbEyftPAzSuunGICRuhE+IXOmpURFdkm5ybUADk+viyQfejNk6q8M5QGX8/EVKw+QWMEP3DTJDag==}
 
    dependencies:
 
      tinyspy: 2.2.1
 
    dev: false
 

	
 
  /@vitest/utils@0.31.4:
 
    resolution: {integrity: sha512-DobZbHacWznoGUfYU8XDPY78UubJxXfMNY1+SUdOp1NsI34eopSA6aZMeaGu10waSOeYwE8lxrd/pLfT0RMxjQ==}
 
    dependencies:
 
      concordance: 5.0.4
 
      loupe: 2.3.7
 
      pretty-format: 27.5.1
 
    dev: false
 

	
 
  /abort-controller@3.0.0:
 
    resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
 
    engines: {node: '>=6.5'}
 
    dependencies:
 
      event-target-shim: 5.0.1
 
    dev: false
 

	
 
  /acorn-walk@8.3.2:
 
    resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==}
 
    engines: {node: '>=0.4.0'}
 
    dev: false
 

	
 
  /acorn@8.11.3:
 
    resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
 
    engines: {node: '>=0.4.0'}
 
    hasBin: true
 
    dev: false
 

	
 
  /ansi-regex@5.0.1:
 
    resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
 
    engines: {node: '>=8'}
 
    dev: false
 

	
 
  /ansi-styles@5.2.0:
 
    resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
 
    engines: {node: '>=10'}
 
    dev: false
 

	
 
  /asn1.js@4.10.1:
 
    resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==}
 
    dependencies:
 
      bn.js: 4.12.0
 
      inherits: 2.0.4
 
      minimalistic-assert: 1.0.1
 
    dev: true
 

	
 
  /assert@2.1.0:
 
    resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==}
 
    dependencies:
 
      call-bind: 1.0.7
 
      is-nan: 1.3.2
 
      object-is: 1.1.6
 
      object.assign: 4.1.5
 
      util: 0.12.5
 
    dev: true
 

	
 
  /assertion-error@1.1.0:
 
    resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
 
    dev: false
 

	
 
  /async@3.2.5:
 
    resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==}
 
    dev: false
 

	
 
  /available-typed-arrays@1.0.7:
 
    resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
 
    engines: {node: '>= 0.4'}
 
    dependencies:
 
      possible-typed-array-names: 1.0.0
 
    dev: true
 

	
 
  /avro-js@1.11.3:
 
    resolution: {integrity: sha512-B1b0wI5iwSkVwj3RQWRzW99/LGoYl6df9j1kWime8r8b0dXCdKU7t7mEOFkOpQFaT/I9JXaL7KAIxM+/3TUk1A==}
 
    dependencies:
 
      underscore: 1.13.6
 
    dev: false
 

	
 
  /avsc@5.7.7:
 
    resolution: {integrity: sha512-9cYNccliXZDByFsFliVwk5GvTq058Fj513CiR4E60ndDwmuXzTJEp/Bp8FyuRmGyYupLjHLs+JA9/CBoVS4/NQ==}
 
    engines: {node: '>=0.11'}
 
    dev: false
 

	
 
  /base64-js@1.5.1:
 
    resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
 

	
 
  /blocking-elements@0.1.1:
 
    resolution: {integrity: sha512-/SLWbEzMoVIMZACCyhD/4Ya2M1PWP1qMKuiymowPcI+PdWDARqeARBjhj73kbUBCxEmTZCUu5TAqxtwUO9C1Ig==}
 
    dev: false
 

	
 
  /blueimp-md5@2.19.0:
 
    resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==}
 
    dev: false
 

	
 
  /bn.js@4.12.0:
 
    resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==}
 
    dev: true
 

	
 
  /bn.js@5.2.1:
 
    resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==}
 
    dev: true
 

	
 
  /brorand@1.1.0:
 
    resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==}
 
    dev: true
 

	
 
  /browser-resolve@2.0.0:
 
    resolution: {integrity: sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==}
 
    dependencies:
 
      resolve: 1.22.8
 
    dev: true
 

	
 
  /browserify-aes@1.2.0:
 
    resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==}
 
    dependencies:
 
      buffer-xor: 1.0.3
 
      cipher-base: 1.0.4
 
      create-hash: 1.2.0
 
      evp_bytestokey: 1.0.3
 
      inherits: 2.0.4
 
      safe-buffer: 5.2.1
 
    dev: true
 

	
 
  /browserify-cipher@1.0.1:
 
    resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==}
 
    dependencies:
 
      browserify-aes: 1.2.0
 
      browserify-des: 1.0.2
 
      evp_bytestokey: 1.0.3
 
    dev: true
 

	
 
  /browserify-des@1.0.2:
 
    resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==}
 
    dependencies:
 
      cipher-base: 1.0.4
 
      des.js: 1.1.0
 
      inherits: 2.0.4
 
      safe-buffer: 5.2.1
 
    dev: true
 

	
 
  /browserify-rsa@4.1.0:
 
    resolution: {integrity: sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==}
 
    dependencies:
 
      bn.js: 5.2.1
 
      randombytes: 2.1.0
 
    dev: true
 

	
 
  /browserify-sign@4.2.3:
 
    resolution: {integrity: sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==}
 
    engines: {node: '>= 0.12'}
 
    dependencies:
 
      bn.js: 5.2.1
 
      browserify-rsa: 4.1.0
 
      create-hash: 1.2.0
 
      create-hmac: 1.1.7
 
      elliptic: 6.5.5
 
      hash-base: 3.0.4
 
      inherits: 2.0.4
 
      parse-asn1: 5.1.7
 
      readable-stream: 2.3.8
 
      safe-buffer: 5.2.1
 
    dev: true
 

	
 
  /browserify-zlib@0.2.0:
 
    resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==}
 
    dependencies:
 
      pako: 1.0.11
 
    dev: true
 

	
 
  /buffer-xor@1.0.3:
 
    resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==}
 
    dev: true
 

	
 
  /buffer@5.7.1:
 
    resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
 
    dependencies:
 
      base64-js: 1.5.1
 
      ieee754: 1.2.1
 
    dev: true
 
@@ -1558,192 +1553,199 @@ packages:
 
      d3-delaunay: 6.0.4
 
      d3-dispatch: 3.0.1
 
      d3-drag: 3.0.0
 
      d3-dsv: 3.0.1
 
      d3-ease: 3.0.1
 
      d3-fetch: 3.0.1
 
      d3-force: 3.0.0
 
      d3-format: 3.1.0
 
      d3-geo: 3.1.1
 
      d3-hierarchy: 3.1.2
 
      d3-interpolate: 3.0.1
 
      d3-path: 3.1.0
 
      d3-polygon: 3.0.1
 
      d3-quadtree: 3.0.1
 
      d3-random: 3.0.1
 
      d3-scale: 4.0.2
 
      d3-scale-chromatic: 3.1.0
 
      d3-selection: 3.0.0
 
      d3-shape: 3.2.0
 
      d3-time: 3.1.0
 
      d3-time-format: 4.1.0
 
      d3-timer: 3.0.1
 
      d3-transition: 3.0.1(d3-selection@3.0.0)
 
      d3-zoom: 3.0.0
 
    dev: false
 

	
 
  /date-time@3.1.0:
 
    resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==}
 
    engines: {node: '>=6'}
 
    dependencies:
 
      time-zone: 1.0.0
 
    dev: false
 

	
 
  /debug@4.3.4:
 
    resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
 
    engines: {node: '>=6.0'}
 
    peerDependencies:
 
      supports-color: '*'
 
    peerDependenciesMeta:
 
      supports-color:
 
        optional: true
 
    dependencies:
 
      ms: 2.1.2
 
    dev: false
 

	
 
  /deep-eql@4.1.3:
 
    resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
 
    engines: {node: '>=6'}
 
    dependencies:
 
      type-detect: 4.0.8
 
    dev: false
 

	
 
  /define-data-property@1.1.4:
 
    resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
 
    engines: {node: '>= 0.4'}
 
    dependencies:
 
      es-define-property: 1.0.0
 
      es-errors: 1.3.0
 
      gopd: 1.0.1
 
    dev: true
 

	
 
  /define-properties@1.2.1:
 
    resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
 
    engines: {node: '>= 0.4'}
 
    dependencies:
 
      define-data-property: 1.1.4
 
      has-property-descriptors: 1.0.2
 
      object-keys: 1.1.1
 
    dev: true
 

	
 
  /delaunator@5.0.1:
 
    resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==}
 
    dependencies:
 
      robust-predicates: 3.0.2
 
    dev: false
 

	
 
  /des.js@1.1.0:
 
    resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==}
 
    dependencies:
 
      inherits: 2.0.4
 
      minimalistic-assert: 1.0.1
 
    dev: true
 

	
 
  /diffie-hellman@5.0.3:
 
    resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==}
 
    dependencies:
 
      bn.js: 4.12.0
 
      miller-rabin: 4.0.1
 
      randombytes: 2.1.0
 
    dev: true
 

	
 
  /domain-browser@4.23.0:
 
    resolution: {integrity: sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA==}
 
    engines: {node: '>=10'}
 
    dev: true
 

	
 
  /echarts@5.5.0:
 
    resolution: {integrity: sha512-rNYnNCzqDAPCr4m/fqyUFv7fD9qIsd50S6GDFgO1DxZhncCsNsG7IfUlAlvZe5oSEQxtsjnHiUuppzccry93Xw==}
 
    dependencies:
 
      tslib: 2.3.0
 
      zrender: 5.5.0
 
    dev: false
 

	
 
  /elliptic@6.5.5:
 
    resolution: {integrity: sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==}
 
    dependencies:
 
      bn.js: 4.12.0
 
      brorand: 1.1.0
 
      hash.js: 1.1.7
 
      hmac-drbg: 1.0.1
 
      inherits: 2.0.4
 
      minimalistic-assert: 1.0.1
 
      minimalistic-crypto-utils: 1.0.1
 
    dev: true
 

	
 
  /es-define-property@1.0.0:
 
    resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==}
 
    engines: {node: '>= 0.4'}
 
    dependencies:
 
      get-intrinsic: 1.2.4
 
    dev: true
 

	
 
  /es-errors@1.3.0:
 
    resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
 
    engines: {node: '>= 0.4'}
 
    dev: true
 

	
 
  /esbuild@0.18.20:
 
    resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==}
 
    engines: {node: '>=12'}
 
    hasBin: true
 
    requiresBuild: true
 
    optionalDependencies:
 
      '@esbuild/android-arm': 0.18.20
 
      '@esbuild/android-arm64': 0.18.20
 
      '@esbuild/android-x64': 0.18.20
 
      '@esbuild/darwin-arm64': 0.18.20
 
      '@esbuild/darwin-x64': 0.18.20
 
      '@esbuild/freebsd-arm64': 0.18.20
 
      '@esbuild/freebsd-x64': 0.18.20
 
      '@esbuild/linux-arm': 0.18.20
 
      '@esbuild/linux-arm64': 0.18.20
 
      '@esbuild/linux-ia32': 0.18.20
 
      '@esbuild/linux-loong64': 0.18.20
 
      '@esbuild/linux-mips64el': 0.18.20
 
      '@esbuild/linux-ppc64': 0.18.20
 
      '@esbuild/linux-riscv64': 0.18.20
 
      '@esbuild/linux-s390x': 0.18.20
 
      '@esbuild/linux-x64': 0.18.20
 
      '@esbuild/netbsd-x64': 0.18.20
 
      '@esbuild/openbsd-x64': 0.18.20
 
      '@esbuild/sunos-x64': 0.18.20
 
      '@esbuild/win32-arm64': 0.18.20
 
      '@esbuild/win32-ia32': 0.18.20
 
      '@esbuild/win32-x64': 0.18.20
 

	
 
  /estree-walker@2.0.2:
 
    resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
 
    dev: true
 

	
 
  /esutils@2.0.3:
 
    resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
 
    engines: {node: '>=0.10.0'}
 
    dev: false
 

	
 
  /event-target-shim@5.0.1:
 
    resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
 
    engines: {node: '>=6'}
 
    dev: false
 

	
 
  /events@3.3.0:
 
    resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
 
    engines: {node: '>=0.8.x'}
 

	
 
  /evp_bytestokey@1.0.3:
 
    resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==}
 
    dependencies:
 
      md5.js: 1.3.5
 
      safe-buffer: 5.2.1
 
    dev: true
 

	
 
  /exenv-es6@1.1.1:
 
    resolution: {integrity: sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ==}
 
    dev: false
 

	
 
  /fast-diff@1.3.0:
 
    resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
 
    dev: false
 

	
 
  /find-up@5.0.0:
 
    resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
 
    engines: {node: '>=10'}
 
    dependencies:
 
      locate-path: 6.0.0
 
      path-exists: 4.0.0
 
    dev: true
 

	
 
  /flexlayout-react@0.7.15(react-dom@18.3.1)(react@18.3.1):
 
    resolution: {integrity: sha512-ydTMdEoQO5BniylxVkSxa59rEY0+96lqqRII+QK+yq6028eHywPuxZawt4g45y5pMb9ptP4N9HPAQXAFsxwowQ==}
 
@@ -2457,192 +2459,196 @@ packages:
 
    dev: false
 

	
 
  /source-map-js@1.2.0:
 
    resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
 
    engines: {node: '>=0.10.0'}
 

	
 
  /stackback@0.0.2:
 
    resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
 
    dev: false
 

	
 
  /std-env@3.7.0:
 
    resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==}
 
    dev: false
 

	
 
  /stream-browserify@3.0.0:
 
    resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==}
 
    dependencies:
 
      inherits: 2.0.4
 
      readable-stream: 3.6.2
 
    dev: true
 

	
 
  /stream-http@3.2.0:
 
    resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==}
 
    dependencies:
 
      builtin-status-codes: 3.0.0
 
      inherits: 2.0.4
 
      readable-stream: 3.6.2
 
      xtend: 4.0.2
 
    dev: true
 

	
 
  /string_decoder@1.1.1:
 
    resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
 
    dependencies:
 
      safe-buffer: 5.1.2
 
    dev: true
 

	
 
  /string_decoder@1.3.0:
 
    resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
 
    dependencies:
 
      safe-buffer: 5.2.1
 

	
 
  /strip-literal@1.3.0:
 
    resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==}
 
    dependencies:
 
      acorn: 8.11.3
 
    dev: false
 

	
 
  /sub-events@1.9.0:
 
    resolution: {integrity: sha512-dnFBayilG9Ku0k/lNs1Y7WV4kv91+ovCoeBV3uIYrY49DylvBb6z9d9ED2ctcrvX2YlReFalpCgJNtSgmrOaJg==}
 
    engines: {node: '>=10.0.0'}
 
    dev: false
 

	
 
  /supports-preserve-symlinks-flag@1.0.0:
 
    resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
 
    engines: {node: '>= 0.4'}
 
    dev: true
 

	
 
  /sylvester@0.0.21:
 
    resolution: {integrity: sha512-yUT0ukFkFEt4nb+NY+n2ag51aS/u9UHXoZw+A4jgD77/jzZsBoSDHuqysrVCBC4CYR4TYvUJq54ONpXgDBH8tA==}
 
    engines: {node: '>=0.2.6'}
 
    dev: false
 

	
 
  /tabbable@5.3.3:
 
    resolution: {integrity: sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==}
 
    dev: false
 

	
 
  /time-zone@1.0.0:
 
    resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==}
 
    engines: {node: '>=4'}
 
    dev: false
 

	
 
  /timers-browserify@2.0.12:
 
    resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==}
 
    engines: {node: '>=0.6.0'}
 
    dependencies:
 
      setimmediate: 1.0.5
 
    dev: true
 

	
 
  /tinybench@2.8.0:
 
    resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==}
 
    dev: false
 

	
 
  /tinypool@0.5.0:
 
    resolution: {integrity: sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==}
 
    engines: {node: '>=14.0.0'}
 
    dev: false
 

	
 
  /tinyspy@2.2.1:
 
    resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==}
 
    engines: {node: '>=14.0.0'}
 
    dev: false
 

	
 
  /tslib@1.14.1:
 
    resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
 
    dev: false
 

	
 
  /tslib@2.3.0:
 
    resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
 
    dev: false
 

	
 
  /tslib@2.6.2:
 
    resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
 
    dev: false
 

	
 
  /tty-browserify@0.0.1:
 
    resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==}
 
    dev: true
 

	
 
  /type-detect@4.0.8:
 
    resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
 
    engines: {node: '>=4'}
 
    dev: false
 

	
 
  /typescript@5.4.5:
 
    resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
 
    engines: {node: '>=14.17'}
 
    hasBin: true
 
    dev: false
 

	
 
  /ufo@1.5.3:
 
    resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==}
 
    dev: false
 

	
 
  /underscore@1.13.6:
 
    resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==}
 
    dev: false
 

	
 
  /undici-types@5.26.5:
 
    resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
 

	
 
  /url@0.11.3:
 
    resolution: {integrity: sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==}
 
    dependencies:
 
      punycode: 1.4.1
 
      qs: 6.12.1
 
    dev: true
 

	
 
  /util-deprecate@1.0.2:
 
    resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
 
    dev: true
 

	
 
  /util@0.12.5:
 
    resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==}
 
    dependencies:
 
      inherits: 2.0.4
 
      is-arguments: 1.1.1
 
      is-generator-function: 1.0.10
 
      is-typed-array: 1.1.13
 
      which-typed-array: 1.1.15
 
    dev: true
 

	
 
  /vite-node@0.31.4(@types/node@20.12.11):
 
    resolution: {integrity: sha512-uzL377GjJtTbuc5KQxVbDu2xfU/x0wVjUtXQR2ihS21q/NK6ROr4oG0rsSkBBddZUVCwzfx22in76/0ZZHXgkQ==}
 
    engines: {node: '>=v14.18.0'}
 
    hasBin: true
 
    dependencies:
 
      cac: 6.7.14
 
      debug: 4.3.4
 
      mlly: 1.7.0
 
      pathe: 1.1.2
 
      picocolors: 1.0.0
 
      vite: 4.5.3(@types/node@20.12.11)
 
    transitivePeerDependencies:
 
      - '@types/node'
 
      - less
 
      - lightningcss
 
      - sass
 
      - stylus
 
      - sugarss
 
      - supports-color
 
      - terser
 
    dev: false
 

	
 
  /vite-plugin-node-polyfills@0.21.0(vite@4.5.3):
 
    resolution: {integrity: sha512-Sk4DiKnmxN8E0vhgEhzLudfJQfaT8k4/gJ25xvUPG54KjLJ6HAmDKbr4rzDD/QWEY+Lwg80KE85fGYBQihEPQA==}
 
    peerDependencies:
 
      vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0
 
    dependencies:
 
      '@rollup/plugin-inject': 5.0.5
 
      node-stdlib-browser: 1.2.0
 
      vite: 4.5.3(@types/node@20.12.11)
 
    transitivePeerDependencies:
 
      - rollup
 
    dev: true
 

	
 
  /vite-plugin-rewrite-all@1.0.2(vite@4.5.3):
 
    resolution: {integrity: sha512-NpiFyHi9w8iHm3kZ28ma/IU16LFCkNJNqTvGy6cjoit2EMBi7dgFWFZFYcwZjUrc+pOMup//rsQTRVILvF2efQ==}
 
    engines: {node: '>=12.0.0'}
 
    deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
 
    peerDependencies:
 
      vite: ^2.0.0 || ^3.0.0 || ^4.0.0
 
    dependencies:
 
      connect-history-api-fallback: 1.6.0
 
      vite: 4.5.3(@types/node@20.12.11)
 
    dev: false
 

	
 
@@ -2701,96 +2707,102 @@ packages:
 
        optional: true
 
      '@vitest/ui':
 
        optional: true
 
      happy-dom:
 
        optional: true
 
      jsdom:
 
        optional: true
 
      playwright:
 
        optional: true
 
      safaridriver:
 
        optional: true
 
      webdriverio:
 
        optional: true
 
    dependencies:
 
      '@types/chai': 4.3.16
 
      '@types/chai-subset': 1.3.5
 
      '@types/node': 20.12.11
 
      '@vitest/expect': 0.31.4
 
      '@vitest/runner': 0.31.4
 
      '@vitest/snapshot': 0.31.4
 
      '@vitest/spy': 0.31.4
 
      '@vitest/utils': 0.31.4
 
      acorn: 8.11.3
 
      acorn-walk: 8.3.2
 
      cac: 6.7.14
 
      chai: 4.4.1
 
      concordance: 5.0.4
 
      debug: 4.3.4
 
      local-pkg: 0.4.3
 
      magic-string: 0.30.10
 
      pathe: 1.1.2
 
      picocolors: 1.0.0
 
      std-env: 3.7.0
 
      strip-literal: 1.3.0
 
      tinybench: 2.8.0
 
      tinypool: 0.5.0
 
      vite: 4.5.3(@types/node@20.12.11)
 
      vite-node: 0.31.4(@types/node@20.12.11)
 
      why-is-node-running: 2.2.2
 
    transitivePeerDependencies:
 
      - less
 
      - lightningcss
 
      - sass
 
      - stylus
 
      - sugarss
 
      - supports-color
 
      - terser
 
    dev: false
 

	
 
  /vm-browserify@1.1.2:
 
    resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==}
 
    dev: true
 

	
 
  /well-known-symbols@2.0.0:
 
    resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==}
 
    engines: {node: '>=6'}
 
    dev: false
 

	
 
  /which-typed-array@1.1.15:
 
    resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==}
 
    engines: {node: '>= 0.4'}
 
    dependencies:
 
      available-typed-arrays: 1.0.7
 
      call-bind: 1.0.7
 
      for-each: 0.3.3
 
      gopd: 1.0.1
 
      has-tostringtag: 1.0.2
 
    dev: true
 

	
 
  /why-is-node-running@2.2.2:
 
    resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==}
 
    engines: {node: '>=8'}
 
    hasBin: true
 
    dependencies:
 
      siginfo: 2.0.0
 
      stackback: 0.0.2
 
    dev: false
 

	
 
  /wicg-inert@3.1.2:
 
    resolution: {integrity: sha512-Ba9tGNYxXwaqKEi9sJJvPMKuo063umUPsHN0JJsjrs2j8KDSzkWLMZGZ+MH1Jf1Fq4OWZ5HsESJID6nRza2ang==}
 
    dev: false
 

	
 
  /xtend@4.0.2:
 
    resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
 
    engines: {node: '>=0.4'}
 
    dev: true
 

	
 
  /yocto-queue@0.1.0:
 
    resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
 
    engines: {node: '>=10'}
 
    dev: true
 

	
 
  /yocto-queue@1.0.0:
 
    resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
 
    engines: {node: '>=12.20'}
 
    dev: false
 

	
 
  /zrender@5.5.0:
 
    resolution: {integrity: sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w==}
 
    dependencies:
 
      tslib: 2.3.0
 
    dev: false
web/calibrate/Light9Calibrate.ts
Show inline comments
 
new file 100644
 
import debug from "debug";
 
import { css, html, LitElement } from "lit";
 
import { customElement, query, state } from "lit/decorators.js";
 
import { CollectorClient } from "../collector/CollectorClient";
 
import { getTopGraph } from "../RdfdbSyncedGraph";
 
import { SyncedGraph } from "../SyncedGraph";
 
import { Light9Camera } from "./Light9Camera";
 
import { XyPlot } from "./XyPlot";
 
export { RdfdbSyncedGraph } from "../RdfdbSyncedGraph";
 
export { Light9Camera } from "./Light9Camera";
 
export { XyPlot } from "./XyPlot";
 
debug.enable("*");
 
const log = debug("calibrate");
 

	
 
async function sleep(ms: number) {
 
  return new Promise((resolve) => setTimeout(resolve, ms));
 
}
 

	
 
@customElement("light9-calibrate")
 
export class Light9Calibrate extends LitElement {
 
  graph!: SyncedGraph;
 
  static styles = [
 
    css`
 
      button {
 
        min-height: 3em;
 
        min-width: 10em;
 
      }
 
    `,
 
  ];
 
  collector: CollectorClient = new CollectorClient("calibrate");
 
  @query("light9-camera", true) cam?: Light9Camera;
 
  @query("xy-plot", true) plot?: XyPlot;
 
  @state() device: string;
 
  constructor() {
 
    super();
 
    this.device = "http://light9.bigasterisk.com/theater/vet/device/parR3";
 
    getTopGraph().then((g) => {
 
      this.graph = g;
 
    });
 
  }
 

	
 
  render() {
 
    return html`<rdfdb-synced-graph></rdfdb-synced-graph>
 
      <h1>Calibrate</h1>
 
      <light9-camera></light9-camera>
 

	
 
      <p>Device to calibrate: [ ${this.device} ]</p>
 

	
 
      <ol>
 
        <li><button @click=${this.setToFull}>Set to full</button></li>
 
        <li><button @click=${this.findSafeExposure}>Find safe exposure</button></li>
 
        <li><button @click=${this.setToZero}>Set to 0</button></li>
 
        <li><button @click=${this.markTare}>Mark tare</button></li>
 
        <li><button @click=${this.calibrateLoop}>Calibrate loop</button></li>
 
      </ol>
 
      <xy-plot label="zebra pixels vs exposure"></xy-plot>
 
      r/g/b/r*g*b lines ,x=send y=seen `;
 
  }
 

	
 
  async withButtonSpinner(ev: MouseEvent, fn: () => Promise<void>) {
 
    const btn = ev.target as HTMLButtonElement;
 
    try {
 
      btn.disabled = true;
 
      await fn();
 
    } finally {
 
      btn.disabled = false;
 
    }
 
  }
 
  async setToFull(ev: MouseEvent) {
 
    await this.withButtonSpinner(ev, async () => {
 
      this.collector.updateSettings([
 
        /// device,attr,value
 
        [this.device, "http://light9.bigasterisk.com/color", "#ffffff"],
 
        [this.device, "http://light9.bigasterisk.com/white", 1],
 
      ]);
 
    });
 
  }
 

	
 
  async findSafeExposure(ev: MouseEvent) {
 
    await this.withButtonSpinner(ev, async () => {
 

	
 
      const gatherSample = async (expo: number) => {
 
        await this.cam?.set("exposureTime", expo);
 
        const settleUntil = Date.now() + 1000;
 
        let miny = this.cam?.saturatedPixelCount!;
 
        while (Date.now() < settleUntil) {
 
          await sleep(50);
 
          miny = Math.min(miny, this.cam?.saturatedPixelCount!);
 
        }
 
        this.plot!.insertPoint(expo, miny);
 
      };
 

	
 
      // todo: drive around without big skips, gradually slower, looking for the max workable expo
 
      let fixedSteps = 8;
 
      const expoMin = 1;
 
      const expoMax = 200;
 
      let expo = 0;
 
      const data=this.plot!.data;
 
      while (data.length < 20) {
 
        if (data.length < fixedSteps + 1) {
 
          expo = expoMin + ((expoMax - expoMin) / fixedSteps) * data.length;
 
        } else {
 
          let x2 = data.findIndex(([_, y]) => y > 2);
 
          if (x2 < 1) x2 = 1;
 
          const x1 = x2 - 1;
 
          log(JSON.stringify([x1, data[x1], x2, data[x2]]));
 
          expo = (data[x1][0] + data[x2][0]) / 2;
 
          log(data);
 
        }
 
        await gatherSample(expo);
 
      }
 
    });
 
  }
 
  async setToZero(ev: MouseEvent) {
 
    await this.withButtonSpinner(ev, async () => {
 
      this.collector.updateSettings([
 
        [this.device, "http://light9.bigasterisk.com/color", "#000000"],
 
        [this.device, "http://light9.bigasterisk.com/white", 0],
 
      ]);
 
    });
 
  }
 
  async markTare(ev: MouseEvent) {
 
    await this.withButtonSpinner(ev, async () => {});
 
  }
 
  async calibrateLoop(ev: MouseEvent) {
 
    await this.withButtonSpinner(ev, async () => {});
 
  }
 
}
web/calibrate/Light9Camera.ts
Show inline comments
 
new file 100644
 
import debug from "debug";
 
import { css, html, LitElement, PropertyValueMap, TemplateResult } from "lit";
 
import { customElement, property, state } from "lit/decorators.js";
 

	
 
@customElement("light9-camera")
 
export class Light9Camera extends LitElement {
 
  static styles = [
 
    css`
 
      :host {
 
        display: flex;
 
      }
 
      #video {
 
        display: none;
 
      }
 
      #stack {
 
        position: relative;
 
        width: 640px;
 
        height: 480px;
 
      }
 
      #stack > * {
 
        position: absolute;
 
        left: 0;
 
        top: 0;
 
      }
 
      #stack > :first-child {
 
        position: static;
 
      }
 
      #stack > img {
 
        opacity: 0;
 
        animation: fadeIn 1s 1s ease-in-out forwards;
 
      }
 
      @keyframes fadeIn {
 
        from {
 
          opacity: 0;
 
        }
 
        to {
 
          opacity: 1;
 
        }
 
      }
 
    `,
 
  ];
 
  videoEl!: HTMLVideoElement;
 
  canvas!: HTMLCanvasElement;
 
  ctx!: CanvasRenderingContext2D;
 
  @state()
 
  vtrack: MediaStreamTrack | undefined;
 

	
 
  @property() saturatedPixelCount = 0;
 
  @property() saturatedPixelFraction = 0;
 

	
 
  @property() videoSettings: MediaTrackSettings & any = {};
 

	
 
  render() {
 
    const saturatedCountDisplay = `${this.saturatedPixelCount} (${(this.saturatedPixelFraction * 100).toFixed(2)}%)`;
 

	
 
    return html`
 
      <video id="video"></video>
 

	
 
      <div id="stack">
 
        <img src="zebra.png" />
 
        <canvas id="canvas"></canvas>
 
      </div>
 
      <div id="controls">
 
        <p>saturated pixels: ${saturatedCountDisplay}</p>
 
        <light9-camera-settings-table .cam=${this} .videoSettings=${this.videoSettings}></light9-camera-settings-table>
 
      </div>
 
    `;
 
  }
 

	
 
  protected async firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>) {
 
    this.videoEl = this.shadowRoot!.getElementById("video") as HTMLVideoElement;
 
    this.canvas = this.shadowRoot!.getElementById("canvas") as HTMLCanvasElement;
 
    this.ctx = this.canvas.getContext("2d", { willReadFrequently: true })!;
 

	
 
    const constraints: MediaStreamConstraints = {
 
      video: {
 
        facingMode: { ideal: "environment" },
 
        frameRate: { max: 10 },
 
      },
 
    };
 
    const stream = await navigator.mediaDevices.getUserMedia(constraints);
 
    const t = stream.getVideoTracks()[0];
 
    await t.applyConstraints({
 
      brightness: 0,
 
      contrast: 32,
 
      colorTemperature: 6600,
 
      exposureMode: "manual",
 
      exposureTime: 250,
 
      whiteBalanceMode: "manual",
 
      focusMode: "manual",
 
      focusDistance: 235,
 
    } as MediaTrackConstraints);
 

	
 
    this.vtrack = t;
 
    this.videoEl.srcObject = stream;
 
    this.videoEl.play();
 
    this.videoSettings = this.vtrack.getSettings();
 

	
 
    this.redrawLoop();
 
  }
 

	
 
  redrawLoop() {
 
    if (this.videoEl.videoWidth !== 0 && this.videoEl.videoHeight !== 0) {
 
      this.redraw();
 
    }
 
    // todo: video frames come slower than raf is waiting
 
    requestAnimationFrame(this.redrawLoop.bind(this));
 
  }
 

	
 
  public async set(k: string, v: any) {
 
    if (!this.vtrack) {
 
      throw new Error("vtrack");
 
    }
 
    await this.vtrack.applyConstraints({ [k]: v });
 
    this.videoSettings = this.vtrack.getSettings();
 
  }
 

	
 
  private redraw() {
 
    this.canvas.width = this.videoEl.videoWidth;
 
    this.canvas.height = this.videoEl.videoHeight;
 
    this.ctx.drawImage(this.videoEl, 0, 0);
 
    this.makeSaturatedPixelsTransparent();
 
  }
 

	
 
  private makeSaturatedPixelsTransparent() {
 
    const imageData = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);
 
    const data = imageData.data;
 
    this.saturatedPixelCount = 0;
 
    for (let i = 0; i < data.length; i += 4) {
 
      if (data[i] === 255 || data[i + 1] === 255 || data[i + 2] === 255) {
 
        this.saturatedPixelCount += 1;
 

	
 
        data[i + 3] = 0;
 
      }
 
    }
 
    this.saturatedPixelFraction = this.saturatedPixelCount / (data.length / 4);
 
    this.ctx.putImageData(imageData, 0, 0);
 
  }
 
}
 

	
 
@customElement("light9-camera-settings-table")
 
export class Light9CameraSettingsTable extends LitElement {
 
  static styles = [
 
    css`
 
      table {
 
        border-collapse: collapse;
 
      }
 
      td {
 
        border: 1px solid gray;
 
        padding: 1px 6px;
 
      }
 
    `,
 
  ];
 

	
 
  boring = [
 
    "aspectRatio",
 
    "backgroundBlur",
 
    "channelCount",
 
    "deviceId",
 
    "displaySurface",
 
    "echoCancellation",
 
    "eyeGazeCorrection",
 
    "faceFraming",
 
    "groupId",
 
    "latency",
 
    "noiseSuppression",
 
    "pointsOfInterest",
 
    "resizeMode",
 
    "sampleRate",
 
    "sampleSize",
 
    "suppressLocalAudioPlayback",
 
    "torch",
 
    "voiceIsolation",
 
  ];
 

	
 
  adjustable: Record<string, { min: string; max: string }> = {
 
    focusDistance: { min: "0", max: "1023" },
 
    brightness: { min: "0", max: "64" },
 
    colorTemperature: { min: "2800", max: "6500" },
 
    exposureTime: { min: "0", max: "400" },
 
  };
 

	
 
  @property() cam!: Light9Camera;
 
  @property() videoSettings: MediaTrackSettings & any = {};
 
  supportedByBrowser: MediaTrackSupportedConstraints;
 
  constructor() {
 
    super();
 
    this.supportedByBrowser = navigator.mediaDevices.getSupportedConstraints();
 
  }
 
  render() {
 
    const rows: TemplateResult<1>[] = [];
 
    for (const key of Object.keys(this.supportedByBrowser)) {
 
      if (!this.boring.includes(key)) {
 
        this.renderRow(key, rows);
 
      }
 
    }
 
    return html`<table>
 
      ${rows}
 
    </table>`;
 
  }
 

	
 
  private renderRow(key: string, rows: any[]) {
 
    let valueDisplay = "";
 
    if (this.videoSettings[key] !== undefined) {
 
      valueDisplay = JSON.stringify(this.videoSettings[key]);
 
    }
 
    let adjuster = html``;
 
    let conf = this.adjustable[key];
 
    if (conf !== undefined) {
 
      adjuster = html`
 
        <input type="range" min="${conf.min}" max="${conf.max}" value="${this.videoSettings[key]}" data-param="${key}" @input=${this.setFromSlider} />
 
      `;
 
    }
 
    rows.push(
 
      html`<tr>
 
        <td>${key}</td>
 
        <td>${valueDisplay}</td>
 
        <td>${adjuster}</td>
 
      </tr>`
 
    );
 
  }
 

	
 
  async setFromSlider(ev: InputEvent) {
 
    const el = ev.target as HTMLInputElement;
 
    await this.cam.set(el.dataset.param as string, parseFloat(el.value));
 
  }
 
}
web/calibrate/XyPlot.ts
Show inline comments
 
new file 100644
 
import debug from "debug";
 
import * as echarts from "echarts";
 
import { css, html, LitElement, PropertyValueMap } from "lit";
 
import { customElement, property } from "lit/decorators.js";
 
debug.enable("*");
 
const log = debug("calibrate");
 

	
 
@customElement("xy-plot")
 
export class XyPlot extends LitElement {
 
  static styles = [
 
    css`
 
      #chart {
 
        width: 800px;
 
        height: 300px;
 
      }
 
    `,
 
  ];
 
  chart!: echarts.ECharts;
 
  @property() label: string = "";
 
  @property() data: number[][] = [];
 
 
 
  render() {
 
    return html`
 
      <fieldset>
 
        <legend>${this.label}</legend>
 
        <div id="chart"></div>
 
      </fieldset>
 
    `;
 
  }
 

	
 
  protected async firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>) {
 
    var chartDom = this.shadowRoot!.getElementById("chart")!;
 
    this.chart = echarts.init(chartDom);
 
    this.chart.setOption({
 
      animation: false,
 
      xAxis: {
 
        type: "value",
 
      },
 
      yAxis: {
 
        type: "value",
 
      },
 
      series: [
 
        {
 
          name: "d",
 
          data: [],
 
          type: "line",
 
        },
 
      ],
 
    });
 
  }
 

	
 
  clear() {
 
    this.data.length = 0;
 
  }
 
  
 
  insertPoint(x: number, y: number) {
 
    this.data.push([x, y]);
 
    this.data.sort((a, b) => a[0] - b[0]);
 
    this.chart.setOption({ series: [{ name: "d", data: this.data }] });
 
  }
 
}
web/calibrate/index.html
Show inline comments
 
new file 100644
 
<!DOCTYPE html>
 
<html>
 
  <head>
 
    <title>calibrate</title>
 
    <meta charset="utf-8" />
 
    <link rel="stylesheet" href="../style.css" />
 
    <script type="module" src="Light9Calibrate"></script>
 
  </head>
 
  <body>
 
    <light9-calibrate></light9-calibrate>
 
  </body>
 
</html>
web/calibrate/zebra.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
web/collector/CollectorClient.ts
Show inline comments
 
new file 100644
 
type Settings = Array<[string,string,string|number]>;
 

	
 
export class CollectorClient {
 
  private settings: Settings;
 
  constructor(public clientName:string) {
 
    this.settings = [];
 
    this.putLoop();
 
  }
 
  private async putLoop() {
 
    await this.put();
 
    setTimeout(() => {
 
      this.putLoop();
 
    }, 1000);
 
  }
 
  private async put() {
 
    await fetch("/service/collector/attrs", {
 
      method: "PUT",
 
      body: JSON.stringify({
 
        client: this.clientName,
 
        clientSession: "unused",
 
        sendTime: Date.now() / 1000,
 
        settings: this.settings,
 
      }),
 
    });
 
  }
 
  public async updateSettings(settings: Settings) {
 
    this.settings = settings;
 
    await this.put()
 
  }
 
}
web/panels.ts
Show inline comments
 
export { Light9AscoltamiUi } from "./ascoltami/Light9AscoltamiUi";
 
export { Light9CollectorUi } from "./collector/Light9CollectorUi";
 
export { Light9EffectListing } from "./effects/Light9EffectListing";
 
export { Light9FadeUi } from "./fade/Light9FadeUi";
 
export { Light9DeviceSettings } from "./live/Light9DeviceSettings";
 
export { Light9Calibrate } from "./calibrate/Light9Calibrate";
 

	
 
const panels: Map<string, Array<string>> = new Map([
 
  ["light9-ascoltami-ui", ["ascoltami", "ascoltami"]],
 
  ["light9-collector-ui", ["collector", "collector"]],
 
  ["light9-device-settings", ["device-settings", "live"]],
 
  ["light9-effect-listing", ["effect-listing" , "effectListing"]],
 
  ["light9-fade-ui", ["fade", "fade"]],
 
  ["light9-calibrate", ["calibrate", "calibrate"]],
 
]);
 

	
 
export function panelElementNames(): string[] {
 
  return Array.from(panels.keys());
 
}
 

	
 
export function panelUrl(elem: string): string {
 
    const row = panels.get(elem);
 
    if (!row) throw new Error("No panel: " + elem);
 
    return "/" + row[1] + "/";
 
  }
 

	
 
export function panelDisplayName(elem: string): string {
 
    const row = panels.get(elem);
 
    if (!row) throw new Error("No panel: " + elem);
 
    return row[0];
 
}  
 
\ No newline at end of file
0 comments (0 inline, 0 general)