<commit_before>pencilBoxApp.controller('CreateQuizController', ['$scope', '$routeParams', 'Contents','CreateQuiz', '$http', '$q','$timeout',
    function ($scope, $routeParams, Contents, CreateQuiz, $http, $q, $timeout) {
        $scope.hasChange = false;
        $scope.hasError = false;
        $scope.current_grade = $routeParams.gradeId;
        $scope.current_subject = $routeParams.subjectId;
        $scope.current_chapter = $routeParams.chapterId;
        $scope.contents = Contents.query({
            chapterId: $routeParams.chapterId,
            subjectId: $routeParams.subjectId, gradeId: $routeParams.gradeId
        });

        $scope.questionTypes = {
            "fill-the-blanks": {
                "name": "Fill the blanks",
                "image": "fill-the-blanks.png",
                "type": "fill-the-blanks",
                defaultQuestion: {
                    "type": "fill-the-blanks",
                    "question": "",
                    "questionCollection": [],
                    "marks": 1
                }
            },
            "multiple-options": {
                "name": "Multiple options",
                "image": "multiple-options.png",
                "type": "multiple-options",
                defaultQuestion: {
                    "marks": 1,
                    "type": "multiple-options",
                    "question": "",
                    "options": [
                        {
                            "value": "",
                            "answer": false
                        },
                        {
                            "value": "",
                            "answer": false
                        }
                    ]
                }
            },
            "match-the-following": {
                "name": "Match the following",
                "image": "match-the-following.png",
                "type": "match-the-following",
                defaultQuestion: {
                    "marks": 1,
                    "type": "match-the-following",
                    "questions": [
                        {
                            "question": "",
                            "answer": ""
                        },
                        {
                            "question": "",
                            "answer": ""
                        }
                    ]
                }
            }
        };

        var getDefaultQuestion = function (type) {
            return angular.copy($scope.questionTypes[type].defaultQuestion);
        };

        $scope.quizJson = {questions: [getDefaultQuestion('fill-the-blanks')]};
        $scope.currentQuestionIndex = 0;

        $scope.showOverlay = function (element) {
            $scope.overlay = new Overlay(element, {closeHandler: true});
        };

        $scope.closeQuiz = function($event) {
            $event.preventDefault();
            var options = {
                title: "Changes not saved",
                description: "You have unsaved changes in the quiz. Do you want to save it?",
                className: "master-password",
                buttons: ["ok", "cancel"],
                buttonName: ["yes", "no"],
                closeHandler: true
            };
            new CustomDialog($q, options).show().then(function () {
                $scope.saveQuiz();
            }).catch(function() {
                $scope.closeOverlay();
            });
        };

        $scope.closeOverlay = function ($event) {
            $scope.overlay.disposeOverlay();
            var url = window.location.href;
            url = url.replace("update-quiz/", "");
            url = url.replace("create-quiz/", "");
            window.location.href = url.replace("update-quiz/", "");
        };

        $scope.overlayLoaded = function () {
            $scope.showOverlay(document.getElementById("create-quiz-mask"));
        };

        $scope.getCurrentQuestionObject = function (index) {
            if (typeof index != "undefined") {
                return $scope.quizJson.questions[index];
            }
            return getDefaultQuestion($scope.currentQuestion.type);
        };

        $scope.addRow = function () {
            if ($scope.currentQuestion.type === "multiple-options") {
                if ($scope.currentQuestion.options.length < 5) {
                    $scope.currentQuestion.options.push({"value": "", "answer": false});
                } else {
                    var options = {
                        title: "Alert",
                        description: "Cannot add more than 5 options",
                        buttons: ["ok"]
                    };
                    new CustomDialog($q, options);
                }
            } else {
                if ($scope.currentQuestion.questions.length < 10) {
                    $scope.currentQuestion.questions.push({"question": "", "answer": ""});
                } else {
                    options = {
                        title: "Alert",
                        description: "Cannot add more than 10 options",
                        buttons: ["ok"]
                    };
                    new CustomDialog($q, options);
                }
            }
            $scope.isValidMultipleOption();
        };
        $scope.deleteRow = function (index) {
            var key = $scope.currentQuestion.type === "multiple-options" ? "options" : "questions";
            if ($scope.currentQuestion[key].length > 2) {
                $scope.currentQuestion[key].splice(index, 1);
            }
            $scope.isValidMultipleOption();
        };

        $scope.saveQuestion = function () {
            if ($scope.hasError()) {
                var options = {
                    title: "Alert",
                    description: "Please fill the red field",
                    buttons: ["ok"]
                };
                new CustomDialog($q, options);
                return false;
            }

            if ($scope.currentQuestion.type === "fill-the-blanks") {
                // Converting into question collection

                var splits = $scope.currentQuestion.question.split('__');
                $scope.currentQuestion.questionCollection = splits.map(function (el, i) {
                    if (i % 2 == 0) {
                        return {type: "question", value: el.trim()};
                    } else {
                        return {type: "answer", value: el.trim()};
                    }
                });
            }

            $scope.currentQuestionIndex = $scope.quizJson.questions.length - 1;
            return true;
        };

        var refreshCurrentQuestion = function () {
            $scope.currentQuestion = $scope.quizJson.questions[$scope.currentQuestionIndex];
        };
        $scope.$watch('currentQuestionIndex', refreshCurrentQuestion);

        $scope.addQuestion = function () {
            //if(!$scope.saveQuestion()) return;
            $scope.quizJson.questions.push($scope.getCurrentQuestionObject());
            $scope.currentQuestionIndex = $scope.quizJson.questions.length - 1;
            $scope.isValidMultipleOption();
        };

        $scope.hasError = function () {
            return document.querySelectorAll(".question-box .error, .question-box .ng-invalid").length > 0;
        };

        $scope.selectQuestion = function (index) {
            $scope.currentQuestionIndex = index;
        };

        var insertAt = function (mainString, insertString, index) {
            var leftPart = mainString.substr(0, index);
            var rightPart = mainString.substr(index, mainString.length);
            return leftPart + insertString + rightPart;
        };

        $scope.addBlank = function () {
            var answer;
            var caretPosition = document.getElementById('fill-in-the-blank-question').selectionStart;
            $scope.promptDialog(null, null, function(inputText){
                answer = inputText;
                $timeout(function() {
                    $scope.currentQuestion.question = insertAt($scope.currentQuestion.question, ' __' + answer + '__ ', caretPosition);
                },0);

            });
        };

        $scope.fillInTheBlankPreview = function () {
            if (!$scope.currentQuestion) return '';
            return $scope.currentQuestion.question ? $scope.currentQuestion.question.replace(/__.*?__/g, '_______') : "";
        };

        $scope.previousQuestion = function () {
            $scope.currentQuestionIndex = Math.max(0, $scope.currentQuestionIndex - 1);
        };
        $scope.nextQuestion = function () {
            $scope.currentQuestionIndex = Math.min($scope.quizJson.questions.length - 1, $scope.currentQuestionIndex + 1);
        };

        $scope.isValidMultipleOption = function () {
            if ($scope.currentQuestion.type === "multiple-options") {
                $scope.mcHasError = true;
                for (var i = 0, length = $scope.currentQuestion.options.length; i < length; i++) {
                    if ($scope.currentQuestion.options[i].answer) {
                        $scope.mcHasError = false;
                        break;
                    }
                }
            }
        };

        $scope.canDeleteQuestion = function () {
            return $scope.quizJson.questions.length > 1;
        };
        $scope.deleteQuestion = function () {
            if (!$scope.canDeleteQuestion()) return;
            var dialogInstance = new CustomDialog($q, {
                title: "Alert",
                description: "Are you sure you want to delete this question?",
                buttons: ["ok", "cancel"]
            }).show();
            dialogInstance
                    .then(function () {
                        $scope.quizJson.questions.splice($scope.currentQuestionIndex, 1);
                        if ($scope.currentQuestionIndex > $scope.quizJson.questions.length - 1) {
                            $scope.currentQuestionIndex = $scope.quizJson.questions.length - 1;
                        } else {
                            refreshCurrentQuestion();
                        }
                    })
                    .catch(function (e) {
                    });
        };

        $scope.isExistingQuestion = function () {
            return $scope.currentQuestionIndex;
        };

        $scope.errorsForQuestion = function (question) {
            if (question.type === "fill-the-blanks") {
                if (question.question.trim().length === 0) {
                    return "Please fill the question";
                } else if (!question.question.trim().match(/__[^_]+__/)) {
                    return "Please provide answer";
                }
            } else if (question.type === "match-the-following") {
                if (question.questions.filter(function (option) {
                            return option.question.trim() === '' || option.answer.trim() === ''
                        }).length > 0) {
                    return "Please fill all the fields.";
                }
            } else {
                if (question.question.trim().length === 0) {
                    return "Please fill the question";
                }
                else if (question.options.filter(function (option) {
                            return option.value.trim() === ''
                        }).length > 0) {
                    return "Please fill all the answer options.";
                }
                else if (question.options.filter(function (option) {
                            return option.answer
                        }).length <= 0) {
                    return "Please set answer to the question";
                }
            }
        };

        var processFib = function () {
            $scope.quizJson.questions.forEach(function (question) {
                if (question.type !== "fill-the-blanks") return;

                // Converting into question collection
                var splits = question.question.split('__');
                question.questionCollection = splits.map(function (el, i) {
                    return i % 2 == 0 ? {type: "question", value: el.trim()} : {type: "answer", value: el.trim()};
                });
            });
        };

        $scope.saveQuiz = function () {
            var error = "";
            if (!$scope.quizJson.name) {
                error = "Please give a name to the Quiz";
            } else if($scope.contents.filter(function(c) {
                        return c.type === 'quiz' && (c.name || '').toLowerCase().trim() === $scope.quizJson.name.toLowerCase().trim();
                    }).length > 0) {
                error = "Another quiz exists with this name, please choose another name.";
            } else {
                var firstInvalidQuestionIndex = $scope.quizJson.questions.findIndex(function (question) {
                    return $scope.errorsForQuestion(question) !== undefined;
                });

                if (firstInvalidQuestionIndex !== undefined && firstInvalidQuestionIndex !== -1) {
                    $scope.currentQuestionIndex = firstInvalidQuestionIndex;
                    error = $scope.errorsForQuestion($scope.quizJson.questions[firstInvalidQuestionIndex])
                }
            }
            if (error) {
                var options = {
                    title: "Alert",
                    description: error || "Please fill the red field",
                    buttons: ["ok"]
                };
                new CustomDialog($q, options);
            } else {
                processFib();
                var data = {
                    grade: $scope.current_grade,
                    subject: $scope.current_subject,
                    chapter: $scope.current_chapter,
                    quiz: $scope.quizJson
                };
                $http.post('/save.php', data, {headers: {'Content-Type': 'application/json'}}).
                        then(function () {
                            $scope.hasChange = false;
                            $scope.closeOverlay();
                            var options = {
                                title: "Success",
                                description: "Successfully saved the quiz.",
                                buttons: ["ok"]
                            };
                            new CustomDialog($q, options);
                        }, function () {
                            console.log(arguments);
                        });
            }
        };

        $scope.verifySaveQuiz = function(){
            var dialogInstance = new CustomDialog($q, {
                title: "Alert",
                description: "Once you save the quiz you cannot make any changes. Do you want to continue?",
                buttons: ["ok", "cancel"],
                buttonName: ["yes","no"]
            }).show();
            dialogInstance
                    .then(function () {
                        $scope.saveQuiz();
                    })
                    .catch(function (e) {
                    });
        };

        $scope.validateInput = function (obj, limit) {
            if (obj.length >= limit) {
                var options = {
                    title: "Alert",
                    description: "You cannot add more than " + limit + " characters",
                    buttons: ["ok"]
                };
                new CustomDialog($q, options);
            }
        };

        $scope.setQuestionType = function (questionType) {
            var setType = function () {
                $scope.currentQuestion = $scope.quizJson.questions[$scope.currentQuestionIndex] = getDefaultQuestion(questionType);
            };
            if (($scope.currentQuestion.question && $scope.currentQuestion.question.trim())
                    || ($scope.currentQuestion.questions && $scope.currentQuestion.questions.filter(function (q) {
                        return q.question || q.answer;
                    }).length > 0)) {
                new CustomDialog($q, {
                    title: "Confirm",
                    description: "You have entered question details. If you change the type, they'll be lost. Do you want to continue?",
                    buttons: ["ok", "cancel"]
                }).show().then(setType);
            } else {
                setType();
            }
        }

        $scope.promptDialog = function ($event, redirect, callbackFn) {
            if($event) {
                $event.preventDefault();
            }
            var options = {
                title: "Alert",
                description: "Enter the answer for the blank.",
                plainText: true,
                buttons: ["ok", "cancel"],
                closeHandler: true,
                callback: function(event){
                    callbackFn(event.context.inputText);
                    event.context.disposeOverlay();
                },
                inputCheck: true,
                placeholder: 'Enter correct answer'
            };
            new CustomDialog($q, options);
            return true;
        };
    }

]);
<commit_msg>Fixs the save quiz dialog sequence<commit_after>pencilBoxApp.controller('CreateQuizController', ['$scope', '$routeParams', 'Contents','CreateQuiz', '$http', '$q','$timeout',
    function ($scope, $routeParams, Contents, CreateQuiz, $http, $q, $timeout) {
        $scope.hasChange = false;
        $scope.hasError = false;
        $scope.current_grade = $routeParams.gradeId;
        $scope.current_subject = $routeParams.subjectId;
        $scope.current_chapter = $routeParams.chapterId;
        $scope.contents = Contents.query({
            chapterId: $routeParams.chapterId,
            subjectId: $routeParams.subjectId, gradeId: $routeParams.gradeId
        });

        $scope.questionTypes = {
            "fill-the-blanks": {
                "name": "Fill the blanks",
                "image": "fill-the-blanks.png",
                "type": "fill-the-blanks",
                defaultQuestion: {
                    "type": "fill-the-blanks",
                    "question": "",
                    "questionCollection": [],
                    "marks": 1
                }
            },
            "multiple-options": {
                "name": "Multiple options",
                "image": "multiple-options.png",
                "type": "multiple-options",
                defaultQuestion: {
                    "marks": 1,
                    "type": "multiple-options",
                    "question": "",
                    "options": [
                        {
                            "value": "",
                            "answer": false
                        },
                        {
                            "value": "",
                            "answer": false
                        }
                    ]
                }
            },
            "match-the-following": {
                "name": "Match the following",
                "image": "match-the-following.png",
                "type": "match-the-following",
                defaultQuestion: {
                    "marks": 1,
                    "type": "match-the-following",
                    "questions": [
                        {
                            "question": "",
                            "answer": ""
                        },
                        {
                            "question": "",
                            "answer": ""
                        }
                    ]
                }
            }
        };

        var getDefaultQuestion = function (type) {
            return angular.copy($scope.questionTypes[type].defaultQuestion);
        };

        $scope.quizJson = {questions: [getDefaultQuestion('fill-the-blanks')]};
        $scope.currentQuestionIndex = 0;

        $scope.showOverlay = function (element) {
            $scope.overlay = new Overlay(element, {closeHandler: true});
        };

        $scope.closeQuiz = function($event) {
            $event.preventDefault();
            var options = {
                title: "Changes not saved",
                description: "You have unsaved changes in the quiz. Do you want to save it?",
                className: "master-password",
                buttons: ["ok", "cancel"],
                buttonName: ["yes", "no"],
                closeHandler: true
            };
            new CustomDialog($q, options).show().then(function () {
                $scope.saveQuiz();
            }).catch(function() {
                $scope.closeOverlay();
            });
        };

        $scope.closeOverlay = function ($event) {
            $scope.overlay.disposeOverlay();
            var url = window.location.href;
            url = url.replace("update-quiz/", "");
            url = url.replace("create-quiz/", "");
            window.location.href = url.replace("update-quiz/", "");
        };

        $scope.overlayLoaded = function () {
            $scope.showOverlay(document.getElementById("create-quiz-mask"));
        };

        $scope.getCurrentQuestionObject = function (index) {
            if (typeof index != "undefined") {
                return $scope.quizJson.questions[index];
            }
            return getDefaultQuestion($scope.currentQuestion.type);
        };

        $scope.addRow = function () {
            if ($scope.currentQuestion.type === "multiple-options") {
                if ($scope.currentQuestion.options.length < 5) {
                    $scope.currentQuestion.options.push({"value": "", "answer": false});
                } else {
                    var options = {
                        title: "Alert",
                        description: "Cannot add more than 5 options",
                        buttons: ["ok"]
                    };
                    new CustomDialog($q, options);
                }
            } else {
                if ($scope.currentQuestion.questions.length < 10) {
                    $scope.currentQuestion.questions.push({"question": "", "answer": ""});
                } else {
                    options = {
                        title: "Alert",
                        description: "Cannot add more than 10 options",
                        buttons: ["ok"]
                    };
                    new CustomDialog($q, options);
                }
            }
            $scope.isValidMultipleOption();
        };
        $scope.deleteRow = function (index) {
            var key = $scope.currentQuestion.type === "multiple-options" ? "options" : "questions";
            if ($scope.currentQuestion[key].length > 2) {
                $scope.currentQuestion[key].splice(index, 1);
            }
            $scope.isValidMultipleOption();
        };

        $scope.saveQuestion = function () {
            if ($scope.hasError()) {
                var options = {
                    title: "Alert",
                    description: "Please fill the red field",
                    buttons: ["ok"]
                };
                new CustomDialog($q, options);
                return false;
            }

            if ($scope.currentQuestion.type === "fill-the-blanks") {
                // Converting into question collection

                var splits = $scope.currentQuestion.question.split('__');
                $scope.currentQuestion.questionCollection = splits.map(function (el, i) {
                    if (i % 2 == 0) {
                        return {type: "question", value: el.trim()};
                    } else {
                        return {type: "answer", value: el.trim()};
                    }
                });
            }

            $scope.currentQuestionIndex = $scope.quizJson.questions.length - 1;
            return true;
        };

        var refreshCurrentQuestion = function () {
            $scope.currentQuestion = $scope.quizJson.questions[$scope.currentQuestionIndex];
        };
        $scope.$watch('currentQuestionIndex', refreshCurrentQuestion);

        $scope.addQuestion = function () {
            //if(!$scope.saveQuestion()) return;
            $scope.quizJson.questions.push($scope.getCurrentQuestionObject());
            $scope.currentQuestionIndex = $scope.quizJson.questions.length - 1;
            $scope.isValidMultipleOption();
        };

        $scope.hasError = function () {
            return document.querySelectorAll(".question-box .error, .question-box .ng-invalid").length > 0;
        };

        $scope.selectQuestion = function (index) {
            $scope.currentQuestionIndex = index;
        };

        var insertAt = function (mainString, insertString, index) {
            var leftPart = mainString.substr(0, index);
            var rightPart = mainString.substr(index, mainString.length);
            return leftPart + insertString + rightPart;
        };

        $scope.addBlank = function () {
            var answer;
            var caretPosition = document.getElementById('fill-in-the-blank-question').selectionStart;
            $scope.promptDialog(null, null, function(inputText){
                answer = inputText;
                $timeout(function() {
                    $scope.currentQuestion.question = insertAt($scope.currentQuestion.question, ' __' + answer + '__ ', caretPosition);
                },0);

            });
        };

        $scope.fillInTheBlankPreview = function () {
            if (!$scope.currentQuestion) return '';
            return $scope.currentQuestion.question ? $scope.currentQuestion.question.replace(/__.*?__/g, '_______') : "";
        };

        $scope.previousQuestion = function () {
            $scope.currentQuestionIndex = Math.max(0, $scope.currentQuestionIndex - 1);
        };
        $scope.nextQuestion = function () {
            $scope.currentQuestionIndex = Math.min($scope.quizJson.questions.length - 1, $scope.currentQuestionIndex + 1);
        };

        $scope.isValidMultipleOption = function () {
            if ($scope.currentQuestion.type === "multiple-options") {
                $scope.mcHasError = true;
                for (var i = 0, length = $scope.currentQuestion.options.length; i < length; i++) {
                    if ($scope.currentQuestion.options[i].answer) {
                        $scope.mcHasError = false;
                        break;
                    }
                }
            }
        };

        $scope.canDeleteQuestion = function () {
            return $scope.quizJson.questions.length > 1;
        };
        $scope.deleteQuestion = function () {
            if (!$scope.canDeleteQuestion()) return;
            var dialogInstance = new CustomDialog($q, {
                title: "Alert",
                description: "Are you sure you want to delete this question?",
                buttons: ["ok", "cancel"]
            }).show();
            dialogInstance
                    .then(function () {
                        $scope.quizJson.questions.splice($scope.currentQuestionIndex, 1);
                        if ($scope.currentQuestionIndex > $scope.quizJson.questions.length - 1) {
                            $scope.currentQuestionIndex = $scope.quizJson.questions.length - 1;
                        } else {
                            refreshCurrentQuestion();
                        }
                    })
                    .catch(function (e) {
                    });
        };

        $scope.isExistingQuestion = function () {
            return $scope.currentQuestionIndex;
        };

        $scope.errorsForQuestion = function (question) {
            if (question.type === "fill-the-blanks") {
                if (question.question.trim().length === 0) {
                    return "Please fill the question";
                } else if (!question.question.trim().match(/__[^_]+__/)) {
                    return "Please provide answer";
                }
            } else if (question.type === "match-the-following") {
                if (question.questions.filter(function (option) {
                            return option.question.trim() === '' || option.answer.trim() === ''
                        }).length > 0) {
                    return "Please fill all the fields.";
                }
            } else {
                if (question.question.trim().length === 0) {
                    return "Please fill the question";
                }
                else if (question.options.filter(function (option) {
                            return option.value.trim() === ''
                        }).length > 0) {
                    return "Please fill all the answer options.";
                }
                else if (question.options.filter(function (option) {
                            return option.answer
                        }).length <= 0) {
                    return "Please set answer to the question";
                }
            }
        };

        var processFib = function () {
            $scope.quizJson.questions.forEach(function (question) {
                if (question.type !== "fill-the-blanks") return;

                // Converting into question collection
                var splits = question.question.split('__');
                question.questionCollection = splits.map(function (el, i) {
                    return i % 2 == 0 ? {type: "question", value: el.trim()} : {type: "answer", value: el.trim()};
                });
            });
        };

        $scope.saveQuiz = function () {
            var data = {
                    grade: $scope.current_grade,
                    subject: $scope.current_subject,
                    chapter: $scope.current_chapter,
                    quiz: $scope.quizJson
                };
            $http.post('/save.php', data, {headers: {'Content-Type': 'application/json'}}).
                then(function () {
                    $scope.hasChange = false;
                    $scope.closeOverlay();
                    var options = {
                        title: "Success",
                        description: "Successfully saved the quiz.",
                        buttons: ["ok"]
                    };
                    new CustomDialog($q, options);
                }, function () {
                    console.log(arguments);
                });
        };

        $scope.verifySaveQuiz = function(){
            var error = "";
            if (!$scope.quizJson.name) {
                error = "Please give a name to the Quiz";
            } else if($scope.contents.filter(function(c) {
                        return c.type === 'quiz' && (c.name || '').toLowerCase().trim() === $scope.quizJson.name.toLowerCase().trim();
                    }).length > 0) {
                error = "Another quiz exists with this name, please choose another name.";
            } else {
                var firstInvalidQuestionIndex = $scope.quizJson.questions.findIndex(function (question) {
                    return $scope.errorsForQuestion(question) !== undefined;
                });

                if (firstInvalidQuestionIndex !== undefined && firstInvalidQuestionIndex !== -1) {
                    $scope.currentQuestionIndex = firstInvalidQuestionIndex;
                    error = $scope.errorsForQuestion($scope.quizJson.questions[firstInvalidQuestionIndex])
                }
            }
            if (error) {
                var options = {
                    title: "Alert",
                    description: error || "Please fill the red field",
                    buttons: ["ok"]
                };
                new CustomDialog($q, options);
            } else {
                processFib();
                var dialogInstance = new CustomDialog($q, {
                    title: "Alert",
                    description: "Once you save the quiz you cannot make any changes. Do you want to continue?",
                    buttons: ["ok", "cancel"],
                    buttonName: ["yes","no"]
                }).show();
                dialogInstance.then(function () {$scope.saveQuiz();}).catch(function (e) {});
            }
        };

        $scope.validateInput = function (obj, limit) {
            if (obj.length >= limit) {
                var options = {
                    title: "Alert",
                    description: "You cannot add more than " + limit + " characters",
                    buttons: ["ok"]
                };
                new CustomDialog($q, options);
            }
        };

        $scope.setQuestionType = function (questionType) {
            var setType = function () {
                $scope.currentQuestion = $scope.quizJson.questions[$scope.currentQuestionIndex] = getDefaultQuestion(questionType);
            };
            if (($scope.currentQuestion.question && $scope.currentQuestion.question.trim())
                    || ($scope.currentQuestion.questions && $scope.currentQuestion.questions.filter(function (q) {
                        return q.question || q.answer;
                    }).length > 0)) {
                new CustomDialog($q, {
                    title: "Confirm",
                    description: "You have entered question details. If you change the type, they'll be lost. Do you want to continue?",
                    buttons: ["ok", "cancel"]
                }).show().then(setType);
            } else {
                setType();
            }
        }

        $scope.promptDialog = function ($event, redirect, callbackFn) {
            if($event) {
                $event.preventDefault();
            }
            var options = {
                title: "Alert",
                description: "Enter the answer for the blank.",
                plainText: true,
                buttons: ["ok", "cancel"],
                closeHandler: true,
                callback: function(event){
                    callbackFn(event.context.inputText);
                    event.context.disposeOverlay();
                },
                inputCheck: true,
                placeholder: 'Enter correct answer'
            };
            new CustomDialog($q, options);
            return true;
        };
    }

]);
<|endoftext|>


