<commit_before>Paloquiz.states.Highscores = function(game) {
    this.currentPage = 0;
    this.friendsScores = [];
    this.userPos = undefined;
    this.profileImagesData = [];
    this.numFriendsInPage = 0;
    this.maxPage = 0;

    this.scores = [];
    this.nameTextStyle;
    this.scoreTextStyle;
    this.positionTextStyle;
    this.nameUserTextStyle;
    this.scoreUserTextStyle;
    this.positionUserTextStyle;
    this.arrowRight;
    this.arrowLeft;
    this.backButton;
};

Paloquiz.states.Highscores.prototype = {

    PAGE_SIZE: 6,

    init: function() {
        this.createLayoutBoxes();

        // Font styles
        this.createFontStyles();
    },

    preload: function() {
        // Enable cross-origin image loading
        this.load.crossOrigin = 'anonymous';
    },

    create: function() {

        // Create game objects
        this.createHighscoreEntries();
        this.createUI();

        // Handler for loaded profile pictures
        this.load.onLoadComplete.add(this.loadComplete, this);

        // Go on only if logged in
        fbInit(function() {
                getJSON('/status', function(gameStatus) {
                    fbGetFriendsScores(function(friendsScores, userPos) {
                        this.friendsScores = friendsScores;
                        this.userPos = userPos;
                        this.maxPage = Math.floor(this.friendsScores.length / this.PAGE_SIZE);
                        // First page at start of game, user page otherwise
                        if (gameStatus['status'] === 'start' || isNaN(userPos)) {
                            this.currentPage = 0;
                        } else {
                            this.currentPage = Math.floor(userPos / this.PAGE_SIZE);
                        }
                        // Finish game if necessary
                        if (gameStatus['status'] === 'finish') {
                            getJSON('/finish');  // No callback - no biggie if it doesn't complete
                        }
                        // Publish score if necessary and load page
                        var currentScore = gameStatus['score'];
                        if (this.friendsScores[userPos] &&
                            (currentScore > this.friendsScores[userPos].score)) {
                            // Score has improved
                            this.friendsScores[userPos].score = currentScore;
                            fbPublishScore(currentScore, this.loadScoresPage, this.loadScoresPage, this);
                        } else {
                            this.loadScoresPage();
                        }
                    }, this);
                }, this);
            },

            function() {
                // Exit if not logged in
                this.state.start('Router');
            },
            this);
    },

    shutdown: function() {
        // Remove handlers
        this.load.onLoadComplete.remove(this.loadComplete, this);

        this.destroyUI();
        this.destroyHighscoreEntries();
    },

    loadComplete: function() {
        for (var i = 0; i < this.numFriendsInPage; i++) {
            if (!this.profileImagesData[i].isSilhouette) {
                this.scores[i].img.loadTexture(i);
            } else {
                this.scores[i].img.loadTexture('noface');
            }
            this.scores[i].img.width = this.IMAGE_SIZE;
            this.scores[i].img.height = this.IMAGE_SIZE;
            this.scores[i].img.anchor.setTo(.5, .5);
            this.scores[i].img.visible = true;
        }
    },

    loadScoresPage: function() {
        // Hide all entries
        this.scores.forEach(function(s) {
            s.img.visible = false;
            s.pos.setStyle(this.positionTextStyle);
            s.pos.visible = false;
            s.name.setStyle(this.nameTextStyle);
            s.name.visible = false;
            s.score.setStyle(this.scoreTextStyle);
            s.score.visible = false;
        }, this);

        // Make sure page is in range
        if (this.currentPage < 0) {
            this.currentPage = 0;
        }
        if (this.currentPage > this.maxPage) {
            this.currentPage = this.maxPage;
        }

        // Hide arrows as needed
        this.arrowRight.visible = this.currentPage < this.maxPage;
        this.arrowLeft.visible = this.currentPage > 0;

        // Count friends in page
        var iFriendStart = this.PAGE_SIZE * this.currentPage;
        var iFriendEnd = Math.min(
            this.PAGE_SIZE * (this.currentPage + 1),
            this.friendsScores.length);
        this.numFriendsInPage = iFriendEnd - iFriendStart;
        this.profileImagesData = new Array(this.numFriendsInPage);

        // Function that starts the loader after every friend information is read
        var readFriends = 0;
        var friendInformationRead = function() {
            readFriends++;
            if (readFriends >= this.numFriendsInPage) {
                this.profileImagesData.forEach(function(img, i) {
                    this.load.image(i, img.url);
                }, this);
                this.load.start();
            }
        }
        friendInformationRead = friendInformationRead.bind(this);

        // Iterate through friends
        for (var iFriend = iFriendStart, iScore = 0; iFriend < iFriendEnd; iFriend++, iScore++) {
            (function(iScore, iFriend) {
                fbGetProfileDetails(this.friendsScores[iFriend].user.id, function(friend) {
                    this.scores[iScore].pos.setText((iFriend + 1) + '.');
                    this.scores[iScore].name.setText(friend.firstName || friend.name);
                    this.scores[iScore].score.setText(this.friendsScores[iFriend].score);
                    // Use special style for the user
                    if (iFriend == this.userPos) {
                        this.scores[iScore].pos.setStyle(this.positionUserTextStyle);
                        this.scores[iScore].name.setStyle(this.nameUserTextStyle);
                        this.scores[iScore].score.setStyle(this.scoreUserTextStyle);
                    }
                    this.scores[iScore].pos.visible = true;
                    this.scores[iScore].name.visible = true;
                    this.scores[iScore].score.visible = true;
                    this.profileImagesData[iScore] = friend.image;
                    friendInformationRead();
                }, this);
            }).bind(this)(iScore, iFriend);
        }
    },

    createFontStyles: function() {
        var textSize = Math.floor(this.NAME_BOX.width / 6.0) + 'px';

        var fontFace = 'Pixel Art';
        var positionTextSize = textSize;
        var nameTextSize = textSize;
        var scoreTextSize = textSize;
        var normalColor = 'white';
        var userColor = 'red';

        // Normal
        this.positionTextStyle = {
            font: fontFace,
            fontSize: positionTextSize,
            fill: normalColor,
            align: 'right',
            boundsAlignH: 'right',
            boundsAlignV: 'middle'
        };
        this.nameTextStyle = {
            font: fontFace,
            fontSize: positionTextSize,
            fill: normalColor,
            align: 'left',
            boundsAlignH: 'left',
            boundsAlignV: 'middle',
            wordWrap: true,
            wordWrapWidth: this.NAME_BOX.width
        };
        this.scoreTextStyle = {
            font: fontFace,
            fontSize: scoreTextSize,
            fill: 'white',
            align: 'right',
            boundsAlignH: 'right',
            boundsAlignV: 'middle'
        };
        // User
        this.positionUserTextStyle = {
            font: fontFace,
            fontSize: positionTextSize,
            fill: userColor,
            align: 'right',
            boundsAlignH: 'right',
            boundsAlignV: 'middle'
        };
        this.nameUserTextStyle = {
            font: fontFace,
            fontSize: nameTextSize,
            fill: userColor,
            align: 'left',
            boundsAlignH: 'left',
            boundsAlignV: 'middle',
            wordWrap: true,
            wordWrapWidth: this.NAME_BOX.width
        };
        this.scoreUserTextStyle = {
            font: fontFace,
            fontSize: scoreTextSize,
            fill: userColor,
            align: 'right',
            boundsAlignH: 'right',
            boundsAlignV: 'middle'
        };
    },

    createHighscoreEntries: function() {
        for (var i = 0; i < this.PAGE_SIZE; i++) {
            var xOffset = 0;
            var yOffset = i * this.ENTRY_BOX.height;

            // Position
            var pos = this.add.text(0, 0, '', this.positionTextStyle);
            pos.setTextBounds(
                this.POSITION_BOX.x + xOffset,
                this.POSITION_BOX.y + yOffset,
                this.POSITION_BOX.width,
                this.POSITION_BOX.height);
            pos.visible = false;

            // Image
            var img = this.add.image(
                this.IMAGE_BOX.x + this.IMAGE_BOX.width / 2 + xOffset,
                this.IMAGE_BOX.y + this.IMAGE_BOX.height / 2 + yOffset,
                'noface');
            img.visible = false;

            // Name
            var name = this.add.text(0, 0, '', this.nameTextStyle);
            name.setTextBounds(
                this.NAME_BOX.x + xOffset,
                this.NAME_BOX.y + yOffset,
                this.NAME_BOX.width,
                this.NAME_BOX.height);
            name.visible = false;

            // Score
            var score = this.add.text(0, 0, '', this.scoreTextStyle);
            score.setTextBounds(
                this.SCORE_BOX.x + xOffset,
                this.SCORE_BOX.y + yOffset,
                this.SCORE_BOX.width,
                this.SCORE_BOX.height);
            score.visible = false;

            this.scores.push({
                pos: pos,
                img: img,
                name: name,
                score: score
            });
        }
    },

    destroyHighscoreEntries: function() {
        for (var i = 0; i < this.scores.length; i++) {
            if (this.scores[i]) {
                if (this.scores[i].img) {
                    this.scores[i].img.loadTexture('noface');
                    this.scores[i].img.destroy();
                }
                if (this.scores[i].name) {
                    this.scores[i].name.destroy();
                }
                if (this.scores[i].pos) {
                    this.scores[i].pos.destroy();
                }
                if (this.scores[i].score) {
                    this.scores[i].score.destroy();
                }
            }
        }
        this.scores = [];
    },

    createUI: function() {
        // Back button to go back to main state
        this.backButton = this.add.button(0, 0, 'back',
            function() {
                this.state.start('Router');
            }, this, 0, 0, 0);
        this.backButton.smoothed = false;
        var backButtonSize = .1 * Math.min(this.world.width, this.world.height);
        this.backButton.width = backButtonSize;
        this.backButton.height = backButtonSize;
        this.backButton.anchor.setTo(0, 0);
        this.backButton.x = this.backButton.width * .2;
        this.backButton.y = this.backButton.height * .2;

        // Arrows to navigate through pages
        var arrowSize = .1 * Math.min(this.world.width, this.world.height);
        this.arrowRight = this.add.button(0, 0, 'arrow',
            function() {
                if (this.currentPage < this.maxPage) {
                    this.currentPage++;
                    this.loadScoresPage();
                }
            }, this, 0, 0, 0);
        this.arrowRight.smoothed = false;
        this.arrowRight.width = arrowSize;
        this.arrowRight.height = arrowSize;
        this.arrowRight.anchor.setTo(1, 1);
        this.arrowRight.x = this.world.width - this.arrowRight.width * .2;
        this.arrowRight.y = this.world.height - this.arrowRight.height * .2;
        this.arrowRight.visible = false;

        this.arrowLeft = this.add.button(0, 0, 'arrow',
            function() {
                if (this.currentPage > 0) {
                    this.currentPage--;
                    this.loadScoresPage();
                }
            }, this, 0, 0, 0);
        this.arrowLeft.width = -arrowSize;
        this.arrowLeft.height = arrowSize;
        this.arrowLeft.smoothed = false;
        this.arrowLeft.anchor.setTo(1, 1);
        this.arrowLeft.x = -this.arrowLeft.width * .2;
        this.arrowLeft.y = this.world.height - this.arrowLeft.height * .2;
        this.arrowLeft.visible = false;
    },

    destroyUI: function() {
        this.backButton.destroy();
        this.arrowRight.destroy();
        this.arrowLeft.destroy();
    },

    // Boxes

    ENTRIES_BOX: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    ENTRY_BOX: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    POSITION_BOX: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    IMAGE_BOX: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    NAME_BOX: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    SCORE_BOX: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    IMAGE_SIZE: 0,

    createLayoutBoxes: function() {
        var margin = .15 * Math.min(this.world.width, this.world.height);
        this.ENTRIES_BOX.x = margin;
        this.ENTRIES_BOX.y = margin;
        this.ENTRIES_BOX.width = this.world.width - 2 * margin;
        this.ENTRIES_BOX.height = this.world.height - 2 * margin;

        this.ENTRY_BOX.x = this.ENTRIES_BOX.x;
        this.ENTRY_BOX.y = this.ENTRIES_BOX.y;
        this.ENTRY_BOX.width = this.ENTRIES_BOX.width;
        this.ENTRY_BOX.height = this.ENTRIES_BOX.height / this.PAGE_SIZE;

        this.POSITION_BOX.x = this.ENTRY_BOX.x + this.ENTRY_BOX.width * .0;
        this.POSITION_BOX.y = this.ENTRY_BOX.y;
        this.POSITION_BOX.width = this.ENTRIES_BOX.width * .05;
        this.POSITION_BOX.height = this.ENTRY_BOX.height;

        this.IMAGE_BOX.x = this.ENTRY_BOX.x + this.ENTRY_BOX.width * .05;
        this.IMAGE_BOX.y = this.ENTRY_BOX.y;
        this.IMAGE_BOX.width = this.ENTRIES_BOX.width * .25;
        this.IMAGE_BOX.height = this.ENTRY_BOX.height;

        this.NAME_BOX.x = this.ENTRY_BOX.x + this.ENTRY_BOX.width * .30;
        this.NAME_BOX.y = this.ENTRY_BOX.y;
        this.NAME_BOX.width = this.ENTRIES_BOX.width * .45;
        this.NAME_BOX.height = this.ENTRY_BOX.height;

        this.SCORE_BOX.x = this.ENTRY_BOX.x + this.ENTRY_BOX.width * .78;
        this.SCORE_BOX.y = this.ENTRY_BOX.y;
        this.SCORE_BOX.width = this.ENTRIES_BOX.width * .22;
        this.SCORE_BOX.height = this.ENTRY_BOX.height;

        this.IMAGE_SIZE = .6 * Math.min(
            this.ENTRY_BOX.width * .25,
            this.ENTRY_BOX.height);
    }

};<commit_msg>Improved highscore init<commit_after>Paloquiz.states.Highscores = function(game) {
    this.currentPage = 0;
    this.friendsScores = [];
    this.userPos = undefined;
    this.profileImagesData = [];
    this.numFriendsInPage = 0;
    this.maxPage = 0;

    this.scores = [];
    this.nameTextStyle;
    this.scoreTextStyle;
    this.positionTextStyle;
    this.nameUserTextStyle;
    this.scoreUserTextStyle;
    this.positionUserTextStyle;
    this.arrowRight;
    this.arrowLeft;
    this.backButton;
};

