<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BinaryNumberContentViewer</title>
    <!-- Since GitHub Raw files use text/plain as MIME type the script cannot be executed when linking directly, instead routed over jsdelivr-->
    <script src="https://cdn.jsdelivr.net/gh/MicroContent/BinaryNumberContentViewer/seamless.child.min.js"></script>
    <script type="application/javascript">
        var connection = window.seamless.connect({
            url: window.location.url,
            allowStyleInjection: true,
        });

        connection.receive(function(data) {
            switch(data.type) {
                case 'setContent':
                    // parent for varying type of input sends data as special object; data.main[0] is the array of arrays with your message inside
                    window.data = {number: parseInt(data.main[0].number,10)}
                    binaryString = parseInt(data.main[0].number,10).toString(2);
                    solution = binaryString.split('').map(function (c) {
                        return c === "1"
                    });
                    init();
                    break;

                case 'submit':
                    if (data.value === 'true'){
                        onSubmit();
                    }
                    break;

                case 'getXapiStatements':
                    stmts = data.stmts;
                    break;
            }
        });

        function init() {
            if(window.data === undefined) {
                window.data = {number: 255};
                binaryString
            }
            document.getElementById('question').innerHTML = "What is the binary representation of " +
                window.data.number + "?<br />Click on the switches to set the correct binary number.";
        }
        function updateLayout() {
            connection.send({
                type: 'updateLayout'
            });
        }
        function sendStatement(stmt) {
            connection.send({
                type: 'sendXapiStatement',
                stmt: stmt
            });
        }
        function getStatements() {
            connection.send({
                type: 'getXapiStatements'
            });
        }
    </script>
</head>
<body>
<!-- EXAMPLE CODE - EDIT BELOW TO VIEW DATA -->
<div style="text-align: center;">
    <p id="question"></p>
    <button id="showHintBtn" class="btn btn-primary" onclick="showHideHint()">Show Hint</button>
    <canvas id="canvas" width="600" height="300" style="width: 100%"></canvas>
    <p id="solution"></p>