<commit_before>(function ($) {
  "use strict";
  /*global alert: true, ODSA */
  $(document).ready(function () {
    var initData, bh,
        settings = new JSAV.utils.Settings($(".jsavsettings")),
        jsav = new JSAV($('.avcontainer'), {settings: settings}),
        exercise,
	arr1, arr2, arr3, arr4,
	input1, input2, input3,
	invoutputarr,
        swapIndex,
        currentinvisoutput,
        invoutput,
        output;

    jsav.recorded();

    function init() {
      var inputlabel1 = jsav.label("Input Runs", {left: 140, top: 200});
      var outputlabel1 = jsav.label("Output Buffer", {left: 350, top: 250});
      var nodeNum = 3;
      currentinvisoutput = jsav.variable(0);
      if(arr1)
      {
	arr1.clear();
      }
      if(arr2)
      {
	arr2.clear();
      }
      if(arr3)
      {
	arr3.clear();
      }
      if(arr4)
      {
	arr4.clear();
      }
      if(invoutputarr)
      {
	invoutputarr.clear();
      }
      invoutput = ["", "", "", "", "", "", "", "", ""];
      output = ["", "", ""];
      input1 = JSAV.utils.rand.numKeys(10, 100, nodeNum);
      input2 = JSAV.utils.rand.numKeys(10, 100, nodeNum);
      input3 = JSAV.utils.rand.numKeys(10, 100, nodeNum);
      input1.sort();
      input2.sort();
      input3.sort();
      // Create an array object under control of JSAV library
      arr1 = jsav.ds.array(input1, {indexed: false, left: 135, top: 230});
      arr2 = jsav.ds.array(input2, {indexed: false, left: 135, top: 280});
      arr3 = jsav.ds.array(input3, {indexed: false, left: 135, top: 330});
      arr4 = jsav.ds.array(output, {indexed: false, left: 350, top: 280});
      invoutputarr = jsav.ds.array(invoutput, {indexed: false, left: 350, top: 200, visible: true});
      // Log the initial state of the exercise
      var exInitData = {};
      exInitData.gen_array = input1;
      ODSA.AV.logExerciseInit(exInitData);

      swapIndex = jsav.variable(-1);
      jsav._undo = [];
      jsav.displayInit();

      // click handler
      arr1.click(clickHandler);
      arr2.click(clickHandler);
      arr3.click(clickHandler);
      arr4.click(clickHandler);

      return [invoutputarr, arr1, arr2, arr3, arr4, currentinvisoutput];
    }

    function fixState(modelState) {
      var modelinvoutputarr = modelState[0];
      var modelarr1 = modelState[1];
      var modelarr2 = modelState[2];
      var modelarr3 = modelState[3];
      var modelarr4 = modelState[4];
      var modelinvisoutput = modelState[5];

      var invoutputsize = modelinvoutputarr.size();
      var arrsize1 = arr1.size();
      var arrsize2 = arr2.size();
      var arrsize3 = arr3.size();
      var arrsize4 = arr4.size();

      // check invoutputarr
      for (var i = 0; i < invoutputsize; i++)
      {
	invoutputarr.value(i, modelinvoutputarr.value(i));
      }

      // check arr1
      for (var j = 0; j < arrsize1; j++)
      {
	arr1.value(j, modelarr1.value(j));
      }

      // check arr2
      for (var k = 0; k < arrsize2; k++)
      {
	arr2.value(k, modelarr2.value(k));
      }

      // check arr3
      for (var l = 0; l < arrsize3; l++)
      {
	arr3.value(l, modelarr3.value(l));
      }

      // check arr1
      for (var m = 0; m < arrsize4; m++)
      {
	arr4.value(m, modelarr4.value(m));
      }
      // only swaps are graded so swapIndex cannot be anything else after correct step
      swapIndex.value(-1);
      // check invis array "size"
      currentinvisoutput.value(modelinvisoutput.value());
    }

    function model(modeljsav) {
      var setWhite = function (index, arr) {
         arr.css(index, {"background-color": "#FFFFFF", "color": "black" });
      };

      var setYellow = function (index, arr) {
         arr.css(index, {"background-color": "#FFFF00", "color": "black" });
      };

      var highlight_background_color = "#2B44CF";
      var highlight = function (index, arr) {
         arr.css(index, {"background-color": highlight_background_color, "color": "white"});
      };

      var modelarr1 = modeljsav.ds.array(input1, {indexed: false, left: 85, top: 30});
      var modelarr2 = modeljsav.ds.array(input2, {indexed: false, left: 85, top: 80});
      var modelarr3 = modeljsav.ds.array(input3, {indexed: false, left: 85, top: 130});
      var modelarr4 = modeljsav.ds.array(output, {indexed: false, left: 300, top: 80});
      var modelinvoutputarr = modeljsav.ds.array(invoutput, {indexed: false, left: 300, top: 0, visible: true});
      var inputlabel2 = modeljsav.label("Input Runs", {left: 90, top: 0});
      var outputlabel2 = modeljsav.label("Output Buffer", {left: 300, top: 50});

      modeljsav.displayInit();
      var currentoutput = 0;
      var currentinvoutput = modeljsav.variable(0);
      var currentinput1 = 0;
      var currentinput2 = 0;
      var currentinput3 = 0;
      modeljsav._undo = [];

      while (modelinvoutputarr.value(8) == "") {
        modeljsav.umsg("We must look at the first value of each input run.");
 	setWhite(0, modelarr4);
  	setWhite(1, modelarr4);
        setWhite(2, modelarr4);
        setYellow(currentinput1, modelarr1);
        setYellow(currentinput2, modelarr2);
        setYellow(currentinput3, modelarr3);

        modeljsav.step();
	// arr1 value is smallest
	if(((modelarr1.value(currentinput1) <= modelarr2.value(currentinput2)) &&
		(modelarr1.value(currentinput1) <= modelarr3.value(currentinput3))) ||
	//must check if other inputs are out of bounds
	(currentinput2 == 3 && (modelarr1.value(currentinput1) <= modelarr3.value(currentinput3))) ||
	(currentinput3 == 3 && (modelarr1.value(currentinput1) <= modelarr2.value(currentinput2))) ||
        (currentinput2 == 3 && currentinput3 == 3))
	{
  	   modeljsav.umsg("The value "+modelarr1.value(currentinput1)+" is removed and sent to the output because it is the smallest value.");
  	   modeljsav.effects.moveValue(modelarr1, currentinput1, modelarr4, currentoutput);
  	   setYellow(currentoutput, modelarr4);
  	   setWhite(currentinput1, modelarr1);
  	   setWhite(currentinput2, modelarr2);
  	   setWhite(currentinput3, modelarr3);
	   currentoutput += 1;
	   currentinput1 += 1;
           modeljsav.stepOption("grade", true);
           modeljsav.step();
	}
	// arr2 value is smallest
	else if(((modelarr2.value(currentinput2) <= modelarr1.value(currentinput1)) &&
		(modelarr2.value(currentinput2) <= modelarr3.value(currentinput3))) ||
	//must check if other inputs are out of bounds
	(currentinput1 == 3 && (modelarr2.value(currentinput2) <= modelarr3.value(currentinput3))) ||
	(currentinput3 == 3 && (modelarr2.value(currentinput2) <= modelarr1.value(currentinput1))) ||
	(currentinput1 == 3 && currentinput3 == 3))
	{
  	   modeljsav.umsg("The value "+modelarr2.value(currentinput2)+" is removed and sent to the output because it is the smallest value.");
  	   modeljsav.effects.moveValue(modelarr2, currentinput2, modelarr4, currentoutput);
  	   setYellow(currentoutput, modelarr4);
  	   setWhite(currentinput1, modelarr1);
  	   setWhite(currentinput2, modelarr2);
  	   setWhite(currentinput3, modelarr3);
	   currentoutput += 1;
	   currentinput2 += 1;
           modeljsav.stepOption("grade", true);
           modeljsav.step();
	}
	// arr3 value is smallest
	else if(((modelarr3.value(currentinput3) <= modelarr1.value(currentinput1)) &&
		(modelarr3.value(currentinput3) <= modelarr2.value(currentinput2))) ||
	//must check if other inputs are out of bounds
	(currentinput1 == 3 && (modelarr3.value(currentinput3) <= modelarr2.value(currentinput2))) ||
	(currentinput2 == 3 && (modelarr3.value(currentinput3) <= modelarr1.value(currentinput1))) ||
	(currentinput1 == 3 && currentinput2 == 3))
	{
  	   modeljsav.umsg("The value "+modelarr3.value(currentinput3)+" is removed and sent to the output because it is the smallest value.");
  	   modeljsav.effects.moveValue(modelarr3, currentinput3, modelarr4, currentoutput);
  	   setYellow(currentoutput, modelarr4);
  	   setWhite(currentinput1, modelarr1);
  	   setWhite(currentinput2, modelarr2);
  	   setWhite(currentinput3, modelarr3);
	   currentoutput += 1;
	   currentinput3 += 1;
           modeljsav.stepOption("grade", true);
           modeljsav.step();
	}

        //check if arr4 needs to be output
        if(modelarr4.value(2) !== "")
	{
	   modeljsav.umsg("We must write the output buffer to the disk.");
  	   modeljsav.effects.moveValue(modelarr4, 0, modelinvoutputarr, currentinvoutput.value());
	   modeljsav.effects.moveValue(modelarr4, 1, modelinvoutputarr, currentinvoutput.value() + 1);
	   modeljsav.effects.moveValue(modelarr4, 2, modelinvoutputarr, currentinvoutput.value() + 2);
	   setYellow(0, modelarr4);
	   setYellow(1, modelarr4);
	   currentinvoutput.value(currentinvoutput.value() + 3);
           currentoutput = 0;
           modeljsav.stepOption("grade", true);
           modeljsav.step();
	}

      }

      return [modelinvoutputarr, modelarr1, modelarr2, modelarr3, modelarr4, currentinvoutput];
    }

var firstSelection, secondSelection;

    function clickHandler(index) {
      jsav._redo = []; // clear the forward stack, should add a method for this in lib
      var sIndex = swapIndex.value();
      if (sIndex === -1) { // if first click
	firstSelection = this;
        firstSelection.css(index, {"font-size": "145%"});
        swapIndex.value(index);
      } else if (sIndex === index) {
	secondSelection = this;
	if(firstSelection === secondSelection)
	{
        	firstSelection.css(index, {"font-size": "100%"});
        	swapIndex.value(-1);
        	firstSelection = null;
        	secondSelection = null;
	}
	// different entities were selected
	else
	{
		firstSelection.css(sIndex, {"font-size": "100%"});
        	jsav.effects.moveValue(firstSelection, sIndex, secondSelection, index);
        	firstSelection = null;
        	secondSelection = null;
        	swapIndex.value(-1);
        	exercise.gradeableStep();
	}
      } else { // second click will swap
        secondSelection = this;
	if(firstSelection === secondSelection)
	{
        	firstSelection.css([sIndex, index], {"font-size": "100%"});
        	firstSelection.swap(sIndex, index, {});
	}
	// different entities were selected
	else
	{
		firstSelection.css(sIndex, {"font-size": "100%"});
        	jsav.effects.moveValue(firstSelection, sIndex, secondSelection, index);
	}
        firstSelection = null;
        secondSelection = null;
        swapIndex.value(-1);
        exercise.gradeableStep();
      }
    }

    // Process About button: Pop up a message with an Alert
    function about() {
      alert("Multiway Merge Proficiency Exercise\nWritten by Josh Horn\nCreated as part of the OpenDSA hypertextbook project\nFor more information, see http://algoviz.org/OpenDSA\nSource and development history available at\nhttps://github.com/OpenDSA/OpenDSA\nCompiled with JSAV library version " + JSAV.version());
    }

    exercise = jsav.exercise(model, init,
                             { compare:  { css: "background-color" },
                               controls: $('.jsavexercisecontrols'),
                               fix: fixState });
    exercise.reset();

    $("#outputbuffer").click(function () {
      if(currentinvisoutput >= invoutputarr.size()) {
	return;
      }
      jsav.effects.moveValue(arr4, 0, invoutputarr, currentinvisoutput.value());
      jsav.effects.moveValue(arr4, 1, invoutputarr, currentinvisoutput.value() + 1);
      jsav.effects.moveValue(arr4, 2, invoutputarr, currentinvisoutput.value() + 2);
      currentinvisoutput.value(currentinvisoutput.value() + 3);
      exercise.gradeableStep();
    });

    $("#about").click(about);});

}(jQuery));
<commit_msg>Fixed the replacement selection bug and labeled the disk array<commit_after>(function ($) {
  "use strict";
  /*global alert: true, ODSA */
  $(document).ready(function () {
    var initData, bh,
        settings = new JSAV.utils.Settings($(".jsavsettings")),
        jsav = new JSAV($('.avcontainer'), {settings: settings}),
        exercise,
	arr1, arr2, arr3, arr4,
	input1, input2, input3,
	invoutputarr,
        swapIndex,
        currentinvisoutput,
        invoutput,
        output;

    jsav.recorded();

    function init() {
      var inputlabel1 = jsav.label("Input Runs", {left: 140, top: 200});
      var outputlabel1 = jsav.label("Output Buffer", {left: 350, top: 250});
      var disklabel = jsav.label("Disk", {left: 475, top: 170});
      var nodeNum = 3;
      currentinvisoutput = jsav.variable(0);
      if(arr1)
      {
	arr1.clear();
      }
      if(arr2)
      {
	arr2.clear();
      }
      if(arr3)
      {
	arr3.clear();
      }
      if(arr4)
      {
	arr4.clear();
      }
      if(invoutputarr)
      {
	invoutputarr.clear();
      }
      invoutput = ["", "", "", "", "", "", "", "", ""];
      output = ["", "", ""];
      input1 = JSAV.utils.rand.numKeys(10, 100, nodeNum);
      input2 = JSAV.utils.rand.numKeys(10, 100, nodeNum);
      input3 = JSAV.utils.rand.numKeys(10, 100, nodeNum);
      input1.sort();
      input2.sort();
      input3.sort();
      // Create an array object under control of JSAV library
      arr1 = jsav.ds.array(input1, {indexed: false, left: 135, top: 230});
      arr2 = jsav.ds.array(input2, {indexed: false, left: 135, top: 280});
      arr3 = jsav.ds.array(input3, {indexed: false, left: 135, top: 330});
      arr4 = jsav.ds.array(output, {indexed: false, left: 350, top: 280});
      invoutputarr = jsav.ds.array(invoutput, {indexed: false, left: 350, top: 200, visible: true});
      // Log the initial state of the exercise
      var exInitData = {};
      exInitData.gen_array = input1;
      ODSA.AV.logExerciseInit(exInitData);

      swapIndex = jsav.variable(-1);
      jsav._undo = [];
      jsav.displayInit();

      // click handler
      arr1.click(clickHandler);
      arr2.click(clickHandler);
      arr3.click(clickHandler);
      arr4.click(clickHandler);

      return [invoutputarr, arr1, arr2, arr3, arr4, currentinvisoutput];
    }

    function fixState(modelState) {
      var modelinvoutputarr = modelState[0];
      var modelarr1 = modelState[1];
      var modelarr2 = modelState[2];
      var modelarr3 = modelState[3];
      var modelarr4 = modelState[4];
      var modelinvisoutput = modelState[5];

      var invoutputsize = modelinvoutputarr.size();
      var arrsize1 = arr1.size();
      var arrsize2 = arr2.size();
      var arrsize3 = arr3.size();
      var arrsize4 = arr4.size();

      // check invoutputarr
      for (var i = 0; i < invoutputsize; i++)
      {
	invoutputarr.value(i, modelinvoutputarr.value(i));
      }

      // check arr1
      for (var j = 0; j < arrsize1; j++)
      {
	arr1.value(j, modelarr1.value(j));
      }

      // check arr2
      for (var k = 0; k < arrsize2; k++)
      {
	arr2.value(k, modelarr2.value(k));
      }

      // check arr3
      for (var l = 0; l < arrsize3; l++)
      {
	arr3.value(l, modelarr3.value(l));
      }

      // check arr1
      for (var m = 0; m < arrsize4; m++)
      {
	arr4.value(m, modelarr4.value(m));
      }
      // only swaps are graded so swapIndex cannot be anything else after correct step
      swapIndex.value(-1);
      // check invis array "size"
      currentinvisoutput.value(modelinvisoutput.value());
    }

    function model(modeljsav) {
      var setWhite = function (index, arr) {
         arr.css(index, {"background-color": "#FFFFFF", "color": "black" });
      };

      var setYellow = function (index, arr) {
         arr.css(index, {"background-color": "#FFFF00", "color": "black" });
      };

      var highlight_background_color = "#2B44CF";
      var highlight = function (index, arr) {
         arr.css(index, {"background-color": highlight_background_color, "color": "white"});
      };

      var modelarr1 = modeljsav.ds.array(input1, {indexed: false, left: 85, top: 30});
      var modelarr2 = modeljsav.ds.array(input2, {indexed: false, left: 85, top: 80});
      var modelarr3 = modeljsav.ds.array(input3, {indexed: false, left: 85, top: 130});
      var modelarr4 = modeljsav.ds.array(output, {indexed: false, left: 300, top: 80});
      var modelinvoutputarr = modeljsav.ds.array(invoutput, {indexed: false, left: 300, top: 0, visible: true});
      var inputlabel2 = modeljsav.label("Input Runs", {left: 90, top: 0});
      var outputlabel2 = modeljsav.label("Output Buffer", {left: 300, top: 50});
      var disklabel2 = modeljsav.label("Disk", {left: 425, top: -25});

      modeljsav.displayInit();
      var currentoutput = 0;
      var currentinvoutput = modeljsav.variable(0);
      var currentinput1 = 0;
      var currentinput2 = 0;
      var currentinput3 = 0;
      modeljsav._undo = [];

      while (modelinvoutputarr.value(8) == "") {
        modeljsav.umsg("We must look at the first value of each input run.");
 	setWhite(0, modelarr4);
  	setWhite(1, modelarr4);
        setWhite(2, modelarr4);
        setYellow(currentinput1, modelarr1);
        setYellow(currentinput2, modelarr2);
        setYellow(currentinput3, modelarr3);

        modeljsav.step();
	// arr1 value is smallest
	if(((modelarr1.value(currentinput1) <= modelarr2.value(currentinput2)) &&
		(modelarr1.value(currentinput1) <= modelarr3.value(currentinput3))) ||
	//must check if other inputs are out of bounds
	(currentinput2 == 3 && (modelarr1.value(currentinput1) <= modelarr3.value(currentinput3))) ||
	(currentinput3 == 3 && (modelarr1.value(currentinput1) <= modelarr2.value(currentinput2))) ||
        (currentinput2 == 3 && currentinput3 == 3))
	{
  	   modeljsav.umsg("The value "+modelarr1.value(currentinput1)+" is removed and sent to the output because it is the smallest value.");
  	   modeljsav.effects.moveValue(modelarr1, currentinput1, modelarr4, currentoutput);
  	   setYellow(currentoutput, modelarr4);
  	   setWhite(currentinput1, modelarr1);
  	   setWhite(currentinput2, modelarr2);
  	   setWhite(currentinput3, modelarr3);
	   currentoutput += 1;
	   currentinput1 += 1;
           modeljsav.stepOption("grade", true);
           modeljsav.step();
	}
	// arr2 value is smallest
	else if(((modelarr2.value(currentinput2) <= modelarr1.value(currentinput1)) &&
		(modelarr2.value(currentinput2) <= modelarr3.value(currentinput3))) ||
	//must check if other inputs are out of bounds
	(currentinput1 == 3 && (modelarr2.value(currentinput2) <= modelarr3.value(currentinput3))) ||
	(currentinput3 == 3 && (modelarr2.value(currentinput2) <= modelarr1.value(currentinput1))) ||
	(currentinput1 == 3 && currentinput3 == 3))
	{
  	   modeljsav.umsg("The value "+modelarr2.value(currentinput2)+" is removed and sent to the output because it is the smallest value.");
  	   modeljsav.effects.moveValue(modelarr2, currentinput2, modelarr4, currentoutput);
  	   setYellow(currentoutput, modelarr4);
  	   setWhite(currentinput1, modelarr1);
  	   setWhite(currentinput2, modelarr2);
  	   setWhite(currentinput3, modelarr3);
	   currentoutput += 1;
	   currentinput2 += 1;
           modeljsav.stepOption("grade", true);
           modeljsav.step();
	}
	// arr3 value is smallest
	else if(((modelarr3.value(currentinput3) <= modelarr1.value(currentinput1)) &&
		(modelarr3.value(currentinput3) <= modelarr2.value(currentinput2))) ||
	//must check if other inputs are out of bounds
	(currentinput1 == 3 && (modelarr3.value(currentinput3) <= modelarr2.value(currentinput2))) ||
	(currentinput2 == 3 && (modelarr3.value(currentinput3) <= modelarr1.value(currentinput1))) ||
	(currentinput1 == 3 && currentinput2 == 3))
	{
  	   modeljsav.umsg("The value "+modelarr3.value(currentinput3)+" is removed and sent to the output because it is the smallest value.");
  	   modeljsav.effects.moveValue(modelarr3, currentinput3, modelarr4, currentoutput);
  	   setYellow(currentoutput, modelarr4);
  	   setWhite(currentinput1, modelarr1);
  	   setWhite(currentinput2, modelarr2);
  	   setWhite(currentinput3, modelarr3);
	   currentoutput += 1;
	   currentinput3 += 1;
           modeljsav.stepOption("grade", true);
           modeljsav.step();
	}

        //check if arr4 needs to be output
        if(modelarr4.value(2) !== "")
	{
	   modeljsav.umsg("We must write the output buffer to the disk.");
  	   modeljsav.effects.moveValue(modelarr4, 0, modelinvoutputarr, currentinvoutput.value());
	   modeljsav.effects.moveValue(modelarr4, 1, modelinvoutputarr, currentinvoutput.value() + 1);
	   modeljsav.effects.moveValue(modelarr4, 2, modelinvoutputarr, currentinvoutput.value() + 2);
	   setYellow(0, modelarr4);
	   setYellow(1, modelarr4);
	   currentinvoutput.value(currentinvoutput.value() + 3);
           currentoutput = 0;
           modeljsav.stepOption("grade", true);
           modeljsav.step();
	}

      }

      return [modelinvoutputarr, modelarr1, modelarr2, modelarr3, modelarr4, currentinvoutput];
    }

var firstSelection, secondSelection;

    function clickHandler(index) {
      jsav._redo = []; // clear the forward stack, should add a method for this in lib
      var sIndex = swapIndex.value();
      if (sIndex === -1) { // if first click
	firstSelection = this;
        firstSelection.css(index, {"font-size": "145%"});
        swapIndex.value(index);
      } else if (sIndex === index) {
	secondSelection = this;
	if(firstSelection === secondSelection)
	{
        	firstSelection.css(index, {"font-size": "100%"});
        	swapIndex.value(-1);
        	firstSelection = null;
        	secondSelection = null;
	}
	// different entities were selected
	else
	{
		firstSelection.css(sIndex, {"font-size": "100%"});
        	jsav.effects.moveValue(firstSelection, sIndex, secondSelection, index);
        	firstSelection = null;
        	secondSelection = null;
        	swapIndex.value(-1);
        	exercise.gradeableStep();
	}
      } else { // second click will swap
        secondSelection = this;
	if(firstSelection === secondSelection)
	{
        	firstSelection.css([sIndex, index], {"font-size": "100%"});
        	firstSelection.swap(sIndex, index, {});
	}
	// different entities were selected
	else
	{
		firstSelection.css(sIndex, {"font-size": "100%"});
        	jsav.effects.moveValue(firstSelection, sIndex, secondSelection, index);
	}
        firstSelection = null;
        secondSelection = null;
        swapIndex.value(-1);
        exercise.gradeableStep();
      }
    }

    // Process About button: Pop up a message with an Alert
    function about() {
      alert("Multiway Merge Proficiency Exercise\nWritten by Josh Horn\nCreated as part of the OpenDSA hypertextbook project\nFor more information, see http://algoviz.org/OpenDSA\nSource and development history available at\nhttps://github.com/OpenDSA/OpenDSA\nCompiled with JSAV library version " + JSAV.version());
    }

    exercise = jsav.exercise(model, init,
                             { compare:  { css: "background-color" },
                               controls: $('.jsavexercisecontrols'),
                               fix: fixState });
    exercise.reset();

    $("#outputbuffer").click(function () {
      if(currentinvisoutput >= invoutputarr.size()) {
	return;
      }
      jsav.effects.moveValue(arr4, 0, invoutputarr, currentinvisoutput.value());
      jsav.effects.moveValue(arr4, 1, invoutputarr, currentinvisoutput.value() + 1);
      jsav.effects.moveValue(arr4, 2, invoutputarr, currentinvisoutput.value() + 2);
      currentinvisoutput.value(currentinvisoutput.value() + 3);
      exercise.gradeableStep();
    });

    $("#about").click(about);});

}(jQuery));
<|endoftext|>