Paloquiz.states.Highscores.prototype = {

    PAGE_SIZE: 6,

    init: function() {
        this.createLayoutBoxes();

        // Font styles
        this.createFontStyles();
    },

    preload: function() {
        // Enable cross-origin image loading
        this.load.crossOrigin = 'anonymous';
    },

    create: function() {

        // Create game objects
        this.createHighscoreEntries();
        this.createUI();

        // Handler for loaded profile pictures
        this.load.onLoadComplete.add(this.loadComplete, this);

        // Go on only if logged in
        fbInit(function() {
                this.checkStatus(true);
            },

            function() {
                // Exit if not logged in
                this.state.start('Router');
            },
            this);
    },

    shutdown: function() {
        // Remove handlers
        this.load.onLoadComplete.remove(this.loadComplete, this);

        this.destroyUI();
        this.destroyHighscoreEntries();
    },

    loadComplete: function() {
        for (var i = 0; i < this.numFriendsInPage; i++) {
            if (!this.profileImagesData[i].isSilhouette) {
                this.scores[i].img.loadTexture(i);
            } else {
                this.scores[i].img.loadTexture('noface');
            }
            this.scores[i].img.width = this.IMAGE_SIZE;
            this.scores[i].img.height = this.IMAGE_SIZE;
            this.scores[i].img.anchor.setTo(.5, .5);
            this.scores[i].img.visible = true;
        }
    },

    checkStatus: function(tryUpdate) {
        getJSON('/status', function(gameStatus) {
            // Check if score is up to date
            fbGetUserScore(function(score) {
                if ((gameStatus['score'] > score) && tryUpdate) {
                    // Score has improved
                    fbPublishScore(currentScore, function() {
                        this.checkStatus(false);
                    }, function() {
                        this.checkStatus(false);
                    }, this);
                    return;
                }
                fbGetFriendsScores(function(friendsScores, userPos) {
                    this.friendsScores = friendsScores;
                    this.userPos = userPos;
                    this.maxPage = Math.floor(this.friendsScores.length / this.PAGE_SIZE);
                    // First page at start of game, user page otherwise
                    if (gameStatus['status'] === 'start' || isNaN(userPos)) {
                        this.currentPage = 0;
                    } else {
                        this.currentPage = Math.floor(userPos / this.PAGE_SIZE);
                    }
                    // Finish game if necessary
                    if (gameStatus['status'] === 'finish') {
                        getJSON('/finish'); // No callback - no biggie if it doesn't complete
                    }
                    this.loadScoresPage();
                }, this);
            }, this);
        }, this);
    }

    loadScoresPage: function() {
        // Hide all entries
        this.scores.forEach(function(s) {
            s.img.visible = false;
            s.pos.setStyle(this.positionTextStyle);
            s.pos.visible = false;
            s.name.setStyle(this.nameTextStyle);
            s.name.visible = false;
            s.score.setStyle(this.scoreTextStyle);
            s.score.visible = false;
        }, this);

        // Make sure page is in range
        if (this.currentPage < 0) {
            this.currentPage = 0;
        }
        if (this.currentPage > this.maxPage) {
            this.currentPage = this.maxPage;
        }

        // Hide arrows as needed
        this.arrowRight.visible = this.currentPage < this.maxPage;
        this.arrowLeft.visible = this.currentPage > 0;

        // Count friends in page
        var iFriendStart = this.PAGE_SIZE * this.currentPage;
        var iFriendEnd = Math.min(
            this.PAGE_SIZE * (this.currentPage + 1),
            this.friendsScores.length);
        this.numFriendsInPage = iFriendEnd - iFriendStart;
        this.profileImagesData = new Array(this.numFriendsInPage);

        // Function that starts the loader after every friend information is read
        var readFriends = 0;
        var friendInformationRead = function() {
            readFriends++;
            if (readFriends >= this.numFriendsInPage) {
                this.profileImagesData.forEach(function(img, i) {
                    this.load.image(i, img.url);
                }, this);
                this.load.start();
            }
        }
        friendInformationRead = friendInformationRead.bind(this);

        // Iterate through friends
        for (var iFriend = iFriendStart, iScore = 0; iFriend < iFriendEnd; iFriend++, iScore++) {
            (function(iScore, iFriend) {
                fbGetProfileDetails(this.friendsScores[iFriend].user.id, function(friend) {
                    this.scores[iScore].pos.setText((iFriend + 1) + '.');
                    this.scores[iScore].name.setText(friend.firstName || friend.name);
                    this.scores[iScore].score.setText(this.friendsScores[iFriend].score);
                    // Use special style for the user
                    if (iFriend == this.userPos) {
                        this.scores[iScore].pos.setStyle(this.positionUserTextStyle);
                        this.scores[iScore].name.setStyle(this.nameUserTextStyle);
                        this.scores[iScore].score.setStyle(this.scoreUserTextStyle);
                    }
                    this.scores[iScore].pos.visible = true;
                    this.scores[iScore].name.visible = true;
                    this.scores[iScore].score.visible = true;
                    this.profileImagesData[iScore] = friend.image;
                    friendInformationRead();
                }, this);
            }).bind(this)(iScore, iFriend);
        }
    },

    createFontStyles: function() {
        var textSize = Math.floor(this.NAME_BOX.width / 6.0) + 'px';

        var fontFace = 'Pixel Art';
        var positionTextSize = textSize;
        var nameTextSize = textSize;
        var scoreTextSize = textSize;
        var normalColor = 'white';
        var userColor = 'red';

        // Normal
        this.positionTextStyle = {
            font: fontFace,
            fontSize: positionTextSize,
            fill: normalColor,
            align: 'right',
            boundsAlignH: 'right',
            boundsAlignV: 'middle'
        };
        this.nameTextStyle = {
            font: fontFace,
            fontSize: positionTextSize,
            fill: normalColor,
            align: 'left',
            boundsAlignH: 'left',
            boundsAlignV: 'middle',
            wordWrap: true,
            wordWrapWidth: this.NAME_BOX.width
        };
        this.scoreTextStyle = {
            font: fontFace,
            fontSize: scoreTextSize,
            fill: 'white',
            align: 'right',
            boundsAlignH: 'right',
            boundsAlignV: 'middle'
        };
        // User
        this.positionUserTextStyle = {
            font: fontFace,
            fontSize: positionTextSize,
            fill: userColor,
            align: 'right',
            boundsAlignH: 'right',
            boundsAlignV: 'middle'
        };
        this.nameUserTextStyle = {
            font: fontFace,
            fontSize: nameTextSize,
            fill: userColor,
            align: 'left',
            boundsAlignH: 'left',
            boundsAlignV: 'middle',
            wordWrap: true,
            wordWrapWidth: this.NAME_BOX.width
        };
        this.scoreUserTextStyle = {
            font: fontFace,
            fontSize: scoreTextSize,
            fill: userColor,
            align: 'right',
            boundsAlignH: 'right',
            boundsAlignV: 'middle'
        };
    },

    createHighscoreEntries: function() {
        for (var i = 0; i < this.PAGE_SIZE; i++) {
            var xOffset = 0;
            var yOffset = i * this.ENTRY_BOX.height;

            // Position
            var pos = this.add.text(0, 0, '', this.positionTextStyle);
            pos.setTextBounds(
                this.POSITION_BOX.x + xOffset,
                this.POSITION_BOX.y + yOffset,
                this.POSITION_BOX.width,
                this.POSITION_BOX.height);
            pos.visible = false;

            // Image
            var img = this.add.image(
                this.IMAGE_BOX.x + this.IMAGE_BOX.width / 2 + xOffset,
                this.IMAGE_BOX.y + this.IMAGE_BOX.height / 2 + yOffset,
                'noface');
            img.visible = false;

            // Name
            var name = this.add.text(0, 0, '', this.nameTextStyle);
            name.setTextBounds(
                this.NAME_BOX.x + xOffset,
                this.NAME_BOX.y + yOffset,
                this.NAME_BOX.width,
                this.NAME_BOX.height);
            name.visible = false;

            // Score
            var score = this.add.text(0, 0, '', this.scoreTextStyle);
            score.setTextBounds(
                this.SCORE_BOX.x + xOffset,
                this.SCORE_BOX.y + yOffset,
                this.SCORE_BOX.width,
                this.SCORE_BOX.height);
            score.visible = false;

            this.scores.push({
                pos: pos,
                img: img,
                name: name,
                score: score
            });
        }
    },

    destroyHighscoreEntries: function() {
        for (var i = 0; i < this.scores.length; i++) {
            if (this.scores[i]) {
                if (this.scores[i].img) {
                    this.scores[i].img.loadTexture('noface');
                    this.scores[i].img.destroy();
                }
                if (this.scores[i].name) {
                    this.scores[i].name.destroy();
                }
                if (this.scores[i].pos) {
                    this.scores[i].pos.destroy();
                }
                if (this.scores[i].score) {
                    this.scores[i].score.destroy();
                }
            }
        }
        this.scores = [];
    },

    createUI: function() {
        // Back button to go back to main state
        this.backButton = this.add.button(0, 0, 'back',
            function() {
                this.state.start('Router');
            }, this, 0, 0, 0);
        this.backButton.smoothed = false;
        var backButtonSize = .1 * Math.min(this.world.width, this.world.height);
        this.backButton.width = backButtonSize;
        this.backButton.height = backButtonSize;
        this.backButton.anchor.setTo(0, 0);
        this.backButton.x = this.backButton.width * .2;
        this.backButton.y = this.backButton.height * .2;

        // Arrows to navigate through pages
        var arrowSize = .1 * Math.min(this.world.width, this.world.height);
        this.arrowRight = this.add.button(0, 0, 'arrow',
            function() {
                if (this.currentPage < this.maxPage) {
                    this.currentPage++;
                    this.loadScoresPage();
                }
            }, this, 0, 0, 0);
        this.arrowRight.smoothed = false;
        this.arrowRight.width = arrowSize;
        this.arrowRight.height = arrowSize;
        this.arrowRight.anchor.setTo(1, 1);
        this.arrowRight.x = this.world.width - this.arrowRight.width * .2;
        this.arrowRight.y = this.world.height - this.arrowRight.height * .2;
        this.arrowRight.visible = false;

        this.arrowLeft = this.add.button(0, 0, 'arrow',
            function() {
                if (this.currentPage > 0) {
                    this.currentPage--;
                    this.loadScoresPage();
                }
            }, this, 0, 0, 0);
        this.arrowLeft.width = -arrowSize;
        this.arrowLeft.height = arrowSize;
        this.arrowLeft.smoothed = false;
        this.arrowLeft.anchor.setTo(1, 1);
        this.arrowLeft.x = -this.arrowLeft.width * .2;
        this.arrowLeft.y = this.world.height - this.arrowLeft.height * .2;
        this.arrowLeft.visible = false;
    },

    destroyUI: function() {
        this.backButton.destroy();
        this.arrowRight.destroy();
        this.arrowLeft.destroy();
    },

    // Boxes

    ENTRIES_BOX: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    ENTRY_BOX: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    POSITION_BOX: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    IMAGE_BOX: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    NAME_BOX: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    SCORE_BOX: {
        x: 0,
        y: 0,
        width: 0,
        height: 0
    },
    IMAGE_SIZE: 0,

    createLayoutBoxes: function() {
        var margin = .15 * Math.min(this.world.width, this.world.height);
        this.ENTRIES_BOX.x = margin;
        this.ENTRIES_BOX.y = margin;
        this.ENTRIES_BOX.width = this.world.width - 2 * margin;
        this.ENTRIES_BOX.height = this.world.height - 2 * margin;

        this.ENTRY_BOX.x = this.ENTRIES_BOX.x;
        this.ENTRY_BOX.y = this.ENTRIES_BOX.y;
        this.ENTRY_BOX.width = this.ENTRIES_BOX.width;
        this.ENTRY_BOX.height = this.ENTRIES_BOX.height / this.PAGE_SIZE;

        this.POSITION_BOX.x = this.ENTRY_BOX.x + this.ENTRY_BOX.width * .0;
        this.POSITION_BOX.y = this.ENTRY_BOX.y;
        this.POSITION_BOX.width = this.ENTRIES_BOX.width * .05;
        this.POSITION_BOX.height = this.ENTRY_BOX.height;

        this.IMAGE_BOX.x = this.ENTRY_BOX.x + this.ENTRY_BOX.width * .05;
        this.IMAGE_BOX.y = this.ENTRY_BOX.y;
        this.IMAGE_BOX.width = this.ENTRIES_BOX.width * .25;
        this.IMAGE_BOX.height = this.ENTRY_BOX.height;

        this.NAME_BOX.x = this.ENTRY_BOX.x + this.ENTRY_BOX.width * .30;
        this.NAME_BOX.y = this.ENTRY_BOX.y;
        this.NAME_BOX.width = this.ENTRIES_BOX.width * .45;
        this.NAME_BOX.height = this.ENTRY_BOX.height;

        this.SCORE_BOX.x = this.ENTRY_BOX.x + this.ENTRY_BOX.width * .78;
        this.SCORE_BOX.y = this.ENTRY_BOX.y;
        this.SCORE_BOX.width = this.ENTRIES_BOX.width * .22;
        this.SCORE_BOX.height = this.ENTRY_BOX.height;

        this.IMAGE_SIZE = .6 * Math.min(
            this.ENTRY_BOX.width * .25,
            this.ENTRY_BOX.height);
    }

};<|endoftext|>


