<commit_before>'use strict';

var ocargo = ocargo || {};

ocargo.Level = function(map, van, ui) {
    this.levelId = null;
    this.map = map;
    this.van = van;
    this.ui = ui;
    this.correct = 0;
    this.attemptData = {};
    this.blockLimit = null;
    this.pathFinder = new ocargo.PathFinder(map);
    this.fails = 0;
    this.hintOpened = false;
};

ocargo.Level.prototype.failsBeforeHintBtn = 3;

ocargo.Level.prototype.play = function(program) {

    this.attemptData = {};
    var commandStack = [];

    if (ocargo.level.blockLimit &&
            ocargo.blocklyControl.getBlocksCount() > ocargo.level.blockLimit) {
        enableDirectControl();
        startPopup("Oh no!", "", "You used too many blocks!");
        sendAttempt(0);
        return;
    }

    ocargo.level.attemptData.level = ocargo.level.levelId.toString();

    for (var i = 0; i < program.stack.length; i++) {
        ocargo.level.recogniseStack(program.stack[i], commandStack);
    }

    this.attemptData.commandStack = JSON.stringify(commandStack);
    program.startBlock.selectWithConnected();

    var stepFunction = stepper(this);

    program.stepCallback = stepFunction;
    this.program = program;
    setTimeout(stepFunction, 500);
};

ocargo.Level.prototype.recogniseStack = function(stack, returnStack) {
    if (stack) {
        for (var i = 0; i < stack.length; i++) {
            var command = recogniseCommand(stack[i], returnStack);
            returnStack.push(command);
        }
    }

    function recogniseCommand(command, returnStack) {
        var parsedCommand = {};
        
        if (command instanceof ForwardCommand) {
            parsedCommand.command = 'Forward';
        } else if (command instanceof TurnLeftCommand) {
            parsedCommand.command = 'Left';
        } else if (command instanceof TurnRightCommand) {
            parsedCommand.command = 'Right';
        } else if (command instanceof TurnAroundCommand) {
            parsedCommand.command = 'TurnAround';

        } else if (command instanceof While) {
            var block = [];
            ocargo.level.recogniseStack(command.body, block);
            parsedCommand.command = 'While';
            parsedCommand.condition = command.condition.toString();
            parsedCommand.block = block;

        } else if (command instanceof If) {
            var commands = command.conditionalCommandSets[0];
            var ifBlock = [];
            parsedCommand.condition = commands.condition.toString();
            ocargo.level.recogniseStack(commands.commands, ifBlock);

            if (command.elseCommands) {
                commands = command.elseCommands;
                var elseBlock = [];
                ocargo.level.recogniseStack(commands, elseBlock);
                parsedCommand.elseBlock = elseBlock;
            }
            parsedCommand.command = 'If';
            parsedCommand.ifBlock = ifBlock;
        }
        return parsedCommand;
    }
};

ocargo.Level.prototype.step = function() {
    if (this.program.canStep()) {
        this.program.step(this);

    } else {
    	if (this.van.currentNode === this.map.destination && !this.program.isTerminated) {
            this.win();
        }
    }
};

ocargo.Level.prototype.win = function() {
    console.debug('You win!');
    ocargo.level.pathFinder.getOptimalPath();
    ocargo.level.pathFinder.getOptimalInstructions();
    var score = ocargo.level.pathFinder.getScore(JSON.parse(ocargo.level.attemptData.commandStack));
    console.debug("score: ", score, " out of 200.");
    sendAttempt();
    ocargo.sound.win();
    var message = '';
    var subtitle = "Your score: " + score + " / " + ocargo.level.pathFinder.max;
    enableDirectControl();

    if (ocargo.level.levelId < LEVEL_COUNT) {
        message = '<button onclick="window.location.href=' + "'/game/" +
                    (ocargo.level.levelId + 1) + "'" + '"">Next level</button>';
    } else {
        message = "Congratulations, that's all we've got for you now! <br>" + 
                  "Why not try to create your own road? <br><br> " +
                  '<button onclick="window.location.href=' + "'/game/level_editor'" +
                  '"">Create your own map!</button> </center>' +
                  '<button onclick="window.location.href=' + "'/home/'" + '"">Home</button>';
    }
    startPopup("You win!", subtitle, message);
};