<commit_before>/******************************************************************************/
/************** Setting Up SlideShow ******************************************/
/******************************************************************************/

var allSlides  = $('.slide');
var currSlide  = 0;
var firstSlide = 0;
var lastSlide  = allSlides.length - 1;

/* nextSlide :: (Int) => Int */
function nextSlide(cur){
  return (cur < allSlides.length - 1) ? cur + 1 : cur ;
}

/* prevSlide :: (Int) => Int */
function prevSlide(cur){
  return cur ? cur - 1 : cur;
}

/* gotoSlide :: (Int) => void */
function gotoSlide(nextSlide){
  if (nextSlide !== currSlide) {
    $(allSlides[currSlide])
          .removeClass('active')
          .addClass('inactive');
    $(allSlides[nextSlide])
          .removeClass('inactive')
          .addClass('active');

    currSlide = nextSlide;
  }
}

$(function () {

  // Initialize: Hide all
  $('.slide').removeClass('active').addClass('inactive');
  $(allSlides[currSlide]).removeClass('inactive').addClass('active');

  // Update
  $('.prevbutton').click(function (event) {
    console.log('prev slide click');
    gotoSlide(prevSlide(currSlide));
    event.preventDefault();
   });

  $('.nextbutton').click(function (event) {
    console.log('next slide click');
    gotoSlide(nextSlide(currSlide));
    event.preventDefault();
   });

  /*
  $(window).on("navigate", function (event, data) {
     var direction = data.state.direction;
     if (direction == 'back') {
       // do something
       gotoSlide(prevSlide(currSlide));
       event.preventDefault();
     }
     if (direction == 'forward') {
       // do something else
       gotoSlide(nextSlide(currSlide));
       event.preventDefault();
     }
   });
  */

  $('#page').on("swipeleft",function(event){
    console.log('next slide swipeleft');
    gotoSlide(nextSlide(currSlide));
    event.preventDefault();
  });

  $('#page').on("swiperight",function(event){
    console.log('next slide swiperight');
    gotoSlide(prevSlide(currSlide));
    event.preventDefault();
  });

  $('.firstbutton').click(function (event) {
    console.log('first slide click');
    gotoSlide(firstSlide);
    event.preventDefault();
   });

  $('.lastbutton').click(function (event) {
    console.log('last slide click');
    gotoSlide(lastSlide);
    event.preventDefault();
   });

});