<commit_before>
var fs = require('fs');
var path = require('path');
var suspend = require('suspend');
var resume = suspend.resume;

var addComponentSymlinks = suspend.async(function* (dirname) {
  console.error('addComponentSymlinks: %j', dirname);

  var stat = yield fs.lstat(dirname, resume());

  // we only care about directories here
  if (!stat) return;
  if (stat.isSymbolicLink()) return;
  if (!stat.isDirectory()) return;

  var dirs;
  var nodeModulesDir = path.resolve(dirname, 'node_modules');
  try {
    dirs = yield fs.readdir(nodeModulesDir, resume());
  } catch (e) {
    // return on ENOENT, everything can be re-thrown
    if ('ENOENT' == e.code) {
      return;
    } else {
      throw e;
    }
  }

  // iterate through the dirs, currently doing all processing in parallel
  for (var i = 0; i < dirs.length; i++) {
    var dir = path.resolve(nodeModulesDir, dirs[i]);
    processDir(dir, suspend.fork());
    addComponentSymlinks(dir, suspend.fork());
  }

  return yield suspend.join();
});

var processDir = suspend.async(function* (dirname) {
  console.error('processDir: %j', dirname);

  // checks the `component.json` in the specified dir
  var stat = yield fs.lstat(dirname, resume());

  // we only care about directories here
  if (!stat) return;
  if (stat.isSymbolicLink()) return;
  if (!stat.isDirectory()) return;

  var componentPath = path.resolve(dirname, 'component.json');
  var component;
  try {
    var data = yield fs.readFile(componentPath, 'utf8', resume());
    component = JSON.parse(data);
  } catch (e) {
    // ignore ENOENT, everything can be re-thrown
    if ('ENOENT' != e.code) throw e;
  }

  if (!component || !component.name) {
    return;
  }
  console.error('read "component.json" file with "name": %j', component.name);

  var nodeModulesDir = path.dirname(dirname);
  var src = path.basename(dirname);
  if (src == component.name) {
    console.error('ignoring matching package and component name: %j', src);
    return;
  }
  var dst = path.resolve(nodeModulesDir, component.name);

  try {
    yield fs.unlink(dst, resume());
  } catch (e) {
    // ignore ENOENT, everything can be re-thrown
    if ('ENOENT' != e.code) throw e;
  }

  // finally, we can add a symlink for this component
  console.log('adding symlink %j -> %j', src, component.name);
  yield fs.symlink(src, dst, resume());

});

module.exports = addComponentSymlinks;
<commit_msg>index: skip symlink if dir already exists<commit_after>
var fs = require('fs');
var path = require('path');
var suspend = require('suspend');
var resume = suspend.resume;

var addComponentSymlinks = suspend.async(function* (dirname) {
  console.error('addComponentSymlinks: %j', dirname);

  var stat = yield fs.lstat(dirname, resume());

  // we only care about directories here
  if (!stat) return;
  if (stat.isSymbolicLink()) return;
  if (!stat.isDirectory()) return;

  var dirs;
  var nodeModulesDir = path.resolve(dirname, 'node_modules');
  try {
    dirs = yield fs.readdir(nodeModulesDir, resume());
  } catch (e) {
    // return on ENOENT, everything can be re-thrown
    if ('ENOENT' == e.code) {
      return;
    } else {
      throw e;
    }
  }

  // iterate through the dirs, currently doing all processing in parallel
  for (var i = 0; i < dirs.length; i++) {
    var dir = path.resolve(nodeModulesDir, dirs[i]);
    processDir(dir, suspend.fork());
    addComponentSymlinks(dir, suspend.fork());
  }

  return yield suspend.join();
});

var processDir = suspend.async(function* (dirname) {
  console.error('processDir: %j', dirname);

  // checks the `component.json` in the specified dir
  var stat = yield fs.lstat(dirname, resume());

  // we only care about directories here
  if (!stat) return;
  if (stat.isSymbolicLink()) return;
  if (!stat.isDirectory()) return;

  var componentPath = path.resolve(dirname, 'component.json');
  var component;
  try {
    var data = yield fs.readFile(componentPath, 'utf8', resume());
    component = JSON.parse(data);
  } catch (e) {
    // ignore ENOENT, everything can be re-thrown
    if ('ENOENT' != e.code) throw e;
  }

  if (!component || !component.name) {
    return;
  }
  console.error('read "component.json" file with "name": %j', component.name);

  var nodeModulesDir = path.dirname(dirname);
  var src = path.basename(dirname);
  if (src == component.name) {
    console.error('ignoring matching package and component name: %j', src);
    return;
  }
  var dst = path.resolve(nodeModulesDir, component.name);

  try {
    yield fs.unlink(dst, resume());
  } catch (e) {
    if ('EPERM' == e.code) {
      console.error('skipping symlink for %s because of existing directory with name: %s', src, component.name);
      return;
    }
    if ('ENOENT' != e.code) throw e;
  }

  // finally, we can add a symlink for this component
  console.log('adding symlink %j -> %j', src, component.name);
  yield fs.symlink(src, dst, resume());

});

module.exports = addComponentSymlinks;
<|endoftext|>


<commit_before>const gulp  = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const eslint = require('gulp-eslint');
const rename = require('gulp-rename');

const sass = require('gulp-sass');
const autoprefixer = require('gulp-autoprefixer');
const cssmin = require('gulp-clean-css');

const htmlmin = require('gulp-htmlmin');
const uglify = require('gulp-uglify');
const concat = require('gulp-concat');
const zip = require('gulp-zip');

const fs = require('fs');
const pkg = require('./package.json');

const VERSION = pkg.version;
const COPYRIGHT =
`/**
 * Particleground.js v${ VERSION } (https://github.com/Barrior/Particleground.js)
 * Copyright 2016 Barrior <Barrior@qq.com>
 * Licensed under the MIT (https://opensource.org/licenses/mit-license.php)
 */
`;

const dist = './public/dist';
const src = './public/src';
let online = false;

gulp.task('sass',function(){
    if( online ){
        return gulp.src(`${src}/sass/build.scss`)
            .pipe(sass())
            .pipe(
                autoprefixer({
                    browsers: [ 'IE >= 9', 'Firefox > 10', 'chrome > 10' ]
                })
            )
            .pipe(cssmin())
            .pipe(rename('site.css'))
            .pipe(gulp.dest(`${dist}/css/`))
    }
    gulp.src(`${src}/sass/build.scss`)
       .pipe(sourcemaps.init())
       .pipe(
           sass({
               outputStyle: 'expanded'
           })
       )
       .pipe(
           autoprefixer({
               browsers: [ 'IE >= 9', 'Firefox > 10', 'chrome > 10' ]
           })
       )
       .pipe(cssmin())
       .pipe(rename('site.css'))
       .pipe(sourcemaps.write('./map'))
       .pipe(gulp.dest(`${dist}/css/`))
});

