#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