/* progPaneSlide :: (Int) => Int */
function progPaneSlide(paneId){
  var paneId = "#program-pane-" + paneId;
  var elem   = $(paneId).closest(".slide");
  return allSlides.index(elem);

/*
var paneId = "#program-pane-1";
var elem   = $(paneId).closest(".slide");
var pos    = allSlides.index(elem);
 */
}
<commit_msg>snapshot of liquid-client<commit_after>/******************************************************************************/
/************** Setting Up SlideShow ******************************************/
/******************************************************************************/

var allSlides  = $('.slide');
var currSlide  = 0;
var firstSlide = 0;
var lastSlide  = allSlides.length - 1;

/* nextSlide :: (Int) => Int */
function nextSlide(cur){
  return (cur < allSlides.length - 1) ? cur + 1 : cur ;
}

/* prevSlide :: (Int) => Int */
function prevSlide(cur){
  return cur ? cur - 1 : cur;
}

/* gotoSlide :: (Int) => void */
function gotoSlide(nextSlide){
  if (nextSlide !== currSlide) {
    $(allSlides[currSlide])
          .removeClass('active')
          .addClass('inactive');
    $(allSlides[nextSlide])
          .removeClass('inactive')
          .addClass('active');

    currSlide = nextSlide;
  }
}

$(function () {

  // Initialize: Hide all
  $('.slide').removeClass('active').addClass('inactive');
  $(allSlides[currSlide]).removeClass('inactive').addClass('active');

  // Update
  $('.prevbutton').click(function (event) {
    console.log('prev slide click');
    gotoSlide(prevSlide(currSlide));
    event.preventDefault();
   });

  $('.nextbutton').click(function (event) {
    console.log('next slide click');
    gotoSlide(nextSlide(currSlide));
    event.preventDefault();
   });

  $('#page').on("swipeleft",function(event){
    console.log('next slide swipeleft');
    gotoSlide(nextSlide(currSlide));
    event.preventDefault();
  });

  $('#page').on("swiperight",function(event){
    console.log('next slide swiperight');
    gotoSlide(prevSlide(currSlide));
    event.preventDefault();
  });

  $('.firstbutton').click(function (event) {
    console.log('first slide click');
    gotoSlide(firstSlide);
    event.preventDefault();
   });

  $('.lastbutton').click(function (event) {
    console.log('last slide click');
    gotoSlide(lastSlide);
    event.preventDefault();
   });

});