gulp.task('js',function(){
    if( online ){
        return gulp.src(`${src}/js/site.js`)
            .pipe(uglify())
            .pipe(gulp.dest(`${dist}/js/`))
    }
    gulp.src(`${src}/js/site.js`)
       .pipe(gulp.dest(`${dist}/js/`))
});

gulp.task('default',function(){
    gulp.watch([`${src}/sass/*.scss`],function(){
        gulp.run('sass');
    });
    gulp.watch([`${src}/js/*.js`],function(){
        gulp.run('js');
    });
});

gulp.task('online', function(){
    online = true;
    gulp.run('sass');
    gulp.run('js');
});

// pack pjs to dev environment
let packDirPath = './pjs-dev/pjs/';
gulp.task('pack-pjs', function () {
    gulp.watch([ packDirPath + '*.js' ], function(){
        fs.readdir(packDirPath, function(err, files){

            files = files.join(' ').replace( /particleground\.js\s|particleground\.all\.js\s/g, '');
            files = ( 'particleground.js ' + files ).split(' ');
            files.forEach(function( v, i, array ){
                array.splice( i, 1, packDirPath + v );
            });

            gulp.src( files )
                .pipe( concat( 'particleground.all.js' ) )
                .pipe( gulp.dest( packDirPath ) )
        });
    });
});

// build pjs production
let prodDir = `pjs-production/${ VERSION }/`;
gulp.task('build-prod', function () {
    gulp.src( packDirPath + '*.js' )
        .pipe( uglify() )
        .pipe( gulp.dest( prodDir ) )
        .on('end', addCopyright);
});

// move production to web site
gulp.task('move', function () {
    gulp.src( prodDir + 'particleground.all.js' )
        .pipe( gulp.dest( `${dist}/js/` ) );

    gulp.src( prodDir + '*' )
        .pipe( zip('particleground.js.zip') )
        .pipe( gulp.dest( dist ) );
});

function addCopyright(){
    [
        'particleground.all.js',
        'particleground.js'
    ]
    .forEach(function( v ){
        let filename = prodDir + v;
        fs.readFile( filename, function( err, data ){
            let writeData = COPYRIGHT + data.toString();
            if( !err ){
                fs.writeFile( filename, writeData, function( err ){
                    !err && console.log( filename + '【写入成功】' );
                });
            }
        });
    });
}<commit_msg>DEFAULT<commit_after>const gulp  = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const eslint = require('gulp-eslint');
const rename = require('gulp-rename');
const sass = require('gulp-sass');
const autoprefixer = require('gulp-autoprefixer');
const cssmin = require('gulp-clean-css');
const htmlmin = require('gulp-htmlmin');
const uglify = require('gulp-uglify');
const concat = require('gulp-concat');
const zip = require('gulp-zip');

const cp = require('child_process');
const fs = require('fs');
const pkg = require('./package.json');

const VERSION = pkg.version;
const COPYRIGHT =
`/**
 * Particleground.js v${ VERSION } (https://github.com/Barrior/Particleground.js)
 * Copyright 2016 Barrior <Barrior@qq.com>
 * Licensed under the MIT (https://opensource.org/licenses/mit-license.php)
 */
`;

const dist = './public/dist';
const src = './public/src';
let online = false;

gulp.task('sass',function(){
    if( online ){
        return gulp.src(`${src}/sass/build.scss`)
            .pipe(sass())
            .pipe(
                autoprefixer({
                    browsers: [ 'IE >= 9', 'Firefox > 10', 'chrome > 10' ]
                })
            )
            .pipe(cssmin())
            .pipe(rename('site.css'))
            .pipe(gulp.dest(`${dist}/css/`))
    }
    gulp.src(`${src}/sass/build.scss`)
       .pipe(sourcemaps.init())
       .pipe(
           sass({
               outputStyle: 'expanded'
           })
       )
       .pipe(
           autoprefixer({
               browsers: [ 'IE >= 9', 'Firefox > 10', 'chrome > 10' ]
           })
       )
       .pipe(cssmin())
       .pipe(rename('site.css'))
       .pipe(sourcemaps.write('./map'))
       .pipe(gulp.dest(`${dist}/css/`))
});

gulp.task('js',function(){
    if( online ){
        return gulp.src(`${src}/js/site.js`)
            .pipe(uglify())
            .pipe(gulp.dest(`${dist}/js/`))
    }
    gulp.src(`${src}/js/site.js`)
       .pipe(gulp.dest(`${dist}/js/`))
});

gulp.task('default',function(){
    gulp.watch([`${src}/sass/*.scss`],function(){
        gulp.run('sass');
    });
    gulp.watch([`${src}/js/*.js`],function(){
        gulp.run('js');
    });
});

gulp.task('online', function(){
    online = true;
    ['css', 'js'].forEach(v => {
        cp.exec(`rm -rf ${dist}/${v}/map`, (err, stdout, stderr) => {
            !err && console.log(`${dist}/${v}/map【文件夹删除成功】`);
        });
    });
    gulp.run('sass');
    gulp.run('js');
});

// pack pjs to dev environment
let packDirPath = './pjs-dev/pjs/';
gulp.task('pack-pjs', function () {
    gulp.watch([ packDirPath + '*.js' ], function(){
        fs.readdir(packDirPath, function(err, files){

            files = files.join(' ').replace( /particleground\.js\s|particleground\.all\.js\s/g, '');
            files = ( 'particleground.js ' + files ).split(' ');
            files.forEach(function( v, i, array ){
                array.splice( i, 1, packDirPath + v );
            });

            gulp.src( files )
                .pipe( concat( 'particleground.all.js' ) )
                .pipe( gulp.dest( packDirPath ) )
        });
    });
});

// build pjs production
let prodDir = `pjs-production/${ VERSION }/`;
gulp.task('build-prod', function () {
    gulp.src( packDirPath + '*.js' )
        .pipe( uglify() )
        .pipe( gulp.dest( prodDir ) )
        .on('end', addCopyright);
});

// move production to web site
gulp.task('move', function () {
    gulp.src( prodDir + 'particleground.all.js' )
        .pipe( gulp.dest( `${dist}/js/` ) );

    gulp.src( prodDir + '*' )
        .pipe( zip('particleground.js.zip') )
        .pipe( gulp.dest( dist ) );
});

function addCopyright(){
    [
        'particleground.all.js',
        'particleground.js'
    ]
    .forEach(function( v ){
        let filename = prodDir + v;
        fs.readFile( filename, function( err, data ){
            let writeData = COPYRIGHT + data.toString();
            if( !err ){
                fs.writeFile( filename, writeData, function( err ){
                    !err && console.log( filename + '【写入成功】' );
                });
            }
        });
    });
}<|endoftext|>


