remote-calibrator 0.3.0-rc.3 → 0.5.0-beta.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. package/CHANGELOG.md +35 -3
  2. package/README.md +34 -49
  3. package/homepage/example.css +4 -3
  4. package/homepage/example.js +42 -22
  5. package/homepage/index.html +19 -4
  6. package/i18n/fetch-languages-sheets.js +11 -1
  7. package/lib/RemoteCalibrator.min.js +1 -1
  8. package/lib/RemoteCalibrator.min.js.LICENSE.txt +19 -2
  9. package/lib/RemoteCalibrator.min.js.map +1 -1
  10. package/netlify.toml +1 -1
  11. package/package.json +25 -24
  12. package/src/WebGazer4RC/package-lock.json +198 -143
  13. package/src/WebGazer4RC/package.json +2 -2
  14. package/src/WebGazer4RC/src/index.mjs +161 -52
  15. package/src/WebGazer4RC/test/webgazer_test.js +1 -1
  16. package/src/check/checkScreenSize.js +84 -0
  17. package/src/components/buttons.js +21 -4
  18. package/src/components/input.js +82 -0
  19. package/src/components/keyBinder.js +5 -6
  20. package/src/components/language.js +5 -0
  21. package/src/components/mediaPermission.js +21 -0
  22. package/src/components/onCanvas.js +2 -2
  23. package/src/components/sound.js +30 -2
  24. package/src/components/swalOptions.js +6 -3
  25. package/src/components/utils.js +27 -1
  26. package/src/components/video.js +9 -6
  27. package/src/const.js +15 -0
  28. package/src/core.js +103 -48
  29. package/src/css/buttons.scss +34 -7
  30. package/src/css/components.scss +57 -0
  31. package/src/css/distance.scss +71 -1
  32. package/src/css/gaze.css +9 -5
  33. package/src/css/main.css +22 -6
  34. package/src/css/panel.scss +33 -3
  35. package/src/css/screenSize.css +6 -5
  36. package/src/css/swal.css +1 -1
  37. package/src/css/video.scss +19 -0
  38. package/src/distance/distance.js +194 -41
  39. package/src/distance/distanceCheck.js +241 -0
  40. package/src/distance/distanceTrack.js +165 -68
  41. package/src/{interpupillaryDistance.js → distance/interPupillaryDistance.js} +27 -19
  42. package/src/gaze/gaze.js +4 -7
  43. package/src/gaze/gazeAccuracy.js +9 -4
  44. package/src/gaze/gazeCalibration.js +14 -4
  45. package/src/gaze/gazeTracker.js +40 -9
  46. package/src/i18n.js +1 -1
  47. package/src/index.js +7 -2
  48. package/src/media/two-side-arrow.svg +1 -0
  49. package/src/media/two-sided-horizontal.svg +1 -0
  50. package/src/media/two-sided-vertical.svg +3 -0
  51. package/src/panel.js +130 -65
  52. package/src/screenSize.js +38 -5
  53. package/webpack.config.js +7 -4
  54. package/media/measureDistance.png +0 -0
  55. package/media/panel.png +0 -0
  56. package/media/screenSize.png +0 -0
  57. package/media/trackGaze.png +0 -0
  58. package/src/displaySize.js +0 -28
package/CHANGELOG.md CHANGED
@@ -9,11 +9,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ### Added
11
11
 