/* progPaneSlide :: (Int) => Int */
function progPaneSlide(paneId){
  var paneId = "#program-pane-" + paneId;
  var elem   = $(paneId).closest(".slide");
  return allSlides.index(elem);

/*
var paneId = "#program-pane-1";
var elem   = $(paneId).closest(".slide");
var pos    = allSlides.index(elem);
 */
}
<|endoftext|>


<commit_before>const path = require('path')

// 初始化环境变量
const defaultInputDir = '../../../../src'
const defaultOutputDir = '../../../../dist/' +
  (process.env.NODE_ENV === 'production' ? 'build' : 'dev') + '/' +
  process.env.UNI_PLATFORM

if (process.env.UNI_INPUT_DIR && process.env.UNI_INPUT_DIR.indexOf('./') === 0) {
  process.env.UNI_INPUT_DIR = path.resolve(process.cwd(), process.env.UNI_INPUT_DIR)
}
if (process.env.UNI_OUTPUT_DIR && process.env.UNI_OUTPUT_DIR.indexOf('./') === 0) {
  process.env.UNI_OUTPUT_DIR = path.resolve(process.cwd(), process.env.UNI_OUTPUT_DIR)
}

process.env.UNI_PLATFORM = process.env.UNI_PLATFORM || 'h5'
process.env.VUE_APP_PLATFORM = process.env.UNI_PLATFORM
process.env.UNI_INPUT_DIR = process.env.UNI_INPUT_DIR || path.resolve(__dirname, defaultInputDir)
process.env.UNI_OUTPUT_DIR = process.env.UNI_OUTPUT_DIR || path.resolve(__dirname, defaultOutputDir)

if (process.env.UNI_PLATFORM === 'app-plus') {
  process.env.UNI_OUTPUT_TMP_DIR = path.resolve(process.env.UNI_OUTPUT_DIR, '../.tmp/app-plus')
}

process.env.UNI_CLI_CONTEXT = path.resolve(__dirname, '../../../../')

process.UNI_LIBRARIES = process.UNI_LIBRARIES || ['@dcloudio/uni-ui']

const {
  isSupportSubPackages,
  runByHBuilderX,
  // isInHBuilderXAlpha,
  getPagesJson,
  getManifestJson
} = require('@dcloudio/uni-cli-shared')

const pagesJsonObj = getPagesJson()
// 读取分包
process.UNI_SUBPACKAGES = {}
if (Array.isArray(pagesJsonObj.subPackages)) {
  pagesJsonObj.subPackages.forEach(subPackage => {
    if (subPackage && subPackage.root) {
      const {
        name,
        root,
        independent
      } = subPackage
      process.UNI_SUBPACKAGES[root] = {
        name,
        root,
        independent
      }
    }
  })
}

const manifestJsonObj = getManifestJson()
const platformOptions = manifestJsonObj[process.env.UNI_PLATFORM] || {}

if (manifestJsonObj.debug) {
  process.env.VUE_APP_DEBUG = true
}

process.UNI_STAT_CONFIG = {
  appid: manifestJsonObj.appid
}

// 默认启用 自定义组件模式
// if (isInHBuilderXAlpha) {
let usingComponentsAbsent = false
if (!platformOptions.hasOwnProperty('usingComponents')) {
  usingComponentsAbsent = true
}
platformOptions.usingComponents = true
// }

if (process.env.UNI_PLATFORM === 'h5') {
  const optimization = platformOptions.optimization
  if (optimization) {
    // 发行模式且主动启用优化
    const treeShaking = optimization.treeShaking
    if (
      treeShaking &&
      treeShaking.enable &&
      process.env.NODE_ENV === 'production'
    ) {
      process.env.UNI_OPT_TREESHAKINGNG = true
      process.UNI_USER_APIS = new Set()
      if (Array.isArray(treeShaking.modules) && treeShaking.modules.length) {
        const {
          parseUserApis
        } = require('@dcloudio/uni-cli-shared/lib/api')
        try {
          const modules = require('@dcloudio/uni-h5/lib/modules.json')
          process.UNI_USER_APIS = parseUserApis(treeShaking.modules || [], modules)
        } catch (e) {}
      }
    }
    if (optimization.prefetch) {
      process.env.UNI_OPT_PREFETCH = true
    }
    if (optimization.preload) {
      process.env.UNI_OPT_PRELOAD = true
    }
  }
}

if (process.env.UNI_PLATFORM === 'mp-qq') { // QQ小程序 强制自定义组件模式
  platformOptions.usingComponents = true
}

let isNVueCompiler = false
if (process.env.UNI_PLATFORM === 'app-plus') {
  if (platformOptions.nvueCompiler === 'uni-app') {
    isNVueCompiler = true
  }
  if (platformOptions.renderer === 'native') {
    process.env.UNI_USING_NATIVE = true
    process.env.UNI_USING_V8 = true
    process.env.UNI_OUTPUT_TMP_DIR = ''
  }
} else { // 其他平台，待确认配置方案
  if (
    manifestJsonObj['app-plus'] &&
    manifestJsonObj['app-plus']['nvueCompiler'] === 'uni-app'
  ) {
    isNVueCompiler = true
  }
}