<commit_before>/* Flow v0.X + genData v1.1 | github.com/bemson | (c) 2011, MIT */
function genData(a){var b=arguments,c=b.callee,d,e,f,g,h,i=[],j=[],k={},l,m,n,o=c,p;if(!(this instanceof c)){b[1]&&(i=typeof b[1]=="function"?[b[1]]:b[1]),f=i.length,b[2]&&(o=b[2]);function q(a,b){this.name=a,this.value=b}q.prototype=o.prototype,q.prototype.constructor=o,l=[["",a]];while(l.length){n=l.shift(),p=new q(n[0],n[1]),e=0,d={parent:0,omit:0,scan:1,exit:0},b=[p.name,p.value,n[2],j,d,k];while(e<f&&!d.exit)i[e++].apply(p,b);d.omit?p._OMIT=!0:j.push(p);if(d.exit)l=[];else{m=[];if(d.scan&&typeof p.value=="object"){h=d.parent&&(d.parent instanceof o||d.parent instanceof c)?d.parent:p;for(g in p.value)p.value.hasOwnProperty(g)&&m.push([g,p.value[g],h])}l=m.concat(l)}}return j}if(a){~{}.toString.call(b[1]).indexOf("y")&&(o=a,b=b[1]),i=i.concat([].slice.call(b));function r(a,b,d){var e=~{}.toString.call(b).indexOf("y");if(!(this instanceof r))return c(a,i.concat(b||[]),d?d:r);if(a)return new c(e?a:r,i.concat(e?b:[].slice.call(arguments)));return this}r.prototype=new o,r.prototype.constructor=o;return r}return this}
!function(a,b,c,d){function l(){}function m(){}function n(a){function b(b){var c=b&&b.toString(f);return typeof c=="object"&&(c.pkgs.filter(function(b){return b.name===a})[0]||{}).pkg||!1}function c(){}function d(){}return b.prototype=new m,b.init=b.dataKey=b.invalidKey=b.onBegin=b.onEnd=b.onTraverse=0,c.prototype=new l,l=c,b.proxy=c.prototype,b.state=d.prototype,h[a]=g.push({name:a,pkg:b,model:c,state:d})-1,b}function o(a){var b=j(a);return b[0].parentIndex=b[0].childIndex=0,b.unshift(j()[0]),b[0].children.push(1),b[0].name="_flow",b[0].index=0,b[0].depth=0,b[0].location="..//",b[0].firstChildIndex=b[0].lastChildIndex=1,b}function p(a,b,c){var d=this;typeof c!="object"&&(c={}),d.prgm=a,d.states=o(a),d.shared={id:++e,currentIndex:0,targetIndex:-1,go:function(a){var b=d.states[a];return b?(d.target=b,d.shared.targetIndex=b.index,d.stop=0,d.go()):!1},stop:function(){return d.stop=1,!0},post:function(a){var b;switch(typeof a){case"function":return d.posts.push(a)-1;case"number":b=~~a;if(d.posts[a])return d.posts[a]=null,!0}return!1}},d.posts=[],d.current=d.states[0],d.target=d.loop=0,d.pkgs=g.map(function(a){function f(){}var e={name:a.name};return f.prototype=new a.pkg,e.pkg=new f,e.pkg.states=k(d.states,[],a.state),typeof a.pkg.init=="function"&&a.pkg.init.call(e.pkg,c),e.pkg.tank=d.shared,e.pkg.proxy=b,e})}function q(a,b){function h(a){return a===f?e:Object.prototype.toString.apply(this,arguments)}function i(){function a(){this.pkgs=c,this.toString=h}return a.prototype=new l,a}if(this instanceof arguments.callee){var c={},d=new(i()),e=new p(a instanceof l?a.toString(f).prgm:a,d,typeof b=="object"?b:{});return g.forEach(function(a){var b=i();b.prototype=new a.model,c[a.name]=new b}),d}throw new Error('Requires "new"')}var e=0,f={},g=[],h={},i=function(a,b,c){return b.length&&g.some(function(d){var e=d.pkg[a];switch(typeof e){case"function":return e(b,c);case"object":if(e instanceof RegExp)return e.test(b)}return!1})},j=new c(function(a,b,c,e,f){var g=this,h=i("invalidKey",a,b),j=i("dataKey",a,b);h||j?(f.omit=1,f.scan=0,j&&!h&&(c.data[a]=b)):(g.inContext=g.parentIndex=g.previousIndex=g.nextIndex=g.firstChildIndex=d,g.index=e.length+1,g.depth=c?c.depth+1:1,g.name=c?a:"_root",g.data={},g.location=c?c.location+a+"/":"//",g.children=[],c&&(g.parentIndex=c.index,c.children.length||(c.firstChildIndex=g.index),g.childIndex=c.children.push(g.index)-1,c.lastChildIndex=g.index,g.childIndex&&(g.previousIndex=c.children[g.childIndex-1],e[g.previousIndex-1].nextIndex=g.index)))}),k=new c(function(a,b,c,d,e){var f=this,g;if(!c)e.omit=1;else{e.scan=0;for(g in b)b.hasOwnProperty(g)&&g!=="inContext"&&(f[g]=b[g])}});g.some||(b.prototype.some=function(a){"use strict";if(this===void 0||this===null)throw new TypeError;var b=Object(this),c=b.length>>>0;if(typeof a!="function")throw new TypeError;var d=arguments[1];for(var e=0;e<c;e++)if(e in b&&a.call(d,b[e],e,b))return!0;return!1}),g.filter||(b.prototype.filter=function(a){"use strict";if(this===void 0||this===null)throw new TypeError;var b=Object(this),c=b.length>>>0;if(typeof a!="function")throw new TypeError;var d=[],e=arguments[1];for(var f=0;f<c;f++)if(f in b){var g=b[f];a.call(e,g,f,b)&&d.push(g)}return d}),g.forEach||(b.prototype.forEach=function(a){"use strict";if(this===void 0||this===null)throw new TypeError;var b=Object(this),c=b.length>>>0;if(typeof a!="function")throw new TypeError;var d=arguments[1];for(var e=0;e<c;e++)a.call(d,b[e],e,b)}),g.map||(b.prototype.map=function(a){"use strict";if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0;if(typeof a!="function")throw new TypeError;var e=new b(d),f=arguments[1];for(var g=0;g<d;g++)e[g]=a.call(f,c[g],g,c);return e}),l.prototype.constructor=q,m.prototype.inState=function(a){return a<this.states.length?!0:!1},p.prototype={go:function(){var a=this,b=a.states,c=a.shared,d,e=0,f=a.current,g=0,h=0,i;if(a.loop)return!!a.target;a.posts=[],a.loop=1,a.fire("Begin");while(a.loop)a.target&&!a.stop?(i=0,d=a.target.index-f.index,d?d>0&&f.index<2||!a.target.location.indexOf(f.location)?f.inContext?(g=0,h=f.firstChildIndex):(g=1,h=1,f.inContext=1):f.inContext?(g=1,h=2,f.inContext=0):(a.target.location.indexOf(b[f.parentIndex].location)&&(d=-1),h=d<0?4:3,f.lastEvent===2||f.lastEvent===h?(g=0,h=d>0?f.nextIndex:f.previousIndex||f.parentIndex):g=1):(g=1,h=f.inContext?0:1,f.inContext&&(a.target=0,c.targetIndex=-1),f.inContext=1),g?(f.lastEvent=h,e++,a.fire("Traverse",[h])):(f.lastEvent=0,f=a.current=b[h],c.currentIndex=h)):!i&&(a.stop||!a.target)?(i=1,a.fire("End")):a.loop=0;return a.posts.forEach(function(a){typeof a=="function"&&a()}),e},fire:function(a,b){b=b||[],b.unshift(a.toLowerCase()),a="on"+a,this.pkgs.forEach(function(c){var d=g[h[c.name]].pkg[a];typeof d=="function"&&d.apply(c.pkg,b)})}},q.pkg=function(a){return arguments.length?typeof a=="string"&&/\w/.test(a)?(h.hasOwnProperty(a)||n(a),g[h[a]].pkg):!1:g.map(function(a){return a.name})},a.Flow=q}(this,Array,genData);<commit_msg>Flow platform - minified for testing (5.3K/2.1K)<commit_after>/* Flow v0.X + genData v1.1 | github.com/bemson | (c) 2011, MIT */
function genData(a){var b=arguments,c=b.callee,d,e,f,g,h,i=[],j=[],k={},l,m,n,o=c,p;if(!(this instanceof c)){b[1]&&(i=typeof b[1]=="function"?[b[1]]:b[1]),f=i.length,b[2]&&(o=b[2]);function q(a,b){this.name=a,this.value=b}q.prototype=o.prototype,q.prototype.constructor=o,l=[["",a]];while(l.length){n=l.shift(),p=new q(n[0],n[1]),e=0,d={parent:0,omit:0,scan:1,exit:0},b=[p.name,p.value,n[2],j,d,k];while(e<f&&!d.exit)i[e++].apply(p,b);d.omit?p._OMIT=!0:j.push(p);if(d.exit)l=[];else{m=[];if(d.scan&&typeof p.value=="object"){h=d.parent&&(d.parent instanceof o||d.parent instanceof c)?d.parent:p;for(g in p.value)p.value.hasOwnProperty(g)&&m.push([g,p.value[g],h])}l=m.concat(l)}}return j}if(a){~{}.toString.call(b[1]).indexOf("y")&&(o=a,b=b[1]),i=i.concat([].slice.call(b));function r(a,b,d){var e=~{}.toString.call(b).indexOf("y");if(!(this instanceof r))return c(a,i.concat(b||[]),d?d:r);if(a)return new c(e?a:r,i.concat(e?b:[].slice.call(arguments)));return this}r.prototype=new o,r.prototype.constructor=o;return r}return this}
!function(a,b,c,d){function m(){}function n(){}function o(a){function b(b){var c=b&&b.toString(f);return typeof c=="object"&&(c.pkgs.filter(function(b){return b.name===a})[0]||{}).pkg||!1}function c(){}function d(){}return b.prototype=new n,b.init=b.dataKey=b.invalidKey=b.onBegin=b.onEnd=b.onTraverse=0,c.prototype=new m,m=c,b.proxy=c.prototype,b.state=d.prototype,h[a]=g.push({name:a,pkg:b,model:c,state:d})-1,b}function p(a){var b=j(a);return b[0].parentIndex=b[0].childIndex=0,b.unshift(j()[0]),b[0].children.push(1),b[0].name="_flow",b[0].index=0,b[0].depth=0,b[0].location="..//",b[0].firstChildIndex=b[0].lastChildIndex=1,b}function q(a,b,c){var d=this;typeof c!="object"&&(c={}),d.prgm=a,d.states=p(a),d.shared={id:++e,currentIndex:0,targetIndex:-1,go:function(a){var b=d.states[a];return b?(d.target=b,d.shared.targetIndex=b.index,d.stop=0,d.go()):!1},stop:function(){return d.stop=1,!0},post:function(a){var b;switch(typeof a){case"function":return d.posts.push(a)-1;case"number":b=~~a;if(d.posts[a])return d.posts[a]=null,!0}return!1}},d.posts=[],d.current=d.states[0],d.target=d.loop=0,d.pkgs=g.map(function(a){function f(){}var e={name:a.name};return f.prototype=new a.pkg,e.pkg=new f,e.pkg.states=k(d.states,[],a.state),typeof a.pkg.init=="function"&&a.pkg.init.call(e.pkg,c),e.pkg.tank=d.shared,e.pkg.proxy=b,e})}function r(a,b){function h(a){return a===f?e:Object.prototype.toString.apply(this,arguments)}function i(){function a(){this.pkgs=c,this.toString=h}return a.prototype=new m,a}if(this instanceof arguments.callee){var c={},d=new(i()),e=new q(a instanceof m?a.toString(f).prgm:a,d,typeof b=="object"?b:{});return g.forEach(function(a){var b=i();b.prototype=new a.model,c[a.name]=new b}),d}throw new Error('Requires "new"')}var e=0,f={},g=[],h={},i=function(a,b,c){return b.length&&g.some(function(d){var e=d.pkg[a];switch(typeof e){case"function":return e(b,c);case"object":if(e instanceof RegExp)return e.test(b)}return!1})},j=new c(function(a,b,c,e,f){var g=this,h=i("invalidKey",a,b),j=i("dataKey",a,b);h||j?(f.omit=1,f.scan=0,j&&!h&&(c.data[a]=b)):(g.inContext=g.parentIndex=g.previousIndex=g.nextIndex=g.firstChildIndex=d,g.index=e.length+1,g.depth=c?c.depth+1:1,g.name=c?a:"_root",g.data={},g.location=c?c.location+a+"/":"//",g.children=[],c&&(g.parentIndex=c.index,c.children.length||(c.firstChildIndex=g.index),g.childIndex=c.children.push(g.index)-1,c.lastChildIndex=g.index,g.childIndex&&(g.previousIndex=c.children[g.childIndex-1],e[g.previousIndex-1].nextIndex=g.index)))}),k=new c(function(a,b,c,d,e){var f=this,g;if(!c)e.omit=1;else{e.scan=0;for(g in b)b.hasOwnProperty(g)&&g!=="inContext"&&(f[g]=b[g])}}),l=b.prototype;l.some||(l.some=function(a,b){for(var c=0,d=this.length;c<d;c++)if(a.call(b,this[c],c,this))return!0;return!1}),l.filter||(l.filter=function(a,b){var c=[],d=0,e=this.length,f;for(;d<e;d++)f=this[d],a.call(b,f,d,this)&&c.push(f);return c}),l.forEach||(l.forEach=function(a,b){for(var c=0,d=this.length;c<d;c++)a.call(b,this[c],c,this)}),l.map||(l.map=function(a,c){var d=0,e=this.length,f=new b(e);for(;d<e;d++)f[d]=a.call(c,this[d],d,this);return f}),m.prototype.constructor=r,n.prototype.inState=function(a){return a<this.states.length?!0:!1},q.prototype={go:function(){var a=this,b=a.states,c=a.shared,d,e=0,f=a.current,g=0,h=0,i;if(a.loop)return!!a.target;a.posts=[],a.loop=1,a.fire("Begin");while(a.loop)a.target&&!a.stop?(i=0,d=a.target.index-f.index,d?d>0&&f.index<2||!a.target.location.indexOf(f.location)?f.inContext?(g=0,h=f.firstChildIndex):(g=1,h=1,f.inContext=1):f.inContext?(g=1,h=2,f.inContext=0):(a.target.location.indexOf(b[f.parentIndex].location)&&(d=-1),h=d<0?4:3,f.lastEvent===2||f.lastEvent===h?(g=0,h=d>0?f.nextIndex:f.previousIndex||f.parentIndex):g=1):(g=1,h=f.inContext?0:1,f.inContext&&(a.target=0,c.targetIndex=-1),f.inContext=1),g?(f.lastEvent=h,e++,a.fire("Traverse",[h])):(f.lastEvent=0,f=a.current=b[h],c.currentIndex=h)):!i&&(a.stop||!a.target)?(i=1,a.fire("End")):a.loop=0;return a.posts.forEach(function(a){typeof a=="function"&&a()}),e},fire:function(a,b){b=b||[],b.unshift(a.toLowerCase()),a="on"+a,this.pkgs.forEach(function(c){var d=g[h[c.name]].pkg[a];typeof d=="function"&&d.apply(c.pkg,b)})}},r.pkg=function(a){return arguments.length?typeof a=="string"&&/\w/.test(a)?(h.hasOwnProperty(a)||o(a),g[h[a]].pkg):!1:g.map(function(a){return a.name})},a.Flow=r}(this,Array,genData);<|endoftext|>


<commit_before>var selectedSchedule = [];
var finals = [];
var ratings = null;

function Course(name, times, days){
	this.name = name;
	this.days = days.replace(/,/g, '').trim();
	this.start = convertTime(times.slice(0,8));
	this.end = convertTime(times.slice(10));
	this.conflicts = function(class2){ //Check if two classes conflict
		for(var day = 0; day < this.days.length; day++){ //Check the days
			var sameDay = class2.days.includes(this.days.charAt(day));
			var sameTime = this.start <= class2.end && this.end >= class2.start;
			if(sameDay && sameTime){
				return class2.name;
			}
		}
		return false;
	}
}

