oTree Forum >

Problem passing results to dataset with javascript

#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

Write a reply

Set forum username