if (isNVueCompiler) {
  process.env.UNI_USING_NVUE_COMPILER = true
}

if (platformOptions.usingComponents === true) {
  if (process.env.UNI_PLATFORM !== 'h5') {
    process.env.UNI_USING_COMPONENTS = true
  }
  if (process.env.UNI_PLATFORM === 'app-plus') {
    process.env.UNI_USING_V8 = true
  }
}

if (
  process.env.UNI_USING_COMPONENTS ||
  process.env.UNI_PLATFORM === 'h5'
) { // 自定义组件模式或 h5 平台
  const uniStatistics = Object.assign(
    manifestJsonObj.uniStatistics || {},
    platformOptions.uniStatistics || {}
  )

  if (uniStatistics.enable !== false) {
    process.env.UNI_USING_STAT = true
    if (!process.UNI_STAT_CONFIG.appid && process.env.NODE_ENV === 'production') {
      console.log()
      console.warn(`当前应用未配置Appid，无法使用uni统计，详情参考：https://ask.dcloud.net.cn/article/36303`)
      console.log()
    }
  }
}

if (process.env.UNI_USING_COMPONENTS) { // 是否启用分包优化
  if (platformOptions.optimization) {
    if (
      isSupportSubPackages() &&
      platformOptions.optimization.subPackages &&
      Object.keys(process.UNI_SUBPACKAGES).length
    ) {
      process.env.UNI_OPT_SUBPACKAGES = true
    }
  }
}

const warningMsg =
  usingComponentsAbsent
    ? `该应用之前可能是非自定义组件模式，目前以自定义组件模式运行。非自定义组件将于2019年11月1日起停止支持。详见：https://ask.dcloud.net.cn/article/36385`
    : `uni-app将于2019年11月1日起停止支持非自定义组件模式 [详情](https://ask.dcloud.net.cn/article/36385)`

const needWarning = !platformOptions.usingComponents || usingComponentsAbsent
let hasNVue = false
// 输出编译器版本等信息
if (process.env.UNI_USING_NATIVE) {
  console.log('当前nvue编译模式：' + (isNVueCompiler ? 'uni-app' : 'weex') +
    ' 。编译模式差异见：https://ask.dcloud.net.cn/article/36074')
} else if (process.env.UNI_PLATFORM !== 'h5') {
  try {
    const modeText = '当前项目编译模式：' +
      (platformOptions.usingComponents ? '自定义组件模式' : '非自定义组件模式') +
      '。编译模式差异见：https://ask.dcloud.net.cn/article/35843'

    let info = ''
    if (process.env.UNI_PLATFORM === 'app-plus') {
      const pagesPkg = require('@dcloudio/webpack-uni-pages-loader/package.json')
      if (pagesPkg) {
        info = '编译器版本：' + pagesPkg['uni-app']['compilerVersion']
      }
      const glob = require('glob')
      hasNVue = !!glob.sync('pages/**/*.nvue', {
        cwd: process.env.UNI_INPUT_DIR
      }).length
      if (hasNVue) {
        console.log(info)
        console.log(modeText)
        if (needWarning) {
          console.log(warningMsg)
        }
        console.log('当前nvue编译模式：' + (isNVueCompiler ? 'uni-app' : 'weex') +
          ' 。编译模式差异见：https://ask.dcloud.net.cn/article/36074')
      } else {
        console.log(info + '，' + modeText)
        if (needWarning) {
          console.log(warningMsg)
        }
      }
    } else {
      console.log(modeText)
      if (needWarning) {
        console.log(warningMsg)
      }
    }
  } catch (e) {}
}
if (process.env.NODE_ENV !== 'production') { // 运行模式性能提示
  let perfMsg = `请注意运行模式下，因日志输出、sourcemap以及未压缩源码等原因，性能和包体积，均不如发行模式。`
  if (hasNVue) { // app-nvue
    perfMsg = perfMsg + `尤其是app-nvue的sourcemap影响较大`
  } else if (process.env.UNI_PLATFORM.indexOf('mp-') === 0) { // 小程序
    perfMsg = perfMsg + `若要正式发布，请点击发行菜单或使用cli发布命令进行发布`
  }
  console.log(perfMsg)
}

const moduleAlias = require('module-alias')

// 将 template-compiler 指向修订后的版本
moduleAlias.addAlias('vue-template-compiler', '@dcloudio/vue-cli-plugin-uni/packages/vue-template-compiler')
moduleAlias.addAlias('@megalo/template-compiler', '@dcloudio/vue-cli-plugin-uni/packages/@megalo/template-compiler')
moduleAlias.addAlias('mpvue-template-compiler', '@dcloudio/vue-cli-plugin-uni/packages/mpvue-template-compiler')

if (runByHBuilderX) {
  const oldError = console.error
  console.error = function (msg) {
    if (typeof msg === 'string' && msg.includes(
      '[BABEL] Note: The code generator has deoptimised the styling of')) {
      const filePath = msg.replace('[BABEL] Note: The code generator has deoptimised the styling of ', '').split(
        ' as ')[0]
      console.log('[警告] `' + path.relative(process.env.UNI_INPUT_DIR, filePath) +
        '` 文件体积超过 500KB，已跳过压缩以及 ES6 转 ES5 的处理，手机端使用过大的js库影响性能。')
    } else {
      oldError.apply(console, arguments)
      // TODO 如果是首次运行遇到错误直接退出
    }
  }
}

module.exports = {
  manifestPlatformOptions: platformOptions
}
<commit_msg>chore(cli): perf msg<commit_after>const path = require('path')

// 初始化环境变量
const defaultInputDir = '../../../../src'
const defaultOutputDir = '../../../../dist/' +
  (process.env.NODE_ENV === 'production' ? 'build' : 'dev') + '/' +
  process.env.UNI_PLATFORM

if (process.env.UNI_INPUT_DIR && process.env.UNI_INPUT_DIR.indexOf('./') === 0) {
  process.env.UNI_INPUT_DIR = path.resolve(process.cwd(), process.env.UNI_INPUT_DIR)
}
if (process.env.UNI_OUTPUT_DIR && process.env.UNI_OUTPUT_DIR.indexOf('./') === 0) {
  process.env.UNI_OUTPUT_DIR = path.resolve(process.cwd(), process.env.UNI_OUTPUT_DIR)
}

process.env.UNI_PLATFORM = process.env.UNI_PLATFORM || 'h5'
process.env.VUE_APP_PLATFORM = process.env.UNI_PLATFORM
process.env.UNI_INPUT_DIR = process.env.UNI_INPUT_DIR || path.resolve(__dirname, defaultInputDir)
process.env.UNI_OUTPUT_DIR = process.env.UNI_OUTPUT_DIR || path.resolve(__dirname, defaultOutputDir)

if (process.env.UNI_PLATFORM === 'app-plus') {
  process.env.UNI_OUTPUT_TMP_DIR = path.resolve(process.env.UNI_OUTPUT_DIR, '../.tmp/app-plus')
}

process.env.UNI_CLI_CONTEXT = path.resolve(__dirname, '../../../../')

process.UNI_LIBRARIES = process.UNI_LIBRARIES || ['@dcloudio/uni-ui']

const {
  isSupportSubPackages,
  runByHBuilderX,
  // isInHBuilderXAlpha,
  getPagesJson,
  getManifestJson
} = require('@dcloudio/uni-cli-shared')

const pagesJsonObj = getPagesJson()
// 读取分包
process.UNI_SUBPACKAGES = {}
if (Array.isArray(pagesJsonObj.subPackages)) {
  pagesJsonObj.subPackages.forEach(subPackage => {
    if (subPackage && subPackage.root) {
      const {
        name,
        root,
        independent
      } = subPackage
      process.UNI_SUBPACKAGES[root] = {
        name,
        root,
        independent
      }
    }
  })
}

const manifestJsonObj = getManifestJson()
const platformOptions = manifestJsonObj[process.env.UNI_PLATFORM] || {}

if (manifestJsonObj.debug) {
  process.env.VUE_APP_DEBUG = true
}

process.UNI_STAT_CONFIG = {
  appid: manifestJsonObj.appid
}

// 默认启用 自定义组件模式
// if (isInHBuilderXAlpha) {
let usingComponentsAbsent = false
if (!platformOptions.hasOwnProperty('usingComponents')) {
  usingComponentsAbsent = true
}
platformOptions.usingComponents = true
// }

if (process.env.UNI_PLATFORM === 'h5') {
  const optimization = platformOptions.optimization
  if (optimization) {
    // 发行模式且主动启用优化
    const treeShaking = optimization.treeShaking
    if (
      treeShaking &&
      treeShaking.enable &&
      process.env.NODE_ENV === 'production'
    ) {
      process.env.UNI_OPT_TREESHAKINGNG = true
      process.UNI_USER_APIS = new Set()
      if (Array.isArray(treeShaking.modules) && treeShaking.modules.length) {
        const {
          parseUserApis
        } = require('@dcloudio/uni-cli-shared/lib/api')
        try {
          const modules = require('@dcloudio/uni-h5/lib/modules.json')
          process.UNI_USER_APIS = parseUserApis(treeShaking.modules || [], modules)
        } catch (e) {}
      }
    }
    if (optimization.prefetch) {
      process.env.UNI_OPT_PREFETCH = true
    }
    if (optimization.preload) {
      process.env.UNI_OPT_PRELOAD = true
    }
  }
}

if (process.env.UNI_PLATFORM === 'mp-qq') { // QQ小程序 强制自定义组件模式
  platformOptions.usingComponents = true
}

let isNVueCompiler = false
if (process.env.UNI_PLATFORM === 'app-plus') {
  if (platformOptions.nvueCompiler === 'uni-app') {
    isNVueCompiler = true
  }
  if (platformOptions.renderer === 'native') {
    process.env.UNI_USING_NATIVE = true
    process.env.UNI_USING_V8 = true
    process.env.UNI_OUTPUT_TMP_DIR = ''
  }
} else { // 其他平台，待确认配置方案
  if (
    manifestJsonObj['app-plus'] &&
    manifestJsonObj['app-plus']['nvueCompiler'] === 'uni-app'
  ) {
    isNVueCompiler = true
  }
}

if (isNVueCompiler) {
  process.env.UNI_USING_NVUE_COMPILER = true
}

if (platformOptions.usingComponents === true) {
  if (process.env.UNI_PLATFORM !== 'h5') {
    process.env.UNI_USING_COMPONENTS = true
  }
  if (process.env.UNI_PLATFORM === 'app-plus') {
    process.env.UNI_USING_V8 = true
  }
}

if (
  process.env.UNI_USING_COMPONENTS ||
  process.env.UNI_PLATFORM === 'h5'
) { // 自定义组件模式或 h5 平台
  const uniStatistics = Object.assign(
    manifestJsonObj.uniStatistics || {},
    platformOptions.uniStatistics || {}
  )

  if (uniStatistics.enable !== false) {
    process.env.UNI_USING_STAT = true
    if (!process.UNI_STAT_CONFIG.appid && process.env.NODE_ENV === 'production') {
      console.log()
      console.warn(`当前应用未配置Appid，无法使用uni统计，详情参考：https://ask.dcloud.net.cn/article/36303`)
      console.log()
    }
  }
}

if (process.env.UNI_USING_COMPONENTS) { // 是否启用分包优化
  if (platformOptions.optimization) {
    if (
      isSupportSubPackages() &&
      platformOptions.optimization.subPackages &&
      Object.keys(process.UNI_SUBPACKAGES).length
    ) {
      process.env.UNI_OPT_SUBPACKAGES = true
    }
  }
}

const warningMsg =
  usingComponentsAbsent
    ? `该应用之前可能是非自定义组件模式，目前以自定义组件模式运行。非自定义组件将于2019年11月1日起停止支持。详见：https://ask.dcloud.net.cn/article/36385`
    : `uni-app将于2019年11月1日起停止支持非自定义组件模式 [详情](https://ask.dcloud.net.cn/article/36385)`