function Final(date, time){
	this.name;
	this.date = date;
	this.startTime = convertTime(time);
	this.endTime = this.startTime + 200;
	this.conflicts = function(final2){
		return this.date == final2.date &&
		this.startTime <= final2.endTime && this.endTime >= final2.startTime;
	}
}

//Converts to 24hr time
function convertTime(time12h) {
	time12h = time12h.trim();
	const [time, modifier] = time12h.split(' ');
  	let [hours, minutes] = time.split(':');
  	if (modifier === 'PM' && hours !== "12") {
    	hours = parseInt(hours, 10) + 12;
  	}
 	return Number(hours + minutes);
}

$(document).ready(function(){
	//Preload your schedule into an array
	loadSchedule();

	//Overwrite the main functions in Schedule Builder API
	var oldDrop = getDropCourseConfirmation;
	getDropCourseConfirmation = function(courseID,ThisButton,ThisFunction,source){
		oldDrop(courseID,ThisButton,ThisFunction,source);
		setTimeout(function(){
			loadSchedule();
			findConflicts("#courseResultsDiv");
			findConflicts("#inlineCourseResultsDiv");
		}, 1500);
	}

	var oldRemove = updateCourseSelections;
	updateCourseSelections = function(generalCourseID,specificCourseID,ThisElement,specifiedAction,spinnerColor){
		oldRemove(generalCourseID,specificCourseID,ThisElement,specifiedAction,spinnerColor);
		setTimeout(function(){
			loadSchedule();
			findConflicts("#courseResultsDiv");
			findConflicts("#inlineCourseResultsDiv");
		}, 1500);
	}

	var oldAdd = UCD.SAOT.COURSES_SEARCH.addCourse;
	UCD.SAOT.COURSES_SEARCH.addCourse = function(resultsRow,ThisButton){
		oldAdd(resultsRow, ThisButton);
		setTimeout(function(){
			loadSchedule();
			findConflicts("#courseResultsDiv");
		}, 1000);
	}

	var oldInlineAdd = UCD.SAOT.COURSES_SEARCH_INLINE.addCourse;
	UCD.SAOT.COURSES_SEARCH_INLINE.addCourse = function(resultsRow,ThisButton){
		oldInlineAdd(resultsRow, ThisButton);
		setTimeout(function(){
			loadSchedule();
			findConflicts("#inlineCourseResultsDiv");
		}, 1000);
	}

	var oldSearch = UCD.SAOT.COURSES_SEARCH.textSearch;
	UCD.SAOT.COURSES_SEARCH.textSearch = function(){
		oldSearch();
		findConflicts("#courseResultsDiv");
	}

	var oldInline = UCD.SAOT.COURSES_SEARCH_INLINE.textSearch;
	UCD.SAOT.COURSES_SEARCH_INLINE.textSearch = function(){
		oldInline();
		findConflicts("#inlineCourseResultsDiv");
	}

	$.ajax({
			'async': false,
			'global': false,
			'url': "https://crossorigin.me/http://104.236.158.81/api/rateapi/index.php",
			'dataType': "json",
			'success': function (data) {
					ratings = data;
			}
	});
});