</div>
<div id="statistics"></div>
<script type="application/javascript">

    function showHideHint() {
        showHint = !showHint;
        draw();
        document.getElementById("showHintBtn").innerHTML = showHint ? "Hide Hint" : "Show Hint";
    }

    function draw() {
        ctx.clearRect(0, 0, 600, 300);
        for (var i = 0; i < 8; i++) {
            if (showHint) {
                ctx.beginPath();
                ctx.font = "24px Arial";
                var text = (Math.pow(2, (7 - i))).toString();
                var twh = Math.round(ctx.measureText(text).width / 2);
                ctx.fillStyle = "#000000";
                ctx.fillText(text, i * 60 + 60 + 20 - twh, 60);
                ctx.closePath();
            }
            ctx.beginPath();
            ctx.strokeStyle = isShowingSolution && active[i] && !solution[i] ? "#ff0000" : "#000000";
            ctx.lineWidth = isShowingSolution && active[i] && !solution[i] ? 3 : 1;
            ctx.arc(i * 60 + 60 + 20, 100, 20, 0, Math.PI * 2, false);
            ctx.stroke();
            if (active[i] || (isShowingSolution && solution[i])) {
                ctx.fillStyle = active[i] ? ((isShowingSolution && !solution[i]) ? "#66ff66" : "#00aa00") : "#ff6666";
                ctx.fill();
            }
            ctx.closePath();
            ctx.lineWidth = 1;
            ctx.beginPath();
            ctx.font = "60px Arial";
            var text = active[i] ? "1" : "0";
            var twh = Math.round(ctx.measureText(text).width / 2);
            ctx.fillStyle = !isShowingSolution || (solution[i] === active[i]) ? "#000000" : "#ff0000";
            ctx.fillText(text, i * 60 + 60 + 20 - twh, 200);
            ctx.closePath();
            if (isShowingSolution) {
                ctx.beginPath();
                ctx.font = "60px Arial";
                var text = solution[i] ? "1" : "0";
                var twh = Math.round(ctx.measureText(text).width / 2);
                ctx.fillStyle = "#00aa00";
                ctx.fillText(text, i * 60 + 60 + 20 - twh, 260);
                ctx.closePath();
            }
        }
    }

    function onCanvasClicked(event) {
        if (!isShowingSolution) {
            var outerRect = {left: 0, top: 0};
            var rect = canvas.getBoundingClientRect();
            var x = (event.clientX - rect.left - outerRect.left) * (600 / (rect.right - rect.left));
            var y = (event.clientY - rect.top - outerRect.top) * (300 / (rect.bottom - rect.top));
            for (var i = 0; i < 8; i++) {
                if (Math.pow(x - (i * 60 + 60 + 20), 2) + Math.pow(y - 100, 2) <= 400) {
                    active[i] = !active[i];
                    onInteraction();
                    break;
                }
            }
        }
        draw();
    }

    function onInteraction() {
        var stmt = {};
        // actor is set by hosting application
        stmt.actor = undefined;
        stmt.verb = {
            "id": "http://adlnet.gov/expapi/verbs/interacted",
            "display": {
                "de-DE": "interagierte",
                "en-US": "interacted",
                "fr-FR": "a interagi",
                "es-ES": "interactuó"
            }
        };
        stmt.object = getXapiObject();
        var responses = [];
        for (var i = 0; i < 8; i++) {
            if (active[i]) {
                responses.push(Math.pow(2, (7 - i)).toString());
            }
        }
        stmt.result = {
            response: responses.reduce(function (acc, e) {
                return (acc.length > 0 && e.length > 0) ? acc + "[,]" + e : acc.length > 0 ? acc : e;
            }, "")
        };
        sendStatement(stmt);
    }

    function getXapiObject() {
        // may be called on init()

        binaryString = window.data.number.toString(2);
        solution = binaryString.split('').map(function (c) {
            return c === "1"
        });
        return {
            "objectType": "Activity",
            // id is set by hosting application
            "id": undefined,
            "definition": {
                "description": {
                    "de-AT": "What is the binary representation of " + window.data.number + "?"
                },
                "type": "http://adlnet.gov/expapi/activities/cmi.interaction",
                "interactionType": "choice",
                "choices": [128, 64, 32, 16, 8, 4, 2, 1].map(function (e, i) {
                    return {
                        id: i.toString(),
                        description: {
                            "de-AT": i.toString()
                        }
                    }
                }),
                "correctResponsesPattern": [solution.map(function (e, i) {
                    return e ? Math.pow(2, (7 - i)).toString() : ""
                })
                    .reduce(function (acc, e) {
                        return (acc.length > 0 && e.length > 0) ? acc + "[,]" + e : acc.length > 0 ? acc : e;
                    }, "")]
            }
        };
    }

    function onSubmit() {
        if (!isShowingSolution) {
            var responses = [];
            var allRight = true;
            // assign classes and disable
            for (var i = 0; i < 8; i++) {
                allRight = allRight && (active[i] === solution[i]);
                if (active[i]) {
                    responses.push(Math.pow(2, (7 - i)).toString());
                }
            }
            var stmt = {};
            // actor is set by hosting application
            stmt.actor = undefined;
            stmt.verb = {
                "id": "http://adlnet.gov/expapi/verbs/answered",
                "display": {
                    "de-DE": "beantwortete",
                    "en-US": "answered",
                    "fr-FR": "a répondu",
                    "es-ES": "contestó"
                }
            };
            stmt.object = getXapiObject();
            stmt.result = {
                response: responses.reduce(function (acc, e) {
                    return (acc.length > 0 && e.length > 0) ? acc + "[,]" + e : acc.length > 0 ? acc : e;
                }, ""),
                success: allRight
            };
            sendStatement(stmt);
            isShowingSolution = true;
            document.getElementById('solution').innerHTML = "Your number is: "
                + active.map(function (e, i) {
                    return e ? Math.pow(2, 7 - i) : 0;
                }).reduce(function (a, e) {
                    return a + e;
                }, 0) + "<br />" + (allRight ? "Correct!" : "Try again!");

            getStatements();
            setTimeout(function() { showStatistics(stmt.result) }, 1000);
            draw();
        } else {
            // remove classes and enable
            isShowingSolution = false;
            document.getElementById('solution').innerHTML = "";
            hideStatistics();
            draw();
        }
        updateLayout();
    }

    function showStatistics(result) {
        var answered = [];
        stmts.forEach(function(s) {
            if (s.verb.id.indexOf('answered') !== -1) {
                answered.push(s);
            }
        });
        if(answered.length === 0) return;
        var correct = [];
        var wrongRespones = {};
        var answeredWrong = 0;
        answered.forEach(function(s) {
            if (s.result.success) {
                correct.push(s);
            } else {
                if (wrongRespones[s.result.response] === undefined) {
                    wrongRespones[s.result.response] = 1;
                } else {
                    wrongRespones[s.result.response]++;
                }

                if (!result.success && result.response === s.result.response) {
                    answeredWrong++;
                }
            }
        });

        var max = {key: '', value: 0};
        for (var response in wrongRespones) {
            if (wrongRespones[response] > max.value)  {
                max.key = response;
                max.value = wrongRespones[response];
            }
        };
        var showLearningMsg = (max.key === result.response && max.value > 4) ? true : false;

        document.getElementById('statistics').innerHTML =
            'Card answered: ' + answered.length + ' time(s)' +
            '<br>Ansered correct: ' + correct.length + ' time(s) (' +  Math.round(correct.length/answered.length*10000)/100 + '%)' +
            (answeredWrong > 1 ? ('<br>You\'ve made the same mistake before ' + (answeredWrong-1) +' time(s).') : ('')) +
            (showLearningMsg ? ('<br>This seems to be your most common mistake, try to reflect why you keep answering that way!') : (''));
        updateLayout();
    }

    function hideStatistics() {
        document.getElementById('statistics').innerHTML = '';
    }

    init();
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext("2d");
    var active = [false, false, false, false, false, false, false, false];
    var stmts = [];
    var binaryString = window.data.number.toString(2);
    var solution = binaryString.split('').map(function (c) {
        return c === "1"
    });
    var showHint = false;
    var isShowingSolution = false;
    draw();
    canvas.addEventListener('click', onCanvasClicked);
    // updateLayout();
</script>
<!-- END OF EXAMPLE CODE -->
</body>
</html>