const needWarning = !platformOptions.usingComponents || usingComponentsAbsent
let hasNVue = false
// 输出编译器版本等信息
if (process.env.UNI_USING_NATIVE) {
  console.log('当前nvue编译模式：' + (isNVueCompiler ? 'uni-app' : 'weex') +
    ' 。编译模式差异见：https://ask.dcloud.net.cn/article/36074')
} else if (process.env.UNI_PLATFORM !== 'h5') {
  try {
    const modeText = '当前项目编译模式：' +
      (platformOptions.usingComponents ? '自定义组件模式' : '非自定义组件模式') +
      '。编译模式差异见：https://ask.dcloud.net.cn/article/35843'

    let info = ''
    if (process.env.UNI_PLATFORM === 'app-plus') {
      const pagesPkg = require('@dcloudio/webpack-uni-pages-loader/package.json')
      if (pagesPkg) {
        info = '编译器版本：' + pagesPkg['uni-app']['compilerVersion']
      }
      const glob = require('glob')
      hasNVue = !!glob.sync('pages/**/*.nvue', {
        cwd: process.env.UNI_INPUT_DIR
      }).length
      if (hasNVue) {
        console.log(info)
        console.log(modeText)
        if (needWarning) {
          console.log(warningMsg)
        }
        console.log('当前nvue编译模式：' + (isNVueCompiler ? 'uni-app' : 'weex') +
          ' 。编译模式差异见：https://ask.dcloud.net.cn/article/36074')
      } else {
        console.log(info + '，' + modeText)
        if (needWarning) {
          console.log(warningMsg)
        }
      }
    } else {
      console.log(modeText)
      if (needWarning) {
        console.log(warningMsg)
      }
    }
  } catch (e) {}
}
if (process.env.NODE_ENV !== 'production') { // 运行模式性能提示
  let perfMsg = `请注意运行模式下，因日志输出、sourcemap以及未压缩源码等原因，性能和包体积，均不及发行模式。`
  if (hasNVue) { // app-nvue
    perfMsg = perfMsg + `尤其是app-nvue的sourcemap影响较大`
  } else if (process.env.UNI_PLATFORM.indexOf('mp-') === 0) { // 小程序
    perfMsg = perfMsg + `若要正式发布，请点击发行菜单或使用cli发布命令进行发布`
  }
  console.log(perfMsg)
}

const moduleAlias = require('module-alias')

// 将 template-compiler 指向修订后的版本
moduleAlias.addAlias('vue-template-compiler', '@dcloudio/vue-cli-plugin-uni/packages/vue-template-compiler')
moduleAlias.addAlias('@megalo/template-compiler', '@dcloudio/vue-cli-plugin-uni/packages/@megalo/template-compiler')
moduleAlias.addAlias('mpvue-template-compiler', '@dcloudio/vue-cli-plugin-uni/packages/mpvue-template-compiler')

if (runByHBuilderX) {
  const oldError = console.error
  console.error = function (msg) {
    if (typeof msg === 'string' && msg.includes(
      '[BABEL] Note: The code generator has deoptimised the styling of')) {
      const filePath = msg.replace('[BABEL] Note: The code generator has deoptimised the styling of ', '').split(
        ' as ')[0]
      console.log('[警告] `' + path.relative(process.env.UNI_INPUT_DIR, filePath) +
        '` 文件体积超过 500KB，已跳过压缩以及 ES6 转 ES5 的处理，手机端使用过大的js库影响性能。')
    } else {
      oldError.apply(console, arguments)
      // TODO 如果是首次运行遇到错误直接退出
    }
  }
}

module.exports = {
  manifestPlatformOptions: platformOptions
}
<|endoftext|>


<commit_before>'use strict';

const app = angular.module('settingsWindow', []);

const remote = require('electron').remote;

const debounce = require('lodash.debounce');

app.run($rootScope => {
    $rootScope.Platform = require('os').platform();
    $rootScope.Electron = remote.app;
    $rootScope.AppName = $rootScope.Electron.getName();
    $rootScope.Version = $rootScope.Electron.getVersion();
    $rootScope.Window = remote.getCurrentWindow();
    $rootScope.Pussh = remote.getGlobal('Pussh');

    $rootScope.Window.focus();
});

app.controller('settings', ($scope, $rootScope) => {
    const Pussh = $rootScope.Pussh;

    $scope.services = Pussh.services.list();
    $scope.settings = Pussh.settings.get();
    $scope.selectedService = Pussh.services.get($scope.settings.selectedService);
    $scope.serviceSettings = $scope.selectedService.getSettings();
    $scope.autoLaunchSetting = false;

    Pussh.settings.getAutoLaunch(state => {
        $scope.autoLaunchSetting = state;
        $scope.$apply();

        $scope.$watch('autoLaunchSetting', () => Pussh.settings.setAutoLaunch($scope.autoLaunchSetting));
    });

    $scope.resetAll = () => Pussh.settings.resetAll();

    $scope.$watch('selectedService', service => {
        $scope.settings.selectedService = service._name;
        $scope.serviceSettings = $scope.selectedService.settings;

        $scope.save();
    });

    $scope.$watch('settings', () => $scope.save(), true);
    $scope.$watch('serviceSettings', () => $scope.save(), true);

    $scope.save = debounce(() => {
        $scope.selectedService.saveSettings();
        Pussh.settings.save();
    }, 1000, {
        leading: true,
        trailing: true
    });
});
<commit_msg>fixes angular issues<commit_after>'use strict';

const app = angular.module('settingsWindow', []);

const remote = require('electron').remote;

const debounce = require('lodash.debounce');

app.run($rootScope => {
    $rootScope.Platform = require('os').platform();
    $rootScope.Electron = remote.app;
    $rootScope.AppName = $rootScope.Electron.getName();
    $rootScope.Version = $rootScope.Electron.getVersion();
    $rootScope.Window = remote.getCurrentWindow();
    $rootScope.Pussh = remote.getGlobal('Pussh');

    $rootScope.Window.focus();
});

app.controller('settings', ($scope, $rootScope) => {
    const Pussh = $rootScope.Pussh;

    $scope.services = Pussh.services.list().map(s => {
        return {
            name: s.name,
            _name: s._name,
            description: s.description,
            settings: s.settings
        }
    });
    $scope.settings = Pussh.settings.get();
    $scope.selectedService = Pussh.services.get($scope.settings.selectedService) || Pussh.services.list()[0];
    $scope.serviceSettings = $scope.selectedService.getSettings();
    $scope.autoLaunchSetting = false;

    Pussh.settings.getAutoLaunch(state => {
        $scope.autoLaunchSetting = state;
        $scope.$apply();

        $scope.$watch('autoLaunchSetting', () => Pussh.settings.setAutoLaunch($scope.autoLaunchSetting));
    });

    $scope.resetAll = () => Pussh.settings.resetAll();

    $scope.$watch('selectedService', service => {
        $scope.settings.selectedService = service._name;
        $scope.serviceSettings = $scope.selectedService.settings;

        $scope.save();
    });

    $scope.$watch('settings', () => $scope.save(), true);
    $scope.$watch('serviceSettings', () => $scope.save(), true);

    $scope.save = debounce(() => {
        Pussh.services.get($scope.selectedService._name).saveSettings();
        Pussh.settings.save();
    }, 1000, {
        leading: true,
        trailing: true
    });
});
<|endoftext|>


<commit_before>/* global define */
define(function () {
    'use strict';

    return {
        frameRenderer: null,

        transformTool: null,

        sceneController: null
    };
});<commit_msg>change GlobalVar<commit_after>/* global define */
define(function () {
    'use strict';

    return {

        frameRenderer: null,

        transformTool: null,

        touchSensorManager: null,

        sceneController: null
    };
});<|endoftext|>


<commit_before>var drawObstacles = function(obstacles, skier, obstaclesImg, increasedSpeed, speedBoost) {
  for (var i = 0; i < obstacles.length; i++) {
    if (skier.jumping === true) {
      speedBoost = 2;
    } else {
      speedBoost = 0;
    }
    if (skier.crashed === false) {
      obstacles[i].go(obstaclesImg, increasedSpeed, speedBoost);
      increasedSpeed += 0.02;
      skier.distance += (0.05 + increasedSpeed/450 + speedBoost/450);
    } else {
      obstacles[i].stop(obstaclesImg);
    }
  }
};

module.exports = drawObstacles;
<commit_msg>Add minor refactoring to the drawing of objects.<commit_after>var drawObstacles = function(obstacles, skier, obstaclesImg, increasedSpeed, speedBoost) {
  for (var i = 0; i < obstacles.length; i++) {
    if (skier.jumping === true) {
      speedBoost = 2;
    } else {
      speedBoost = 0;
    }
    obstacleCreation(skier, obstacles, i, obstaclesImg, increasedSpeed, speedBoost);
  }
};

function obstacleCreation(skier, obstacles, i, obstaclesImg, increasedSpeed, speedBoost) {
  if (skier.crashed === false) {
    obstacles[i].go(obstaclesImg, increasedSpeed, speedBoost);
    increasedSpeed += 0.02;
    skier.distance += (0.05 + increasedSpeed/450 + speedBoost/450);
  } else {
    obstacles[i].stop(obstaclesImg);
  }
}

module.exports = drawObstacles;
<|endoftext|>


<commit_before>// Title Case a Sentence

// Return the provided string with the first letter of each word capitalized.
// Make sure the rest of the word is in lower case.

// For the purpose of this exercise, you should also capitalize connecting words like "the" and "of".

<commit_msg>add params/ solution<commit_after>// Title Case a Sentence

// Return the provided string with the first letter of each word capitalized.
// Make sure the rest of the word is in lower case.

// For the purpose of this exercise, you should also capitalize connecting words like "the" and "of".

/**
 * @param {string} s
 * @return {str}
 */

function titleCase(str) {
  var words = str.split(' ');
  for (var i = 0; i < words.length; i += 1) {
    words[i] = words[i].charAt(0).toUpperCase() + words[i].slice(1).toLowerCase();
  }
  return words.join(' ');
}

titleCase("I'm a little tea pot");
<|endoftext|>


<commit_before>import { getCacheName, clearCache } from './utils';
/*
 * activate : Object -> Function
 *
 * @description
 * Will reactivate the store with stored data and send it to the clients.
 *
 * @param {object} opts
 * @param {object} opts.store        REQUIRED: A redux store
 * @param {string} opts.name         The cache name
 * @param {string} opts.version      The cache version
 *
 * Note: `self` refers to the service worker's global scope (like `window`).
 *
 */
const activate = ({store, name, version}) => {
  if (!store) throw TypeError('Missing required parameter: store');

  const cacheName = getCacheName(name, version);

  store.dispatch({type: 'ACTIVATE'});

  return (event) => {
    event.waitUntil(
      self.caches.keys()
        .then(keys => {
          return Promise.all(keys.map(key => {
            if (key !== cacheName) {
              console.log(`Deleting old cache: ${key}.`);
              return self.caches.delete(key);
            }
          }));
        })
        .then(() => self.clients.claim())
        .then(() => self.clients.matchAll())
        .then(clients => {
          return Promise.all(clients.map(c => c.postMessage(store.getState())));
        })
        .catch(err => console.error(err))
    );
  };
};

export default activate;
<commit_msg>adds the new clearCache function<commit_after>import { getCacheName, clearCache } from './utils';
/*
 * activate : Object -> Function
 *
 * @description
 * Will reactivate the store with stored data and send it to the clients.
 *
 * @param {object} opts
 * @param {object} opts.store        REQUIRED: A redux store
 * @param {string} opts.name         The cache name
 * @param {string} opts.version      The cache version
 *
 * Note: `self` refers to the service worker's global scope (like `window`).
 *
 */
const activate = ({store, name, version}) => {
  if (!store) throw TypeError('Missing required parameter: store');

  const cacheName = getCacheName(name, version);

  store.dispatch({type: 'ACTIVATE'});

  return (event) => {
    event.waitUntil(
      self.caches.keys()
        .then(keys => clearCache(keys, cacheName))
        .then(() => self.clients.claim())
        .then(() => self.clients.matchAll())
        .then(clients => {
          return Promise.all(clients.map(c => c.postMessage(store.getState())));
        })
        .catch(err => console.error(err))
    );
  };
};