ocargo.Level.prototype.fail = function(msg) {
    var title = 'Oh dear! :(';
    console.debug(title);
    enableDirectControl();
    ocargo.sound.failure();
    startPopup(title, '', msg);
    var level = this;
    level.fails++;
    if (level.fails >= level.failsBeforeHintBtn) {
	    var hintBtns = $("#hintPopupBtn");
		if (hintBtns.length === null || hintBtns.length === 0) {
			$("#myModal > .mainText").append('<p id="hintBtnPara">' +
                '<button id="hintPopupBtn">Are you stuck? Need a hint?</button>' + 
                '</p><p id="hintText">' + HINT + '</p>');
			if(level.hintOpened){
				$("#hintBtnPara").hide();
			} else {
				$("#hintText" ).hide();
				$("#hintPopupBtn").click( function(){
					$("#hintText").show(500);
					$("#hintBtnPara").hide();
					level.hintOpened = true;
				});
			}
    	}
    }
    sendAttempt(0);
};

function stepper(level) {
    return function() {
        try {
            if (level.program.canStep()) {
                level.correct = level.correct + 1;
                level.program.step(level);
            } else {
                if (level.van.currentNode === level.map.destination && !level.program.isTerminated) {
                    level.win();
                } else if(level.program.isTerminated) {
                    level.fail("Program terminated!");
                    $("#myModal > .title").text("Stopping...");
                }
                else {
                    level.fail("You ran out of instructions!");
                    level.program.terminate();
                }
            }
        } catch (error) {
            level.program.terminate();
            throw error;
        }
    };
}