12
+ - Latency for gaze and viewing distance tracking. The latency is calculated by comparing the timestamps of the moment when the video stream is fed into the model for estimation and when the result is produced and recorded. You can access it by `data.value.latencyMs` where `data` is the argument passed into the callback function of `.trackGaze()` and `.trackDistance`.
13
+ - Viewing distance monitoring. Three new options for `.trackDistance()` are added: `desiredDistanceCm` (default undefined), `desiredDistanceTolerance` (default 0.1), and `desiredDistanceMonitor` (default false). If a number is given for `desiredDistanceCm`, the program will check the viewing distance and call for "Move CLOSER." or "Move FURTHER." to the participants, until the participant moved to the desired distance and the experiment will resume. Setting `desiredDistanceMonitor` to true will repeat this process through the rest of the experiment.
14
+ - `debug` and `i18n` options of `.panel()`. When set to `true`, The first one adds some useful options, e.g., to skip calibration, for you to use when debugging. The second one adds a language picker for participants to choose their own languages (the default choice is always the one set on initiation).
15
+ - Update near point tracking to be more accurate. The webcam is assumed to be at the top middle of the screen.
16
+ - "Redo last response" button for the blind spot test.
17
+ - Measurement repeatability check for the blind spot test. The data will be accepted only if the right eye measurement and the left eye measurement are close enough, i.e. their averages disagree by less than 20%. If not, the measurement will repeat until the averages agree with each other. After that, the median of all measures will be chosen as the final result.
18
+ - The raw data of the blind spot test is also saved now, the new data structure is `{ value, timestamp, method, raw }`. The raw data is an array of all kept measures (a measure is deleted after the participant chose to redo the last response).
19
+
20
+ ### Changed
21
+
22
+ - Rename "Head Tracking" to "Distance Tracking" globally.
23
+ - Polish translations.
24
+ - Elements, like `.calibration-background`, have a higher `z-index` to avoid being covered by external elements.
25
+
26
+ ## [0.3.0] - 2021-10-16
27
+
28
+ ### Added
29
+
12
30
  **i18n!**
13
31
 
14
32
  - Internationalization! A full list of supported languages can be found at https://docs.google.com/spreadsheets/d/1UFfNikfLuo8bSromE34uWDuJrMPFiJG3VpoQKdCGkII/edit#gid=0.
15
33
  - A few new getters related to languages:
16
- - `.userLanguage` (as a part of `.environment()`)
34
+ - `.userLanguage`
17
35
  - `.language` (e.g., `en-US`, `zh-CN`)
18
36
  - `.languageNameEnglish` (e.g., `English`, `Chinese (Simplified)`)
19
37
  - `.languageNameNative` (e.g., `简体中文`)
@@ -24,17 +42,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
24
42
  - `.newLanguage(lang = 'en-US')` to set a new language for the calibrator.
25
43
  - Allows researchers to set language on initialization using the `language` option. Set to `AUTO` (default) will let the calibrator go with the user language.
26
44
  - `.isMobile` getter.
27
- - Call `.environment()` automatically when initializing the calibrator.
45
+ - Call `._environment()` and `._displaySize()` automatically when initializing the calibrator.
28
46
  - Instructions in the viewing distance measurement (and head tracking setup) is scrollable to avoid overlapping with the canvas on small screen sizes.
29
47
  - Automatically minimize the mobile address bar when a calibration task starts.
48
+ - Safer type check for callback functions to avoid fatal errors.
49
+ - Version console log on loading.
30
50
 
31
51
  ### Changed
32
52
 
33
53
  - Improved UI and performance for small screens and mobile devices.
34
54
  - Take Return instead of Space for confirming screen size measurement.
