class TriangleSingleRisk extends React.Component { constructor(props) { super(props); } componentDidMount() { let ball_0 = document.getElementById("ball_0") let ball_1 = document.getElementById("ball_1") let ball_2 = document.getElementById("ball_2") let x_start = parseInt(window.getComputedStyle(ball_0).left, 10) + 45 let y_start = parseInt(window.getComputedStyle(ball_0).top, 10) + 12.5 let x_end = parseInt(window.getComputedStyle(ball_1).left, 10) let y_end = parseInt(window.getComputedStyle(ball_1).top, 10) + 25 var newLine = document.createElementNS('http://www.w3.org/2000/svg','line'); newLine.setAttribute('id','line1'); newLine.setAttribute('x1',x_start ); newLine.setAttribute('y1',y_start); newLine.setAttribute('x2',x_end); newLine.setAttribute('y2',y_end); newLine.setAttribute("stroke", "black") $("#lineSVG").append(newLine); x_start = parseInt(window.getComputedStyle(ball_0).left, 10) + 46 y_start = parseInt(window.getComputedStyle(ball_0).top, 10) + 37.5 x_end = parseInt(window.getComputedStyle(ball_2).left, 10) y_end = parseInt(window.getComputedStyle(ball_2).top, 10) + 20 newLine = document.createElementNS('http://www.w3.org/2000/svg','line'); newLine.setAttribute('id','line2'); newLine.setAttribute('x1',x_start ); newLine.setAttribute('y1',y_start); newLine.setAttribute('x2',x_end); newLine.setAttribute('y2',y_end); newLine.setAttribute("stroke", "black") $("#lineSVG").append(newLine); } render() { const upTick = this.props.upTick const downTick = (this.props.downTick || -this.props.upTick) // Use downTick only if supplied return ( <>
) } } class DecisionTree extends React.Component { constructor(props) { super(props); this.componentDidMount = this.componentDidMount.bind(this); this.drawLines = this.drawLines.bind(this); } componentDidMount() { let round = this.props.currentRound let lastID = this.props.drawn[round] let submittedContinuation = [-500, -500] // Initialize with nonsensical values if (this.props.continuationDec) { submittedContinuation = this.props.continuationDec.slice(0,this.props.currentRound + 1) } let submittedStop = submittedContinuation.findIndex(element => element == "Stop") if (this.props.pulse && lastID >= 0 && round <5 && submittedStop == -1) { // Make current ball pulse document.getElementById("ball_"+lastID).classList.add("pulse") } // Draw lines if (round >= 1) { // Clear canvas before painting $("#lineSVG").empty(); for (let i = 1; i <= round; i++) { let ele1 = this.props.drawn[i-1] let ele2 = this.props.drawn[i] if (!(i > submittedStop && submittedStop != -1)) { this.drawLines(ele1, ele2, i) } } } } drawLines(id1, id2, layer) { let start = document.getElementById("ball_"+ id1) let end = document.getElementById("ball_" + id2) let x_start = parseInt(window.getComputedStyle(start).left, 10) + 25 let y_start = 0 let x_end = parseInt(window.getComputedStyle(end).left, 10) let y_end = 0 let color = "black" if (id2-id1 == layer) { //Up move y_start = parseInt(window.getComputedStyle(start).top, 10) + 8 y_end = parseInt(window.getComputedStyle(end).top, 10) + 18 color = "#0f5132" } else if (id2-id1 == layer + 1) { // Down mode y_start = parseInt(window.getComputedStyle(start).top, 10) + 18 y_end = parseInt(window.getComputedStyle(end).top, 10) + 8 color = "#842029" } if (window.getComputedStyle(start).left.indexOf('%') >= 0) { // Need to overwrite values let bg = document.getElementById("lineSVG") let width = parseInt(bg.style.width) let height = parseInt(bg.style.height) x_start = (parseInt(window.getComputedStyle(start).left, 10) * width / 100) + 25 x_end = (parseInt(window.getComputedStyle(end).left, 10) * width / 100) if (id2-id1 == layer) { y_start = (parseInt(window.getComputedStyle(start).top, 10) * height / 100) + 8 y_end = (parseInt(window.getComputedStyle(end).top, 10) * height / 100) + 18 } else if (id2-id1 == layer + 1) { // Down move y_start = (parseInt(window.getComputedStyle(start).top, 10) * height / 100) + 18 y_end = (parseInt(window.getComputedStyle(end).top, 10) * height / 100) + 8 } } var newLine = document.createElementNS('http://www.w3.org/2000/svg','line'); newLine.setAttribute('id',"line_"+layer); newLine.setAttribute('x1',x_start ); newLine.setAttribute('y1',y_start); newLine.setAttribute('x2',x_end); newLine.setAttribute('y2',y_end); newLine.setAttribute("stroke", color) newLine.setAttribute("stroke-width", 2) $("#lineSVG").append(newLine); } render() { const upTick = this.props.upTick const downTick = (this.props.downTick || this.props.upTick) // Use downTick only if supplied // Find stop decision let submittedContinuation = [-500, -500] // Initialize with nonsensical values if (this.props.continuationDec) { submittedContinuation = this.props.continuationDec.slice(0,this.props.currentRound + 1) } let submittedStop = submittedContinuation.findIndex(element => element == "Stop") let stopIndex = 200 if (submittedStop >= 0) { stopIndex = this.props.drawn[submittedStop] } else if (this.props.currentRound == 5 ) { stopIndex = this.props.drawn[this.props.currentRound] } let arrButtons = [] let index = -1 for (let layer = 1; layer <= 5; layer++) { for (let i =0; i < layer; i++) { index ++ // Increase index by one arrButtons.push( ) } } let layer = 6 for (let i =0; i < layer; i++) { index ++ // Increase index by one arrButtons.push( ) } return (
{arrButtons} {/*Very important to wrap the buttons inside a div*/}
) } } // Ball designs function BallSingleRisk(props) { let style = { flex : 1, // MARK width: "50px", // Note: 30 would also work height: "50px", // marginLeft: "20px", // marginTop: "50px", borderRadius: "50%", border: "0.5px solid black", display: "block", position: 'absolute', // MARK change 7 to change no of layers top: "45%", left: (100 / 3 * (props.layer) - 1 - 15).toString() + '%', fontSize: 10, color: "white", // Do not show content padding: "0px", } let idName = "ball_" + props.index; // Background depends on clicked or not if (props.currentNode == props.index) { style.background = "darkblue" } else if (props.isClicked[props.index]) { (props.prob[props.index] === 0) ? (style.background = "black") : (props.prob[props.index] === 100) ? (style.background = "transparent") : (props.prob[props.index] === -100) ? style.background = ("linear-gradient(to right, white, black)") : style.background = "url('/static/img/questionmark_s.png') center center" // Use questionmark picture) } else { // Has not been clicked style.background = props.initialColor } let textShown = "" let greyScheme = { 0 : "#F5F5F5", 10: "#E8E8E8", 20: "#DCDCDC", 30: "#D3D3D3", 40: "#C0C0C0", 50: "#BEBEBE", 60: "#A9A9A9", 70: "#989898", 80: "#808080", 90: "#696969", 100: "#606060", } if (0< props.prob[props.index] && props.prob[props.index] < 100 && !(props.currentNode == props.index)) { textShown = 100-props.prob[props.index] let greyIndex = Math.round((100-props.prob[props.index])/10) * 10; style.background = greyScheme[greyIndex] if (greyIndex >= 80) { style.color = "white" } else { style.color = "black" // Show probability inside node } } // Only for instructions if (props.prob[props.index] === -200 && !(props.currentNode == props.index)) { style.background = "url('/static/img/questionmark_s.png') center center" } return <> } function DisabledBallSingleRisk(props) { //defines the properties of the circle as a button let style = { background: "black", width: "50px", height: "50px", borderRadius: "50%", border: "0.5px solid black", display: "block", position: 'absolute', // MARK change 7 to change no of layers top: (25 + ((props.inlayer-1) * 40) // offset für Elemente in Layer ).toString() + '%', left: (100 / 3 * (props.layer) - 1 - 15).toString() + '%' } let containerstyle = { height: "50px", width: "100px", position: 'absolute', // MARK change 7 to change no of layers top: (25 + ((props.inlayer-1) * 40) // offset für Elemente in Layer ).toString() + '%', left: (100 / 3 * (props.layer) - 1 + 5).toString() + '%' } let idName = "ball_" + props.index; let text = "" if (props.inlayer == 1) { text = "W = £" + (js_vars.upTick).toFixed(2) } else { text = "L = -£" + (js_vars.upTick).toFixed(2) } if (props.drawn == props.index) { //style.background = "blue" if (props.drawn == 1) { style.border = "1px solid #0f5132" style.background = "#d1e7dd" } else if (props.drawn == 2) { style.border = "1px solid #842029" style.background = "#f8d7da" } } style.color = "white" style.textAlign = "center" return <> } function DisabledBallDecision(props) { //defines the properties of the circle as a button let style = { background: "black", width: "25px", height: "25px", borderRadius: "50%", border: "none", display: "block", position: 'absolute', // MARK change 7 to change no of layers top: ((props.inlayer * (100 / 7) + 40) // offset für Elemente in Layer - (props.layer * 0.5 * (100 / 7)) // offeset nach Layer - (0.06 * props.pay_up * (props.layer * 0.5 * (100 / 7))) // Versetzung nach payoff differenz - (0.06 * props.pay_down * (props.layer * 0.5 * (100 / 7))) ).toString() + '%', left: (100 / 7 * (props.layer) - 5).toString() + '%' } let idName = "ball_" + props.index; let textShown = "" if (props.index == props.stopIndex) { style.background = '#FFD700' textShown = "B" style.fontSize = 15 style.color = "black" style.border= "0.5px solid black" } return }