// This function will insert the ratings into the results.
function insertRating(element, meetings)
{
	// Starts the process to find the prof link and ratings;
	var professor = element.find('a[href^="mailto:"]')[0];
	if (professor != undefined){
		var fullname = professor.innerText.replace(/\./g,' ').split(/[ ,]+/); // Gets the professor name and splits it up into FIrst and Last Name.
		var first = fullname[0], last = fullname[1];
		if (ratings[last][first] === "undefined") return;
		professor.href = "http://www.ratemyprofessors.com/ShowRatings.jsp?tid=" + ratings[last][first]['url']; // Replaces mailing link with ratemyprofessor link.
		professor.setAttribute('target', "_blank");

		if ($(meetings[0]).children()[4].style.width != "16%"){ // Creates the Overall Rating Div.
			$(meetings[0]).children()[4].style.width = "16%";
			$(meetings[0]).append('
Overall: '+ ratings[last][first]['quality'] +'
');
		}

		if ($(meetings[1]).children()[4].style.width != "16%"){// Creates the Difficulty Rating Div.
			$(meetings[1]).children()[4].style.width = "16%";
			$(meetings[1]).append('
Difficulty: '+ ratings[last][first]['diff'] +'
');
		}

		if (meetings.length == 4){ // Will create a bottom div for the rating if it does not have it. Specifcally for classes with only lectures.
			$(meetings[0]).parent().append('

Difficulty: '+ ratings[last][first]['diff'] +'

');
		}
	}

}

//This is the main function: Marks the classes that conflict with your currently selected schedule.
function findConflicts(divName){
	var loop = setInterval(function(){
		var searchResults = $(divName).children();
		if(searchResults.length){
			var header = document.getElementsByClassName('data-column column-header align-left');
			if (header[5].style.width != "10%") { // If the ratings label has not been added, add the raings label.
				header[5].style.width = "10%";
				header[5].parentNode.innerHTML += '
Rating(s):
';
			}
			searchResults.each(function(){ //For every class in search results
				var meetings = $(this).find(".meetings").children();
				if(!(meetings.length)) return; // Checks if the results returned any classes.
				insertRating($(this), meetings); // Calls function to insert the rating into the meetings HTML element.
				//Check if its in your schedule
				if(inSchedule(this)){
					$(this).css({"background-color":"#cfe4ff"}); //Change to blue
					return; //Continue
				}
				var conflicts = false;
				for(var i = 0; ($(meetings[i]).children()[1]) && !conflicts; i++){ //Check every meeting (lecture, discussion, lab)
					var times = $(meetings[i]).children()[1].innerHTML;
					var days = $(meetings[i]).children()[2].innerHTML;
					var potential = new Course("", times, days);
					//Loop through current schedule to check for conficts
					for(var curr = 0; curr < selectedSchedule.length; curr++){
						conflicts = potential.conflicts(selectedSchedule[curr]);
						if(conflicts){break;}
					}
				}
				if(!conflicts){ //Check finals
					conflicts = finalsConflict(this);
				}
				if(conflicts){
					$(this).css({"background-color": "#ffdcdc"}); //Change to red
					addTooltip(this, conflicts);
				} else if (isFull(this)){
					$(this).css({"background-color": "#fff470"}); //Change to yellow
					removeTooltip(this);
				} else {
					$(this).css({"background-color": "#ceffce"}); //Change to green
					removeTooltip(this);
				}
			});
			clearInterval(loop);
		}
	}, 25);
}

//Adds a tooltip to display which class conflicts
function addTooltip(element, conflictName){
	var title = $(element).find(".data-column.title")[1];
	$(title).attr("data-balloon", "Conflicts with: " + conflictName);
	$(title).attr("data-balloon-pos", "up");
}

//Removes tooltips for when user removes classes and conflicts change
function removeTooltip(element){
	var title = $(element).find(".data-column.title")[1];
	$(title).removeAttr("data-balloon");
	$(title).removeAttr("data-balloon-pos");
}

//Checks if a class is already in your schedule
function inSchedule(listing){
	var savedBtn = $(listing).find(".btn-success");
	if(!savedBtn.length){return false;}
	//This check is added because saved button stays there after you remove a class
	var title = $(listing).find(".data-column.title")[1].innerHTML;
	for(var i = 0; i < selectedSchedule.length; i++){
		if(selectedSchedule[i].name.includes(title)){
			return true;
		}
	}
	return false;
}

//Checks if a final conflicts with current finals
function finalsConflict(element){
	var final = getFinal(element, ".details", ".title");
	if(final){
		for(var i = 0; i < finals.length; i++){
			if(final.conflicts(finals[i])){return finals[i].name;}
		}
	}
	return false;
}

//Returns if a class is full or not
function isFull(element){
	var data = $(element).find(".float-left")[0];
	data = $(data).children()[1];
	var seats = $(data).children()[2].innerHTML;
	return seats.charAt(0) == "0";
}

//Preloads the currently selected schedule into two arrays: one for classes and one for finals
function loadSchedule(){
	//Reset arrays
	selectedSchedule = [];
	finals = [];
	var schedule = $('.CourseItem.gray-shadow-border.clearfix');
	schedule.each(function(index, element){ //For every class in your schedule
		var name = $(".classTitle.height-justified");
		var classTitle = name[index].innerHTML;
		var sections = $(this).find(".meeting.clearfix");
		//Get the final
		var final = getFinal(this, ".classDescription", ".boldTitle");
		final.name = classTitle + " Final";
		finals.push(final);
		sections.each(function(){ //For every meeting (lecture, discussion, lab)
			var sectionInfo = $(this).children();
			var times = sectionInfo[1].innerHTML;
			var days = sectionInfo[2].innerHTML;
			if(days){ //Not an empty string, so add to schedule
				var newClass = new Course(classTitle, times, days);
				selectedSchedule.push(newClass);
			}
		});
	});
}

//Gets the time and date of a final and return it as an object
function getFinal(element, div, title){
	var data = $(element).find(div);
	var finalText = $(data[0]).find(title + ":contains('Final')").parent();
	if(finalText.length){
		var string = finalText[0].innerHTML;
		var firstDigit = string.search(/\d/);
		string = string.substr(firstDigit);
		var space = string.search(" ");
		var date = string.substr(0, space);
		var time = string.substr(space + 1);
		return new Final(date, time);
	}
}
<commit_msg>Script to generate json from ratings database<commit_after>var selectedSchedule = [];
var finals = [];
var ratings = null;

function Course(name, times, days){
	this.name = name;
	this.days = days.replace(/,/g, '').trim();
	this.start = convertTime(times.slice(0,8));
	this.end = convertTime(times.slice(10));
	this.conflicts = function(class2){ //Check if two classes conflict
		for(var day = 0; day < this.days.length; day++){ //Check the days
			var sameDay = class2.days.includes(this.days.charAt(day));
			var sameTime = this.start <= class2.end && this.end >= class2.start;
			if(sameDay && sameTime){
				return class2.name;
			}
		}
		return false;
	}
}

function Final(date, time){
	this.name;
	this.date = date;
	this.startTime = convertTime(time);
	this.endTime = this.startTime + 200;
	this.conflicts = function(final2){
		return this.date == final2.date &&
		this.startTime <= final2.endTime && this.endTime >= final2.startTime;
	}
}

//Converts to 24hr time
function convertTime(time12h) {
	time12h = time12h.trim();
	const [time, modifier] = time12h.split(' ');
  	let [hours, minutes] = time.split(':');
  	if (modifier === 'PM' && hours !== "12") {
    	hours = parseInt(hours, 10) + 12;
  	}
 	return Number(hours + minutes);
}

$(document).ready(function(){
	//Preload your schedule into an array
	loadSchedule();

	//Overwrite the main functions in Schedule Builder API
	var oldDrop = getDropCourseConfirmation;
	getDropCourseConfirmation = function(courseID,ThisButton,ThisFunction,source){
		oldDrop(courseID,ThisButton,ThisFunction,source);
		setTimeout(function(){
			loadSchedule();
			findConflicts("#courseResultsDiv");
			findConflicts("#inlineCourseResultsDiv");
		}, 1500);
	}

	var oldRemove = updateCourseSelections;
	updateCourseSelections = function(generalCourseID,specificCourseID,ThisElement,specifiedAction,spinnerColor){
		oldRemove(generalCourseID,specificCourseID,ThisElement,specifiedAction,spinnerColor);
		setTimeout(function(){
			loadSchedule();
			findConflicts("#courseResultsDiv");
			findConflicts("#inlineCourseResultsDiv");
		}, 1500);
	}

	var oldAdd = UCD.SAOT.COURSES_SEARCH.addCourse;
	UCD.SAOT.COURSES_SEARCH.addCourse = function(resultsRow,ThisButton){
		oldAdd(resultsRow, ThisButton);
		setTimeout(function(){
			loadSchedule();
			findConflicts("#courseResultsDiv");
		}, 1000);
	}

	var oldInlineAdd = UCD.SAOT.COURSES_SEARCH_INLINE.addCourse;
	UCD.SAOT.COURSES_SEARCH_INLINE.addCourse = function(resultsRow,ThisButton){
		oldInlineAdd(resultsRow, ThisButton);
		setTimeout(function(){
			loadSchedule();
			findConflicts("#inlineCourseResultsDiv");
		}, 1000);
	}

	var oldSearch = UCD.SAOT.COURSES_SEARCH.textSearch;
	UCD.SAOT.COURSES_SEARCH.textSearch = function(){
		oldSearch();
		findConflicts("#courseResultsDiv");
	}

	var oldInline = UCD.SAOT.COURSES_SEARCH_INLINE.textSearch;
	UCD.SAOT.COURSES_SEARCH_INLINE.textSearch = function(){
		oldInline();
		findConflicts("#inlineCourseResultsDiv");
	}

	$.ajax({
			'async': false,
			'global': false,
			'url': "https://crossorigin.me/http://104.236.158.81/api/rateapi/index.php",
			'dataType': "json",
			'success': function (data) {
					ratings = data;
			}
	});
});

// This function will insert the ratings into the results.
function insertRating(element, meetings)
{
	// Starts the process to find the prof link and ratings;
	var professor = element.find('a[href^="mailto:"]')[0];
	if (professor){
		var fullname = professor.innerText.replace(/\./g,' ').split(/[ ,]+/); // Gets the professor name and splits it up into FIrst and Last Name.
		var first = fullname[0], last = fullname[1];
		if (!ratings[last] || !ratings[last][first]){return;}
		professor.href = "http://www.ratemyprofessors.com/ShowRatings.jsp?tid=" + ratings[last][first]['url']; // Replaces mailing link with ratemyprofessor link.
		professor.setAttribute('target', "_blank");

		if ($(meetings[0]).children()[4].style.width != "16%"){ // Creates the Overall Rating Div.
			$(meetings[0]).children()[4].style.width = "16%";
			$(meetings[0]).append('
Overall: '+ ratings[last][first]['quality'] +'
');
		}

		if ($(meetings[1]).children()[4].style.width != "16%"){// Creates the Difficulty Rating Div.
			$(meetings[1]).children()[4].style.width = "16%";
			$(meetings[1]).append('
Difficulty: '+ ratings[last][first]['diff'] +'
');
		}

		if (meetings.length == 4){ // Will create a bottom div for the rating if it does not have it. Specifcally for classes with only lectures.
			$(meetings[0]).parent().append('

Difficulty: '+ ratings[last][first]['diff'] +'

');
		}
	}

}

//This is the main function: Marks the classes that conflict with your currently selected schedule.
function findConflicts(divName){
	var loop = setInterval(function(){
		var searchResults = $(divName).children();
		if(searchResults.length){
			var header = document.getElementsByClassName('data-column column-header align-left');
			if (header[5].style.width != "10%") { // If the ratings label has not been added, add the raings label.
				header[5].style.width = "10%";
				header[5].parentNode.innerHTML += '
Ratings:
';
			}
			searchResults.each(function(){ //For every class in search results
				var meetings = $(this).find(".meetings").children();
				// Checks if the results returned any classes.
				if(meetings.length){
					insertRating($(this), meetings); // Calls function to insert the rating into the meetings HTML element.
				}
				//Check if its in your schedule
				if(inSchedule(this)){
					$(this).css({"background-color":"#cfe4ff"}); //Change to blue
					return; //Continue
				}
				var conflicts = false;
				for(var i = 0; ($(meetings[i]).children()[1]) && !conflicts; i++){ //Check every meeting (lecture, discussion, lab)
					var times = $(meetings[i]).children()[1].innerHTML;
					var days = $(meetings[i]).children()[2].innerHTML;
					var potential = new Course("", times, days);
					//Loop through current schedule to check for conficts
					for(var curr = 0; curr < selectedSchedule.length; curr++){
						conflicts = potential.conflicts(selectedSchedule[curr]);
						if(conflicts){break;}
					}
				}
				if(!conflicts){ //Check finals
					conflicts = finalsConflict(this);
				}
				if(conflicts){
					$(this).css({"background-color": "#ffdcdc"}); //Change to red
					addTooltip(this, conflicts);
				} else if (isFull(this)){
					$(this).css({"background-color": "#fff470"}); //Change to yellow
					removeTooltip(this);
				} else {
					$(this).css({"background-color": "#ceffce"}); //Change to green
					removeTooltip(this);
				}
			});
			clearInterval(loop);
		}
	}, 25);
}

//Adds a tooltip to display which class conflicts
function addTooltip(element, conflictName){
	var title = $(element).find(".data-column.title")[1];
	$(title).attr("data-balloon", "Conflicts with: " + conflictName);
	$(title).attr("data-balloon-pos", "up");
}

//Removes tooltips for when user removes classes and conflicts change
function removeTooltip(element){
	var title = $(element).find(".data-column.title")[1];
	$(title).removeAttr("data-balloon");
	$(title).removeAttr("data-balloon-pos");
}

//Checks if a class is already in your schedule
function inSchedule(listing){
	var savedBtn = $(listing).find(".btn-success");
	if(!savedBtn.length){return false;}
	//This check is added because saved button stays there after you remove a class
	var title = $(listing).find(".data-column.title")[1].innerHTML;
	for(var i = 0; i < selectedSchedule.length; i++){
		if(selectedSchedule[i].name.includes(title)){
			return true;
		}
	}
	return false;
}

//Checks if a final conflicts with current finals
function finalsConflict(element){
	var final = getFinal(element, ".details", ".title");
	if(final){
		for(var i = 0; i < finals.length; i++){
			if(final.conflicts(finals[i])){return finals[i].name;}
		}
	}
	return false;
}

//Returns if a class is full or not
function isFull(element){
	var data = $(element).find(".float-left")[0];
	data = $(data).children()[1];
	var seats = $(data).children()[2].innerHTML;
	return seats.charAt(0) == "0";
}

//Preloads the currently selected schedule into two arrays: one for classes and one for finals
function loadSchedule(){
	//Reset arrays
	selectedSchedule = [];
	finals = [];
	var schedule = $('.CourseItem.gray-shadow-border.clearfix');
	schedule.each(function(index, element){ //For every class in your schedule
		var name = $(".classTitle.height-justified");
		var classTitle = name[index].innerHTML;
		var sections = $(this).find(".meeting.clearfix");
		//Get the final
		var final = getFinal(this, ".classDescription", ".boldTitle");
		final.name = classTitle + " Final";
		finals.push(final);
		sections.each(function(){ //For every meeting (lecture, discussion, lab)
			var sectionInfo = $(this).children();
			var times = sectionInfo[1].innerHTML;
			var days = sectionInfo[2].innerHTML;
			if(days){ //Not an empty string, so add to schedule
				var newClass = new Course(classTitle, times, days);
				selectedSchedule.push(newClass);
			}
		});
	});
}

//Gets the time and date of a final and return it as an object
function getFinal(element, div, title){
	var data = $(element).find(div);
	var finalText = $(data[0]).find(title + ":contains('Final')").parent();
	if(finalText.length){
		var string = finalText[0].innerHTML;
		var firstDigit = string.search(/\d/);
		string = string.substr(firstDigit);
		var space = string.search(" ");
		var date = string.substr(0, space);
		var time = string.substr(space + 1);
		return new Final(date, time);
	}
}
<|endoftext|>


<commit_before>/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';
import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View
} from 'react-native';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import rootReducer from './app/reducers/rootReducer.js';
import ViewContainer from './app/containers/container_viewContainer';
import thunk from 'redux-thunk';
import createLogger from 'redux-logger';
import promise from 'redux-promise';
import Signin from './app/containers/container_FBLogin';
import FriendList from './app/components/FriendList';
import { Router, Scene, Actions} from 'react-native-router-flux';

//creates logger
const logger = createLogger();
// creates store
const store = createStore(
  rootReducer,
  applyMiddleware(thunk, promise, logger)
);

const findAR = () => (
  <Provider store={store}>
    <Router scenes={scenes} />
  </Provider>
);

const scenes = Actions.create(
  <Scene key="root" hideNavBar>
      <Scene initial key="login" component={Signin} />
      <Scene key="view" component={ViewContainer} />
      <Scene key="friends" component={FriendList} />
  </Scene>
);
AppRegistry.registerComponent('findAR', () => findAR);
<commit_msg>Clean up comments<commit_after>'use strict';
import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View
} from 'react-native';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import rootReducer from './app/reducers/rootReducer.js';
import ViewContainer from './app/containers/container_viewContainer';
import thunk from 'redux-thunk';
import createLogger from 'redux-logger';
import promise from 'redux-promise';
import Signin from './app/containers/container_FBLogin';
import FriendList from './app/components/FriendList';
import { Router, Scene, Actions} from 'react-native-router-flux';

//creates logger
const logger = createLogger();
// creates store
const store = createStore(
  rootReducer,
  applyMiddleware(thunk, promise, logger)
);

const findAR = () => (
  <Provider store={store}>
    <Router scenes={scenes} />
  </Provider>
);

const scenes = Actions.create(
  <Scene key="root" hideNavBar>
      <Scene initial key="login" component={Signin} />
      <Scene key="view" component={ViewContainer} />
      <Scene key="friends" component={FriendList} />
  </Scene>
);
AppRegistry.registerComponent('findAR', () => findAR);
<|endoftext|>


<commit_before>'use strict'
var cleanup = require('rollup-plugin-cleanup');
var { src, dest, series, parallel } = require('gulp');
var events = require('events');
var insert = require('gulp-insert');
var mocha = require('gulp-mocha');
var rename = require('gulp-rename');
var rollup = require('rollup');
var sucrase = require('@rollup/plugin-sucrase');
var terser = require('gulp-terser');
var typescript = require('@rollup/plugin-typescript');

events.EventEmitter.defaultMaxListeners = 0;

var items = [
    require('./build/npm/navigation/package.json'),
    Object.assign({ globals: { navigation: 'Navigation', react: 'React',
            'react-dom': 'ReactDOM' } },
        require('./build/npm/navigation-react/package.json')),
    Object.assign({ globals: { navigation: 'Navigation',
            'navigation-react': 'NavigationReact', react: 'React' } },
        require('./build/npm/navigation-react-mobile/package.json')),
    Object.assign({ globals: { navigation: 'Navigation', react: 'React',
            'navigation-react': 'NavigationReact', 'react-native': 'ReactNative' },
            format: 'es', web: true },
        require('./build/npm/navigation-react-native/package.json')),
];
function rollupTask(name, input, file, globals, format) {
    var include = input.replace(name + '.ts', '**');
    var tsconfig = input.replace(name + '.ts', 'tsconfig.json');
    return rollup.rollup({
        input,
        external: Array.isArray(globals) ? globals : Object.keys(globals),
        plugins: input.indexOf('Test') === -1
            ? [ typescript({ include, tsconfig }), cleanup({ comments: 'none' }) ]
            : [ sucrase({ include: input, transforms: ['typescript','jsx'] }) ]
    }).then((bundle) => bundle.write({ format, name, globals, file }));
}
function buildTask(name, input, file, globals, details) {
    var info = `/**
 * ${details.name} v${details.version}
 * (c) Graham Mendick - ${details.homepage}
 * License: ${details.license}
 */
`;
    return rollupTask(name, input, file, globals, 'iife')
        .then(() => (
            src(file)
                .pipe(insert.prepend(info))
                .pipe(dest('./build/dist'))
                .pipe(rename(file.replace(/js$/, 'min.js')))
                .pipe(terser())
                .pipe(insert.prepend(info))
                .pipe(dest('.'))
        ));
}
var packageNative = () => {
    var nativeFolders = ['android', 'ios']
        .map(folder => `./NavigationReactNative/src/${folder}/**/*`);
    return src(nativeFolders, {base: './NavigationReactNative/src'})
        .pipe(dest('./build/npm/navigation-react-native'));
};
var nameFunc = (func, name) => {
    func.displayName = name;
    return func;
};
var itemTasks = items.reduce((tasks, item) => {
    var packageName = item.name;
    var upperName = packageName.replace(/\b./g, (val) => val.toUpperCase());
    var name = upperName.replace(/-/g, '');
    var tsFrom = './' + name + '/src/' + name + '.ts';
    var jsTo = './build/dist/' + packageName.replace(/-/g, '.') + '.js';
    var jsPackageTo = './build/npm/' + packageName + '/' + packageName.replace(/-/g, '.') + '.js';
    item.name = upperName.replace(/-/g, ' ');
    var { globals = {}, format = 'cjs', web = false } = item;
    tasks.buildTasks.push(
        nameFunc(() => buildTask(name, tsFrom, jsTo, globals, item), 'build' + name));
    tasks.packageTasks.push(
        nameFunc(() => rollupTask(name, tsFrom, jsPackageTo, globals, format), 'package' + name)
    );
    if (web) {
        tasks.packageTasks.push(
            nameFunc(() => rollupTask(name + '.web', tsFrom.replace('.ts', '.web.ts'), jsPackageTo.replace('.js', '.web.js'), globals, format), 'package' + name + 'Web')
        );
    }
    return tasks;
}, { buildTasks: [], packageTasks: [] });

var tests = [
    { name: 'NavigationRouting', to: 'navigationRouting.test.js' },
    { name: 'StateConfig', to: 'stateConfig.test.js' },
    { name: 'Navigation', to: 'navigation.test.js' },
    { name: 'NavigationData', to: 'navigationData.test.js' },
    { name: 'FluentNavigation', to: 'fluentNavigation.test.js' },
    { name: 'NavigationLink', to: 'navigationLink.test.js', folder: 'React', ext: 'tsx' },
    { name: 'NavigationBackLink', to: 'navigationBackLink.test.js', folder: 'React', ext: 'tsx' },
    { name: 'RefreshLink', to: 'refreshLink.test.js', folder: 'React', ext: 'tsx' },
    { name: 'FluentLink', to: 'fluentLink.test.js', folder: 'React', ext: 'tsx' },
    { name: 'NavigatingHook', to: 'navigatingHook.test.js', folder: 'ReactMobile', ext: 'tsx' },
    { name: 'NavigatedHook', to: 'navigatedHook.test.js', folder: 'ReactMobile', ext: 'tsx' },
    { name: 'UnloadingHook', to: 'unloadingHook.test.js', folder: 'ReactMobile', ext: 'tsx' },
    { name: 'UnloadedHook', to: 'unloadedHook.test.js', folder: 'ReactMobile', ext: 'tsx' },
    { name: 'NavigationMotion', to: 'navigationMotion.test.js', folder: 'ReactMobile', ext: 'tsx' }
];
function testTask(name, input, file) {
    var globals = [
        'mocha', 'assert', 'react', 'react-dom', 'react-dom/test-utils', 'jsdom',
        'tslib', 'navigation', 'navigation-react',  'navigation-react-mobile'
    ];
    return rollupTask(name, input, file, globals, 'cjs')
        .then(() =>
            src(file)
                .pipe(mocha({ reporter: 'progress' }))
                .on('error', err => console.log(err.message))
        );
}
var testTasks = tests.reduce((tasks, test) => {
    var folder = './Navigation' + (test.folder || '') + '/test/';
    var file = folder + test.name + 'Test.' + (test.ext || 'ts');
    var to = './build/dist/' + test.to;
    tasks.push(nameFunc(() => testTask(test.name, file, to), 'test' + test.name));
    return tasks;
}, []);
var packageDeps = parallel(
    itemTasks.packageTasks.find(({displayName}) => displayName === 'packageNavigation'),
    itemTasks.packageTasks.find(({displayName}) => displayName === 'packageNavigationReact'),
    itemTasks.packageTasks.find(({displayName}) => displayName === 'packageNavigationReactMobile')
);
exports.build = parallel(...itemTasks.buildTasks);
exports.package = parallel(packageNative, ...itemTasks.packageTasks);
exports.test = series(packageDeps, parallel(...testTasks));

<commit_msg>Reverted changes now using separate project<commit_after>'use strict'
var cleanup = require('rollup-plugin-cleanup');
var { src, dest, series, parallel } = require('gulp');
var events = require('events');
var insert = require('gulp-insert');
var mocha = require('gulp-mocha');
var rename = require('gulp-rename');
var rollup = require('rollup');
var sucrase = require('@rollup/plugin-sucrase');
var terser = require('gulp-terser');
var typescript = require('@rollup/plugin-typescript');

events.EventEmitter.defaultMaxListeners = 0;

var items = [
    require('./build/npm/navigation/package.json'),
    Object.assign({ globals: { navigation: 'Navigation', react: 'React',
            'react-dom': 'ReactDOM' } },
        require('./build/npm/navigation-react/package.json')),
    Object.assign({ globals: { navigation: 'Navigation',
            'navigation-react': 'NavigationReact', react: 'React' } },
        require('./build/npm/navigation-react-mobile/package.json')),
    Object.assign({ globals: { navigation: 'Navigation', react: 'React',
            'navigation-react': 'NavigationReact', 'react-native': 'ReactNative' },
            format: 'es' },
        require('./build/npm/navigation-react-native/package.json')),
];
function rollupTask(name, input, file, globals, format) {
    var include = input.replace(name + '.ts', '**');
    var tsconfig = input.replace(name + '.ts', 'tsconfig.json');
    return rollup.rollup({
        input,
        external: Array.isArray(globals) ? globals : Object.keys(globals),
        plugins: input.indexOf('Test') === -1
            ? [ typescript({ include, tsconfig }), cleanup({ comments: 'none' }) ]
            : [ sucrase({ include: input, transforms: ['typescript','jsx'] }) ]
    }).then((bundle) => bundle.write({ format, name, globals, file }));
}
function buildTask(name, input, file, globals, details) {
    var info = `/**
 * ${details.name} v${details.version}
 * (c) Graham Mendick - ${details.homepage}
 * License: ${details.license}
 */
`;
    return rollupTask(name, input, file, globals, 'iife')
        .then(() => (
            src(file)
                .pipe(insert.prepend(info))
                .pipe(dest('./build/dist'))
                .pipe(rename(file.replace(/js$/, 'min.js')))
                .pipe(terser())
                .pipe(insert.prepend(info))
                .pipe(dest('.'))
        ));
}
var packageNative = () => {
    var nativeFolders = ['android', 'ios']
        .map(folder => `./NavigationReactNative/src/${folder}/**/*`);
    return src(nativeFolders, {base: './NavigationReactNative/src'})
        .pipe(dest('./build/npm/navigation-react-native'));
};
var nameFunc = (func, name) => {
    func.displayName = name;
    return func;
};
var itemTasks = items.reduce((tasks, item) => {
    var packageName = item.name;
    var upperName = packageName.replace(/\b./g, (val) => val.toUpperCase());
    var name = upperName.replace(/-/g, '');
    var tsFrom = './' + name + '/src/' + name + '.ts';
    var jsTo = './build/dist/' + packageName.replace(/-/g, '.') + '.js';
    var jsPackageTo = './build/npm/' + packageName + '/' + packageName.replace(/-/g, '.') + '.js';
    item.name = upperName.replace(/-/g, ' ');
    var { globals = {}, format = 'cjs' } = item;
    tasks.buildTasks.push(
        nameFunc(() => buildTask(name, tsFrom, jsTo, globals, item), 'build' + name));
    tasks.packageTasks.push(
        nameFunc(() => rollupTask(name, tsFrom, jsPackageTo, globals, format), 'package' + name)
    );
    return tasks;
}, { buildTasks: [], packageTasks: [] });

var tests = [
    { name: 'NavigationRouting', to: 'navigationRouting.test.js' },
    { name: 'StateConfig', to: 'stateConfig.test.js' },
    { name: 'Navigation', to: 'navigation.test.js' },
    { name: 'NavigationData', to: 'navigationData.test.js' },
    { name: 'FluentNavigation', to: 'fluentNavigation.test.js' },
    { name: 'NavigationLink', to: 'navigationLink.test.js', folder: 'React', ext: 'tsx' },
    { name: 'NavigationBackLink', to: 'navigationBackLink.test.js', folder: 'React', ext: 'tsx' },
    { name: 'RefreshLink', to: 'refreshLink.test.js', folder: 'React', ext: 'tsx' },
    { name: 'FluentLink', to: 'fluentLink.test.js', folder: 'React', ext: 'tsx' },
    { name: 'NavigatingHook', to: 'navigatingHook.test.js', folder: 'ReactMobile', ext: 'tsx' },
    { name: 'NavigatedHook', to: 'navigatedHook.test.js', folder: 'ReactMobile', ext: 'tsx' },
    { name: 'UnloadingHook', to: 'unloadingHook.test.js', folder: 'ReactMobile', ext: 'tsx' },
    { name: 'UnloadedHook', to: 'unloadedHook.test.js', folder: 'ReactMobile', ext: 'tsx' },
    { name: 'NavigationMotion', to: 'navigationMotion.test.js', folder: 'ReactMobile', ext: 'tsx' }
];
function testTask(name, input, file) {
    var globals = [
        'mocha', 'assert', 'react', 'react-dom', 'react-dom/test-utils', 'jsdom',
        'tslib', 'navigation', 'navigation-react',  'navigation-react-mobile'
    ];
    return rollupTask(name, input, file, globals, 'cjs')
        .then(() =>
            src(file)
                .pipe(mocha({ reporter: 'progress' }))
                .on('error', err => console.log(err.message))
        );
}
var testTasks = tests.reduce((tasks, test) => {
    var folder = './Navigation' + (test.folder || '') + '/test/';
    var file = folder + test.name + 'Test.' + (test.ext || 'ts');
    var to = './build/dist/' + test.to;
    tasks.push(nameFunc(() => testTask(test.name, file, to), 'test' + test.name));
    return tasks;
}, []);
var packageDeps = parallel(
    itemTasks.packageTasks.find(({displayName}) => displayName === 'packageNavigation'),
    itemTasks.packageTasks.find(({displayName}) => displayName === 'packageNavigationReact'),
    itemTasks.packageTasks.find(({displayName}) => displayName === 'packageNavigationReactMobile')
);
exports.build = parallel(...itemTasks.buildTasks);
exports.package = parallel(packageNative, ...itemTasks.packageTasks);
exports.test = series(packageDeps, parallel(...testTasks));
<|endoftext|>