55
+ - (Breaking) `.fullScreenData` getter is changed to `.fullscreenData`.
56
+ - Viewing distance methods become `BlindSpot` or `FaceMesh`.
57
+
58
+ ### Fixed
59
+
60
+ - Participants can now continue (restart) calibration tasks after quitting at the middle of the last one.
61
+ - Various fixes and updates for the panel.
62
+ - Gaze and head trackers stop working on Safari when the video preview is turned off. (#49)
63
+ - Fatal error due to cannot detect devices for VR headsets.
64
+ - Remove wrongly labelled camera icon for measuring viewing distance task in the panel.
35
65
 
36
66
  ### Removed
37
67
 
68
+ - (Breaking) `.environment()` and `.displaySize()`. Values can be accessed directly throw the getters.
38
69
  - The responsive arrow in the screen size calibration with credit card.
39
70
 
40
71
  ## [0.2.3] - 2021-10-05
@@ -244,7 +275,8 @@ No new feature updates in this release. Updated dependency packages and the lice
244
275
 
245
276
  The framework and some basic functions, e.g., screen size calibration. Released for integration testing.
246
277
 
247
- [unreleased]: https://github.com/EasyEyes/remote-calibrator/compare/v0.2.3...develop
278
+ [unreleased]: https://github.com/EasyEyes/remote-calibrator/compare/v0.3.0...develop
279
+ [0.3.0]: https://github.com/EasyEyes/remote-calibrator/compare/v0.2.3...v0.3.0
248
280
  [0.2.3]: https://github.com/EasyEyes/remote-calibrator/compare/v0.2.2...v0.2.3
249
281
  [0.2.2]: https://github.com/EasyEyes/remote-calibrator/compare/v0.2.1...v0.2.2
250
282
  [0.2.1]: https://github.com/EasyEyes/remote-calibrator/compare/v0.2.0...v0.2.1
package/README.md CHANGED
@@ -10,8 +10,6 @@
10
10
 
11
11
  Welcome to Remote Calibrator! This package contains several useful tools to calibrate and track for the remote psychophysics experiments, e.g., crowd-sourced through Amazon Mechanical Turk.
12
12
 
13
- The features/functions marked with 🚧 are still work-in-progress and not available yet.
14
-
15
13
  ## Demo
16
14
 
17
15
  Please visit https://calibrator.app for the demo. More information can be found at https://easyeyes.app/remote-calibrator/.
@@ -47,18 +45,18 @@ RemoteCalibrator.measureDistance({}, data => {
47
45
 
48
46
  ## Functions
49
47
 
50
- | Task | Functions |
51
- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
52
- | [🎬 Initialize](#-initialize) | [`init()`](#-initialize) (always required) |
53
- | [🍱 Panel](#-panel) | [`async panel()`](#-panel) `removePanel()` `resetPanel()` |
54
- | [🖥️ Screen](#️-screen) | [`displaySize()`](#measure-display-pixels) [`screenSize()`](#measure-screen-size) |
55
- | [📏 Viewing Distance](#-viewing-distance) | [`measureDistance()`](#-viewing-distance) |
56
- | [🙂 Head Tracking](#-head-tracking) | (viewing distance and [near point](#near-point)) [`trackDistance()`](#-head-tracking) [`async getDistanceNow()`](#async-get-distance-now) [Lifecycle](#lifecycle) [Others](#others) |
57
- | [👀 Gaze](#-gaze) | [`trackGaze()`](#start-tracking) [`async getGazeNow()`](#async-get-gaze-now) [`calibrateGaze()`](#calibrate) [`getGazeAccuracy()`](#get-accuracy-) [Lifecycle](#lifecycle-1) [Others](#others-1) |
58
- | [💻 Environment](#-environment) | [`environment()`](#-environment) |
59
- | [💄 Customization](#-customization) | `backgroundColor()` `videoOpacity()` `showCancelButton()` |
60
- | [📔 Other Functions](#-other-functions) | `checkInitialized()` `getFullscreen()` `newLanguage()` |
61
- | [🎣 Getters](#-getters) | [Experiment](#experiment) [Environment](#environment) [i18n](#i18n) [All Data](#all-data) [Others](#others-2) |
48
+ | Task | Functions |
49
+ | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
50
+ | [🎬 Initialize](#-initialize) | [`init()`](#-initialize) (always required) |
51
+ | [🍱 Panel](#-panel) | [`async panel()`](#-panel) `removePanel()` `resetPanel()` |
52
+ | [🖥️ Screen](#️-screen) | [Display Pixel Dimensions](#measure-display-pixels) [`screenSize()`](#measure-screen-size) |
53
+ | [📏 Viewing Distance](#-viewing-distance) | [`measureDistance()`](#-viewing-distance) |
54
+ | [🙂 Distance Tracking](#-distance-tracking) | (viewing distance and [near point](#near-point)) [`trackDistance()`](#-distance-tracking) [`async getDistanceNow()`](#async-get-distance-now) [`checkDistance()`](#check-distance) [Lifecycle](#lifecycle) [Others](#others) |
55
+ | [👀 Gaze](#-gaze) | [`trackGaze()`](#start-tracking) [`async getGazeNow()`](#async-get-gaze-now) [`calibrateGaze()`](#calibrate) [`getGazeAccuracy()`](#get-accuracy-) [Lifecycle](#lifecycle-1) [Others](#others-1) |
56
+ | [💻 Environment](#-environment) | [System and Browser Environment](#-environment) |
57
+ | [💄 Customization](#-customization) | `backgroundColor()` `videoOpacity()` `showCancelButton()` |
58
+ | [📔 Other Functions](#-other-functions) | `checkInitialized()` `getFullscreen()` `newLanguage()` |
59
+ | [🎣 Getters](#-getters) | [Experiment](#experiment) [Environment](#environment) [i18n](#i18n) [All Data](#all-data) [Others](#others-2) |
62
60
 
63
61
  Arguments in square brackets are optional, e.g. `init([options, [callback]])` means both `options` configuration and the `callback` function are optional, but you have to put `options`, e.g., `{}`, if you want to call the callback function. The default values of `options` are listed in each section with explanation.
64
62
 
@@ -118,15 +116,13 @@ The `data` passed into the callback function is an [object](https://www.w3school
118
116
 
119
117
  ### 🍱 Panel
120
118
 
121
- ![Panel](./media/panel.png)
122
-
123
119
  ```js
124
120
  /* async */ .panel(tasks, parentQuery, [options, [callback, [resolveOnFinish]]])
125
121
  ```
126
122
 
127
123
  `.panel()` is a powerful tool to help you set up a graphical user interface for participants to go through step-by-step and calibrate or set up tracking. It is highly customizable: tasks, task order, title, description, and "Done" button can all be customized. It is appended to the parent HTML node as set by `parentQuery`, e.g., if the parent node has id `main-area`, put `#main-area` as the `parentQuery`. Can only run once. Return a JavaScript [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) that will resolve the `resolveOnFinish` once the "Done" button is pressed.
128
124
 
129
- `tasks` is an array of tasks which can be a string or an object. Valid names are `screenSize`, `displaySize`, `measureDistance`, `trackDistance`, `trackGaze`, `environment` (system information).
125
+ `tasks` is an array of tasks which can be a string or an object. Valid names are `screenSize`, `measureDistance`, `trackDistance`, `trackGaze`.
130
126
 
131
127
  <!-- prettier-ignore -->
132
128
  ```js
@@ -174,18 +170,10 @@ You can also use `.removePanel()` to remove the panel element after the calibrat
174
170
 
175
171
  #### Measure Display Pixels
176
172
 
177
- ```js
178
- .displaySize([callback])
179
- ```
180
-
181
- Get the display width and height in pixels. This is just a wrapper of vanilla JavaScript's `window.innerWidth`, `window.screenWidth`, etc.
182
-
183
- Pass `{ value: { displayWidthPx, displayHeightPx, windowWidthPx, windowHeightPx }, timestamp }` to callback.
173
+ Get the display width and height in pixels. You can use `.displayWidthPx` `.displayHeightPx` `.windowWidthPx` `.windowHeightPx` getters. For example, `RemoteCalibrator.windowWidthPx.value` will give you the inner width of the current browser window.
184
174
 
185
175
  #### Measure Screen Size
186
176
 
187
- ![Screen Size](./media/screenSize.png)
188
-
189
177
  ```js
190
178
  .screenSize([options, [callback]])
191
179
  ```
@@ -200,8 +188,6 @@ Pass `{ value: { screenWidthCm, screenHeightCm, screenDiagonalCm, screenDiagonal
200
188
  // Enter fullscreen if set to true
201
189
  // Will be ignored if already in fullscreen mode
202
190
  fullscreen: false,
203
- // Quit fullscreen when calibration finished
204
- quitFullscreenOnFinished: false, 🚧
205
191
  // How many times the participant needs to calibrate
206
192
  repeatTesting: 1,
207
193
  // The length of decimal place of the returned value
@@ -219,8 +205,6 @@ Pass `{ value: { screenWidthCm, screenHeightCm, screenDiagonalCm, screenDiagonal
219
205
 
220
206
  #### Measure
221
207
 
222
- ![Measure Viewing Distance](./media/measureDistance.png)
223
-
224
208
  ```js
225
209
  .measureDistance([options, [callback]])
226
210
  ```
@@ -233,7 +217,6 @@ Pass `{ value, timestamp, method }` (equivalent to `RemoteCalibrator.viewingDist
233
217
  /* [options] Default value */
234
218
  {
235
219
  fullscreen: false,
236
- quitFullscreenOnFinished: false, 🚧
237
220
  // How many times each of the eye will be used to test
238
221
  // By default, right eye 2 times, then left eye 2 times
239
222
  repeatTesting: 2,
@@ -243,17 +226,17 @@ Pass `{ value, timestamp, method }` (equivalent to `RemoteCalibrator.viewingDist
243
226
  }
244
227
  ```
245
228
 
246
- ### 🙂 Head Tracking
229
+ ### 🙂 Distance Tracking
247
230
 
248
231
  ```js
249
232
  .trackDistance([options, [callbackStatic, [callbackTrack]]])
250
233
  ```
251
234
 
252
- Measure the viewing distance and then predict the real-time distance based on the change of the interpupillary distance, measured by [face landmarks](https://github.com/tensorflow/tfjs-models/tree/master/face-landmarks-detection). `callbackStatic` is called after getting the blind spot result and `callbackTrack` is called every time a new result from estimation is derived.
235
+ Measure the viewing distance and then predict the real-time distance based on the change of the inter-pupillary distance, measured by [face landmarks](https://github.com/tensorflow/tfjs-models/tree/master/face-landmarks-detection). `callbackStatic` is called after getting the blind spot result and `callbackTrack` is called every time a new result from estimation is derived.
253
236
 
254
- Pass `{ value: { viewingDistanceCm, nearPointCm: { x, y } }, timestamp, method }` to callback.
237
+ Pass `{ value: { viewingDistanceCm, nearPointCm: { x, y }, latencyMs }, timestamp, method }` to callback.
255
238
 
256
- `method` can be either `"Blind Spot"` (for measures from blind spot tests) or `"Facemesh Predict"` (for later dynamic estimates).
239
+ `method` can be either `"BlindSpot"` (for measures from blind spot tests) or `"FaceMesh"` (for later dynamic estimates).
257
240
 
258
241
  ```js
259
242
  /* [options] Default value */
@@ -264,12 +247,14 @@ Pass `{ value: { viewingDistanceCm, nearPointCm: { x, y } }, timestamp, method }
264
247
  showVideo: true,
265
248
  showFaceOverlay: false,
266
249
  decimalPlace: 1,
267
- // Measurement per second
268
- framerate: 3,
250
+ framerate: 3, // Measurement per second
251
+ desiredDistanceCm: undefined,
252
+ desiredDistanceTolerance: 0.1, // Range [0.1, 1]
253
+ desiredDistanceMonitor: false,
269
254
  // Near point
270
255
  nearPoint: true,
271
256
  showNearPoint: false,
272
- headline: "🙂 Set up for Head Tracking",
257
+ headline: "🙂 Set up for Distance Tracking",
273
258
  description: "...",
274
259
  }
275
260
  ```
@@ -282,6 +267,14 @@ Pass `{ value: { viewingDistanceCm, nearPointCm: { x, y } }, timestamp, method }
282
267
 
283
268
  You can pause active distance tracking, and use this function to get the latest distance at the moment when the user makes reactions. If no callback function is passed in, it will use the one from `.trackDistance()` as the default.
284
269
 
270
+ #### Check Distance
271
+
272
+ ```js
273
+ .checkDistance(desiredCm, errorTolerance)
274
+ ```
275
+
276
+ Check the current viewing distance and compare it to the desired distance. Guide the participant to the target distance if needed.
277
+
285
278
  #### Near Point
286
279
 
287
280
  The observer's near point is the orthogonal nearest viewing point in the screen, or the plane containing the screen. To track the near point, we assume that the webcam view is orthogonal to the display, and it is placed around 0.5cm above the top center of the screen (e.g., the built-in webcam of a MacBook). Our method is based on the Facemesh model and can give you an approximate estimation of the near point.
@@ -304,8 +297,6 @@ The value returned are the horizontal and vertical offsets, in centimeters, comp
304
297
 
305
298
  #### Start Tracking
306
299
 
307
- ![Start Gaze Tracking](./media/trackGaze.png)
308
-
309
300
  ```js
310
301
  .trackGaze([options, [callbackOnCalibrationEnd, [callbackTrack]]])
311
302
  ```
@@ -392,13 +383,7 @@ Pop an interface for participants to calibrate their gaze position on the screen
392
383
 
393
384
  ### 💻 Environment
394
385
 
395
- ```js
396
- .environment([callback])
397
- ```
398
-
399
- Get the setup information of the experiment, including browser type, device model, operating system family and version, etc. This function does not create its own timestamp, but use the one associated with `id`, i.e. the one created when `init()` is called.
400
-
401
- Pass `{ value: { browser, browserVersion, model, manufacturer, engine, system, systemFamily, description, fullDescription, userLanguage }, timestamp }` to callback.
386
+ Get the setup information of the experiment, including browser type, device model, operating system family and version, etc. See the Getters section for more details.
402
387
 
403
388
  ### 💄 Customization
404
389
 
@@ -463,9 +448,9 @@ Use the following keywords to retrieve the whole dataset.
463
448
  - `.screenData`
464
449
  - `.viewingDistanceData`
465
450
  - `.nearPointData`
466
- - `.PDData` (Interpupillary distance data)
451
+ - `.PDData` (Inter-pupillary distance data)
467
452
  - `.gazeData`
468
- - `.fullScreenData`
453
+ - `.fullscreenData`
469
454
  - `.environmentData`
470
455
  - `.languageData`
471
456
 
@@ -42,6 +42,7 @@ body {
42
42
  border: 1px solid #ccc;
43
43
  border-radius: 7px;
44
44
  transition: opacity 600ms;
45
+ overflow-wrap: break-word;
45
46
  }
46
47
 
47
48
  #toolbox *,
@@ -109,9 +110,9 @@ code {
109
110
  display: block;
110
111
  }
111
112
 
112
- /* .getters button {
113
- flex: 0 1 auto;
114
- } */
113
+ .getters {
114
+ margin-bottom: 1rem;
115
+ }
115
116
 
116
117
  .disabled {
117
118
  opacity: 0.5;
@@ -35,6 +35,7 @@ function printMessage(message) {
35
35
  p.innerHTML = 'No data can be found. Need measurement or calibration first.'
36
36
  else p.innerHTML = gotData(message)
37
37
  experimentElement.appendChild(p)
38
+ experimentElement.scrollTop = experimentElement.scrollHeight
38
39
  return p
39
40
  }
40
41
 
@@ -99,21 +100,33 @@ function makePanel(e) {
99
100
  [
100
101
  {
101
102
  name: 'screenSize',
103
+ callback: data => {
104
+ printMessage(
105
+ `[CALLBACK] Screen size calibration finished! This message is printed in the callback function. Only this task's callback is set up with a print function.`
106
+ )
107
+ },
102
108
  },
103
109
  {
104
110
  name: 'trackGaze',
111
+ callbackOnCalibrationEnd: data => {
112
+ console.log(data)
113
+ },
105
114
  },
115
+ 'measureDistance',
106
116
  {
107
117
  name: 'trackDistance',
108
118
  options: {
109
119
  nearPoint: false,
110
120
  },
121
+ callbackStatic: data => {
122
+ console.log(data)
123
+ },
111
124
  },
112
125
  ],
113
126
  '#experiment',
114
127
  {},
115
- () => {
116
- printMessage('Panel finished!')
128
+ data => {
129
+ printMessage(`Panel finished at ${parseTimestamp(data.timestamp)}!`)
117
130
  }
118
131
  )
119
132
  changeClass(e.target, 'complete')
@@ -124,17 +137,17 @@ function makePanel(e) {
124
137
  * Measure the display size
125
138
  *
126
139
  */
127
- function measureDisplaySize(e) {
128
- RemoteCalibrator.displaySize(displayData => {
129
- printMessage(
130
- `Display size is ${displayData.value.displayWidthPx} px in width and ${
131
- displayData.value.displayHeightPx
132
- } px in height, measured at ${parseTimestamp(displayData.timestamp)}.`
133
- )
134
-
135
- changeClass(e.target, 'complete')
136
- })
137
- }
140
+ // function measureDisplaySize(e) {
141
+ // RemoteCalibrator.displaySize(displayData => {
142
+ // printMessage(
143
+ // `Display size is ${displayData.value.displayWidthPx} px in width and ${
144
+ // displayData.value.displayHeightPx
145
+ // } px in height, measured at ${parseTimestamp(displayData.timestamp)}.`
146
+ // )
147
+
148
+ // changeClass(e.target, 'complete')
149
+ // })
150
+ // }
138
151
 
139
152
  /**
140
153
  *
@@ -189,9 +202,12 @@ function trackViewingDistance(e) {
189
202
  let trackP
190
203
  RemoteCalibrator.trackDistance(
191
204
  {
192
- showVideo: false,
205
+ showVideo: true,
193
206
  nearPoint: true,
194
207
  showNearPoint: true,
208
+ desiredDistanceCm: 60,
209
+ desiredDistanceMonitor: true,
210
+ desiredDistanceMonitorCancelable: false,
195
211
  },
196
212
  distanceData => {
197
213
  measureDistanceCallback(distanceData)
@@ -206,7 +222,9 @@ function trackViewingDistance(e) {
206
222
  data.method
207
223
  } method. The near point is at [${data.value.nearPointCm.x} cm, ${
208
224
  data.value.nearPointCm.y
209
- } cm] compared to the center of the screen.`
225
+ } cm] compared to the center of the screen. Latency is ${
226
+ data.value.latencyMs
227
+ } ms.`
210
228
  )
211
229
  }
212
230
  )
@@ -304,7 +322,9 @@ function trackGaze(e) {
304
322
  gazeP.innerHTML = gotData(
305
323
  `The gaze position is [${data.value.x} px, ${
306
324
  data.value.y
307
- } px] at ${parseTimestamp(data.timestamp)}.`
325
+ } px] at ${parseTimestamp(data.timestamp)}. Latency is ${
326
+ data.value.latencyMs
327
+ } ms.`
308
328
  )
309
329
  }
310
330
  )
@@ -398,10 +418,10 @@ function getGazeNow() {
398
418
  * Get environment info
399
419
  *
400
420
  */
401
- function getEnvironment(e) {
402
- RemoteCalibrator.environment(data => {
403
- printMessage('Environment: ' + data.value.description + '.')
421
+ // function getEnvironment(e) {
422
+ // RemoteCalibrator.environment(data => {
423
+ // printMessage('Environment: ' + data.value.description + '.')
404
424
 
405
- changeClass(e.target, 'complete')
406
- })
407
- }
425
+ // changeClass(e.target, 'complete')
426
+ // })
427
+ // }
@@ -61,6 +61,7 @@
61
61
 
62
62
  <div id="getters-exp" class="getters flex-wrapper"></div>
63
63
  <div id="getters-env" class="getters flex-wrapper"></div>
64
+ <div id="getters-data" class="getters flex-wrapper"></div>
64
65
  </div>
65
66
 
66
67
  <div id="experiment"></div>
@@ -93,7 +94,7 @@
93
94
  // [name, actual function name, function name used in this demo]
94
95
  ['Initialize', 'init', 'initialize'],
95
96
  ['Make a Panel', 'panel', 'makePanel'],
96
- ['Measure Display Pixels Px', 'displaySize', 'measureDisplaySize'],
97
+ // ['Measure Display Pixels Px', 'displaySize', 'measureDisplaySize'],
97
98
  ['Measure Screen Size Cm', 'screenSize', 'measureScreenSize'],
98
99
  [
99
100
  'Measure Viewing Distance',
@@ -107,7 +108,7 @@
107
108
  ],
108
109
  ['Track Gaze', 'trackGaze', 'trackGaze'],
109
110
  // Environment
110
- ['Get Environment', 'environment', 'getEnvironment'],
111
+ // ['Get Environment', 'environment', 'getEnvironment'],
111
112
  ]
112
113
 
113
114
  const functionsElement = document.getElementById('functions')
@@ -116,6 +117,7 @@
116
117
  })
117
118
 
118
119
  const gettersExp = [
120
+ 'id',
119
121
  'displayWidthPx',
120
122
  'displayHeightPx',
121
123
  'windowWidthPx',
@@ -130,7 +132,6 @@
130
132
  'nearPointCm',
131
133
  'gazePositionPx',
132
134
  'isFullscreen',
133
- 'id',
134
135
  'language',
135
136
  'languageNameEnglish',
136
137
  'languageNameNative',
@@ -154,16 +155,29 @@
154
155
  'version',
155
156
  ]
156
157
 
158
+ const gettersData = [
159
+ 'displayData',
160
+ 'screenData',
161
+ 'viewingDistanceData',
162
+ 'nearPointData',
163
+ 'PDData',
164
+ 'gazeData',
165
+ 'fullscreenData',
166
+ 'environmentData',
167
+ 'languageData',
168
+ ]
169
+
157
170
  function setGetters(gE, gS) {
158
171
  gS.forEach(getter => {
159
172
  let b = document.createElement('button')
160
173
  b.className = 'disabled'
161
- b.onclick = () =>
174
+ b.onclick = () => {
162
175
  printMessage(
163
176
  RemoteCalibrator[getter]
164
177
  ? `<code>${JSON.stringify(RemoteCalibrator[getter])}</code>`
165
178
  : 'nodata'
166
179
  )
180
+ }
167
181
  b.innerHTML = `<code>.${getter}</code>`
168
182
  gE.appendChild(b)
169
183
  })
@@ -171,6 +185,7 @@
171
185
 
172
186
  setGetters(document.getElementById('getters-exp'), gettersExp)
173
187
  setGetters(document.getElementById('getters-env'), gettersEnv)
188
+ setGetters(document.getElementById('getters-data'), gettersData)
174
189
 
175
190
  // i18n
176
191
  const langPickerParent = document.getElementById('rc-language')
@@ -14,7 +14,7 @@ async function processLanguageSheet() {
14
14
  const rows = await googleSheets.spreadsheets.values.get({
15
15
  auth,
16
16
  spreadsheetId,
17
- range: 'Sheet1',
17
+ range: 'Translations',
18
18
  })
19
19
 
20
20
  const rowsJSON = XLSX.utils.sheet_to_json(
@@ -31,6 +31,16 @@ async function processLanguageSheet() {
31
31
  data[language] = translations
32
32
  }
33
33
 
34
+ for (let phrase in data) {
35
+ for (let lang in data[phrase]) {
36
+ if (data[phrase][lang].includes('XX'))
37
+ while (data[phrase][lang].includes('XX'))
38
+ data[phrase][lang] = data[phrase][lang]
39
+ .replace('XXX', 'xxx')
40
+ .replace('XX', 'xx')
41
+ }
42
+ }
43
+
34
44
  const exportWarning = `/*
35
45
  Do not modify this file! Run npm \`npm run phrases\` at ROOT of this project to fetch from the Google Sheets.
36
46
  https://docs.google.com/spreadsheets/d/1UFfNikfLuo8bSromE34uWDuJrMPFiJG3VpoQKdCGkII/edit#gid=0