xxxxxxxxxx
166
/*
notes:
since we're ranking similarity i really don't see the point of multiple sliders so other than (maybe) stylistic congruency and general edits (link to sheets etc.) i dont see what should change.
This similarity rating demo can load multiple images as stimuli and display 2 images at a time. The order is fully randomized. Image file names/numbers and rating values will be stored, and can be downloaded afterwards.
*/
const filenames = ['1.jpg', '2.jpg', '3.jpg', '4.jpg'];
var imgX1 = 100;
var imgX2 = 620;
var imgY = 30;
var imgSize = 480;
var lineY = imgY + imgSize + 160;
var imgAmount = 4;
var img = [];
var sliderX1 = 150;
var sliderX2 = 1050;
var sliderBallRadius = 18;
var ratingValue;
var leftLabel = 'not so similar';
var rightLabel = 'very similar';
var labelYOffset = 35;
var trialNumber = 1;
var imgMatrix = makeCombinations(imgAmount);
function preload() {
// for (var i = 1; i <= imgAmount; i++) {
// print('img/' + i + '.jpg');
// img[i] = loadImage('img/' + i + '.jpg');
// }
for (var i = 0; i < filenames.length; i++) {
img[i] = loadImage('img/' + filenames[i]);
}
}
function setup() {
shuffleMatrix(imgMatrix);
createCanvas(1200, 800);
data = new p5.Table();
data.addColumn('Camera1');
data.addColumn('Camera2');
data.addColumn('Similarity Ratings');
}
function draw() {
background(220);
if (trialNumber <= imgMatrix.length) {
image(img[imgMatrix[trialNumber - 1][0]], imgX1, imgY, imgSize, imgSize);
image(img[imgMatrix[trialNumber - 1][1]], imgX2, imgY, imgSize, imgSize);
fill(0, 102, 153);
noStroke();
textSize(22);
textAlign(LEFT);
text('Please rate the similarity of the 2 cameras showed above', 100, 560);
fill(80);
textSize(18);
text('Move mouse horizontally to adjust slider, click to respond and proceed to next trial.', 100, 590);
strokeWeight(4);
stroke(80);
line(sliderX1, lineY, sliderX2, lineY);
drawSliderTicks();
fill(158, 194, 208);
stroke(50);
strokeWeight(4);
ellipse(sliderX(mouseX), lineY, sliderBallRadius);
fill(0);
noStroke();
textSize(18);
text(leftLabel, sliderX1, lineY + labelYOffset);
textAlign(RIGHT);
text(rightLabel, sliderX2, lineY + labelYOffset);
} else {
//final page, data download instruction
fill(0, 102, 153);
noStroke();
textSize(28);
textAlign(CENTER);
text('The End', 600, 400);
fill(100);
textSize(20);
text('Press Enter to download the rating data', 600, 450);
}
}
function mouseClicked() {
if (trialNumber <= imgMatrix.length) {
ratingValue = round(100 * ratingX(mouseX));
// save the data
let newRow = data.addRow();
newRow.setNum('Camera1', imgMatrix[trialNumber - 1][0]);
newRow.setNum('Camera2', imgMatrix[trialNumber - 1][1]);
newRow.setNum('Similarity Ratings', ratingValue);
trialNumber++;
}
}
function keyPressed() {
if (keyCode === ENTER) {
saveTable(data, 'Camera Similarity Rating.csv');
}
}
function sliderX(mx) {
var mq = max([mx, sliderX1]);
return min([mq, sliderX2]);
}
function ratingX(mx) {
var mq = max([mx, sliderX1]);
var mq = min([mq, sliderX2]);
return map(mq, sliderX1, sliderX2, 0, 1);
}
function drawSliderTicks() {
var tickHeight = -8;
var nTicks = 6;
for (var i = 0; i < nTicks; i++) {
var xtemp = map(i, 0, nTicks - 1, sliderX1, sliderX2);
line(xtemp, lineY, xtemp, lineY - tickHeight);
}
}
function makeCombinations(n) {
//create a 2 by n matrix
holder = [];
for (var i = 1; i < n + 1; i++) {
for (var j = i + 1; j < n + 1; j++) {
holder.push([i, j]);
}
}
return holder;
}
function shuffleOrder(a) {
// The modern version of the Fisher–Yates shuffle
// https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm
var j, x;
for (var i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = a[i];
a[i] = a[j];
a[j] = x;
}
}
function shuffleMatrix(matrix){
shuffleOrder(matrix);
for (var i = 0;i<matrix.length;i++) {
shuffleOrder(matrix[i]);
}}