function sendAttempt(score) {

    // Send out the submitted data.
    if (ocargo.level.levelId) {
        var attemptData = JSON.stringify(ocargo.level.attemptData);

        $.ajax({
            url : '/game/submit',<commit_msg>Made program reset correctly when an unexpected error occurs (otherwise you have to refresh the page)<commit_after>'use strict';

var ocargo = ocargo || {};

ocargo.Level = function(map, van, ui) {
    this.levelId = null;
    this.map = map;
    this.van = van;
    this.ui = ui;
    this.correct = 0;
    this.attemptData = {};
    this.blockLimit = null;
    this.pathFinder = new ocargo.PathFinder(map);
    this.fails = 0;
    this.hintOpened = false;
};

ocargo.Level.prototype.failsBeforeHintBtn = 3;

ocargo.Level.prototype.play = function(program) {

    this.attemptData = {};
    var commandStack = [];

    if (ocargo.level.blockLimit &&
            ocargo.blocklyControl.getBlocksCount() > ocargo.level.blockLimit) {
        enableDirectControl();
        startPopup("Oh no!", "", "You used too many blocks!");
        sendAttempt(0);
        return;
    }

    ocargo.level.attemptData.level = ocargo.level.levelId.toString();

    for (var i = 0; i < program.stack.length; i++) {
        ocargo.level.recogniseStack(program.stack[i], commandStack);
    }

    this.attemptData.commandStack = JSON.stringify(commandStack);
    program.startBlock.selectWithConnected();

    var stepFunction = stepper(this);

    program.stepCallback = stepFunction;
    this.program = program;
    setTimeout(stepFunction, 500);
};

ocargo.Level.prototype.recogniseStack = function(stack, returnStack) {
    if (stack) {
        for (var i = 0; i < stack.length; i++) {
            var command = recogniseCommand(stack[i], returnStack);
            returnStack.push(command);
        }
    }

    function recogniseCommand(command, returnStack) {
        var parsedCommand = {};
        
        if (command instanceof ForwardCommand) {
            parsedCommand.command = 'Forward';
        } else if (command instanceof TurnLeftCommand) {
            parsedCommand.command = 'Left';
        } else if (command instanceof TurnRightCommand) {
            parsedCommand.command = 'Right';
        } else if (command instanceof TurnAroundCommand) {
            parsedCommand.command = 'TurnAround';

        } else if (command instanceof While) {
            var block = [];
            ocargo.level.recogniseStack(command.body, block);
            parsedCommand.command = 'While';
            parsedCommand.condition = command.condition.toString();
            parsedCommand.block = block;

        } else if (command instanceof If) {
            var commands = command.conditionalCommandSets[0];
            var ifBlock = [];
            parsedCommand.condition = commands.condition.toString();
            ocargo.level.recogniseStack(commands.commands, ifBlock);

            if (command.elseCommands) {
                commands = command.elseCommands;
                var elseBlock = [];
                ocargo.level.recogniseStack(commands, elseBlock);
                parsedCommand.elseBlock = elseBlock;
            }
            parsedCommand.command = 'If';
            parsedCommand.ifBlock = ifBlock;
        }
        return parsedCommand;
    }
};

ocargo.Level.prototype.step = function() {
    if (this.program.canStep()) {
        this.program.step(this);

    } else {
    	if (this.van.currentNode === this.map.destination && !this.program.isTerminated) {
            this.win();
        }
    }
};

ocargo.Level.prototype.win = function() {
    console.debug('You win!');
    ocargo.level.pathFinder.getOptimalPath();
    ocargo.level.pathFinder.getOptimalInstructions();
    var score = ocargo.level.pathFinder.getScore(JSON.parse(ocargo.level.attemptData.commandStack));
    console.debug("score: ", score, " out of 200.");
    sendAttempt();
    ocargo.sound.win();
    var message = '';
    var subtitle = "Your score: " + score + " / " + ocargo.level.pathFinder.max;
    enableDirectControl();

    if (ocargo.level.levelId < LEVEL_COUNT) {
        message = '<button onclick="window.location.href=' + "'/game/" +
                    (ocargo.level.levelId + 1) + "'" + '"">Next level</button>';
    } else {
        message = "Congratulations, that's all we've got for you now! <br>" + 
                  "Why not try to create your own road? <br><br> " +
                  '<button onclick="window.location.href=' + "'/game/level_editor'" +
                  '"">Create your own map!</button> </center>' +
                  '<button onclick="window.location.href=' + "'/home/'" + '"">Home</button>';
    }
    startPopup("You win!", subtitle, message);
};

ocargo.Level.prototype.fail = function(msg) {
    var title = 'Oh dear! :(';
    console.debug(title);
    enableDirectControl();
    ocargo.sound.failure();
    startPopup(title, '', msg);
    var level = this;
    level.fails++;
    if (level.fails >= level.failsBeforeHintBtn) {
	    var hintBtns = $("#hintPopupBtn");
		if (hintBtns.length === null || hintBtns.length === 0) {
			$("#myModal > .mainText").append('<p id="hintBtnPara">' +
                '<button id="hintPopupBtn">Are you stuck? Need a hint?</button>' + 
                '</p><p id="hintText">' + HINT + '</p>');
			if(level.hintOpened){
				$("#hintBtnPara").hide();
			} else {
				$("#hintText" ).hide();
				$("#hintPopupBtn").click( function(){
					$("#hintText").show(500);
					$("#hintBtnPara").hide();
					level.hintOpened = true;
				});
			}
    	}
    }
    sendAttempt(0);
};

function stepper(level) {
    return function() {
        try {
            if (level.program.canStep()) {
                level.correct = level.correct + 1;
                level.program.step(level);
            } else {
                if (level.van.currentNode === level.map.destination && !level.program.isTerminated) {
                    level.win();
                } else if(level.program.isTerminated) {
                    level.fail("Program terminated!");
                    $("#myModal > .title").text("Stopping...");
                }
                else {
                    level.fail("You ran out of instructions!");
                    level.program.terminate();
                }
            }
        } catch (error) {
            level.fail("Your program crashed!");
            level.program.terminate();
            throw error;
        }
    };
}

function sendAttempt(score) {

    // Send out the submitted data.
    if (ocargo.level.levelId) {
        var attemptData = JSON.stringify(ocargo.level.attemptData);

        $.ajax({
            url : '/game/submit',
{'fraction_non_alphanumeric': 0.1436650695153562, 'fraction_numerical': 0.0031419370041630666, 'mean_word_length': 2.183, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '788474', 'n_tokens_mistral': 3790, 'n_tokens_neox': 3632, 'n_words': 721}