@decidables/detectable-elements 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decidables/detectable-elements",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "detectable-elements: Web Components for visualizing Signal Detection Theory",
5
5
  "keywords": [
6
6
  "web component",
@@ -56,11 +56,11 @@
56
56
  "gulp": "^4.0.2"
57
57
  },
58
58
  "dependencies": {
59
- "@decidables/decidables-elements": "^0.3.0",
59
+ "@decidables/decidables-elements": "^0.3.1",
60
60
  "@decidables/detectable-math": "^0.1.1",
61
61
  "d3": "^7.3.0",
62
62
  "jstat": "^1.9.5",
63
63
  "lit": "^2.2.1"
64
64
  },
65
- "gitHead": "6cb4f73701fe96a9344ae979a1a8d6782e7bc94d"
65
+ "gitHead": "0afa544a1711ac1d34594934ab6c03064481810f"
66
66
  }
@@ -81,7 +81,7 @@ export default class DetectableControl extends DetectableElement {
81
81
  this.duration = undefined;
82
82
  this.coherence = undefined;
83
83
  this.payoff = undefined;
84
- this.colors = ['none', 'accuracy', 'stimulus', 'response', 'outcome'];
84
+ this.colors = ['none', 'accuracy', 'stimulus', 'response', 'outcome', 'all'];
85
85
  this.color = undefined;
86
86
  this.zRoc = undefined;
87
87
  this.run = false;
@@ -239,6 +239,7 @@ export default class DetectableControl extends DetectableElement {
239
239
  <decidables-toggle-option name="toggle" value="stimulus" ?checked=${this.color === 'stimulus'}>Stimulus</decidables-toggle-option>
240
240
  <decidables-toggle-option name="toggle" value="response" ?checked=${this.color === 'response'}>Response</decidables-toggle-option>
241
241
  <decidables-toggle-option name="toggle" value="outcome" ?checked=${this.color === 'outcome'}>Outcome</decidables-toggle-option>
242
+ <decidables-toggle-option name="toggle" value="all" ?checked=${this.color === 'all'}>All</decidables-toggle-option>
242
243
  </decidables-toggle>
243
244
  `
244
245
  : html``}
@@ -302,6 +302,11 @@ export default class DetectableResponse extends DetectableElement {
302
302
  border: 1px solid var(---color-element-border);
303
303
  }
304
304
 
305
+ :host([payoff="trial"]) .feedback,
306
+ :host([payoff="total"]) .feedback {
307
+ height: 5rem;
308
+ }
309
+
305
310
  .feedback.h {
306
311
  background-color: var(---color-h-light);
307
312
  }
@@ -337,17 +342,12 @@ export default class DetectableResponse extends DetectableElement {
337
342
  line-height: 1.15;
338
343
  }
339
344
 
340
- :host([payoff="trial"]) .feedback,
341
- :host([payoff="total"]) .feedback {
342
- height: 4rem;
343
- }
344
-
345
345
  /* Payoff feedback */
346
- .payoff {
346
+ .total {
347
347
  text-align: center;
348
348
  }
349
349
 
350
- .payoff .label {
350
+ .total .label {
351
351
  font-weight: 600;
352
352
  }
353
353
  `,
@@ -355,6 +355,21 @@ export default class DetectableResponse extends DetectableElement {
355
355
  }
356
356
 
357
357
  render() {
358
+ const payoffFormatter = new Intl.NumberFormat('en-US', {
359
+ style: 'currency',
360
+ currency: 'USD',
361
+ minimumFractionDigits: 0,
362
+ maximumFractionDigits: 0,
363
+ });
364
+ const payoffFormat = (number) => {
365
+ return payoffFormatter.formatToParts(number).map(({type, value}) => {
366
+ if (type === 'minusSign') {
367
+ return '−';
368
+ }
369
+ return value;
370
+ }).reduce((string, part) => { return string + part; });
371
+ };
372
+
358
373
  return html`
359
374
  <div class="holder">
360
375
  <div class="responses">
@@ -394,15 +409,15 @@ export default class DetectableResponse extends DetectableElement {
394
409
  ? html`<span class="outcome">Error</span>`
395
410
  : html`<span class="outcome">No<br>Response</span>`
396
411
  : ''}
397
- ${(this.payoff === 'trial' || this.payoff === 'total')
398
- ? html`<span class="payoff">${this.trialPayoff}</span>`
412
+ ${((this.state === 'feedback') && (this.payoff === 'trial' || this.payoff === 'total'))
413
+ ? html`<span class="payoff">${payoffFormat(this.trialPayoff)}</span>`
399
414
  : html``}
400
415
  </div>`
401
416
  : html``}
402
417
  ${(this.payoff === 'total')
403
418
  ? html`
404
- <div class="payoff">
405
- <span class="label">Total: </span><span class="value">${this.totalPayoff}</span>
419
+ <div class="total">
420
+ <span class="label">Total: </span><span class="value">${payoffFormat(this.totalPayoff)}</span>
406
421
  </div>`
407
422
  : html``}
408
423
  </div>`
@@ -118,8 +118,8 @@ export default class DetectableTable extends DetectableElement {
118
118
  this.summaries = ['stimulusRates', 'responseRates', 'accuracy'];
119
119
  this.summary = new Set();
120
120
 
121
- this.colors = ['none', 'accuracy', 'stimulus', 'response', 'outcome'];
122
- this.color = 'outcome';
121
+ this.colors = ['none', 'accuracy', 'stimulus', 'response', 'outcome', 'all'];
122
+ this.color = 'all';
123
123
 
124
124
  this.h = 40;
125
125
  this.m = 60;
@@ -318,7 +318,7 @@ export default class DetectableTable extends DetectableElement {
318
318
 
319
319
  /* Color schemes & Table emphasis */
320
320
 
321
- /* (Default) Outcome color scheme */
321
+ /* (Default) All color scheme */
322
322
  .h {
323
323
  background: var(---color-h-light);
324
324
  border-top: 2px solid var(---color-element-emphasis);
@@ -417,6 +417,15 @@ export default class DetectableTable extends DetectableElement {
417
417
  background: var(---color-element-background);
418
418
  }
419
419
 
420
+ /* Outcome color scheme */
421
+ :host([color="outcome"]) .hr,
422
+ :host([color="outcome"]) .far,
423
+ :host([color="outcome"]) .ppv,
424
+ :host([color="outcome"]) .fomr,
425
+ :host([color="outcome"]) .acc {
426
+ background: var(---color-element-background);
427
+ }
428
+
420
429
  /* No color scheme */
421
430
  :host([color="none"]) .cr,
422
431
  :host([color="none"]) .fa,
@@ -440,6 +449,14 @@ export default class DetectableTable extends DetectableElement {
440
449
  minimumFractionDigits: 0,
441
450
  maximumFractionDigits: 0,
442
451
  });
452
+ const payoffFormat = (number) => {
453
+ return payoffFormatter.formatToParts(number).map(({type, value}) => {
454
+ if (type === 'minusSign') {
455
+ return '−';
456
+ }
457
+ return value;
458
+ }).reduce((string, part) => { return string + part; });
459
+ };
443
460
 
444
461
  this.alignState();
445
462
  let h;
@@ -455,25 +472,25 @@ export default class DetectableTable extends DetectableElement {
455
472
  h = html`
456
473
  <decidables-spinner ?disabled=${!this.interactive} min="0" .value="${this.h}" @input=${this.hInput.bind(this)}>
457
474
  <span>Hits</span>
458
- ${this.payoff ? html`<span class="payoff">${payoffFormatter.format(this.hPayoff)}</span>` : html``}
475
+ ${this.payoff ? html`<span class="payoff">${payoffFormat(this.hPayoff)}</span>` : html``}
459
476
  </decidables-spinner>
460
477
  `;
461
478
  m = html`
462
479
  <decidables-spinner ?disabled=${!this.interactive} min="0" .value="${this.m}" @input=${this.mInput.bind(this)}>
463
480
  <span>Misses</span>
464
- ${this.payoff ? html`<span class="payoff">${payoffFormatter.format(this.mPayoff)}</span>` : html``}
481
+ ${this.payoff ? html`<span class="payoff">${payoffFormat(this.mPayoff)}</span>` : html``}
465
482
  </decidables-spinner>
466
483
  `;
467
484
  fa = html`
468
485
  <decidables-spinner ?disabled=${!this.interactive} min="0" .value="${this.fa}" @input=${this.faInput.bind(this)}>
469
486
  <span>False Alarms</span>
470
- ${this.payoff ? html`<span class="payoff">${payoffFormatter.format(this.faPayoff)}</span>` : html``}
487
+ ${this.payoff ? html`<span class="payoff">${payoffFormat(this.faPayoff)}</span>` : html``}
471
488
  </decidables-spinner>
472
489
  `;
473
490
  cr = html`
474
491
  <decidables-spinner ?disabled=${!this.interactive} min="0" .value="${this.cr}" @input=${this.crInput.bind(this)}>
475
492
  <span>Correct Rejections</span>
476
- ${this.payoff ? html`<span class="payoff">${payoffFormatter.format(this.crPayoff)}</span>` : html``}
493
+ ${this.payoff ? html`<span class="payoff">${payoffFormat(this.crPayoff)}</span>` : html``}
477
494
  </decidables-spinner>
478
495
  `;
479
496
  hr = html`
@@ -503,13 +520,13 @@ export default class DetectableTable extends DetectableElement {
503
520
  `;
504
521
  } else {
505
522
  h = html`<span>Hits</span>
506
- ${this.payoff ? html`<span class="payoff">${payoffFormatter.format(this.hPayoff)}</span>` : html``}`;
523
+ ${this.payoff ? html`<span class="payoff">${payoffFormat(this.hPayoff)}</span>` : html``}`;
507
524
  m = html`<span>Misses</span>
508
- ${this.payoff ? html`<span class="payoff">${payoffFormatter.format(this.mPayoff)}</span>` : html``}`;
525
+ ${this.payoff ? html`<span class="payoff">${payoffFormat(this.mPayoff)}</span>` : html``}`;
509
526
  fa = html`<span>False Alarms</span>
510
- ${this.payoff ? html`<span class="payoff">${payoffFormatter.format(this.faPayoff)}</span>` : html``}`;
527
+ ${this.payoff ? html`<span class="payoff">${payoffFormat(this.faPayoff)}</span>` : html``}`;
511
528
  cr = html`<span>Correct Rejections</span>
512
- ${this.payoff ? html`<span class="payoff">${payoffFormatter.format(this.crPayoff)}</span>` : html``}`;
529
+ ${this.payoff ? html`<span class="payoff">${payoffFormat(this.crPayoff)}</span>` : html``}`;
513
530
  hr = html`<span>Hit Rate</span>`;
514
531
  far = html`<span>False Alarm Rate</span>`;
515
532
  acc = html`<span>Accuracy</span>`;
@@ -188,7 +188,7 @@ export default class RDKTask extends DetectableElement {
188
188
  ];
189
189
  }
190
190
 
191
- render() { // eslint-disable-line class-methods-use-this
191
+ render() { /* eslint-disable-line class-methods-use-this */
192
192
  return html``;
193
193
  }
194
194
 
@@ -376,7 +376,7 @@ export default class ROCSpace extends DetectableElement {
376
376
  ];
377
377
  }
378
378
 
379
- render() { // eslint-disable-line class-methods-use-this
379
+ render() { /* eslint-disable-line class-methods-use-this */
380
380
  return html`
381
381
  ${DetectableElement.svgFilters}
382
382
  `;
@@ -473,7 +473,7 @@ export default class SDTModel extends DetectableElement {
473
473
  ];
474
474
  }
475
475
 
476
- render() { // eslint-disable-line class-methods-use-this
476
+ render() { /* eslint-disable-line class-methods-use-this */
477
477
  return html`
478
478
  ${DetectableElement.svgFilters}
479
479
  `;
@@ -643,7 +643,7 @@ export default class SDTModel extends DetectableElement {
643
643
  })
644
644
  .on('drag', (event, datum) => {
645
645
  this.drag = true;
646
- let muS = this.muS; // eslint-disable-line prefer-destructuring
646
+ let muS = this.muS; /* eslint-disable-line prefer-destructuring */
647
647
  if (this.interactive) {
648
648
  muS = xScale.invert(event.x);
649
649
  // Clamp Signal Curve to stay visible
@@ -653,7 +653,7 @@ export default class SDTModel extends DetectableElement {
653
653
  ? xScale.domain()[1]
654
654
  : muS;
655
655
  }
656
- let hS = this.hS; // eslint-disable-line prefer-destructuring
656
+ let hS = this.hS; /* eslint-disable-line prefer-destructuring */
657
657
  if (this.unequal) {
658
658
  hS = yScale.invert(event.y);
659
659
  // Clamp Signal Curve to stay visible
@@ -849,7 +849,7 @@ export default class SDTModel extends DetectableElement {
849
849
  .on('keydown', this.interactive
850
850
  ? (event) => {
851
851
  if (['ArrowRight', 'ArrowLeft'].includes(event.key)) {
852
- let muN = this.muN; // eslint-disable-line prefer-destructuring
852
+ let muN = this.muN; /* eslint-disable-line prefer-destructuring */
853
853
  switch (event.key) {
854
854
  case 'ArrowRight':
855
855
  muN += event.shiftKey ? 0.01 : 0.1;
@@ -1044,7 +1044,7 @@ export default class SDTModel extends DetectableElement {
1044
1044
  .on('keydown.sensitivity', this.interactive
1045
1045
  ? (event) => {
1046
1046
  if (['ArrowRight', 'ArrowLeft'].includes(event.key)) {
1047
- let muS = this.muS; // eslint-disable-line prefer-destructuring
1047
+ let muS = this.muS; /* eslint-disable-line prefer-destructuring */
1048
1048
  switch (event.key) {
1049
1049
  case 'ArrowRight':
1050
1050
  muS += event.shiftKey ? 0.01 : 0.1;
@@ -1072,7 +1072,7 @@ export default class SDTModel extends DetectableElement {
1072
1072
  .on('keydown.variance', this.unequal
1073
1073
  ? (event) => {
1074
1074
  if (['ArrowUp', 'ArrowDown'].includes(event.key)) {
1075
- let hS = this.hS; // eslint-disable-line prefer-destructuring
1075
+ let hS = this.hS; /* eslint-disable-line prefer-destructuring */
1076
1076
  switch (event.key) {
1077
1077
  case 'ArrowUp':
1078
1078
  hS += event.shiftKey ? 0.002 : 0.02;
@@ -1326,7 +1326,7 @@ export default class SDTModel extends DetectableElement {
1326
1326
  );
1327
1327
  return (time) => {
1328
1328
  element.d = interpolateD(time);
1329
- d3.select(element).text(+(element.d).toFixed(3));
1329
+ d3.select(element).text(d3.format('.3')(element.d));
1330
1330
  };
1331
1331
  });
1332
1332
  // EXIT
@@ -1384,7 +1384,7 @@ export default class SDTModel extends DetectableElement {
1384
1384
  );
1385
1385
  return (time) => {
1386
1386
  element.c = interpolateC(time);
1387
- d3.select(element).text(+(element.c).toFixed(3));
1387
+ d3.select(element).text(d3.format('.3')(element.c));
1388
1388
  };
1389
1389
  });
1390
1390
  // EXIT
@@ -1450,7 +1450,7 @@ export default class SDTModel extends DetectableElement {
1450
1450
  );
1451
1451
  return (time) => {
1452
1452
  element.s = interpolateS(time);
1453
- d3.select(element).text(+(element.s).toFixed(3));
1453
+ d3.select(element).text(d3.format('.3')(element.s));
1454
1454
  };
1455
1455
  });
1456
1456
  // EXIT
@@ -1480,7 +1480,7 @@ export default class SDTModel extends DetectableElement {
1480
1480
  .call(dragThreshold)
1481
1481
  .on('keydown', (event) => {
1482
1482
  if (['ArrowRight', 'ArrowLeft'].includes(event.key)) {
1483
- let l = this.l; // eslint-disable-line prefer-destructuring
1483
+ let l = this.l; /* eslint-disable-line prefer-destructuring */
1484
1484
  switch (event.key) {
1485
1485
  case 'ArrowRight':
1486
1486
  l += event.shiftKey ? 0.01 : 0.1;
@@ -0,0 +1,121 @@
1
+
2
+ import {html} from 'lit';
3
+
4
+ import '@decidables/decidables-elements/spinner';
5
+ import SDTMath from '@decidables/detectable-math';
6
+
7
+ import SDTEquation from './sdt-equation';
8
+
9
+ /*
10
+ SDTEquationHFa2Ppv element
11
+ <sdt-equation-hm2hr>
12
+
13
+ Attributes:
14
+ Hits; Misses; Hit Rate;
15
+ */
16
+ export default class SDTEquationHFa2Ppv extends SDTEquation {
17
+ static get properties() {
18
+ return {
19
+ h: {
20
+ attribute: 'hits',
21
+ type: Number,
22
+ reflect: true,
23
+ },
24
+ fa: {
25
+ attribute: 'false-alarms',
26
+ type: Number,
27
+ reflect: true,
28
+ },
29
+ ppv: {
30
+ attribute: false,
31
+ type: Number,
32
+ reflect: false,
33
+ },
34
+ };
35
+ }
36
+
37
+ constructor() {
38
+ super();
39
+ this.h = 0;
40
+ this.fa = 0;
41
+ this.alignState();
42
+ }
43
+
44
+ alignState() {
45
+ this.ppv = SDTMath.hFa2Ppv(this.h, this.fa);
46
+ }
47
+
48
+ sendEvent() {
49
+ this.dispatchEvent(new CustomEvent('sdt-equation-hfa2ppv-change', {
50
+ detail: {
51
+ h: this.h,
52
+ fa: this.fa,
53
+ ppv: this.ppv,
54
+ },
55
+ bubbles: true,
56
+ }));
57
+ }
58
+
59
+ hInput(event) {
60
+ this.h = parseInt(event.target.value, 10);
61
+ this.alignState();
62
+ this.sendEvent();
63
+ }
64
+
65
+ faInput(event) {
66
+ this.fa = parseInt(event.target.value, 10);
67
+ this.alignState();
68
+ this.sendEvent();
69
+ }
70
+
71
+ render() {
72
+ this.alignState();
73
+ let h;
74
+ let fa;
75
+ let ppv;
76
+ if (this.numeric) {
77
+ h = html`
78
+ <decidables-spinner class="h" ?disabled=${!this.interactive} min="0" .value="${this.h}" @input=${this.hInput.bind(this)}>
79
+ <var>Hits</var>
80
+ </decidables-spinner>
81
+ `;
82
+ fa = html`
83
+ <decidables-spinner class="fa" ?disabled=${!this.interactive} min="0" .value="${this.fa}" @input=${this.faInput.bind(this)}>
84
+ <var>False Alarms</var>
85
+ </decidables-spinner>
86
+ `;
87
+ ppv = html`
88
+ <decidables-spinner class="ppv" disabled min="0" max="1" step=".001" .value="${+this.ppv.toFixed(3)}">
89
+ <var>Positive Predictive Value</var>
90
+ </decidables-spinner>
91
+ `;
92
+ } else {
93
+ h = html`<var class="h">Hits</var>`;
94
+ fa = html`<var class="fa">False Alarms</var>`;
95
+ ppv = html`<var class="ppv">Positive Predictive Value</var>`;
96
+ }
97
+ return html`
98
+ <div class="holder">
99
+ <table class="equation">
100
+ <tbody>
101
+ <tr>
102
+ <td rowspan="2">
103
+ ${ppv}<span class="equals">=</span>
104
+ </td>
105
+ <td class="underline">
106
+ ${h}
107
+ </td>
108
+ </tr>
109
+ <tr>
110
+ <td>
111
+ ${h}<span class="plus">+</span>${fa}
112
+ </td>
113
+ </tr>
114
+ </tbody>
115
+ </table>
116
+ </div>
117
+ `;
118
+ }
119
+ }
120
+
121
+ customElements.define('sdt-equation-hfa2ppv', SDTEquationHFa2Ppv);
@@ -2,7 +2,9 @@
2
2
  export {default as SDTEquationDC2Far} from './dc2far';
3
3
  export {default as SDTEquationDC2Hr} from './dc2hr';
4
4
  export {default as SDTEquationFaCr2Far} from './facr2far';
5
+ export {default as SDTEquationHFa2Ppv} from './hfa2ppv';
5
6
  export {default as SDTEquationHM2Hr} from './hm2hr';
6
7
  export {default as SDTEquationHMFaCr2Acc} from './hmfacr2acc';
7
8
  export {default as SDTEquationHrFar2C} from './hrfar2c';
8
9
  export {default as SDTEquationHrFar2D} from './hrfar2d';
10
+ export {default as SDTEquationMCr2Fomr} from './mcr2fomr';
@@ -0,0 +1,121 @@
1
+
2
+ import {html} from 'lit';
3
+
4
+ import '@decidables/decidables-elements/spinner';
5
+ import SDTMath from '@decidables/detectable-math';
6
+
7
+ import SDTEquation from './sdt-equation';
8
+
9
+ /*
10
+ SDTEquationMCr2Fomr element
11
+ <sdt-equation-mcr2fomr>
12
+
13
+ Attributes:
14
+ Hits; Misses; Hit Rate;
15
+ */
16
+ export default class SDTEquationMCr2Fomr extends SDTEquation {
17
+ static get properties() {
18
+ return {
19
+ m: {
20
+ attribute: 'misses',
21
+ type: Number,
22
+ reflect: true,
23
+ },
24
+ cr: {
25
+ attribute: 'correct-rejections',
26
+ type: Number,
27
+ reflect: true,
28
+ },
29
+ fomr: {
30
+ attribute: false,
31
+ type: Number,
32
+ reflect: false,
33
+ },
34
+ };
35
+ }
36
+
37
+ constructor() {
38
+ super();
39
+ this.m = 0;
40
+ this.cr = 0;
41
+ this.alignState();
42
+ }
43
+
44
+ alignState() {
45
+ this.fomr = SDTMath.mCr2Fomr(this.m, this.cr);
46
+ }
47
+
48
+ sendEvent() {
49
+ this.dispatchEvent(new CustomEvent('sdt-equation-mcr2fomr-change', {
50
+ detail: {
51
+ m: this.m,
52
+ cr: this.cr,
53
+ fomr: this.fomr,
54
+ },
55
+ bubbles: true,
56
+ }));
57
+ }
58
+
59
+ mInput(event) {
60
+ this.m = parseInt(event.target.value, 10);
61
+ this.alignState();
62
+ this.sendEvent();
63
+ }
64
+
65
+ crInput(event) {
66
+ this.cr = parseInt(event.target.value, 10);
67
+ this.alignState();
68
+ this.sendEvent();
69
+ }
70
+
71
+ render() {
72
+ this.alignState();
73
+ let m;
74
+ let cr;
75
+ let fomr;
76
+ if (this.numeric) {
77
+ m = html`
78
+ <decidables-spinner class="m" ?disabled=${!this.interactive} min="0" .value="${this.m}" @input=${this.mInput.bind(this)}>
79
+ <var>Misses</var>
80
+ </decidables-spinner>
81
+ `;
82
+ cr = html`
83
+ <decidables-spinner class="cr" ?disabled=${!this.interactive} min="0" .value="${this.cr}" @input=${this.crInput.bind(this)}>
84
+ <var>Correct Rejections</var>
85
+ </decidables-spinner>
86
+ `;
87
+ fomr = html`
88
+ <decidables-spinner class="fomr" disabled min="0" max="1" step=".001" .value="${+this.fomr.toFixed(3)}">
89
+ <var>False Omission Rate</var>
90
+ </decidables-spinner>
91
+ `;
92
+ } else {
93
+ m = html`<var class="m">Misses</var>`;
94
+ cr = html`<var class="cr">Correct Rejections</var>`;
95
+ fomr = html`<var class="fomr">False Omission Rate</var>`;
96
+ }
97
+ return html`
98
+ <div class="holder">
99
+ <table class="equation">
100
+ <tbody>
101
+ <tr>
102
+ <td rowspan="2">
103
+ ${fomr}<span class="equals">=</span>
104
+ </td>
105
+ <td class="underline">
106
+ ${m}
107
+ </td>
108
+ </tr>
109
+ <tr>
110
+ <td>
111
+ ${m}<span class="plus">+</span>${cr}
112
+ </td>
113
+ </tr>
114
+ </tbody>
115
+ </table>
116
+ </div>
117
+ `;
118
+ }
119
+ }
120
+
121
+ customElements.define('sdt-equation-mcr2fomr', SDTEquationMCr2Fomr);
@@ -45,6 +45,7 @@ export default class SDTEquation extends DetectableElement {
45
45
  /* Overall <table> */
46
46
  .equation {
47
47
  text-align: center;
48
+ white-space: nowrap;
48
49
 
49
50
  border-collapse: collapse;
50
51
 
@@ -118,6 +119,14 @@ export default class SDTEquation extends DetectableElement {
118
119
  background: var(---color-fa-light);
119
120
  }
120
121
 
122
+ .ppv {
123
+ background: var(---color-present-light);
124
+ }
125
+
126
+ .fomr {
127
+ background: var(---color-absent-light);
128
+ }
129
+
121
130
  .acc {
122
131
  background: var(---color-acc-light);
123
132
  }
@@ -3,4 +3,5 @@ export {default as SDTExampleDoubleInteractive} from './double-interactive';
3
3
  export {default as SDTExampleHuman} from './human';
4
4
  export {default as SDTExampleInteractive} from './interactive';
5
5
  export {default as SDTExampleModel} from './model';
6
+ export {default as SDTExampleMultiple} from './multiple';
6
7
  export {default as SDTExampleUnequal} from './unequal';
@@ -0,0 +1,76 @@
1
+
2
+ import DecidablesConverterArray from '@decidables/decidables-elements/converter-array';
3
+
4
+ import SDTExample from './sdt-example';
5
+
6
+ /*
7
+ SDTExampleMulti element
8
+ <sdt-example-multi>
9
+ */
10
+ export default class SDTExampleMultiple extends SDTExample {
11
+ static get properties() {
12
+ return {
13
+ variable: {
14
+ attribute: 'variable',
15
+ type: String,
16
+ reflect: true,
17
+ },
18
+ values: {
19
+ attribute: 'values',
20
+ converter: DecidablesConverterArray,
21
+ reflect: true,
22
+ },
23
+ };
24
+ }
25
+
26
+ constructor() {
27
+ super();
28
+ this.variables = ['d', 'c'];
29
+ this.variable = 'd';
30
+ this.values = [0, 1];
31
+ }
32
+
33
+ firstUpdated(/* changedProperties */) {
34
+ this.detectableControl = this.querySelector('detectable-control');
35
+ this.rocSpace = this.querySelector('roc-space');
36
+ this.sdtModel = this.querySelector('sdt-model');
37
+
38
+ if (this.detectableControl) {
39
+ this.detectableControl.addEventListener('detectable-control-z-roc', (event) => {
40
+ this.rocSpace.zRoc = event.detail.zRoc;
41
+ });
42
+ }
43
+
44
+ if (this.rocSpace) {
45
+ this.rocSpace.setWithSDT(1, 0, 'default', '', 1);
46
+ if (this.variable === 'd') {
47
+ this.values.forEach((d, index) => {
48
+ this.rocSpace.setWithSDT(d, this.sdtModel.c, `point${index}`, index + 1, this.sdtModel.s);
49
+ });
50
+ } else if (this.variable === 'c') {
51
+ this.values.forEach((c, index) => {
52
+ this.rocSpace.setWithSDT(this.sdtModel.d, c, `point${index}`, index + 1, this.sdtModel.s);
53
+ });
54
+ }
55
+ }
56
+
57
+ if (this.sdtModel) {
58
+ this.sdtModel.addEventListener('sdt-model-change', (event) => {
59
+ if (this.rocSpace) {
60
+ this.rocSpace.setWithSDT(event.detail.d, event.detail.c, 'default', '', event.detail.s);
61
+ if (this.variable === 'd') {
62
+ this.values.forEach((d, index) => {
63
+ this.rocSpace.setWithSDT(d, event.detail.c, `point${index}`, index + 1, event.detail.s);
64
+ });
65
+ } else if (this.variable === 'c') {
66
+ this.values.forEach((c, index) => {
67
+ this.rocSpace.setWithSDT(event.detail.d, c, `point${index}`, index + 1, event.detail.s);
68
+ });
69
+ }
70
+ }
71
+ });
72
+ }
73
+ }
74
+ }
75
+
76
+ customElements.define('sdt-example-multiple', SDTExampleMultiple);