// Note: We keep the data and the states in this component class TriangleExplain extends React.Component { constructor(props) { super(props); this.state = { // Check whether all nodes are clicked isClicked: [ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true ], // Save continuation decision in percent continuation: [ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, // 1, 1, 1, 1, 1, 1, 1 // 1, 1, 1, 1, 1, 1, 1, 1 ], // Save outcome path drawn: [0], indArray: [ [0], [1, 2], [3, 4, 5], [6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19, 20] ], currentRound: 0, coinTossCounter: 0, lastRiskWon:"", payment : [], imagePath: '/static/img/coin_questionmark.png', imagePathGuess: '/static/img/coin.png', winningSide: "", nextCoin: false, hoverNodes: false, riskOutcome: [], coinTossOutcome: [], } this.simulateCoinToss = this.simulateCoinToss.bind(this); this.nextCoin = this.nextCoin.bind(this); this.winningSideUpdate = this.winningSideUpdate.bind(this); this.submitData = this.submitData.bind(this); } componentDidMount() { this.calculateEarnings(); // Hide cursor on triangle if hoverNodes is false const {hoverNodes} = this.state if (!hoverNodes) { var balls = document.getElementsByClassName("ball"); for (let i = 0; i < balls.length; i++) { balls.item(i).style.cursor = 'default'; } document.getElementById("treeStructure").style.cursor = 'default'; } } winningSideUpdate(chosenSide) { // Disable winning side buttons var ele = document.getElementsByName("winningSideInput"); for(var i=0;i this.simulateCoinToss(), 500 ); } simulateCoinToss() { const userInput = this.state.winningSide let {currentRound, drawn, coinTossCounter, lastRiskWon, riskOutcome, coinTossOutcome} = this.state coinTossOutcome.push(userInput) //document.getElementById("pickWinningSide").classList.add("d-none") // Grey background for selection section document.getElementById("pickWinningSide").classList.remove("alert-warning"); document.getElementById("pickWinningSide").classList.add("alert-secondary"); // Disable winniing side buttons var ele = document.getElementsByName("winningSideInput"); for(var i=0;i
From now on, you again resolve the single risk with one click.":""} ` } } else { document.getElementById("coinTossLost").classList.remove("d-none") document.getElementById("moveDown").classList.remove("d-none") document.getElementById("placeholderFooter").classList.add("d-none") drawn[currentRound] = drawn[currentRound-1] + currentRound + 1 this.setState({drawn}) if (currentRound < 3 && coinTossCounter <3) { document.getElementById("explainDiv").classList.remove("d-none") document.getElementById("explainText").innerHTML = ` Because you lost this repetition of the single risk, you moved down in the triangle depicted on the right. Your accumulated earnings decreased by £${js_vars.upTick.toFixed(2)}, to £${parseFloat(this.state.payment[this.state.drawn[this.state.drawn.length-1]]).toFixed(2)}. ${(currentRound == 3) ? "

From now on, you can again resolve the single risk with one click.":""} ` } } riskOutcome.push(drawn[currentRound]) if (currentRound == 5) { this.props.treeCompleted(); this.setState({hoverNodes:true}, () => { // Enable mouse pointer on tree var balls = document.getElementsByClassName("ball"); for (let i = 0; i < balls.length; i++) { balls.item(i).style.cursor = 'auto'; } document.getElementById("treeStructure").style.cursor = 'auto'; }) } this.setState({ nextCoin: true, coinTossCounter: coinTossCounter + 1, currentRound, lastRiskWon: (userInput == coinOutcome), riskOutcome: riskOutcome, coinTossOutcome: coinTossOutcome, }) } coin() { let coinSide = "" let outcome = Math.round(Math.random()) if (outcome === 0){ coinSide = "H" this.setState({ imagePath: '/static/img/coin_h.png', }) } else { coinSide = "T" this.setState({ imagePath: '/static/img/coin_t.png', }) } return coinSide } nextCoin() { this.setState({ imagePath: '/static/img/coin_questionmark.png', imagePathGuess: '/static/img/coin.png', winningSide: '', nextCoin: false, }) document.getElementById("coinTossWon").classList.add("d-none") document.getElementById("coinTossLost").classList.add("d-none") document.getElementById("moveUp").classList.add("d-none") document.getElementById("moveDown").classList.add("d-none") document.getElementById("placeholderFooter").classList.remove("d-none") if (this.state.coinTossCounter < 4) { document.getElementById("explainDiv").classList.add("d-none") } // Yellow background for selection section document.getElementById("pickWinningSide").classList.remove("alert-secondary"); document.getElementById("pickWinningSide").classList.add("alert-warning"); var ele = document.getElementsByName("winningSideInput"); for(var i=0;i { const {indArray} = this.state; let upTick = js_vars.upTick let payment = [] let j = 0 for (let i in indArray) { for (let k in indArray[i]) { payment[j] = upTick * i - 2 * k * upTick; j++ } } this.setState({payment}) } mouseEnter = (e, currentNode) => { const {payment, hoverNodes} = this.state if (hoverNodes){ setTimeout(function() { document.getElementById("accumulatedEarnings").classList.remove("d-none") document.getElementById("accumulatedEarnings").style.backgroundColor = "#72C3F1" document.getElementById("drawnEarningsText").classList.add("d-none") document.getElementById("accumulatedEarnings").innerHTML = ` Your accumulated earnings at this ball are
£${payment[currentNode].toFixed(2)} ` }, 300); setTimeout(function() { document.getElementById("accumulatedEarnings").style.backgroundColor = "" }, 900); } else { var balls = document.getElementsByClassName("ball"); for (let i = 0; i < balls.length; i++) { balls.item(i).style.cursor = 'default'; } } } mouseLeave = () => { setTimeout(function() { document.getElementById("accumulatedEarnings").classList.add("d-none") document.getElementById("drawnEarningsText").classList.remove("d-none") }, 300); } voidFunction(){ return } // Submit information buttons work submitData = () =>{ let data = { riskOutcome: this.state.riskOutcome, coinToss: this.state.coinTossOutcome, } liveSend(data) // Sends state to oTree backend } render () { return ( <>
{/* Left column */}
Coin toss: Win or lose?
Coin toss outcome The winning side
 
Heads Tails
this.winningSideUpdate("H")} className="largerRadio"/> this.winningSideUpdate("T")} className="largerRadio"/>
You won this single risk.
You lost this single risk.
{/* Right column */}
The repeated risk
Your accumulated earnings at this ball are

£{parseFloat(this.state.payment[this.state.drawn[this.state.drawn.length-1]]).toFixed(2)}
You moved up.
{(this.state.coinTossCounter >= 3) ?
:<> }
You moved down.
{(this.state.coinTossCounter >= 3) ?
:<> }
{ (this.state.coinTossCounter < 4) ?
{((this.state.winningSide != "") && (this.state.nextCoin)) ? : <> }
: <>} ) } }