This commit is contained in:
Andreas Wilms
2025-09-08 16:25:55 +02:00
commit cdcd870b6f
614 changed files with 343437 additions and 0 deletions

859
PCSurvey/survey.js Normal file
View File

@@ -0,0 +1,859 @@
"use strict";
var urlvar = jsPsych.data.urlVariables();
var user_agent_string = navigator.userAgent;
function saveData(name, data) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "PCstatic/write_data.php");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify({ filename: name, filedata: data }));
}
var string_final = urlvar.campaign + urlvar.worker + urlvar.randkey;
var verification = "mw-" + sha256(string_final);
// definiting two different response scales that can be used on the rating scales.
var comp_option = ["No", "Small", "Visible", "Large", "Huge"];
var total_option = ["Bad", "Poor", "Fair", "Good", "Excellent"];
var better_option = ["Left", "Similar", "Right"];
var no_data = {
type: "html-keyboard-response",
stimulus:
"<p>This task is only available with a valid workerID and campaignID.</p>",
choices: jsPsych.NO_KEYS,
};
var full_data = {
type: "html-keyboard-response",
stimulus:
"<p>We are sorry, the maximum amount of workers for this task has already been reached.</p>",
choices: jsPsych.NO_KEYS,
};
var small_screen = {
type: "html-keyboard-response",
stimulus:
"<p>Your browser screen size is only " +
$(window).width() +
"x" +
$(window).height() +
" pixels. For this study is must be at least 920x680 pixels. Try to switch your browser to fullscreen (press F11) or increase your screen resolution. Then reload this page.</p>",
choices: jsPsych.NO_KEYS,
};
function checkSize() {
if ($(window).width() < 920 || $(window).height() < 680) {
return true;
} else {
return false;
}
}
// The if's check that preconditions are met before the study can be started.
var start_if = {
timeline: [no_data],
conditional_function: function () {
if (urlvar.worker == null || urlvar.campaign == null) {
return true;
} else {
return false;
}
},
}
var start_if2 = {
timeline: [full_data],
conditional_function: function () {
return false;
},
}
var start_if3 = {
timeline: [small_screen],
conditional_function: function () {
return checkSize();
},
}
// Predefined element position coordinates for each stimulus needed for evaluation block generation
const positions_bremen = [[13, 13.5, 17], [31, 50, 2], [-65, -7, 9], [-40, -68, 3], [-35, 64, 4], [-5, 76, 1], [-18, 30, 0],[-15, -27, 0]];
const positions_randersacker = [[-6, -7, 0.6],[-4.5, -18, 4],[-13, -33, -0.5],[-6, -14.5, -0.5], [8, -0.4, 1], [1.7, -8, 7.3]];
// Build all possible test blocks, which are chosen dynamically later and actually used
// Functions create based on tested condition jsTimelineObjects here: sequential with one element for each cloud
const TQ0001 = generate_test_data_for_pointclouds_sequentiell("Q00", "Q01", "bremen", twoRandomPositions(positions_bremen));
const TQ0002 = generate_test_data_for_pointclouds_sequentiell("Q00", "Q02", "bremen", twoRandomPositions(positions_bremen));
const TQ0003 = generate_test_data_for_pointclouds_sequentiell("Q00", "Q03", "bremen", twoRandomPositions(positions_bremen));
const TQ0004 = generate_test_data_for_pointclouds_sequentiell("Q00", "Q04", "bremen", twoRandomPositions(positions_bremen));
const TQ0005 = generate_test_data_for_pointclouds_sequentiell("Q00", "Q05", "bremen", twoRandomPositions(positions_bremen));
const TQ0006 = generate_test_data_for_pointclouds_sequentiell("Q00", "Q06", "bremen", twoRandomPositions(positions_bremen));
const TQ1001 = generate_test_data_for_pointclouds_sequentiell("Q10", "Q11", "randersacker", twoRandomPositions(positions_randersacker));
const TQ1002 = generate_test_data_for_pointclouds_sequentiell("Q10", "Q12", "randersacker", twoRandomPositions(positions_randersacker));
const TQ1003 = generate_test_data_for_pointclouds_sequentiell("Q10", "Q13", "randersacker", twoRandomPositions(positions_randersacker));
const TQ1004 = generate_test_data_for_pointclouds_sequentiell("Q10", "Q14", "randersacker", twoRandomPositions(positions_randersacker));
const TQ1005 = generate_test_data_for_pointclouds_sequentiell("Q10", "Q15", "randersacker", twoRandomPositions(positions_randersacker));
const TQ1006 = generate_test_data_for_pointclouds_sequentiell("Q10", "Q16", "randersacker", twoRandomPositions(positions_randersacker));
/*
// Example objects when testing for two elements
const TQ0001 = generate_test_data_for_pointclouds_sequentiell_2_elements("Q00", "Q01", "bremen", fourRandomPositions(positions_bremen));
const TQ0002 = generate_test_data_for_pointclouds_sequentiell_2_elements("Q00", "Q02", "bremen", fourRandomPositions(positions_bremen));
const TQ0003 = generate_test_data_for_pointclouds_sequentiell_2_elements("Q00", "Q03", "bremen", fourRandomPositions(positions_bremen));
const TQ0004 = generate_test_data_for_pointclouds_sequentiell_2_elements("Q00", "Q04", "bremen", fourRandomPositions(positions_bremen));
const TQ0005 = generate_test_data_for_pointclouds_sequentiell_2_elements("Q00", "Q05", "bremen", fourRandomPositions(positions_bremen));
const TQ0006 = generate_test_data_for_pointclouds_sequentiell_2_elements("Q00", "Q06", "bremen", fourRandomPositions(positions_bremen));
const TQ1001 = generate_test_data_for_pointclouds_sequentiell_2_elements("Q00", "Q01", "randersacker", fourRandomPositions(positions_randersacker));
const TQ1002 = generate_test_data_for_pointclouds_sequentiell_2_elements("Q00", "Q01", "randersacker", fourRandomPositions(positions_randersacker));
const TQ1003 = generate_test_data_for_pointclouds_sequentiell_2_elements("Q00", "Q01", "randersacker", fourRandomPositions(positions_randersacker));
const TQ1004 = generate_test_data_for_pointclouds_sequentiell_2_elements("Q00", "Q01", "randersacker", fourRandomPositions(positions_randersacker));
const TQ1005 = generate_test_data_for_pointclouds_sequentiell_2_elements("Q00", "Q01", "randersacker", fourRandomPositions(positions_randersacker));
const TQ1006 = generate_test_data_for_pointclouds_sequentiell_2_elements("Q00", "Q01", "randersacker", fourRandomPositions(positions_randersacker));
// Example objects when testing for three elements
const TQ0001 = generate_test_data_for_pointclouds_sequentiell_3_elements("Q00", "Q01", "bremen", sixRandomPositions(positions_bremen));
const TQ0002 = generate_test_data_for_pointclouds_sequentiell_3_elements("Q00", "Q02", "bremen", sixRandomPositions(positions_bremen));
const TQ0003 = generate_test_data_for_pointclouds_sequentiell_3_elements("Q00", "Q03", "bremen", sixRandomPositions(positions_bremen));
const TQ0004 = generate_test_data_for_pointclouds_sequentiell_3_elements("Q00", "Q04", "bremen", sixRandomPositions(positions_bremen));
const TQ0005 = generate_test_data_for_pointclouds_sequentiell_3_elements("Q00", "Q05", "bremen", sixRandomPositions(positions_bremen));
const TQ0006 = generate_test_data_for_pointclouds_sequentiell_3_elements("Q00", "Q06", "bremen", sixRandomPositions(positions_bremen));
const TQ1001 = generate_test_data_for_pointclouds_sequentiell_3_elements("Q00", "Q01", "randersacker", sixRandomPositions(positions_randersacker));
const TQ1002 = generate_test_data_for_pointclouds_sequentiell_3_elements("Q00", "Q01", "randersacker", sixRandomPositions(positions_randersacker));
const TQ1003 = generate_test_data_for_pointclouds_sequentiell_3_elements("Q00", "Q01", "randersacker", sixRandomPositions(positions_randersacker));
const TQ1004 = generate_test_data_for_pointclouds_sequentiell_3_elements("Q00", "Q01", "randersacker", sixRandomPositions(positions_randersacker));
const TQ1005 = generate_test_data_for_pointclouds_sequentiell_3_elements("Q00", "Q01", "randersacker", sixRandomPositions(positions_randersacker));
const TQ1006 = generate_test_data_for_pointclouds_sequentiell_3_elements("Q00", "Q01", "randersacker", sixRandomPositions(positions_randersacker));
*/
// Functions that output evaluation blocks based on input. Input follows rules (see example inputs above).
function generate_test_data_for_pointclouds_paired(cloudLeft, cloudRight, type, positions) {
const letter1 = generateRandomLetter();
const letter2 = generateRandomLetter();
var data = [
{
data: {
js_url: "PCstatic/js/pik.js",
controlLetter1: letter1,
controlLetter2: letter2,
positions: positions,
cloudRight: cloudRight,
cloudLeft: cloudLeft,
type: type,
},
timeline: [
{ url: `potree/paired_comparison_template.html` },
{
type: "survey-multi-choice",
questions: [
{
prompt: "<b>Which point cloud looked better?</b>",
options: better_option,
required: true,
horizontal: true,
},
{
prompt:
"<b>What letter combination was displayed in the last point cloud?</b>",
options: generiereUndMischePaar(letter1 + letter2),
required: true,
horizontal: true,
},
],
},
],
},
];
return data;
}
function generate_test_data_for_pointclouds_sequentiell(
cloudOne,
cloudTwo,
type,positions
) {
const letter1 = generateRandomLetter();
const letter2 = generateRandomLetter();
var data = [
{
data: {
js_url: "PCstatic/js/pik.js",
controlLetter1: letter1,
controlLetter2: letter2,
positions: positions,
cloudOne: cloudOne,
cloudTwo: cloudTwo,
type: type,
perspectives: [],
tab_switch: 0,
},
timeline: [
{ url: `potree/sequentiell_template.html` },
{
type: "survey-multi-choice",
questions: [
{
prompt: "<b>How would you rate the Point Cloud?</b>",
options: total_option,
required: true,
horizontal: true,
},
{
prompt:
"<b>What letter/number was displayed in the last point cloud?</b>",
options: generateRandomLetterChoice(letter1),
required: true,
horizontal: true,
},
],
},
{ url: `potree/sequentiell_template2.html` },
{
type: "survey-multi-choice",
questions: [
{
prompt: "<b>How would you rate the Point Cloud?</b>",
options: total_option,
required: true,
horizontal: true,
},
{
prompt:
"<b>How would you rate the difference compared to the previous point cloud?</b>",
options: comp_option,
required: true,
horizontal: true,
},
{
prompt:
"<b>What letter/number was displayed in the last point cloud?</b>",
options: generateRandomLetterChoice(letter2),
required: true,
horizontal: true,
},
],
},
],
},
];
return data;
}
function generate_test_data_for_pointclouds_sequentiell_2_elements(
cloudOne,
cloudTwo,
type,positions
) {
const letter1 = generateRandomLetter();
const letter2 = generateRandomLetter();
const letter3 = generateRandomLetter();
const letter4 = generateRandomLetter();
var choices12 = generateRandomChoicesTwo(letter1, letter2);
var choices34 = generateRandomChoicesTwo(letter3, letter4);
var data = [
{
data: {
js_url: "PCstatic/js/pik.js",
controlLetter1: letter1,
controlLetter2: letter2,
controlLetter3: letter3,
controlLetter4: letter4,
positions: positions,
cloudOne: cloudOne,
cloudTwo: cloudTwo,
type: type,
perspectives: [],
tab_switch: 0,
},
timeline: [
{ url: `potree/sequentiell_template.html` },
{
type: "survey-multi-choice",
questions: [
{
prompt: "<b>How would you rate the Point Cloud?</b>",
options: total_option,
required: true,
horizontal: true,
},
{
prompt:
"<b>Which element was displayed in the last point cloud?</b>",
options: choices12[0],
required: true,
horizontal: true,
},
{
prompt:
"<b>Which element was displayed in the last point cloud?</b>",
options: choices12[1],
required: true,
horizontal: true,
},
],
},
{ url: `potree/sequentiell_template2.html` },
{
type: "survey-multi-choice",
questions: [
{
prompt: "<b>How would you rate the Point Cloud?</b>",
options: total_option,
required: true,
horizontal: true,
},
{
prompt:
"<b>How would you rate the difference compared to the previous point cloud?</b>",
options: comp_option,
required: true,
horizontal: true,
},
{
prompt:
"<b>Which element was displayed in the last point cloud?</b>",
options: choices34[0],
required: true,
horizontal: true,
},
{
prompt:
"<b>Which element was displayed in the last point cloud?</b>",
options: choices34[1],
required: true,
horizontal: true,
},
],
},
],
},
];
return data;
}
function generate_test_data_for_pointclouds_sequentiell_3_elements(
cloudOne,
cloudTwo,
type,positions
) {
const letter1 = generateRandomLetter();
const letter2 = generateRandomLetter();
const letter3 = generateRandomLetter();
const letter4 = generateRandomLetter();
const letter5 = generateRandomLetter();
const letter6 = generateRandomLetter();
var choices123 = generateRandomChoicesThree(letter1, letter2, letter3);
var choices456 = generateRandomChoicesThree(letter4, letter5, letter6);
var data = [
{
data: {
js_url: "PCstatic/js/pik.js",
controlLetter1: letter1,
controlLetter2: letter2,
controlLetter3: letter3,
controlLetter4: letter4,
controlLetter5: letter5,
controlLetter6: letter6,
positions: positions,
cloudOne: cloudOne,
cloudTwo: cloudTwo,
type: type,
perspectives: [],
tab_switch: 0,
},
timeline: [
{ url: `potree/sequentiell_template.html` },
{
type: "survey-multi-choice",
questions: [
{
prompt: "<b>How would you rate the Point Cloud?</b>",
options: total_option,
required: true,
horizontal: true,
},
{
prompt:
"<b>Which element was displayed in the last point cloud?</b>",
options: choices123[0],
required: true,
horizontal: true,
},
{
prompt:
"<b>Which element was displayed in the last point cloud?</b>",
options: choices123[1],
required: true,
horizontal: true,
},
{
prompt:
"<b>Which element was displayed in the last point cloud?</b>",
options: choices123[2],
required: true,
horizontal: true,
},
],
},
{ url: `potree/sequentiell_template2.html` },
{
type: "survey-multi-choice",
questions: [
{
prompt: "<b>How would you rate the Point Cloud?</b>",
options: total_option,
required: true,
horizontal: true,
},
{
prompt:
"<b>How would you rate the difference compared to the previous point cloud?</b>",
options: comp_option,
required: true,
horizontal: true,
},
{
prompt:
"<b>Which element was displayed in the last point cloud?</b>",
options: choices456[0],
required: true,
horizontal: true,
},
{
prompt:
"<b>Which element was displayed in the last point cloud?</b>",
options: choices456[1],
required: true,
horizontal: true,
},
{
prompt:
"<b>Which element was displayed in the last point cloud?</b>",
options: choices456[2],
required: true,
horizontal: true,
},
],
},
],
},
];
return data;
}
// Support functions for the main test object generation functions (see above)
function twoRandomPositions(positions) {
let randomIndex1 = Math.floor(Math.random() * positions.length);
let randomIndex2 = Math.floor(Math.random() * positions.length);
while (randomIndex1 == randomIndex2) {
randomIndex2 = Math.floor(Math.random() * positions.length);
}
return [positions[randomIndex1], positions[randomIndex2]];
}
function fourRandomPositions(positions) {
if (positions.length < 4) {
throw new Error("The positions array must contain at least 4 elements");
}
let result = [];
let availableIndices = [...Array(positions.length).keys()];
for (let i = 0; i < 4; i++) {
let randomIndex = Math.floor(Math.random() * availableIndices.length);
let selectedIndex = availableIndices[randomIndex];
result.push(positions[selectedIndex]);
availableIndices.splice(randomIndex, 1);
}
return result;
}
function sixRandomPositions(positions) {
if (positions.length < 6) {
throw new Error("The positions array must contain at least 6 elements");
}
let result = [];
let availableIndices = [...Array(positions.length).keys()];
for (let i = 0; i < 6; i++) {
let randomIndex = Math.floor(Math.random() * availableIndices.length);
let selectedIndex = availableIndices[randomIndex];
result.push(positions[selectedIndex]);
availableIndices.splice(randomIndex, 1);
}
return result;
}
function generateRandomLetter() {
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
const randomIndex = Math.floor(Math.random() * 35);
return alphabet[randomIndex];
}
function generateRandomLetterChoice(initialLetter) {
let choices = [initialLetter];
while (choices.length < 10) {
let newLetter = generateRandomLetter();
if (!choices.includes(newLetter)) {
choices.push(newLetter);
}
}
//durchmischen des arrays
for (let i = choices.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[choices[i], choices[j]] = [choices[j], choices[i]];
}
return choices;
}
function generateRandomChoicesTwo(initialElement1, initialElement2) {
let choices1 = [initialElement1];
let choices2 = [initialElement2];
while (choices1.length < 10) {
let newLetter = generateRandomLetter();
if (!choices1.includes(newLetter) && newLetter != initialElement2) {
choices1.push(newLetter);
}
}
//durchmischen des arrays
for (let i = choices1.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[choices1[i], choices1[j]] = [choices1[j], choices1[i]];
}
while (choices2.length < 10) {
let newLetter = generateRandomLetter();
if (!choices2.includes(newLetter) && !choices1.includes(newLetter)) {
choices2.push(newLetter);
}
}
//durchmischen des arrays
for (let i = choices2.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[choices2[i], choices2[j]] = [choices2[j], choices2[i]];
}
return [choices1, choices2];
}
function generateRandomChoicesThree(initialElement1, initialElement2, initialElement3) {
let choices1 = [initialElement1];
let choices2 = [initialElement2];
let choices3 = [initialElement3];
while (choices1.length < 10) {
let newLetter = generateRandomLetter();
if (!choices1.includes(newLetter) && newLetter != initialElement2 && newLetter != initialElement3) {
choices1.push(newLetter);
}
}
//durchmischen des arrays
for (let i = choices1.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[choices1[i], choices1[j]] = [choices1[j], choices1[i]];
}
while (choices2.length < 10) {
let newLetter = generateRandomLetter();
if (!choices2.includes(newLetter) && !choices1.includes(newLetter) && newLetter != initialElement3) {
choices2.push(newLetter);
}
}
//durchmischen des arrays
for (let i = choices2.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[choices2[i], choices2[j]] = [choices2[j], choices2[i]];
}
while (choices3.length < 10) {
let newLetter = generateRandomLetter();
if (!choices3.includes(newLetter) && !choices1.includes(newLetter) && !choices2.includes(newLetter)) {
choices3.push(newLetter);
}
}
//durchmischen des arrays
for (let i = choices3.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[choices3[i], choices3[j]] = [choices3[j], choices3[i]];
}
return [choices1, choices2, choices3];
}
function generiereUndMischePaar(initialesPaar) {
// Funktion, um ein zufälliges Paar von Buchstaben zu generieren
function zufaelligesPaar() {
return generateRandomLetter() + generateRandomLetter();
}
// Initialisiert das Array mit dem übergebenen Paar
let paare = [initialesPaar];
// Generiert 9 zufällige Paare
while (paare.length < 10) {
let neuesPaar = zufaelligesPaar();
// Stellt sicher, dass das generierte Paar einzigartig ist
if (!paare.includes(neuesPaar)) {
paare.push(neuesPaar);
}
}
// Mischung des Arrays
for (let i = paare.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[paare[i], paare[j]] = [paare[j], paare[i]];
}
return paare;
}
// Create 4 Block timeline with 2 Randersacker and 2 Bremen
// Uses previously generated test blocks
function generateBlockSequence() {
const test_data_bremen_seq = [
TQ0001,
TQ0002,
TQ0003,
TQ0004,
TQ0005,
TQ0006,
];
const test_data_randersacker_seq = [
TQ1001,
TQ1002,
TQ1003,
TQ1004,
TQ1005,
TQ1006,
];
const block_sequence = [];
if (Math.random() < 0.5) {
//zuerst 2 zufällige Bremen, dann 2 zufällige Randersacker
let randomIndex1 = Math.floor(Math.random() * test_data_bremen_seq.length);
let randomIndex2 = Math.floor(Math.random() * test_data_bremen_seq.length);
while (randomIndex1 == randomIndex2) {
randomIndex2 = Math.floor(Math.random() * test_data_bremen_seq.length);
}
block_sequence.push(test_data_bremen_seq[randomIndex1]);
block_sequence.push(test_data_bremen_seq[randomIndex2]);
randomIndex1 = Math.floor(Math.random() * test_data_randersacker_seq.length);
randomIndex2 = Math.floor(Math.random() * test_data_randersacker_seq.length);
while (randomIndex1 == randomIndex2) {
randomIndex2 = Math.floor(Math.random() * test_data_randersacker_seq.length);
}
block_sequence.push(test_data_randersacker_seq[randomIndex1]);
block_sequence.push(test_data_randersacker_seq[randomIndex2]);
} else {
//zuerst 2 zufällige Randersacker, dann 2 zufällige Bremen
let randomIndex1 = Math.floor(Math.random() * test_data_randersacker_seq.length);
let randomIndex2 = Math.floor(Math.random() * test_data_randersacker_seq.length);
while (randomIndex1 == randomIndex2) {
randomIndex2 = Math.floor(Math.random() * test_data_randersacker_seq.length);
}
block_sequence.push(test_data_randersacker_seq[randomIndex1]);
block_sequence.push(test_data_randersacker_seq[randomIndex2]);
randomIndex1 = Math.floor(Math.random() * test_data_bremen_seq.length);
randomIndex2 = Math.floor(Math.random() * test_data_bremen_seq.length);
while (randomIndex1 == randomIndex2) {
randomIndex2 = Math.floor(Math.random() * test_data_bremen_seq.length);
}
block_sequence.push(test_data_bremen_seq[randomIndex1]);
block_sequence.push(test_data_bremen_seq[randomIndex2]);
}
return block_sequence;
}
var test_data = generateBlockSequence();
// jsTimelineObjs containing pages for introduction, information and instructions
var welcome = {
type: "external-html",
url: "PCstatic/html/welcome.html",
cont_btn: "consent",
executeScript: true,
};
var instructions0 = {
type: "external-html",
url: "PCstatic/html/instructions_P0.html",
cont_btn: "consent",
executeScript: true,
};
var instructions1 = {
type: "external-html",
url: "PCstatic/html/instructions_P1_no_ emphasis_quality.html",
cont_btn: "consent",
executeScript: true,
};
var instructions2 = {
type: "external-html",
url: "PCstatic/html/instructions_P2.html",
cont_btn: "consent",
executeScript: true,
};
var post_test_survey = {
// still just a test
type: "survey-text",
preamble: "<h3>One last question</h3>",
questions: [
{
prompt:
"What made a point cloud look good or bad? Please describe on what you have focused most. Also write any feedback here.",
rows: 10,
columns: 100,
},
],
on_finish: function () {
var interaction_data = jsPsych.data.getInteractionData();
jsPsych.data.get().addToLast({
interaction: interaction_data.json(),
useragent: user_agent_string,
campaign: urlvar.campaign,
worker: urlvar.worker,
randkey: urlvar.randkey,
verificationcode: verification,
});
},
};
var debrief_block = {
type: "instructions",
allow_keys: false,
pages: [
'<p>Thank you very much for your participation.' +
'<p>Your Microworkers verification code is: <b>'+verification+'</b></p>' +
'<p>Please copy this code to Microworkers to receive your payment, afterwards you can close this window.</p>' +
'<p>----------------------------------------------------------------------------------------------------</p>' +
"<b>What have we tested?</b>" +
"<p>Two methods of reduction are presented alongside the original. The first, known as octree can be described as follows:</p>"+
"<p>The number of points per volume in the cloud is higher in the inner regions and lower in the outer regions. They can be saved as Octrees.</p>" +
'<img id="Bsp1" style="width:600px;height:300px;margin:10px" src="PCstatic/img/Octree.png" />' +
"<p>The space of the cloud is divided into 8 sections, which can be subdivided again. The leaves of the tree are the points.</p>" +
"<p>One method to reduce a point cloud is to subdivide the Octree to a certain size. Then only allow a certain maximum amount of points per leaf (e.g. 2). This especially reduces the cloud in very dense regions and leaves the sparse regions untouched.</p>" +
"<p>Another method is to project the point cloud onto a sphere and then project the sphere onto a 2D picture (similar to 2D maps of earth). The picture is now reduced in size and then converted back into a point cloud.</p>" +
"<p>These and other methods were tested in the survey together with other factors that could influence the QoE of a viewer.</p>" +
"<br>" +
"<p>Thank you again for your participation!</p>" +
"<br>",
],
on_load: function () {
jsPsych.data
.get()
.addToLast({ Window: $(window).width() + "x" + $(window).height() });
saveData(taskName + "data", jsPsych.data.get().json());
},
};
// creates jsTimelineObj for the trial/test run
let letter1 = generateRandomLetter();
let choices = generateRandomLetterChoice(letter1);
let cloudOne = "trial";
let positions = [
[0, 0, 0],
];
let trial_run = {
type: "external-html",
cont_btn: "end-trial",
executeScript: true,
data: {
js_url: "PCstatic/js/pik.js",
controlLetter1: letter1,
positions: positions,
cloudOne: cloudOne,
type: "trial",
},
timeline: [
{ url: `potree/sequentiell_template.html` },
{
type: "survey-multi-choice",
questions: [
{
prompt: "<b>How would you rate the Point Cloud?</b>",
options: total_option,
required: true,
horizontal: true,
},
{
prompt: "<b>What element was displayed in the last point cloud?</b>",
options: choices,
required: true,
horizontal: true,
},
],
},
],
};
let feedback_trial = {
type: "external-html",
url: "PCstatic/html/feedback_no_emphasis_quality.html",
executeScript: true,
cont_btn: "end-trial",
};
const testRunLoop = {
timeline: [trial_run, feedback_trial],
loop_function: function (data) {
var responses = JSON.parse(
jsPsych.data.get().last(2).select("responses").values
);
var controlLetter1 = jsPsych.data.get().last(2).select("controlLetter1")
.values[0];
if (responses.Q1 != controlLetter1) {
//repeat the loop
new Notification("Test Run Feedback");
return true;
} else {
//end the loop
false;
}
},
};
jsPsych.data.addProperties();
// Now build the timeline for the study run. Push all desired objects into it in the correct order
var timeline = [];
timeline.push(start_if)
timeline.push(start_if2)
timeline.push(start_if3)
timeline.push(welcome);
timeline.push(instructions0)
timeline.push(instructions1)
timeline.push(instructions2)
timeline.push(testRunLoop);
test_data.forEach(function (this_test) {
var test_block = {
type: "external-html",
timeline: this_test,
executeScript: true,
cont_btn: "end-trial",
force_refresh: true,
};
timeline.push(test_block);
});
timeline.push(post_test_survey);
// When this block is reached, the captured data is saved
timeline.push(debrief_block);
//jsPsych init function starts test.
jsPsych.init({
timeline: timeline,
show_progress_bar: true,
});