#1
by
AngelVJimenez
Hello,
I have created an experiment with OTree Studio in which participants individually play with a wheel of fortune. The wheel of fortune has 20 segments, 14 of them represent “success” and 6 “fail”. I want that this outcome is passed to the data.
I want the data to have a spin_result variable with two possible values: 1 (if the wheel results in “success”) and 0 (if the wheel results in “fail”).
I have been able to have a working wheel of fortune. Unfortunately, I have not been able to pass the result in the wheel to the data.
Does somebody know how to do this? Thank you.
My code is the following.
CONSTANTS:
C.SUCCESS_SEGMENTS = 14
C.TOTAL_SEGMENTS = 20
PLAYER FIELD:
spin_result = models.IntegerField()
VARS_FOR TEMPLATE:
def vars_for_template(player):
return {
'successSegments': C.SUCCESS_SEGMENTS,
'totalSegments': C.TOTAL_SEGMENTS,
}
HTML & JAVASPRIPT
Note: the html template and javascript has been adapted from here: https://codesandbox.io/s/wheel-of-fortune-1475d?from-embed=&file=/src/index.js
HTML TEMPLATE:
<meta charset="UTF-8" />
<script defer src="src/index.js"></script>
<link rel="stylesheet" href="src/styles.css" />
<div id="wheelOfFortune">
<canvas id="wheel" width="500" height="500"></canvas>
<div id="spin">SPIN</div>
</div>
<form id="spinForm" action="" method="post">
<input type="hidden" name="spin_result" value="">
</form>
JAVASCRIPT:
// Retrieve data from OTree
let successSegments = {{ successSegments }};
let totalSegments = {{ totalSegments }};
let failureSegments = totalSegments - successSegments;
let sectors = [];
let ratio = successSegments / failureSegments;
let successPlaced = 0;
let failurePlaced = 0;
for (let i = 0; i < totalSegments; i++) {
if ((successPlaced / (failurePlaced + 1)) < ratio && successPlaced < successSegments) {
sectors.push({ color: '#3cb878', label: 'success' });
successPlaced++;
} else if (failurePlaced < failureSegments) {
sectors.push({ color: '#ee1c24', label: 'fail' });
failurePlaced++;
}
}
const rand = (m, M) => Math.random() * (M - m) + m;
const tot = sectors.length;
const spinEl = document.querySelector('#spin');
const ctx = document.querySelector('#wheel').getContext('2d');
const dia = ctx.canvas.width;
const rad = dia / 2;
const PI = Math.PI;
const TAU = 2 * PI;
const arc = TAU / sectors.length;
const friction = 0.991;
let angVel = 0;
let ang = 0;
let hasSpun = false; // Added to ensure only one spin
const getIndex = () => Math.floor(tot - (ang / TAU) * tot) % tot;
function drawSector(sector, i) {
const ang = arc * i;
ctx.save();
ctx.beginPath();
ctx.fillStyle = sector.color;
ctx.moveTo(rad, rad);
ctx.arc(rad, rad, rad, ang, ang + arc);
ctx.lineTo(rad, rad);
ctx.fill();
ctx.translate(rad, rad);
ctx.rotate(ang + arc / 2);
ctx.textAlign = 'right';
ctx.fillStyle = '#fff';
ctx.font = 'bold 30px sans-serif';
ctx.fillText(sector.label, rad - 10, 10);
ctx.restore();
}
function rotate() {
const sector = sectors[getIndex()];
ctx.canvas.style.transform = `rotate(${ang - PI / 2}rad)`;
spinEl.textContent = !angVel ? 'SPIN' : sector.label;
spinEl.style.background = sector.color;
if (!angVel && hasSpun) {
// Set the result value based on the wheel outcome
let resultValue = (sector.label === "success") ? 1 : 0;
// Update the hidden input field with the result
document.querySelector("input[name=spin_result]").value = resultValue;
setTimeout(() => {
document.querySelector("#spinForm").submit();
}, 3000);
}
}
function frame() {
if (!angVel) return;
angVel *= friction;
if (angVel < 0.002) angVel = 0;
ang += angVel;
ang %= TAU;
rotate();
}
function engine() {
frame();
requestAnimationFrame(engine);
}
function init() {
sectors.forEach(drawSector);
rotate();
engine();
spinEl.addEventListener('click', () => {
if (!angVel && !hasSpun) {
angVel = rand(0.25, 0.45);
hasSpun = true; // Mark the wheel as spun
}
});
}
init();
I imagine the problem is something to do with the live_method.
Because of this, I have defined a player function called “live_method”:
def live_method(player, data):
player.spin_result = data
And then created another function within the javascript:
function sendValue_spin_result() {
console.log('in sending');
liveSend(parseInt(spinForm.value));
}
Unfortunately, it does not record the data in the dataset.
Can you help? Thanks
Angel
#2
by
Ignacio_Alastrue
Hi Angel, Please contact me on ignacio.alastrue@playstudies.com and I will further explain. Best Ignacio