-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
665 lines (566 loc) · 29.8 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Responsive Tachometer SVG Slider</title>
<style>
body {
margin: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #ffffff;
font-family: Arial, Helvetica, sans-serif;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
width: 100vw;
height: 100vh;
overflow: hidden;
}
.container {
width: 100vw;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #ffffff;
aspect-ratio: 5 / 4; /* Aspect ratio 4:3 */
height: 100%;
}
/* vertical stacked: */
.numberOfResults {
align-items: center;
justify-content: center;
font-size: max(12px, 2vw);
text-align: center; /* Center text within each label */
font-weight: 300;
display: flex;
}
.questionHeader {
/* height: 20vh; */
font-size: max(20px, 4vw);
text-align: center; /* Center text within each label */
font-weight: 600;
margin: 0 5vw 0 5vw;
}
.slider-container {
width: 100vw;
overflow: visible;
z-index: 2;
}
.labels {
display: flex;
justify-content: space-between;
width: 88%; /* This matches the width of the slider path relative to SVG width */
margin: 0 auto; /* Center the container */
font-size: max(16px, 3vw);
text-align: center;
}
.slider {
stroke: #E6F6FF;
stroke-width: 6;
fill: none;
}
.thumb {
fill: #ffffff;
cursor: pointer;
stroke: #00447E; /* Adding a border color */
stroke-width: 2; /* Border width */
}
.root {
fill: #24B9D6;
stroke: #ffffff; /* Adding a border color */
stroke-width: 2; /* Border width */
}
.needle {
fill: none;
stroke: #212121; /* Color of the needle */
stroke-width: 5; /* Starting thickness of the needle */
stroke-linecap: round; /* Makes the ends of the path rounded */
}
text {
user-select: none;
}
.label {
width: auto;
overflow: hidden;
flex-basis: 50%;
}
#answer1 {
text-align: left;
margin-left: 0;
}
#answer2 {
text-align: right;
margin-right: 0;
}
#liveIndicator {
width: 32px;
height: 32px;
}
#centerSpan {
flex-basis: 10%;
flex-shrink: 0;
}
</style>
</head>
<body>
<div class="container">
<div class="numberOfResults">
LIVE ABSTIMMUNG
<svg id="liveIndicator" xmlns="http://www.w3.org/2000/svg" overflow="visible">
<circle fill="#24B9D6" cx="50%" cy="50%" r="22.5%">
<animate
attributeName="r"
values="19.5%; 22.5%; 19.5%"
dur="3s"
repeatCount="indefinite"
/>
<animate
attributeName="opacity"
values="1; 1; 0; 0"
dur="3s"
repeatCount="indefinite"
/>
</circle>
<circle cx="50%" cy="50%" r="15%" stroke="white" fill="#24B9D6" stroke-width="7.5%">
<animate
attributeName="stroke-width"
values="4.5%; 7.5%; 4.5%"
dur="3s"
repeatCount="indefinite"
/>
<animate
attributeName="r"
values="13.5%; 15%; 13.5%"
dur="3s"
repeatCount="indefinite"
/>
</circle>
</svg>
</div>
<div class="questionHeader">
<span id="question"></span>
</div>
<div class="slider-container">
<svg id="sliderSVG" viewBox="0 0 300 150" preserveAspectRatio="xMidYMid meet" overflow="visible">
<!-- Curved slider path -->
<path id="sliderPath" d="M 25 150 A 125 125 0 0 1 275 150" class="slider"></path>
<!-- Tachometer needle -->
<line id="needle" x1="150" y1="150" x2="150" y2="50" class="needle"></line>
<!-- Slider thumb -->
<circle id="thumb" cx="150" cy="25" r="13" class="thumb">
<animate
attributeName="r"
values="13; 15; 13"
dur="2s"
repeatCount="indefinite"
/>
</circle>
<g id="arrows" fill="#00447E">
<path transform="translate(113, 15) scale(0.6)" d="M25.2058 1.77375C25.7575 1.74713 26.2262 2.17274 26.2529 2.72439C26.2795 3.27603 25.8539 3.7448 25.3022 3.77142L25.2058 1.77375ZM1.08967 10.6609C0.56142 10.4998 0.263828 9.94092 0.42498 9.41267L3.0511 0.80433C3.21225 0.27608 3.77112 -0.0215123 4.29938 0.13964C4.82763 0.300791 5.12522 0.859662 4.96407 1.38791L2.62974 9.03977L10.2816 11.3741C10.8098 11.5353 11.1074 12.0941 10.9463 12.6224C10.7851 13.1506 10.2263 13.4482 9.69801 13.2871L1.08967 10.6609ZM25.254 2.77258C25.3022 3.77142 25.3023 3.77141 25.3025 3.77141C25.3025 3.77141 25.3025 3.77141 25.3026 3.7714C25.3026 3.7714 25.3025 3.77141 25.3024 3.77141C25.3022 3.77142 25.3016 3.77145 25.3007 3.7715C25.2989 3.77159 25.2958 3.77175 25.2914 3.77198C25.2827 3.77244 25.2689 3.77319 25.2501 3.77428C25.2126 3.77645 25.1554 3.77994 25.0793 3.7851C24.9271 3.79543 24.6998 3.81242 24.4054 3.83879C23.8164 3.89154 22.9593 3.98175 21.8977 4.13106C19.7731 4.42987 16.8373 4.96427 13.5966 5.90528L13.0389 3.98461C16.3917 3.01105 19.4241 2.45927 21.6192 2.15055C22.7175 1.99608 23.6082 1.90218 24.227 1.84677C24.5365 1.81905 24.7781 1.80095 24.9439 1.78969C25.0268 1.78407 25.0907 1.78016 25.1347 1.77761C25.1567 1.77634 25.1737 1.77541 25.1856 1.77478C25.1915 1.77447 25.1962 1.77423 25.1996 1.77405C25.2013 1.77397 25.2026 1.7739 25.2037 1.77385C25.2042 1.77382 25.2046 1.7738 25.205 1.77379C25.2052 1.77378 25.2054 1.77377 25.2055 1.77376C25.2057 1.77375 25.2058 1.77375 25.254 2.77258ZM13.5966 5.90528C10.3544 6.84671 7.4132 8.01906 5.27984 8.95795C4.21434 9.42687 3.35321 9.8363 2.76016 10.1276C2.4637 10.2732 2.23441 10.3892 2.08027 10.4683C2.0032 10.5078 1.94493 10.5381 1.90646 10.5582C1.88723 10.5683 1.87295 10.5758 1.86374 10.5806C1.85913 10.5831 1.8558 10.5848 1.85375 10.5859C1.85272 10.5865 1.85202 10.5868 1.85164 10.587C1.85145 10.5871 1.85134 10.5872 1.85131 10.5872C1.8513 10.5872 1.85134 10.5872 1.85133 10.5872C1.85139 10.5872 1.85147 10.5871 1.38146 9.70446C0.911455 8.8218 0.911576 8.82173 0.911717 8.82166C0.911791 8.82162 0.911953 8.82153 0.912101 8.82145C0.912398 8.8213 0.912777 8.82109 0.913237 8.82085C0.914157 8.82036 0.915402 8.8197 0.91697 8.81887C0.920106 8.81721 0.924535 8.81486 0.930242 8.81185C0.941654 8.80583 0.958177 8.79713 0.979684 8.78589C1.0227 8.76339 1.08566 8.73068 1.16756 8.68868C1.33135 8.60467 1.57097 8.48346 1.87842 8.33245C2.49318 8.03049 3.37984 7.60901 4.47421 7.12738C6.66061 6.16515 9.68753 4.95775 13.0389 3.98461L13.5966 5.90528Z" ></path>
<path transform="translate(170, 15) scale(0.6)" d="m1.4295 1.7738c-0.5517-0.02662-1.0204 0.39899-1.0471 0.95064-0.0266 0.55164 0.399 1.0204 0.9507 1.047zm24.116 8.8872c0.52825-0.1611 0.82584-0.71998 0.66469-1.2482l-2.6261-8.6083c-0.16115-0.52825-0.72002-0.82584-1.2483-0.66469-0.52825 0.16115-0.82584 0.72002-0.66469 1.2483l2.3343 7.6519-7.6519 2.3343c-0.5282 0.1612-0.8258 0.72-0.6647 1.2483 0.1612 0.5282 0.72 0.8258 1.2483 0.6647zm-24.164-7.8883c-0.0482 0.99884-0.0483 0.99883-0.0485 0.99883l-1e-4 -1e-5s1e-4 1e-5 2e-4 1e-5c2e-4 1e-5 8e-4 4e-5 0.0017 9e-5 0.0018 9e-5 0.0049 2.5e-4 0.0093 4.8e-4 0.0087 4.6e-4 0.0225 0.00121 0.0413 0.0023 0.0375 0.00217 0.0947 0.00566 0.1708 0.01082 0.1522 0.01033 0.3795 0.02732 0.6739 0.05369 0.589 0.05275 1.4461 0.14296 2.5077 0.29227 2.1246 0.29881 5.0604 0.83321 8.3011 1.7742l0.5577-1.9207c-3.3528-0.97356-6.3852-1.5253-8.5803-1.8341-1.0983-0.15447-1.989-0.24837-2.6078-0.30378-0.3095-0.02772-0.5511-0.04582-0.7169-0.05708-0.0829-0.00562-0.1468-0.00953-0.1908-0.01208-0.022-0.00127-0.039-0.0022-0.0509-0.00283-0.0059-3.1e-4 -0.0106-5.5e-4 -0.014-7.3e-4 -0.0017-8e-5 -3e-3 -1.5e-4 -0.0041-2e-4 -5e-4 -3e-5 -9e-4 -5e-5 -0.0013-6e-5 -2e-4 -1e-5 -4e-4 -2e-5 -5e-4 -3e-5 -2e-4 -1e-5 -3e-4 -1e-5 -0.0485 0.99882zm11.657 3.1327c3.2422 0.94143 6.1834 2.1138 8.3168 3.0527 1.0655 0.46892 1.9266 0.87835 2.5197 1.1696 0.29646 0.1456 0.52575 0.2616 0.67989 0.3407 0.07707 0.0395 0.13534 0.0698 0.17381 0.0899 0.01923 0.0101 0.03351 0.0176 0.04272 0.0224 0.0046 0.0025 0.0079 0.0042 0.01 0.0053 1e-3 6e-4 0.0017 9e-4 0.0021 0.0011 1.9e-4 1e-4 3e-4 2e-4 3.3e-4 2e-4h-2e-5c-6e-5 0-1.4e-4 -1e-4 0.46987-0.88274 0.47-0.88266 0.46988-0.88273 0.46974-0.8828-7.4e-5 -4e-5 -2.36e-4 -1.3e-4 -3.84e-4 -2.1e-4 -2.97e-4 -1.5e-4 -6.76e-4 -3.6e-4 -0.0011-6e-4 -9.2e-4 -4.9e-4 -0.0022-0.00115-0.0037-0.00198-0.0031-0.00166-0.0076-0.00401-0.01327-0.00702-0.01141-0.00602-0.02793-0.01472-0.04944-0.02596-0.04302-0.0225-0.10598-0.05521-0.18788-0.09721-0.16379-0.08401-0.40341-0.20522-0.71086-0.35623-0.61476-0.30196-1.5014-0.72344-2.5958-1.2051-2.1864-0.96223-5.2133-2.1696-8.5647-3.1428z" ></path>
</g>
<!-- Slider root -->
<circle id="root" cx="150" cy="150" r="10" class="root"></circle>
<!-- Display value -->
<text id="valueDisplay" x="150" y="10" text-anchor="middle" font-size="6" style="visibility: hidden;">Value: 0</text>
<!-- Display 1/3 value -->
<rect id="background1_3" x="55" y="112" width="20" height="10" fill="white" filter="url(#blur)" style="visibility: hidden;"></rect>
<text id="valueDisplay1_3" x="65" y="120" text-anchor="middle" font-size="9" font-weight="bold"></text>
<!-- Display 2/3 value -->
<rect id="background2_3" x="140" y="47" width="20" height="10" fill="white" filter="url(#blur)" style="visibility: hidden;"></rect>
<text id="valueDisplay2_3" x="150" y="55" text-anchor="middle" font-size="9" font-weight="bold"></text>
<!-- Display 3/3 value -->
<rect id="background3_3" x="225" y="112" width="20" height="10" fill="white" filter="url(#blur)" style="visibility: hidden;"></rect>
<text id="valueDisplay3_3" x="235" y="120" text-anchor="middle" font-size="9" font-weight="bold" fill="black"></text>
<defs>
<filter id="blur" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur stdDeviation="1" />
</filter>
</defs>
</svg>
</div>
<div class="labels">
<span class="label" id="answer1"></span>
<span id="centerSpan"></span>
<span class="label" id="answer2"></span>
</div>
</div>
<script>
const DEFAULT_POLLY_URL = 'https://app.apptivegrid.de/api/users/62398e23b8b578b35b971df0/spaces/66bcc1d7f549cad6d6dbf2be/grids/66bcc1dcf549ca6236dbf2c4/entities/BqWFtLCV6KM?layout=key';
const thumb = document.getElementById('thumb');
const needle = document.getElementById('needle');
const valueDisplay = document.getElementById('valueDisplay');
const path = document.getElementById('sliderPath');
const svg = document.getElementById('sliderSVG');
const pathLength = path.getTotalLength();
let userResult = null;
let isDragging = false;
let isSubmitting = false;
let hasSubmitted = false;
let lastThumbPosition = { x: 150, y: 50 };
const needleLength = 100; // Constant length for the needle
let entity = null; // apptive entitiy
// Desktop Event
thumb.addEventListener('mousedown', startDrag);
document.addEventListener('mousemove', onDrag);
document.addEventListener('mouseup', endDrag);
// Mobile event listeners
thumb.addEventListener('touchstart', startDrag);
document.addEventListener('touchmove', onDrag);
document.addEventListener('touchend', endDrag);
function startDrag(e) {
e.preventDefault();
if (typeof pollyMessageListener !== 'undefined' && pollyMessageListener !== null) {
pollyMessageListener.postMessage('startDrag');
} else {
console.warn('pollyMessageListener is not defined or does not support postMessage');
}
isDragging = true;
e.preventDefault();
document.getElementById('arrows').style.visibility = 'hidden';
}
function onDrag(e) {
e.preventDefault();
if (typeof pollyMessageListener !== 'undefined' && pollyMessageListener !== null) {
pollyMessageListener.postMessage('onDrag');
} else {
console.warn('pollyMessageListener is not defined or does not support postMessage');
}
if (!isDragging) return;
let clientX = e.clientX || e.touches[0].clientX;
let clientY = e.clientY || e.touches[0].clientY;
const svgPoint = getSVGPoint(clientX, clientY);
const { x, y } = getClosestPointOnPath(svgPoint.x, svgPoint.y);
thumb.setAttribute('cx', x);
thumb.setAttribute('cy', y);
const value = calculateValue(x, y);
valueDisplay.textContent = `Value: ${value}`;
userResult = value
lastThumbPosition = { x, y }; // Store the final thumb position
}
function endDrag(e) {
e.preventDefault();
if (typeof pollyMessageListener !== 'undefined' && pollyMessageListener !== null) {
pollyMessageListener.postMessage('endDrag');
} else {
console.warn('pollyMessageListener is not defined or does not support postMessage');
}
isDragging = false;
if (userResult === null) return;
if (hasSubmitted) {
console.log('You have already submitted your answer.');
return;
}
if (isSubmitting) {
console.log('Submission is in progress. Please wait.');
return;
}
animateNeedleToPosition(lastThumbPosition.x, lastThumbPosition.y);
// Example usage:
let data = {
result: parseInt(userResult),
entityId: entity['_id'],
entity_uri: entity['_links']['self']['href'],
// Add more key-value pairs as needed
};
isSubmitting = true;
postDataToApptiveGrid(data)
.then(result => {
console.log('Data successfully posted:', result);
hasSubmitted = true; // Mark as submitted
drawCircles();
calculatePercentages(entity);
setVoteSubmitted();
})
.catch(error => {
console.error('Failed to post data:', error);
}).finally(() => {
isSubmitting = false; // Reset submitting flag
});
}
function getSVGPoint(x, y) {
const point = svg.createSVGPoint();
point.x = x;
point.y = y;
return point.matrixTransform(svg.getScreenCTM().inverse());
}
function getClosestPointOnPath(x, y) {
let closestPoint = path.getPointAtLength(0);
let minDist = distance(x, y, closestPoint.x, closestPoint.y);
for (let i = 1; i < pathLength; i++) {
const point = path.getPointAtLength(i);
const dist = distance(x, y, point.x, point.y);
if (dist < minDist) {
minDist = dist;
closestPoint = point;
}
}
return closestPoint;
}
function distance(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
}
function calculateValue(x, y) {
const centerX = 150;
const centerY = 150;
// Calculate the angle from the center point (bottom of the arc)
const angle = Math.atan2(y - centerY, x - centerX);
if (angle == Math.PI) return 0;
// Normalize angle to the range [0, Math.PI]
// Math.PI corresponds to the leftmost point (0)
// 0 corresponds to the rightmost point (10)
const normalizedAngle = (angle + Math.PI) / Math.PI;
// Scale the normalized angle to a value between 0 and 10
const value = normalizedAngle * 9;
// Round to the nearest integer
return Math.round(value);
}
function animateNeedleToPosition(finalX, finalY) {
const centerX = 150;
const centerY = 150;
const dx = finalX - centerX;
const dy = finalY - centerY;
const angle = Math.atan2(dy, dx);
const targetX = centerX + needleLength * Math.cos(angle);
const targetY = centerY + needleLength * Math.sin(angle);
let startTime = null;
function animate(time) {
if (!startTime) startTime = time;
const elapsed = time - startTime;
const progress = Math.min(elapsed / 1000, 1); // 1000ms duration
const bounceProgress = (p) => {
const n1 = 7.5625, d1 = 2.75;
if (p < 1 / d1) {
return n1 * p * p;
} else if (p < 2 / d1) {
return n1 * (p -= 1.5 / d1) * p + 0.75;
} else if (p < 2.5 / d1) {
return n1 * (p -= 2.25 / d1) * p + 0.9375;
} else {
return n1 * (p -= 2.625 / d1) * p + 0.984375;
}
};
const easedProgress = bounceProgress(progress);
// Calculate the current angle during the animation
const currentAngle = angle + (Math.PI / 8) * (1 - easedProgress) * Math.sin(easedProgress * Math.PI * 4);
// Maintain constant needle length
const currentX = centerX + needleLength * Math.cos(currentAngle);
const currentY = centerY + needleLength * Math.sin(currentAngle);
needle.setAttribute('x2', currentX);
needle.setAttribute('y2', currentY);
if (progress < 1) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
}
// Recalculate the value display, thumb position, and needle position on resize
window.addEventListener('resize', () => {
const thumbCX = parseFloat(thumb.getAttribute('cx'));
const thumbCY = parseFloat(thumb.getAttribute('cy'));
const value = calculateValue(thumbCX, thumbCY);
valueDisplay.textContent = `Value: ${value}`;
animateNeedleToPosition(thumbCX, thumbCY);
});
document.addEventListener("DOMContentLoaded", function() {
const urlParams = new URLSearchParams(window.location.search);
const url = urlParams.get('url') || DEFAULT_POLLY_URL;
const username = urlParams.get('username') || '23bd064465e583233eab7807507a715c';
const password = urlParams.get('password') || 'a7hkqxt2qj8rfverccyzn4agt';
if (url && username && password) {
const authHeader = 'Basic ' + btoa(username + ':' + password);
fetch(url, {
method: 'GET',
headers: {
'Authorization': authHeader
}
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
return response.json(); // Parse the JSON data
})
.then(data => {
// Assuming 'question' is a key in the JSON response
entity = data;
document.getElementById('question').textContent = data['question'] || 'No question found in response.';
document.getElementById('answer1').textContent = data['answer_1'] || 'No answer_1 found in response.';
document.getElementById('answer2').textContent = data['answer_2'] || 'No answer_2 found in response.';
if (previouslySubmitted()) {
showResults();
}
})
.catch(error => {
document.getElementById('valueDisplay').textContent = 'Fehler: ' + error.message;
});
} else {
document.getElementById('valueDisplay').textContent = 'Fehler: URL, Benutzername oder Passwort fehlen in den Parametern.';
}
});
function getPollyEntity() {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get('url') || DEFAULT_POLLY_URL;
}
function getVotedUrlArray() {
const stringArray = localStorage.getItem('voteUrl')
if (!stringArray) {
return []
}
return JSON.parse(stringArray)
}
function setVoteSubmitted() {
const array = getVotedUrlArray();
array.push(getPollyEntity());
localStorage.setItem('voteUrl', JSON.stringify(array));
}
function previouslySubmitted() {
const array = getVotedUrlArray();
return array.includes(getPollyEntity());
}
function showResults() {
hasSubmitted = true; // Mark as submitted
document.getElementById('needle').setAttribute('style', 'display: none')
document.getElementById('thumb').setAttribute('style', 'display: none')
document.getElementById('arrows').setAttribute('style', 'display: none')
drawCircles();
calculatePercentages(entity);
}
async function postDataToApptiveGrid(data) {
const url = entity['flow_uri'];
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// Include Authorization header if required
// 'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
},
body: JSON.stringify(data) // Convert data to JSON string
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.data; // Assuming the response is JSON
console.log('Success:', result);
return result;
} catch (error) {
console.error('Error:', error);
throw error;
}
}
function drawCircles() {
const svg = document.getElementById('sliderSVG');
// Center and radius of the large circle
const root = document.getElementById('root');
const centerX = parseFloat(root.getAttribute('cx'));
const centerY = parseFloat(root.getAttribute('cy'));
const R_large = parseFloat(root.getAttribute('r'));
// Base radius for small circles
const r_small = 0.927 / 5 * R_large; // Adjusting the small circle radius proportionally
// Draw multiple cascades of circles
let currentRadius = R_large + r_small; // Starting radius for first cascade
let cascade = 0;
while (cascade < 20 ) { // Limit the cascades to a reasonable size
// Calculate the circumference of the current cascade's circle
const circumference = Math.PI * currentRadius;
// Calculate the number of circles that can fit in this circumference
const numSmallCircles = Math.floor(circumference / (2 * r_small));
// Angle between adjacent small circles
const angleIncrement = (- Math.PI) / numSmallCircles;
for (let i = 0; i <= numSmallCircles; i++) {
const angle = i * angleIncrement;
const smallCenterX = centerX + currentRadius * Math.cos(angle);
const smallCenterY = centerY + currentRadius * Math.sin(angle);
const smallCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
smallCircle.setAttribute('cx', smallCenterX);
smallCircle.setAttribute('cy', smallCenterY);
smallCircle.setAttribute('r', r_small);
smallCircle.setAttribute('stroke', 'white');
smallCircle.setAttribute('fill', 'grey');
const sector = getSectorForAngle(angle);
const resultInSector = getResultForSector(sector);
console.log(`Resultes: ${resultInSector} in sector: ${sector}`);
if (resultInSector >= ((cascade / 2) * 10) ){
svg.insertBefore(smallCircle, svg.firstChild);
}
}
// Increase the radius for the next cascade
currentRadius += 2 * r_small;
cascade++;
}
}
function getSectorForAngle(angle) {
// Ensure the angle is between -Math.PI and 0
if (angle > 0) angle = 0;
if (angle < -Math.PI) angle = -Math.PI;
// Map angle from [-Math.PI, 0] to [0, 10] in 11 steps
const sectorValue = (angle + Math.PI) / Math.PI * 10;
// Round to the nearest integer to get one of the 11 steps
return Math.round(sectorValue);
}
function getResultForSector(sector){
const result = entity[`${sector}`];
const summOfResults = entity['numberOfResults']['value'];
const percent = Math.round((result / summOfResults) * 100 );
const norm = normalize(percent);
console.log(`Resultes: ${result} percent: ${percent} percent normalized: ${norm} in sector: ${sector}`);
return norm
}
function normalize(percent) {
let highestValue = getHighestValue(entity)
const summOfResults = entity['numberOfResults']['value'];
const highestValueInPercent = Math.round((highestValue / summOfResults) * 100 );
let normalized = (80 / highestValueInPercent) * percent ;
return normalized ;
}
function getHighestValue(aEntity) {
// Define the keys we are interested in
const keys = ['0', '1', '2', '3', '4', '5' , '6', '7', '8', '9', '10'];
// Use Math.max to find the highest value among the specified keys
const highestValue = Math.max(...keys.map(key => aEntity[key]));
return highestValue;
}
function calculatePercentages(data) {
// Extract the total number of results
const totalResults = data.numberOfResults.value;
// Define the ranges
const range1 = [0, 1, 2, 3]; // 0 to 3
const range2 = [4, 5, 6]; // 4 to 6
const range3 = [7, 8, 9, 10]; // 7 to 10
// Sum the values in each range
let sumRange1 = range1.reduce((sum, key) => sum + (data[key] || 0), 0);
let sumRange2 = range2.reduce((sum, key) => sum + (data[key] || 0), 0);
let sumRange3 = range3.reduce((sum, key) => sum + (data[key] || 0), 0);
// Calculate the percentage for each range and round it to the nearest integer
let percentageRange1 = Math.round((sumRange1 / totalResults) * 100);
let percentageRange2 = Math.round((sumRange2 / totalResults) * 100);
let percentageRange3 = Math.round((sumRange3 / totalResults) * 100);
// Return the results as an object
let result = {
range_0_3: percentageRange1 + '%',
range_4_6: percentageRange2 + '%',
range_7_10: percentageRange3 + '%'
};
const valueDisplay1_3 = document.getElementById('valueDisplay1_3');
const valueDisplay2_3 = document.getElementById('valueDisplay2_3');
const valueDisplay3_3 = document.getElementById('valueDisplay3_3');
valueDisplay1_3.textContent = result.range_0_3;
valueDisplay2_3.textContent = result.range_4_6;
valueDisplay3_3.textContent = result.range_7_10;
// show a background
document.getElementById('background1_3').style.visibility = 'visible';
document.getElementById('background2_3').style.visibility = 'visible';
document.getElementById('background3_3').style.visibility = 'visible';
}
</script>
</body>
</html>