export default activate;
<|endoftext|>


<commit_before>import moment from 'moment'
import _ from 'lodash'

export const INTERVAL = 1000
const PLACEHOLDER = 'Soon™'

export class Countdown {
  constructor () {
    this.intervalID = 0
    this.time = PLACEHOLDER
  }

  pad (n, width) {
    n = n + ''
    return n.length >= width ? n : new Array(width - n.length + 1).join("0") + n
  }

  start (event) {
    // If there is already a clock ticking, kill it.
    if (this.intervalID !== 0) {
      clearInterval(this.intervalID)
    }

    this.intervalID = setInterval(() => {
      var eventTime = event.unix()
      var currentTime = moment().unix()
      var diffTime = eventTime - currentTime
      var d = moment.duration(diffTime, 'seconds') // duration

      d = moment.duration(d - INTERVAL, 'milliseconds')

      // If we're ever at a negative interval, stop immediately.
      // Technically we probably only really need the seconds here, but
      // if we use all of them any future cases will be fixed immediately.
      if (_.some([d.hours(), d.minutes(), d.seconds()], (n) => n < 0)) {
        console.log("Closing interval.")
        clearInterval(this.intervalID)
        this.time = PLACEHOLDER
        return
      }

      // Add hours left, but only if there are hours left.
      let hours = ""
      if (d.hours() > 0) {
        hours = this.pad(d.hours(), 2) + ":"
      }

      if (d.hours() === 0 && d.minutes() === 0 && d.seconds() === 0) {
        this.time = PLACEHOLDER
      } else {
        this.time = hours + this.pad(d.minutes(), 2) + ":" + this.pad(d.seconds(), 2)
      }
    }, INTERVAL)
  }
}

export class Clock {
  constructor () {
    this.time = "00:00 (+02:00)"
  }
  start () {
    setInterval(() => {
      this.time = moment().format("HH:mm (Z)")
    }, 1000)
  }
}
<commit_msg>Set the inital clock time to be  the current time.<commit_after>import moment from 'moment'
import _ from 'lodash'

export const INTERVAL = 1000
const PLACEHOLDER = 'Soon™'

export class Countdown {
  constructor () {
    this.intervalID = 0
    this.time = PLACEHOLDER
  }

  pad (n, width) {
    n = n + ''
    return n.length >= width ? n : new Array(width - n.length + 1).join("0") + n
  }

  start (event) {
    // If there is already a clock ticking, kill it.
    if (this.intervalID !== 0) {
      clearInterval(this.intervalID)
    }

    this.intervalID = setInterval(() => {
      var eventTime = event.unix()
      var currentTime = moment().unix()
      var diffTime = eventTime - currentTime
      var d = moment.duration(diffTime, 'seconds') // duration

      d = moment.duration(d - INTERVAL, 'milliseconds')

      // If we're ever at a negative interval, stop immediately.
      // Technically we probably only really need the seconds here, but
      // if we use all of them any future cases will be fixed immediately.
      if (_.some([d.hours(), d.minutes(), d.seconds()], (n) => n < 0)) {
        console.log("Closing interval.")
        clearInterval(this.intervalID)
        this.time = PLACEHOLDER
        return
      }

      // Add hours left, but only if there are hours left.
      let hours = ""
      if (d.hours() > 0) {
        hours = this.pad(d.hours(), 2) + ":"
      }

      if (d.hours() === 0 && d.minutes() === 0 && d.seconds() === 0) {
        this.time = PLACEHOLDER
      } else {
        this.time = hours + this.pad(d.minutes(), 2) + ":" + this.pad(d.seconds(), 2)
      }
    }, INTERVAL)
  }
}

export class Clock {
  constructor () {
    this.time = this._getTime()
  }

  start () {
    setInterval(() => {
      this.time = this._getTime()
    }, 1000)
  }

  _getTime () {
    return moment().format("HH:mm (Z)")
  }
}
<|endoftext|>


<commit_before>function ${ id }_content_updated() {
  MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
  update_schematics();

  // dynamic math display: generate MathML on click
  $.each($("[id^=input_${ id }_]"), function(index,value){
      theid = value.id.replace("input_","");		// ID of the response
      if (document.getElementById("display_" + theid)){
	  MathJax.Hub.queue.Push(function () {
	      math = MathJax.Hub.getAllJax("display_" + theid)[0];
	      if (math){
		  math.Text(document.getElementById("input_" + theid).value);
	      }
	  });
      };
  });

//  for (var key in codemirror_set) {
//      codemirror_set[key].refresh();
//  }

  $('#check_${ id }').unbind('click').click(function() {
  $("input.schematic").each(function(index,element){ element.schematic.update_value(); });
  $(".CodeMirror").each(function(index,element){ if (element.CodeMirror.save) element.CodeMirror.save(); });

  // dynamic math display: generate MathML on click
  $.each($("[id^=input_${ id }_]"), function(index,value){
      theid = value.id.replace("input_","");		// ID of the response
      if (document.getElementById("display_" + theid)){
	  MathJax.Hub.queue.Push(function () {
	      math = MathJax.Hub.getAllJax("display_" + theid)[0];
	      if (math){
		  math.Text(document.getElementById("input_" + theid).value);
		  UpdateMathML(math,theid);
	      }
	  });
      };
  });

    var submit_data={};
    $.each($("[id^=input_${ id }_]"), function(index,value){
	    if (value.type==="checkbox"){
		if (value.checked) {
		    if (typeof submit_data[value.name] == 'undefined'){
			submit_data[value.name]=[];
		    }
		    submit_data[value.name].push(value.value);
		}
	    }
	    if (value.type==="radio"){
		if (value.checked) {
		    submit_data[value.name]= value.value;
		}
	    }
	    else{
		submit_data[value.id]=value.value;
	    }
    });
    postJSON('${ MITX_ROOT_URL }/modx/problem/${ id }/problem_check',
      submit_data,
      function(json) {
        switch(json.success) {
        case 'incorrect': // Worked, but answer not
        case 'correct':
          $('#main_${ id }').html(json.contents);
          ${ id }_content_updated();
          break;
        default:
          alert(json.success);
      }}
    );
    log_event('problem_check', submit_data);
  });

  $('#reset_${ id }').unbind('click').click(function() {
    var submit_data={};
    $.each($("[id^=input_${ id }_]"), function(index,value){
      submit_data[value.id]=value.value;
    });

    postJSON('${ MITX_ROOT_URL }/modx/problem/${ id }/problem_reset', {'id':'${ id }'}, function(html_as_json) {
      $('#main_${ id }').html(html_as_json);
      ${ id }_content_updated();
    });
    log_event('problem_reset', submit_data);
  });

  // show answer button
  // TODO: the button should turn into "hide answer" afterwards
  $('#show_${ id }').unbind('click').click(function() {
    postJSON('${ MITX_ROOT_URL }/modx/problem/${ id }/problem_show', {}, function(data) {
      for (var key in data) {
	  if ($.isArray(data[key])){
	      for (var ans_index in data[key]){
		  var choice_id = 'input_'+key+'_'+data[key][ans_index];
		  $("label[for="+choice_id+"]").attr("correct_answer", "true");
	      }
	  }
	  $("#answer_"+key).text(data[key]);
    }
  });

    log_event('problem_show', {'problem':'${ id }'});
  });

  $('#save_${ id }').unbind('click').click(function() {
    $("input.schematic").each(function(index,element){ element.schematic.update_value(); });
    var submit_data={};
    $.each($("[id^=input_${ id }_]"), function(index,value) {
      submit_data[value.id]=value.value;
    });
    postJSON('${ MITX_ROOT_URL }/modx/problem/${ id }/problem_save',
      submit_data,
      function(data) {
        if(data.success) {
          alert('Saved');
    }});
    log_event('problem_save', submit_data);
  });
}

function ${ id }_load() {
  $('#main_${ id }').load('${ ajax_url }problem_get?id=${ id }', ${ id }_content_updated);
}

$(function() {
  ${ id }_load();
});
<commit_msg>another fix to dynamath display timing - problem.js content_updated display<commit_after>function ${ id }_content_updated() {
  MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
  update_schematics();

  // dynamic math display: generate MathML on click
  $.each($("[id^=display_${ id }_]"), function(index,value){
      theid = value.id.replace("display_","");		// ID of the response
      if (document.getElementById("input_" + theid)){
	  MathJax.Hub.queue.Push(function () {
	      math = MathJax.Hub.getAllJax(value.id)[0];
	      if (math){
		  math.Text(document.getElementById("input_" + theid).value);
	      }
	  });
      };
  });

//  for (var key in codemirror_set) {
//      codemirror_set[key].refresh();
//  }

  $('#check_${ id }').unbind('click').click(function() {
  $("input.schematic").each(function(index,element){ element.schematic.update_value(); });
  $(".CodeMirror").each(function(index,element){ if (element.CodeMirror.save) element.CodeMirror.save(); });

  // dynamic math display: generate MathML on click
  $.each($("[id^=input_${ id }_]"), function(index,value){
      theid = value.id.replace("input_","");		// ID of the response
      if (document.getElementById("display_" + theid)){
	  MathJax.Hub.queue.Push(function () {
	      math = MathJax.Hub.getAllJax("display_" + theid)[0];
	      if (math){
		  math.Text(document.getElementById("input_" + theid).value);
		  UpdateMathML(math,theid);
	      }
	  });
      };
  });

    var submit_data={};
    $.each($("[id^=input_${ id }_]"), function(index,value){
	    if (value.type==="checkbox"){
		if (value.checked) {
		    if (typeof submit_data[value.name] == 'undefined'){
			submit_data[value.name]=[];
		    }
		    submit_data[value.name].push(value.value);
		}
	    }
	    if (value.type==="radio"){
		if (value.checked) {
		    submit_data[value.name]= value.value;
		}
	    }
	    else{
		submit_data[value.id]=value.value;
	    }
    });
    postJSON('${ MITX_ROOT_URL }/modx/problem/${ id }/problem_check',
      submit_data,
      function(json) {
        switch(json.success) {
        case 'incorrect': // Worked, but answer not
        case 'correct':
          $('#main_${ id }').html(json.contents);
          ${ id }_content_updated();
          break;
        default:
          alert(json.success);
      }}
    );
    log_event('problem_check', submit_data);
  });

  $('#reset_${ id }').unbind('click').click(function() {
    var submit_data={};
    $.each($("[id^=input_${ id }_]"), function(index,value){
      submit_data[value.id]=value.value;
    });

    postJSON('${ MITX_ROOT_URL }/modx/problem/${ id }/problem_reset', {'id':'${ id }'}, function(html_as_json) {
      $('#main_${ id }').html(html_as_json);
      ${ id }_content_updated();
    });
    log_event('problem_reset', submit_data);
  });

  // show answer button
  // TODO: the button should turn into "hide answer" afterwards
  $('#show_${ id }').unbind('click').click(function() {
    postJSON('${ MITX_ROOT_URL }/modx/problem/${ id }/problem_show', {}, function(data) {
      for (var key in data) {
	  if ($.isArray(data[key])){
	      for (var ans_index in data[key]){
		  var choice_id = 'input_'+key+'_'+data[key][ans_index];
		  $("label[for="+choice_id+"]").attr("correct_answer", "true");
	      }
	  }
	  $("#answer_"+key).text(data[key]);
    }
  });

    log_event('problem_show', {'problem':'${ id }'});
  });

  $('#save_${ id }').unbind('click').click(function() {
    $("input.schematic").each(function(index,element){ element.schematic.update_value(); });
    var submit_data={};
    $.each($("[id^=input_${ id }_]"), function(index,value) {
      submit_data[value.id]=value.value;
    });
    postJSON('${ MITX_ROOT_URL }/modx/problem/${ id }/problem_save',
      submit_data,
      function(data) {
        if(data.success) {
          alert('Saved');
    }});
    log_event('problem_save', submit_data);
  });
}

function ${ id }_load() {
  $('#main_${ id }').load('${ ajax_url }problem_get?id=${ id }', ${ id }_content_updated);
}

$(function() {
  ${ id }_load();
});
<|endoftext|>