<commit_before>(function ($, _) {

    /**
     * 0,1,2 -> [0, 2]
     * 3,4,5 -> [3, 5]
     * 6,7,8 -> [6, 8]
     *
     * @param n
     * @returns {*[start, end]}
     */
    function range(n) {
        var end = Math.ceil((n + 1) / 3) * 3;
        return [end - 3, end - 1];
    }

    /**
     * square:
     *  11, 21, 31
     *  12, 22, 32
     *  13, 23, 33
     *
     * @param x
     * @param y
     * @returns {*} current pos
     */
    function square(x, y) {
        var pos = function (n) {
            return Math.ceil((n + 1) / 3);
        };

        return pos(x) * 10 + pos(y);
    }

    function deepCopy(arr) {
        return _.map(arr, function (row) {
            return _.map(row, function (item) {
                return item;
            });
        });
    }

    var Sudoku = function (soduku) {
        // [1, 2, 3, 4, 5, 6, 7, 8, 9];
        this.nines = _.range(1, 10);

        this.origin = soduku;

        // a stack save every state.
        this.snapshots = [];

        this.currentState = {};
        this.currentState.sudoku = deepCopy(this.origin);

        this.calculate();
    };

    Sudoku.prototype.push = function () {
        this.snapshots.push({
            sudoku: deepCopy(_.result(this.currentState, 'sudoku')),
            index: _.result(this.currentState, 'index'),
            target: _.clone(_.result(this.currentState, 'target'))
        });

        // clear current state
        delete this.currentState.index;
        delete this.currentState.target;

        //console.log('snapshot length:', this.snapshots.length);
    };

    Sudoku.prototype.pop = function () {
        return this.snapshots.pop();
    };

    /**
     * get available numbers in the (row, col)
     *
     * @param x 0-8 index of col
     * @param y 0-8 index of row
     */
    Sudoku.prototype.available = function (x, y) {
        var target = this.currentState.sudoku;

        // get row
        var related = _.clone(target[y]);

        // get col
        _.each(target, function (row) {
            related.push(row[x]);
        });

        // get square
        var rangeX = range(x);
        var rangeY = range(y);
        for (var i = rangeY[0]; i <= rangeY[1]; i++) {
            for (var j = rangeX[0]; j <= rangeX[1]; j++) {
                related.push(target[i][j]);
            }
        }

        return _.difference(this.nines, related);
    };

    Sudoku.prototype.calculate = function () {
        console.log('----------------------- begin calculate ---------------------------');

        this.currentState.hasBlank = false;
        this.currentState.hasZeros = false;

        var dummy = [];
        var target = this.currentState.sudoku;

        _.each(target, function (row, i) {
            if (this.currentState.hasZeros) {
                return false;  // break: return false;
            }

            _.each(row, function (num, j) {
                if (num !== 0) {
                    return;
                }

                this.currentState.hasBlank = true;

                var avails = this.available(j, i);
                if (avails.length === 0) {
                    this.currentState.hasZeros = true;
                    return false; // break
                }

                dummy.push({
                    x: j,
                    y: i,
                    square: square(j, i),
                    avails: avails,
                    count: avails.length
                });

                console.log('(', j, ',', i, ')', avails);
            }, this);
        }, this);

        console.log('------------- after calculate before check ----', dummy.length, '----------------');

        this.currentState.avails = dummy;
        this.sort();

        if (!this.check()) {
            this.toLastState();
            this.calculate();
        }
    };

    Sudoku.prototype.check = function () {
        var ones = this.ones();
        if (ones.length <= 1) {
            return true;
        }

        var grouped = _.groupBy(ones, function (item) {
            return item.avails[0];
        });

        if (_.keys(grouped).length === ones.length) {
            return true
        }

        var multi = _.filter(_.values(grouped), function (items) {
            return items.length > 1;
        });

        var valid = true;
        _.each(multi, function (items) {
            var len = items.length;

            // not in same column
            var xs = _.uniq(_.map(items, function (item) {
                return item.x;
            }));

            if (xs.length !== len) {
                //console.log('error in same column', items);
                valid = false;
                return false;
            }

            // not in same row
            var ys = _.uniq(_.map(items, function (item) {
                return item.y;
            }));

            if (ys.length !== len) {
                //console.log('error in same row', items);
                valid = false;
                return false;
            }

            // not in same square
            var squares = _.uniq(_.map(items, function (item) {
                return item.square;
            }));

            if (squares.length !== len) {
                //console.log('error in same square', items);
                valid = false;
                return false;
            }

        }, this);

        return valid;
    };

    Sudoku.prototype.sort = function () {
        this.currentState.avails = _.sortBy(this.currentState.avails, function (item) {
            return item.count;
        });
    };

    Sudoku.prototype.hasBlank = function () {
        return this.currentState.hasBlank;
    };

    /**
     * return if this current state could be solved.
     *
     * @returns {boolean}
     */
    Sudoku.prototype.unsolvable = function () {
        return this.currentState.hasZeros;
    };

    /**
     * array contains item which avails count = 1
     *
     * @returns []
     */
    Sudoku.prototype.ones = function () {
        return _.filter(this.currentState.avails, function (item) {
            return item.count === 1;
        });
    };

    Sudoku.prototype.hasOne = function () {
        return _.any(this.currentState.avails, function (item) {
            return item.count === 1;
        });
    };

    Sudoku.prototype.toLastState = function () {
        this.currentState = this.pop();
        //console.log('unsolvable, to last state, length:', this.snapshots.length);
        this.tryNext();
    };

    Sudoku.prototype.fill = function () {
        while (this.hasBlank()) {
            if (this.unsolvable()) {
                this.toLastState();
            } else if (this.hasOne()) {
                this.fillOnes();
            } else {
                this.fillMulti();
            }

            this.calculate();
        }
    };

    Sudoku.prototype.fillManually = function () {
        if (this.hasBlank()) {
            if (this.unsolvable()) {
                this.toLastState();
            } else if (this.hasOne()) {
                this.fillOnes();
            } else {
                this.fillMulti();
            }
        }

        this.calculate();
    };

    Sudoku.prototype.tryNext = function () {
        var dummy = this.currentState.target;

        var index = ++this.currentState.index;
        if (index === dummy.avails.length) {
            this.toLastState();
            return;
        }

        this.push();

        console.log('try (', dummy.x, ',', dummy.y, ') avails[', index, '] =', dummy.avails[index]);
        this.fillOne(dummy.x, dummy.y, dummy.avails[index]);
    };

    Sudoku.prototype.fillMulti = function () {
        if (_.isUndefined(this.currentState.target)) {
            this.currentState.target = _.first(this.currentState.avails);
        }

        if (_.isUndefined(this.currentState.index)) {
            this.currentState.index = -1;
        }

        this.tryNext();
    };

    Sudoku.prototype.fillOnes = function () {
        //console.log('ones exist.');
        _.each(this.ones(), function (item) {
            this.fillOne(item.x, item.y, item.avails[0]);
        }, this);
    };

    Sudoku.prototype.fillOne = function (x, y, value) {
        console.log('fill (', x, ',' , y, ') =', value);
        this.currentState.sudoku[y][x] = value;
    };

    Sudoku.prototype.render = function () {
        var $table = $('

');
        $table.append('
-	0	1	2	3	4	5	6	7	8
');
        _.each(this.currentState.sudoku, function (row, i) {
            var $row = $('

');
            $row.append('' + i + '	');
            _.each(row, function (num) {
                if (num === 0) {
                    num = ' ';
                }

                $row.append($('' + num + '	'));
            });
            $table.append($row);
        });

        $('.sudoku-wrapper').empty().append($table);
    };

    $(function () {

        var veryDifficult1 = [
            [0, 0, 9, 0, 0, 0, 0, 0, 0],
            [6, 0, 0, 0, 4, 0, 0, 3, 0],
            [0, 0, 7, 6, 0, 0, 0, 2, 0],
            [3, 0, 0, 0, 0, 2, 1, 0, 0],
            [0, 0, 5, 9, 0, 0, 7, 0, 0],
            [0, 0, 8, 0, 0, 0, 0, 0, 5],
            [0, 1, 0, 0, 0, 4, 9, 0, 0],
            [0, 9, 0, 0, 7, 0, 0, 0, 6],
            [0, 0, 0, 0, 0, 0, 8, 0, 0]
        ];

        var easy1 = [
            [6, 9, 0, 0, 0, 5, 1, 0, 0],
            [0, 0, 0, 0, 1, 3, 8, 0, 0],
            [1, 0, 0, 0, 0, 2, 0, 0, 0],
            [4, 7, 3, 0, 0, 0, 6, 5, 0],
            [0, 0, 5, 0, 9, 0, 0, 7, 0],
            [9, 6, 0, 0, 5, 0, 4, 0, 8],
            [3, 0, 0, 2, 0, 8, 7, 0, 5],
            [2, 0, 4, 0, 0, 6, 0, 8, 0],
            [0, 0, 0, 0, 3, 0, 2, 0, 0]
        ];

        var sudoku = new Sudoku(easy1);
        sudoku.render();

        $('#calculate').on('click', function () {
            sudoku = new Sudoku(easy1);
            sudoku.render();

            setTimeout(function () {
                var start = new Date();
                sudoku.fill();
                console.log('spend:', (new Date() - start));

                sudoku.render();
            }, 1000);
        });

        $('#calculate-manually').on('click', function () {
            sudoku.fillManually();
            sudoku.render();
        });
    });

})(jQuery, _);<commit_msg>it is absolutely right<commit_after>(function ($, _) {

    /**
     * 0,1,2 -> [0, 2]
     * 3,4,5 -> [3, 5]
     * 6,7,8 -> [6, 8]
     *
     * @param n
     * @returns {*[start, end]}
     */
    function range(n) {
        var end = Math.ceil((n + 1) / 3) * 3;
        return [end - 3, end - 1];
    }

    /**
     * square:
     *  11, 21, 31
     *  12, 22, 32
     *  13, 23, 33
     *
     * @param x
     * @param y
     * @returns {*} current pos
     */
    function square(x, y) {
        var pos = function (n) {
            return Math.ceil((n + 1) / 3);
        };

        return pos(x) * 10 + pos(y);
    }

    function deepCopy(arr) {
        return _.map(arr, function (row) {
            return _.map(row, function (item) {
                return item;
            });
        });
    }

    var Sudoku = function (soduku) {
        // [1, 2, 3, 4, 5, 6, 7, 8, 9];
        this.nines = _.range(1, 10);

        this.origin = soduku;

        // a stack save every state.
        this.snapshots = [];

        this.currentState = {};
        this.currentState.sudoku = deepCopy(this.origin);

        this.parse();
    };

    Sudoku.prototype.push = function () {
        this.snapshots.push({
            sudoku: deepCopy(_.result(this.currentState, 'sudoku')),
            index: _.result(this.currentState, 'index'),
            target: _.clone(_.result(this.currentState, 'target'))
        });

        // clear current state
        delete this.currentState.index;
        delete this.currentState.target;

        //console.log('snapshot length:', this.snapshots.length);
    };

    Sudoku.prototype.pop = function () {
        return this.snapshots.pop();
    };

    /**
     * get available numbers in the (row, col)
     *
     * @param x 0-8 index of col
     * @param y 0-8 index of row
     */
    Sudoku.prototype.available = function (x, y) {
        var target = this.currentState.sudoku;

        // get row
        var related = _.clone(target[y]);

        // get col
        _.each(target, function (row) {
            related.push(row[x]);
        });

        // get square
        var rangeX = range(x);
        var rangeY = range(y);
        for (var i = rangeY[0]; i <= rangeY[1]; i++) {
            for (var j = rangeX[0]; j <= rangeX[1]; j++) {
                related.push(target[i][j]);
            }
        }

        return _.difference(this.nines, related);
    };

    Sudoku.prototype.parse = function () {
        //console.log('----------------------- begin parse ---------------------------');

        this.currentState.hasBlank = false;
        this.currentState.hasZeros = false;

        var dummy = [];
        var target = this.currentState.sudoku;

        for (var i = 0; i < target.length; i++) {
            var row = target[i];
            if (this.currentState.hasZeros) {
                break;
            }

            for (var j = 0; j < row.length; j++) {
                var num = row[j];
                if (num !== 0) {
                    continue;
                }

                this.currentState.hasBlank = true;

                var avails = this.available(j, i);
                if (avails.length === 0) {
                    this.currentState.hasZeros = true;
                    break;
                }

                dummy.push({
                    x: j,
                    y: i,
                    square: square(j, i),
                    avails: avails,
                    count: avails.length
                });

                //console.log('(', j, ',', i, ')', avails);
            }
        }

        //console.log('------------- after parse before check ----', dummy.length, '----------------');

        this.currentState.avails = dummy;
        this.sort();

        if (!this.check()) {
            this.toLastState();
            this.parse();
        }
    };

    Sudoku.prototype.check = function () {
        var ones = this.ones();
        if (ones.length <= 1) {
            return true;
        }

        var grouped = _.groupBy(ones, function (item) {
            return item.avails[0];
        });

        if (_.keys(grouped).length === ones.length) {
            return true
        }

        var multi = _.filter(_.values(grouped), function (items) {
            return items.length > 1;
        });

        var valid = true;
        _.each(multi, function (items) {
            var len = items.length;

            // not in same column
            var xs = _.uniq(_.map(items, function (item) {
                return item.x;
            }));

            if (xs.length !== len) {
                //console.log('error in same column', items);
                valid = false;
                return false;
            }

            // not in same row
            var ys = _.uniq(_.map(items, function (item) {
                return item.y;
            }));

            if (ys.length !== len) {
                //console.log('error in same row', items);
                valid = false;
                return false;
            }

            // not in same square
            var squares = _.uniq(_.map(items, function (item) {
                return item.square;
            }));

            if (squares.length !== len) {
                //console.log('error in same square', items);
                valid = false;
                return false;
            }

        }, this);

        return valid;
    };

    Sudoku.prototype.sort = function () {
        this.currentState.avails = _.sortBy(this.currentState.avails, function (item) {
            return item.count;
        });
    };

    Sudoku.prototype.hasBlank = function () {
        return this.currentState.hasBlank;
    };

    /**
     * return if this current state could be solved.
     *
     * @returns {boolean}
     */
    Sudoku.prototype.unsolvable = function () {
        return this.currentState.hasZeros;
    };

    /**
     * array contains item which avails count = 1
     *
     * @returns []
     */
    Sudoku.prototype.ones = function () {
        return _.filter(this.currentState.avails, function (item) {
            return item.count === 1;
        });
    };

    Sudoku.prototype.hasOne = function () {
        return _.any(this.currentState.avails, function (item) {
            return item.count === 1;
        });
    };

    Sudoku.prototype.toLastState = function () {
        this.currentState = this.pop();
        //console.log('unsolvable, to last state, length:', this.snapshots.length);
        this.tryNext();
    };

    Sudoku.prototype.fill = function () {
        while (this.hasBlank()) {
            if (this.unsolvable()) {
                this.toLastState();
            } else if (this.hasOne()) {
                this.fillOnes();
            } else {
                this.fillMulti();
            }

            this.parse();
        }
    };

    Sudoku.prototype.fillManually = function () {
        if (this.hasBlank()) {
            if (this.unsolvable()) {
                this.toLastState();
            } else if (this.hasOne()) {
                this.fillOnes();
            } else {
                this.fillMulti();
            }
        }

        this.parse();
    };

    Sudoku.prototype.tryNext = function () {
        var dummy = this.currentState.target;

        var index = ++this.currentState.index;
        if (index === dummy.avails.length) {
            this.toLastState();
            return;
        }

        this.push();

        //console.log('try (', dummy.x, ',', dummy.y, ') avails[', index, '] =', dummy.avails[index]);
        this.fillOne(dummy.x, dummy.y, dummy.avails[index]);
    };

    Sudoku.prototype.fillMulti = function () {
        if (_.isUndefined(this.currentState.target)) {
            this.currentState.target = _.first(this.currentState.avails);
        }

        if (_.isUndefined(this.currentState.index)) {
            this.currentState.index = -1;
        }

        this.tryNext();
    };

    Sudoku.prototype.fillOnes = function () {
        //console.log('ones exist.');
        _.each(this.ones(), function (item) {
            this.fillOne(item.x, item.y, item.avails[0]);
        }, this);
    };

    Sudoku.prototype.fillOne = function (x, y, value) {
        //console.log('fill (', x, ',' , y, ') =', value);
        this.currentState.sudoku[y][x] = value;
    };

    Sudoku.prototype.render = function () {
        var $table = $('

');
        $table.append('
-	0	1	2	3	4	5	6	7	8
');
        _.each(this.currentState.sudoku, function (row, i) {
            var $row = $('

');
            $row.append('' + i + '	');
            _.each(row, function (num) {
                if (num === 0) {
                    num = ' ';
                }

                $row.append($('' + num + '	'));
            });
            $table.append($row);
        });

        $('.sudoku-wrapper').empty().append($table);
    };

    $(function () {

        var veryDifficult1 = [
            [0, 0, 9, 0, 0, 0, 0, 0, 0],
            [6, 0, 0, 0, 4, 0, 0, 3, 0],
            [0, 0, 7, 6, 0, 0, 0, 2, 0],
            [3, 0, 0, 0, 0, 2, 1, 0, 0],
            [0, 0, 5, 9, 0, 0, 7, 0, 0],
            [0, 0, 8, 0, 0, 0, 0, 0, 5],
            [0, 1, 0, 0, 0, 4, 9, 0, 0],
            [0, 9, 0, 0, 7, 0, 0, 0, 6],
            [0, 0, 0, 0, 0, 0, 8, 0, 0]
        ];

        var easy1 = [
            [6, 9, 0, 0, 0, 5, 1, 0, 0],
            [0, 0, 0, 0, 1, 3, 8, 0, 0],
            [1, 0, 0, 0, 0, 2, 0, 0, 0],
            [4, 7, 3, 0, 0, 0, 6, 5, 0],
            [0, 0, 5, 0, 9, 0, 0, 7, 0],
            [9, 6, 0, 0, 5, 0, 4, 0, 8],
            [3, 0, 0, 2, 0, 8, 7, 0, 5],
            [2, 0, 4, 0, 0, 6, 0, 8, 0],
            [0, 0, 0, 0, 3, 0, 2, 0, 0]
        ];

        var cusotm1 = [
            [6, 0, 0, 0, 0, 5, 0, 0, 0],
            [0, 0, 0, 0, 1, 3, 8, 0, 0],
            [0, 0, 0, 0, 0, 2, 0, 0, 0],
            [4, 0, 3, 0, 0, 0, 6, 5, 0],
            [0, 0, 5, 0, 9, 0, 0, 7, 0],
            [9, 6, 0, 0, 5, 0, 0, 0, 8],
            [0, 0, 0, 0, 0, 8, 0, 0, 5],
            [2, 0, 0, 0, 0, 6, 0, 8, 0],
            [0, 0, 0, 0, 3, 0, 2, 0, 0]
        ];

        var sudoku = new Sudoku(veryDifficult1);
        sudoku.render();

        $('#calculate').on('click', function () {
            sudoku = new Sudoku(veryDifficult1);
            sudoku.render();

            setTimeout(function () {
                var start = new Date();
                sudoku.fill();
                console.log('spend:', (new Date() - start));

                sudoku.render();
            }, 1000);
        });

        $('#calculate-manually').on('click', function () {
            sudoku.fillManually();
            sudoku.render();
        });
    });

})(jQuery, _);<|endoftext|>


<commit_before>var currentBuilding = '113';
var historyType = 'daily';
var buildingNameMap = {};
var jsonRequestQueue = [];
var liveTimeout = -1, historyTimeout = -1;
var historyGraphs = {'electricity':null, 'heating':null, 'cooling':null};

new JSONHttpRequest('/buildingmap.json',
					function(result) {buildingNameMap = result;populateBuildings();},
					function() {showError("Unable to load building list. Please refresh.");}
					);

function JSONHttpRequest(URL, loadCallback, errorCallback)
{
	var _this = this;
	this.URL = URL;
	this.loadCallback = loadCallback;
	this.errorCallback = errorCallback;
	this.onRequestComplete = function () {
		try
		{
			var response = JSON.parse(_this.httpRequest.responseText);
		}
		catch(SyntaxError)
		{
			_this.errorCallback("Unable to parse server response.");
			return;
		}
		_this.loadCallback(response);
	};
	this.httpRequest = new XMLHttpRequest();
	this.httpRequest.addEventListener("load",
										function() {
											_this.onRequestComplete();
											delete jsonRequestQueue.shift();
										},
										false);
	this.httpRequest.addEventListener("error",
										function() {
											_this.errorCallback("Unable to access the server.");
											delete jsonRequestQueue.shift();
										},
										false);
	this.httpRequest.open('GET', URL);
	this.httpRequest.send();
	jsonRequestQueue.push(this);
}

// Everything has to load before we use polymer
window.addEventListener("load", function() {
	forceUpdate();
	setTimeout(showError("WARNING: UNC's servers are experiencing problems causing significant historical data innacuracies."), 1000);
	}, false);

function forceUpdate()
{
	updateLiveData();
	updateHistoricalData();
}
function updateLiveData()
{
	updateLiveChart(document.querySelectorAll("meter-card")[0].shadowRoot, currentBuilding, 'electricity');
	updateLiveChart(document.querySelectorAll("meter-card")[1].shadowRoot, currentBuilding, 'heating');
	updateLiveChart(document.querySelectorAll("meter-card")[2].shadowRoot, currentBuilding, 'cooling');
	if (liveTimeout != -1)
		clearTimeout(liveTimeout);
	liveTimeout = setTimeout(updateLiveData, 5000);
}
function updateHistoricalData()
{
	updateHistoryGraph(document.querySelectorAll("history-card")[0].shadowRoot, currentBuilding, 'electricity');
	updateHistoryGraph(document.querySelectorAll("history-card")[1].shadowRoot, currentBuilding, 'heating');
	updateHistoryGraph(document.querySelectorAll("history-card")[2].shadowRoot, currentBuilding, 'cooling');
	if (historyTimeout != -1)
		clearTimeout(historyTimeout);
	historyTimeout = setTimeout(updateHistoricalData, 1000*60*60);
}

/*
 * Displays a small error popup
 */
function showError(message)
{
	try
	{
		var elem = document.querySelector('#ajaxError');
		elem.text = message;
		elem.show();
	}
	catch (error){;}
}
String.prototype.capitalize = function() {
	return this.charAt(0).toUpperCase() + this.slice(1);
}
function updateLiveChart(livecard, buildingID, energyType)
{
	var name = buildingNameMap[buildingID];
	// Request data
	var request = new JSONHttpRequest(
		'api.php?building=' + buildingID + '&live=true',
		function (result) {drawLiveChart(result, livecard, name, energyType);},
		showError
	);
}
function updateHistoryGraph(livecard, buildingID, energyType)
{
	// Request data
	var request = new JSONHttpRequest(
		'api.php?building=' + buildingID,
		function (result) {drawHistoryGraph(result, livecard, energyType);},
		showError
	);
}
function drawLiveChart(jsonResult, livecard, buildingName, energyType)
{
	if (!livecard)
		return;
	// Validate
	if (jsonResult == null)
	{
		showError("No data avalible.");
		livecard.host.style.display = "none";
		return;
	}
	if (jsonResult == {} || !jsonResult[energyType])
	{
		showError("Invalid live " + energyType + " data");
		livecard.host.style.display = "none";
		return;
	}
	else
	{
		livecard.host.style.display = "block";
	}

	var ctx = livecard.getElementById('livechart').getContext("2d");
	var graph = {};

    // User Specs
	graph.x = 200; // Center X
	graph.y = 200; // Center Y
	graph.d = 250; // Graph Diameter
	graph.val = jsonResult[energyType]['amount'] / jsonResult[energyType]['maxRange']; // Current decimal value (0.0 - 1.0)

    // Autogen
	graph.r = graph.d / 2.0;
	graph.start = 3 * Math.PI / 4.0;
	graph.end = 9 * Math.PI / 4.0;
	graph.valEnd = graph.start + graph.val * 3 * Math.PI / 2.0;

    // Gray
	ctx.beginPath();
	ctx.strokeStyle = "#FFFFFF";
	ctx.fillStyle = "#808080";
	ctx.arc(graph.x, graph.y, graph.r, graph.start, graph.end);
	ctx.arc(graph.x, graph.y, graph.r / 2.0, graph.end, graph.start, true);
	ctx.closePath();
	ctx.fill();
	ctx.stroke();
	var c = document.getElementById("myCanvas2");

    // Red
	ctx.beginPath();
	ctx.strokeStyle = "#FFFFFF";
	ctx.fillStyle = "#FF0000";
	ctx.arc(graph.x, graph.y, graph.r, graph.start, graph.valEnd);
	ctx.arc(graph.x, graph.y, graph.r / 2.0, graph.valEnd, graph.start, true);
	ctx.closePath();
	ctx.fill();
	ctx.stroke();

	// Fill
	livecard.getElementById("amount").innerHTML = jsonResult[energyType]['amount'];
	livecard.getElementById("units").innerHTML = jsonResult[energyType]['nativeUnit'];
	livecard.getElementById("building").innerHTML = buildingName;
	livecard.getElementById("title").innerHTML = "Current " + energyType.capitalize() + " Usage";
}
/**
 * WARNING: The history data is notoriously bad. This tries to show data from the previous year
 * and may have significant mislabeling.
 */
function drawHistoryGraph(jsonResult, historycard, energyType)
{
	if (!historycard)
		return;
	// Validate
	if (jsonResult == null)
	{
		showError("No data avalible.");
		historycard.host.style.display = "none";
		return;
	}
	try {
		var dataTable = generateHistory(jsonResult, energyType);
		historycard.host.style.display = "block";
	}
	catch (e) {
		showError("Invalid historical " + energyType + " data");
		historycard.host.style.display = "none";
		return;
	}
	var ctx = historycard.getElementById("historygraph").getContext("2d");
	var data = {
		labels: dataTable[1],
		datasets: [
			{
				label: energyType.capitalize(),
				fillColor: "rgba(220,220,220,0.2)",
				strokeColor: "rgba(220,220,220,1)",
				pointColor: "rgba(220,220,220,1)",
				pointStrokeColor: "#fff",
				pointHighlightFill: "#fff",
				pointHighlightStroke: "rgba(220,220,220,1)",
				data: dataTable[0]
			}
		]
	};
	var options = {
		scaleLabel: "<%= value + '" + dataTable[2] + "' %>",
		animationSteps: 20,
	};

	if (historyGraphs[energyType] == null)
		// Render initial chart
		historyGraphs[energyType] = new Chart(ctx).Line(data, options);
	else if (historyGraphs[energyType].datasets[0].points.length == data.datasets[0].data.length) {
		// Update existing chart
		for (var i = 0; i < data.datasets[0].data.length; i++) {
			historyGraphs[energyType].datasets[0].points[i].value = data.datasets[0].data[i];
			historyGraphs[energyType].update();
		}
	}
	else {
		// Reload existing chart with new data
		while (historyGraphs[energyType].datasets[0].points.length)
			historyGraphs[energyType].removeData();
		for (var i = 0; i < data.datasets[0].data.length; i++)
			historyGraphs[energyType].addData([data.datasets[0].data[i]], data.labels[i]);
	}
	historycard.getElementById("title").innerHTML = "Historical " + energyType.capitalize() + " Usage";
}
function historyTypeString() {
	switch (historyType)
	{
	case 'daily':
		return '24 Hours';
	case 'monthly':
		return '30 Days';
	case 'weekly':
		return '7 Days';
	case 'yearly':
		return '10 Months';
	}
}
function historyString(input) {
	switch (input)
	{
	case '24 Hours':
		return 'daily';
	case '30 Days':
		return 'monthly';
	case '7 Days':
		return 'weekly';
	case '10 Months':
		return 'yearly';
	}
}
function generateHistory(jsonResult, energyType) {
	var history = [];
	var labels = [];
	var date = new Date();
	switch (historyType) {
		case 'daily': {
			date.setHours(0);
			while (labels.length < 24) {
				if (jsonResult['data'][energyType][historyType]['current'].length > labels.length)
					history.push(Math.round(Number(jsonResult['data'][energyType][historyType]['current'][labels.length]['amount'])));
				else
					history.push(0);
				var hour;
				if (date.getHours() == 0 || date.getHours() == 12)
					hour = "12";
				else
					hour = String(date.getHours() % 12);
				if (date.getHours() < 12)
					hour += "am";
				else
					hour += "pm";
				labels.push(hour);
				date.setHours(date.getHours() + 1);
			}
			break;
		}
		case 'weekly': {
			var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
			date.setDate(1);
			while (labels.length < 7) {
				if (jsonResult['data'][energyType][historyType]['current'].length > labels.length)
					history.push(Math.round(Number(jsonResult['data'][energyType][historyType]['current'][labels.length]['amount'])));
				else
					history.push(0);
				labels.push(days[date.getDay()]);
				date.setDate(date.getDate() + 1);
			}
			break;
		}
		case 'monthly': {
			date.setDate(1);
			while (true) {
				if (jsonResult['data'][energyType][historyType]['current'].length > labels.length)
					history.push(Math.round(Number(jsonResult['data'][energyType][historyType]['current'][labels.length]['amount'])));
				else
					history.push(0);
				labels.push(date.getDate());
				date.setDate(date.getDate() + 1);
				if (date.getDate() == 1)
					break;
			}
			break;
		}
		case 'yearly': {
			var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
			while (labels.length < 10) {
				history.push(Math.round(Number(jsonResult['data'][energyType][historyType]['previous'][labels.length]['amount'])));
				date.setMonth(date.getMonth() - 1);
				labels.push(months[date.getMonth()]);
			}
			break;
		}
		default: {
			showError("Invalid historyType.");
		}
	}
	var units = jsonResult['data'][energyType][historyType]['previous'][0]['unit'];
	for (var i = 0; i < history.length; i++) {
		switch (energyType) {
			case 'electricity':
				// Default units for electricity are kWh, but there in the possiblity for larger units (eg. MWh, GWh...) So adjust back to Wh first.
				units = "Wh";
				history[i] *= 1000;
			case 'cooling':
				if (history[i] >= 1000) {
					history[i] *= 0.001;
					units = 'k' + units;
				}
				else if (history[i] >= 1000000) {
					history[i] *= 0.000001;
					units = 'M' + units;
				}
				else if (history[i] >= 1000000000) {
					history[i] *= 0.000000001;
					units = 'G' + units;
				}
				else if (history[i] >= 1000000000000) {
					history[i] *= 0.000000000001;
					units = 'T' + units;
				}
				break;
			case 'heating':
				// Not sure about these units
				break;
			default:
				showError("Unknown energy type");
		}
	}
	return [history, labels, units];
}

function changeBuilding(newID) {
	// Reset initial selection on new selection
	if (newID != "113")
		document.getElementById("113").className = "";
	while (jsonRequestQueue.length > 0)
		jsonRequestQueue.pop().httpRequest.abort();
	currentBuilding = newID;
	forceUpdate();
}

function populateBuildings() {
	var currName;
	var buildingList = document.querySelector('core-menu');
	for (var ID in buildingNameMap) {
		// We have a few hand-picked demo buildings at the top, don't include them twice.
		if (ID == "113" || ID == "104" || ID == "083" || ID == "086" || ID == "027")
			continue;
		currName = document.createElement("core-item");
		currName.label = buildingNameMap[ID];
		currName.id = ID;
		buildingList.appendChild(currName);
	}
}

<commit_msg>Tweak the live and historical update interval<commit_after>var currentBuilding = '113';
var historyType = 'daily';
var buildingNameMap = {};
var jsonRequestQueue = [];
var liveTimeout = -1, historyTimeout = -1;
var historyGraphs = {'electricity':null, 'heating':null, 'cooling':null};

new JSONHttpRequest('/buildingmap.json',
					function(result) {buildingNameMap = result;populateBuildings();},
					function() {showError("Unable to load building list. Please refresh.");}
					);

function JSONHttpRequest(URL, loadCallback, errorCallback)
{
	var _this = this;
	this.URL = URL;
	this.loadCallback = loadCallback;
	this.errorCallback = errorCallback;
	this.onRequestComplete = function () {
		try
		{
			var response = JSON.parse(_this.httpRequest.responseText);
		}
		catch(SyntaxError)
		{
			_this.errorCallback("Unable to parse server response.");
			return;
		}
		_this.loadCallback(response);
	};
	this.httpRequest = new XMLHttpRequest();
	this.httpRequest.addEventListener("load",
										function() {
											_this.onRequestComplete();
											delete jsonRequestQueue.shift();
										},
										false);
	this.httpRequest.addEventListener("error",
										function() {
											_this.errorCallback("Unable to access the server.");
											delete jsonRequestQueue.shift();
										},
										false);
	this.httpRequest.open('GET', URL);
	this.httpRequest.send();
	jsonRequestQueue.push(this);
}

// Everything has to load before we use polymer
window.addEventListener("load", function() {
	forceUpdate();
	setTimeout(showError("WARNING: UNC's servers are experiencing problems causing significant historical data innacuracies."), 1000);
	}, false);

function forceUpdate()
{
	updateLiveData();
	updateHistoricalData();
}
function updateLiveData()
{
	updateLiveChart(document.querySelectorAll("meter-card")[0].shadowRoot, currentBuilding, 'electricity');
	updateLiveChart(document.querySelectorAll("meter-card")[1].shadowRoot, currentBuilding, 'heating');
	updateLiveChart(document.querySelectorAll("meter-card")[2].shadowRoot, currentBuilding, 'cooling');
	if (liveTimeout != -1)
		clearTimeout(liveTimeout);
	// Continue to update the live data every 10s
	liveTimeout = setTimeout(updateLiveData, 10*1000);
}
function updateHistoricalData()
{
	updateHistoryGraph(document.querySelectorAll("history-card")[0].shadowRoot, currentBuilding, 'electricity');
	updateHistoryGraph(document.querySelectorAll("history-card")[1].shadowRoot, currentBuilding, 'heating');
	updateHistoryGraph(document.querySelectorAll("history-card")[2].shadowRoot, currentBuilding, 'cooling');
	if (historyTimeout != -1)
		clearTimeout(historyTimeout);
	// Continue to update the historical data every 15m
	historyTimeout = setTimeout(updateHistoricalData, 1000*60*15);
}

/*
 * Displays a small error popup
 */
function showError(message)
{
	try
	{
		var elem = document.querySelector('#ajaxError');
		elem.text = message;
		elem.show();
	}
	catch (error){;}
}
String.prototype.capitalize = function() {
	return this.charAt(0).toUpperCase() + this.slice(1);
}
function updateLiveChart(livecard, buildingID, energyType)
{
	var name = buildingNameMap[buildingID];
	// Request data
	var request = new JSONHttpRequest(
		'api.php?building=' + buildingID + '&live=true',
		function (result) {drawLiveChart(result, livecard, name, energyType);},
		showError
	);
}
function updateHistoryGraph(livecard, buildingID, energyType)
{
	// Request data
	var request = new JSONHttpRequest(
		'api.php?building=' + buildingID,
		function (result) {drawHistoryGraph(result, livecard, energyType);},
		showError
	);
}
function drawLiveChart(jsonResult, livecard, buildingName, energyType)
{
	if (!livecard)
		return;
	// Validate
	if (jsonResult == null)
	{
		showError("No data avalible.");
		livecard.host.style.display = "none";
		return;
	}
	if (jsonResult == {} || !jsonResult[energyType])
	{
		showError("Invalid live " + energyType + " data");
		livecard.host.style.display = "none";
		return;
	}
	else
	{
		livecard.host.style.display = "block";
	}

	var ctx = livecard.getElementById('livechart').getContext("2d");
	var graph = {};

    // User Specs
	graph.x = 200; // Center X
	graph.y = 200; // Center Y
	graph.d = 250; // Graph Diameter
	graph.val = jsonResult[energyType]['amount'] / jsonResult[energyType]['maxRange']; // Current decimal value (0.0 - 1.0)

    // Autogen
	graph.r = graph.d / 2.0;
	graph.start = 3 * Math.PI / 4.0;
	graph.end = 9 * Math.PI / 4.0;
	graph.valEnd = graph.start + graph.val * 3 * Math.PI / 2.0;

    // Gray
	ctx.beginPath();
	ctx.strokeStyle = "#FFFFFF";
	ctx.fillStyle = "#808080";
	ctx.arc(graph.x, graph.y, graph.r, graph.start, graph.end);
	ctx.arc(graph.x, graph.y, graph.r / 2.0, graph.end, graph.start, true);
	ctx.closePath();
	ctx.fill();
	ctx.stroke();
	var c = document.getElementById("myCanvas2");

    // Red
	ctx.beginPath();
	ctx.strokeStyle = "#FFFFFF";
	ctx.fillStyle = "#FF0000";
	ctx.arc(graph.x, graph.y, graph.r, graph.start, graph.valEnd);
	ctx.arc(graph.x, graph.y, graph.r / 2.0, graph.valEnd, graph.start, true);
	ctx.closePath();
	ctx.fill();
	ctx.stroke();

	// Fill
	livecard.getElementById("amount").innerHTML = jsonResult[energyType]['amount'];
	livecard.getElementById("units").innerHTML = jsonResult[energyType]['nativeUnit'];
	livecard.getElementById("building").innerHTML = buildingName;
	livecard.getElementById("title").innerHTML = "Current " + energyType.capitalize() + " Usage";
}
/**
 * WARNING: The history data is notoriously bad. This tries to show data from the previous year
 * and may have significant mislabeling.
 */
function drawHistoryGraph(jsonResult, historycard, energyType)
{
	if (!historycard)
		return;
	// Validate
	if (jsonResult == null)
	{
		showError("No data avalible.");
		historycard.host.style.display = "none";
		return;
	}
	try {
		var dataTable = generateHistory(jsonResult, energyType);
		historycard.host.style.display = "block";
	}
	catch (e) {
		showError("Invalid historical " + energyType + " data");
		historycard.host.style.display = "none";
		return;
	}
	var ctx = historycard.getElementById("historygraph").getContext("2d");
	var data = {
		labels: dataTable[1],
		datasets: [
			{
				label: energyType.capitalize(),
				fillColor: "rgba(220,220,220,0.2)",
				strokeColor: "rgba(220,220,220,1)",
				pointColor: "rgba(220,220,220,1)",
				pointStrokeColor: "#fff",
				pointHighlightFill: "#fff",
				pointHighlightStroke: "rgba(220,220,220,1)",
				data: dataTable[0]
			}
		]
	};
	var options = {
		scaleLabel: "<%= value + '" + dataTable[2] + "' %>",
		animationSteps: 20,
	};

	if (historyGraphs[energyType] == null)
		// Render initial chart
		historyGraphs[energyType] = new Chart(ctx).Line(data, options);
	else if (historyGraphs[energyType].datasets[0].points.length == data.datasets[0].data.length) {
		// Update existing chart
		for (var i = 0; i < data.datasets[0].data.length; i++) {
			historyGraphs[energyType].datasets[0].points[i].value = data.datasets[0].data[i];
			historyGraphs[energyType].update();
		}
	}
	else {
		// Reload existing chart with new data
		while (historyGraphs[energyType].datasets[0].points.length)
			historyGraphs[energyType].removeData();
		for (var i = 0; i < data.datasets[0].data.length; i++)
			historyGraphs[energyType].addData([data.datasets[0].data[i]], data.labels[i]);
	}
	historycard.getElementById("title").innerHTML = "Historical " + energyType.capitalize() + " Usage";
}
function historyTypeString() {
	switch (historyType)
	{
	case 'daily':
		return '24 Hours';
	case 'monthly':
		return '30 Days';
	case 'weekly':
		return '7 Days';
	case 'yearly':
		return '10 Months';
	}
}
function historyString(input) {
	switch (input)
	{
	case '24 Hours':
		return 'daily';
	case '30 Days':
		return 'monthly';
	case '7 Days':
		return 'weekly';
	case '10 Months':
		return 'yearly';
	}
}
function generateHistory(jsonResult, energyType) {
	var history = [];
	var labels = [];
	var date = new Date();
	switch (historyType) {
		case 'daily': {
			date.setHours(0);
			while (labels.length < 24) {
				if (jsonResult['data'][energyType][historyType]['current'].length > labels.length)
					history.push(Math.round(Number(jsonResult['data'][energyType][historyType]['current'][labels.length]['amount'])));
				else
					history.push(0);
				var hour;
				if (date.getHours() == 0 || date.getHours() == 12)
					hour = "12";
				else
					hour = String(date.getHours() % 12);
				if (date.getHours() < 12)
					hour += "am";
				else
					hour += "pm";
				labels.push(hour);
				date.setHours(date.getHours() + 1);
			}
			break;
		}
		case 'weekly': {
			var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
			date.setDate(1);
			while (labels.length < 7) {
				if (jsonResult['data'][energyType][historyType]['current'].length > labels.length)
					history.push(Math.round(Number(jsonResult['data'][energyType][historyType]['current'][labels.length]['amount'])));
				else
					history.push(0);
				labels.push(days[date.getDay()]);
				date.setDate(date.getDate() + 1);
			}
			break;
		}
		case 'monthly': {
			date.setDate(1);
			while (true) {
				if (jsonResult['data'][energyType][historyType]['current'].length > labels.length)
					history.push(Math.round(Number(jsonResult['data'][energyType][historyType]['current'][labels.length]['amount'])));
				else
					history.push(0);
				labels.push(date.getDate());
				date.setDate(date.getDate() + 1);
				if (date.getDate() == 1)
					break;
			}
			break;
		}
		case 'yearly': {
			var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
			while (labels.length < 10) {
				history.push(Math.round(Number(jsonResult['data'][energyType][historyType]['previous'][labels.length]['amount'])));
				date.setMonth(date.getMonth() - 1);
				labels.push(months[date.getMonth()]);
			}
			break;
		}
		default: {
			showError("Invalid historyType.");
		}
	}
	var units = jsonResult['data'][energyType][historyType]['previous'][0]['unit'];
	for (var i = 0; i < history.length; i++) {
		switch (energyType) {
			case 'electricity':
				// Default units for electricity are kWh, but there in the possiblity for larger units (eg. MWh, GWh...) So adjust back to Wh first.
				units = "Wh";
				history[i] *= 1000;
			case 'cooling':
				if (history[i] >= 1000) {
					history[i] *= 0.001;
					units = 'k' + units;
				}
				else if (history[i] >= 1000000) {
					history[i] *= 0.000001;
					units = 'M' + units;
				}
				else if (history[i] >= 1000000000) {
					history[i] *= 0.000000001;
					units = 'G' + units;
				}
				else if (history[i] >= 1000000000000) {
					history[i] *= 0.000000000001;
					units = 'T' + units;
				}
				break;
			case 'heating':
				// Not sure about these units
				break;
			default:
				showError("Unknown energy type");
		}
	}
	return [history, labels, units];
}

function changeBuilding(newID) {
	// Reset initial selection on new selection
	if (newID != "113")
		document.getElementById("113").className = "";
	while (jsonRequestQueue.length > 0)
		jsonRequestQueue.pop().httpRequest.abort();
	currentBuilding = newID;
	forceUpdate();
}

function populateBuildings() {
	var currName;
	var buildingList = document.querySelector('core-menu');
	for (var ID in buildingNameMap) {
		// We have a few hand-picked demo buildings at the top, don't include them twice.
		if (ID == "113" || ID == "104" || ID == "083" || ID == "086" || ID == "027")
			continue;
		currName = document.createElement("core-item");
		currName.label = buildingNameMap[ID];
		currName.id = ID;
		buildingList.appendChild(currName);
	}
}

<|endoftext|>


<commit_before>$(document).ready(function(){
	var turn=0;
	var userChoice;
	var computerChoice;
	var gameReady=false;
	var gameOver=false;
	function clickResponse(){
		$("#X").hide();
		$("#O").hide();
		$("h2").html("Play!");
		$("h2").css("margin-bottom", "43px");
		gameReady=true;
	}
	$("#X").click(function(){
		userChoice="X";
		computerChoice="O";
		clickResponse();
		});
	$("#O").click(function(){
		userChoice="O";
		computerChoice="X";
		clickResponse();

	})
	var options=["top-left","top-center","top-right",
				"center-left","center-center","center-right",
				"bottom-left","bottom-center","bottom-right"];
	//EASY VERSION-uses random choices
	$(".square").click(function(){
		if (($(this).hasClass("unclickable")==false)&&gameReady==true&&gameOver==false){
		$(this).html(userChoice);
		$(this).addClass("unclickable");
		$(this).addClass("user");
		turn++;
		findWinner();
		if (turn<8&&gameOver==false){
				console.log(turn);
				hardComputerResponse();
	}
		findWinner();
		if (turn==9){
			var status=$("h2").html();
			if (status!=="Player has won!"&&status!=="Computer has won!"){
				$("h2").html("Cat's Game!");
					setTimeout(function(){
						window.location.reload();
					}, 3000);
			}
		}
	}

	});

	function computerResponse(){
		var compSel=Math.ceil(Math.random() * (9)-1);
		while($("#"+(options[compSel])).hasClass("unclickable")){
			compSel=Math.ceil(Math.random() * (9)-1);
		}
		$("#"+(options[compSel])).html(computerChoice);
		$("#"+(options[compSel])).addClass("unclickable").addClass("computer");
		turn++;
	}

	function hardComputerResponse(){
	var arr=[[0,1,2],[3,4,5],[6,7,8]];
	var vertArr=[[0,3,6],[1,4,7],[2,5,8]];
	var diagonalArr=[[0,4,8],[6,4,2]];
		//turn 1,2
		//if X plays corner, O plays center
		if (turn==1){
		$("#top-left, #top-center, #top-right, #center-left, #center-right, #bottom-left, #bottom-center, #bottom-right").each(function(){	if($(this).hasClass("user")){
				$("#center-center").html(computerChoice).addClass("unclickable").addClass("computer");
				turn++;}
								});

		var compSel=Math.ceil(Math.random() * (9)-1);
		if ($("#center-center").hasClass("user")){
			while([0,2,6,8].includes(compSel)==false){
			compSel=Math.ceil(Math.random() * (9)-1);
		}
		$("#"+(options[compSel])).html(computerChoice);
		$("#"+(options[compSel])).addClass("unclickable").addClass("computer");
		turn++;
		}

	}
		//turn 3,4

		//first if comp has two in a row, do third
		function turnThreeFive(num1,num2, num3, markerClass){
if (turn==3||turn==5||turn==7){
	if ($("#"+options[num1]).hasClass(markerClass)&&$("#"+options[num2]).hasClass(markerClass)&&$("#"+options[num3]).hasClass("unclickable")==false){
		console.log("target is "+ options[num3]);
		if ($("#"+(options[num3])).hasClass("unclickable")==false){
		$("#"+(options[num3])).html(computerChoice);
		$("#"+(options[num3])).addClass("unclickable").addClass("computer");
		turn++;
			}
		}
	}
}

var check=function(array,playerID){
		for(var i=0;i<array.length;i++){
		for (var j=0; j<3; j++) {
    turnThreeFive(array[i][0],array[i][1],array[i][2],playerID);
    //console.log(array[i][0]+" "+array[i][1]+" "+array[i][2]);
    array[i].slice(0, 3).join(",");
    array[i].push(array[i].shift());
		}
	}
};

if (turn==3||turn==5||turn==7){
	console.log("checking...");
	check(arr, "computer");
	check(vertArr, "computer");
	check(diagonalArr, "computer");
	check(arr, "user");
	check(vertArr, "user");
	check(diagonalArr, "user");
	if (turn==3||turn==5||turn==7){
		computerResponse();
	}
}
		//turn 5,6

		//turn 7,8

	}

	function findWinner(){
		var playerArray=[0,0,0,0,0,0,0,0];
		var compArray=[0,0,0,0,0,0,0,0];
		var topVictory="#top-left, #top-center, #top-right";
		var centerVictory="#center-left, #center-center, #center-right";
		var bottomVictory="#bottom-left, #bottom-center, #bottom-right";
		var leftVerticalVictory="#top-left, #center-left, #bottom-left";
		var centerVerticalVictory="#top-center, #center-center, #bottom-center";
		var rightVerticalVictory="#top-right, #center-right, #bottom-right";
		var diagonalLeftRight="#top-left, #center-center, #bottom-right";
		var diagonalRightLeft="#top-right, #center-center, #bottom-left";
		var vicArr=[topVictory,centerVictory,bottomVictory,leftVerticalVictory,centerVerticalVictory,
		rightVerticalVictory,diagonalLeftRight,diagonalRightLeft];

		function winner(className, controller, arraySlot, condition){
		$(condition).each(function(){

			if($(this).hasClass(className)){
				arraySlot++;
				if (arraySlot==3){
					gameOver=true;
					$("h2").html(controller+" has won!");
					setTimeout(function(){
						window.location.reload();
					}, 3000);
				}
			}});
		}
		for (var i=0;i<vicArr.length;i++){
			var cond=vicArr[i];
			winner("computer", "Computer",compArray[i], cond);
			winner("user", "Player",playerArray[i], cond);
		}
	}
});<commit_msg>Update main.js<commit_after>$(document).ready(function(){
	var turn=0, userChoice, computerChoice, gameReady=false, gameOver=false;
	function clickResponse(){
		$("#X").hide();
		$("#O").hide();
		$("h2").html("Play!");
		$("h2").css("margin-bottom", "43px");
		gameReady=true;
	}
	$("#X").click(function(){
		userChoice="X";
		computerChoice="O";
		clickResponse();
		});
	$("#O").click(function(){
		userChoice="O";
		computerChoice="X";
		clickResponse();

	})
	var options=["top-left","top-center","top-right",
				"center-left","center-center","center-right",
				"bottom-left","bottom-center","bottom-right"];
	//EASY VERSION-uses random choices
	$(".square").click(function(){
		if (($(this).hasClass("unclickable")==false)&&gameReady==true&&gameOver==false){
		$(this).html(userChoice);
		$(this).addClass("unclickable");
		$(this).addClass("user");
		turn++;
		findWinner();
		if (turn<8&&gameOver==false){
				console.log(turn);
				hardComputerResponse();
	}
		findWinner();
		if (turn==9){
			var status=$("h2").html();
			if (status!=="Player has won!"&&status!=="Computer has won!"){
				$("h2").html("Cat's Game!");
					setTimeout(function(){
						window.location.reload();
					}, 3000);
			}
		}
	}

	});

	function computerResponse(){
		var compSel=Math.ceil(Math.random() * (9)-1);
		while($("#"+(options[compSel])).hasClass("unclickable")){
			compSel=Math.ceil(Math.random() * (9)-1);
		}
		$("#"+(options[compSel])).html(computerChoice);
		$("#"+(options[compSel])).addClass("unclickable").addClass("computer");
		turn++;
	}

	function hardComputerResponse(){
	var arr=[[0,1,2],[3,4,5],[6,7,8]];
	var vertArr=[[0,3,6],[1,4,7],[2,5,8]];
	var diagonalArr=[[0,4,8],[6,4,2]];
		//turn 1,2
		//if X plays corner, O plays center
		if (turn==1){
		$("#top-left, #top-center, #top-right, #center-left, #center-right, #bottom-left, #bottom-center, #bottom-right").each(function(){	if($(this).hasClass("user")){
				$("#center-center").html(computerChoice).addClass("unclickable").addClass("computer");
				turn++;}
								});

		var compSel=Math.ceil(Math.random() * (9)-1);
		if ($("#center-center").hasClass("user")){
			while([0,2,6,8].includes(compSel)==false){
			compSel=Math.ceil(Math.random() * (9)-1);
		}
		$("#"+(options[compSel])).html(computerChoice);
		$("#"+(options[compSel])).addClass("unclickable").addClass("computer");
		turn++;
		}

	}
		//turn 3,4

		//first if comp has two in a row, do third
		function turnThreeFive(num1,num2, num3, markerClass){
if (turn==3||turn==5||turn==7){
	if ($("#"+options[num1]).hasClass(markerClass)&&$("#"+options[num2]).hasClass(markerClass)&&$("#"+options[num3]).hasClass("unclickable")==false){
		console.log("target is "+ options[num3]);
		if ($("#"+(options[num3])).hasClass("unclickable")==false){
		$("#"+(options[num3])).html(computerChoice);
		$("#"+(options[num3])).addClass("unclickable").addClass("computer");
		turn++;
			}
		}
	}
}

var check=function(array,playerID){
		for(var i=0;i<array.length;i++){
		for (var j=0; j<3; j++) {
    turnThreeFive(array[i][0],array[i][1],array[i][2],playerID);
    array[i].slice(0, 3).join(",");
    array[i].push(array[i].shift());
		}
	}
};

if (turn==3||turn==5||turn==7){
	console.log("checking...");
	check(arr, "computer");
	check(vertArr, "computer");
	check(diagonalArr, "computer");
	check(arr, "user");
	check(vertArr, "user");
	check(diagonalArr, "user");
	if (turn==3||turn==5||turn==7){
		computerResponse();
	}
}
		//turn 5,6

		//turn 7,8

	}

	function findWinner(){
		var playerArray=[0,0,0,0,0,0,0,0],
            compArray=[0,0,0,0,0,0,0,0],
            topVictory="#top-left, #top-center, #top-right",
            centerVictory="#center-left, #center-center, #center-right",
            bottomVictory="#bottom-left, #bottom-center, #bottom-right",
            leftVerticalVictory="#top-left, #center-left, #bottom-left",
            centerVerticalVictory="#top-center, #center-center, #bottom-center",
            rightVerticalVictory="#top-right, #center-right, #bottom-right",
            diagonalLeftRight="#top-left, #center-center, #bottom-right",
            diagonalRightLeft="#top-right, #center-center, #bottom-left",
            vicArr=[topVictory,centerVictory,bottomVictory,leftVerticalVictory,centerVerticalVictory,
		    rightVerticalVictory,diagonalLeftRight,diagonalRightLeft];

		function winner(className, controller, arraySlot, condition){
		$(condition).each(function(){

			if($(this).hasClass(className)){
				arraySlot++;
				if (arraySlot==3){
					gameOver=true;
					$("h2").html(controller+" has won!");
					setTimeout(function(){
						window.location.reload();
					}, 3000);
				}
			}});
		}
		for (var i=0;i<vicArr.length;i++){
			var cond=vicArr[i];
			winner("computer", "Computer",compArray[i], cond);
			winner("user", "Player",playerArray[i], cond);
		}
	}
});
<|endoftext|>


<commit_before>var balltop=0 , bouncetime=1000,p=0;
$(document).ready(function(){
    $(".main section").hide();
    $("nav a").click(function(){
        $(".main section").hide();
        $(".main section:eq(" + $(this).index() + ")").fadeIn();
    });
    $("nav a:eq(0)").click();
    if($(window).width()>=480){
        $("nav").hover(function(){
            $(".arrow").fadeOut();
        },
        function(){
            $(".arrow").delay(300).fadeIn();
        }
        );
    }

    var bouncetime = 1000;
    var ballheight = 485;
    var ballsize = 80;
    balltop =20;
    var n=15;

    ballbounce();
    function ballbounce() {
        $('#creatures').animate({'top':balltop}, bouncetime, 'easeOutQuad', function() {
            if(p<12)
            {$('figure').delay(900).animate({'height':70+p*1.1},90);
             }
            $('#creatures').animate({'top':ballheight}, bouncetime, 'easeInQuad', function() {
               if(p<12)
               {$('figure').animate({'height':90},100);}
                     if(document.height>document.width)
                        var e= Math.sqrt(1-Math.pow(document.width/document.height,2));//calculating e
                     else
                        var e= Math.sqrt(1-Math.pow(document.height/document.width,2));//calculating e
                     var b= document.height/(n-2), b2=Math.pow(b,2);
                     var x2= Math.pow($('.cursor').position().left,2), y2=Math.pow($('.cursor').position().top,2);
                     for( i=1;i<=n;i++){
                          var a1= Math.pow(i,2)*b2/(1-Math.pow(e,2));
                          var a2= Math.pow(i+1,2)*b2/(1-Math.pow(e,2));
                                if (x2/a1+y2/(Math.pow(i,2)*b2)-1 >0 && x2/a2+y2/(Math.pow(i+1,2)*b2)-1 <=0) {
                                    if(i<=12) {
                                        p=i;
                                        // bouncetime=1000;
                                        $('figure').removeClass('nervous');
                                        balltop=40*i;
                                        $('.mouth').animate({'height':45-3*i})
                                        break;
                                    }
                                    if(i>=13) {
                                        p=i;
                                        balltop=465;
                                        // bouncetime=1;
                                        // $('figure').removeClass('nervous');
                                        $('.mouth').animate({'height':9+2*i})
                                        $('figure').addClass('nervous');
                                    }

                                }

                                    if(x2/a1+y2/(Math.pow(1,2)*b2)-1 <0)
                                    {
                                        balltop=40;
                                    }
                                    if(x2/a2+y2/(Math.pow(n,2)*b2)-1 >0)
                                    {
                                        balltop= 465;
                                        $('figure').addClass('nervous');
                                    }
                        }
                ballbounce();
                });
         });
    }

$(document).mousemove(function(h){
    $(".cursor").css('top',h.pageY);
    $(".cursor").css('left',h.pageX);

});
$("#myButton span").hide();
$(".myButton").click(function(){
    $("#myButton span").fadeIn();
    return false;
});
});<commit_msg>Update Refer to Friend Button<commit_after>var balltop=0 , bouncetime=1000,p=0;
$(document).ready(function(){
    $(".main section").hide();
    $("nav a").click(function(){
        $(".main section").hide();
        $(".main section:eq(" + $(this).index() + ")").fadeIn();
    });
    $("nav a:eq(0)").click();
    if($(window).width()>=480){
        $("nav").hover(function(){
            $(".arrow").fadeOut();
        },
        function(){
            $(".arrow").delay(300).fadeIn();
        }
        );
    }

    var bouncetime = 1000;
    var ballheight = 485;
    var ballsize = 80;
    balltop =20;
    var n=15;

    ballbounce();
    function ballbounce() {
        $('#creatures').animate({'top':balltop}, bouncetime, 'easeOutQuad', function() {
            if(p<12)
            {$('figure').delay(900).animate({'height':70+p*1.1},90);
             }
            $('#creatures').animate({'top':ballheight}, bouncetime, 'easeInQuad', function() {
               if(p<12)
               {$('figure').animate({'height':90},100);}
                     if(document.height>document.width)
                        var e= Math.sqrt(1-Math.pow(document.width/document.height,2));//calculating e
                     else
                        var e= Math.sqrt(1-Math.pow(document.height/document.width,2));//calculating e
                     var b= document.height/(n-2), b2=Math.pow(b,2);
                     var x2= Math.pow($('.cursor').position().left,2), y2=Math.pow($('.cursor').position().top,2);
                     for( i=1;i<=n;i++){
                          var a1= Math.pow(i,2)*b2/(1-Math.pow(e,2));
                          var a2= Math.pow(i+1,2)*b2/(1-Math.pow(e,2));
                                if (x2/a1+y2/(Math.pow(i,2)*b2)-1 >0 && x2/a2+y2/(Math.pow(i+1,2)*b2)-1 <=0) {
                                    if(i<=12) {
                                        p=i;
                                        // bouncetime=1000;
                                        $('figure').removeClass('nervous');
                                        balltop=40*i;
                                        $('.mouth').animate({'height':45-3*i})
                                        break;
                                    }
                                    if(i>=13) {
                                        p=i;
                                        balltop=465;
                                        // bouncetime=1;
                                        // $('figure').removeClass('nervous');
                                        $('.mouth').animate({'height':9+2*i})
                                        $('figure').addClass('nervous');
                                    }

                                }

                                    if(x2/a1+y2/(Math.pow(1,2)*b2)-1 <0)
                                    {
                                        balltop=40;
                                    }
                                    if(x2/a2+y2/(Math.pow(n,2)*b2)-1 >0)
                                    {
                                        balltop= 465;
                                        $('figure').addClass('nervous');
                                    }
                        }
                ballbounce();
                });
         });
    }

$(document).mousemove(function(h){
    $(".cursor").css('top',h.pageY);
    $(".cursor").css('left',h.pageX);

});
$("#myButton span").hide();
$(".myButton").click(function(){
    $("#myButton span").fadeIn();
    return true;
});
});
<|endoftext|>


<commit_before>var canvas,
  context;

$(function () {
  var gridWidth = 100,
    gridHeight = 50,
    gridSize = 10;

  canvas = $("#mainCanvas")[0];
  context = canvas.getContext('2d');

  init(gridWidth, gridHeight, gridSize);
});

function init(width, height, size) {
  GRID.init(width, height, size);
  GAME.init();
  GRID.draw();
}

function randomPop() {
  var randomX = Math.floor(Math.random() * GRID.getWidth());
  var randomY = Math.floor(Math.random() * GRID.getHeight());

  GAME.isAlive(randomX, randomY, 4);
  GRID.draw();
}

function glider() {
  var center_x = Math.floor(GRID.getWidth() / 2);
  var center_y = Math.floor(GRID.getHeight() / 2);

  GAME.isAlive(center_x, center_y - 1, 4);
  GAME.isAlive(center_x + 1, center_y, 4);
  GAME.isAlive(center_x - 1, center_y + 1, 4);
  GAME.isAlive(center_x, center_y + 1, 4);
  GAME.isAlive(center_x + 1, center_y + 1, 4);
  GRID.draw();
}

function acorn() {
  var center_x = Math.floor(GRID.getWidth() / 2);
  var center_y = Math.floor(GRID.getHeight() / 2);

  GAME.isAlive(center_x - 1, center_y - 1, 4);
  GAME.isAlive(center_x + 1, center_y, 4);
  GAME.isAlive(center_x - 2, center_y + 1, 4);
  GAME.isAlive(center_x - 1, center_y + 1, 4);
  GAME.isAlive(center_x + 2, center_y + 1, 4);
  GAME.isAlive(center_x + 3, center_y + 1, 4);
  GAME.isAlive(center_x + 4, center_y + 1, 4);
  GRID.draw();
}

function changeGridSize() {
  var size = $('#sizeSelection').val().split("x");
  console.log(size)
  GAME.stop();
  GRID.init(parseInt(size[0]), parseInt(size[1]), parseInt(size[2]));
  GAME.init();
  GRID.draw();
}

function selectSpeed() {
  var speed = parseInt($('#speedSelection').val());
  GAME.setSpeed(speed);
}

function selectGridStyle() {
  var style = parseInt($('#gridSelection').val());
  GRID.setGridStyle(style)
}

function selectTrailSize() {
  var trailSize = parseInt($('#trailSelection').val());
  GRID.setTrailSize(trailSize);
}

var GRID = (function () {
  var width,
    height,
    size,
    gridStyle = 2,
    trailSize = 3;

  return {
    init: function (gridWidth, gridHeight, gridSize) {
      var gridCanvas = $("#gridOverlay")[0],
        gridContext = gridCanvas.getContext('2d'),
        color;

      gridContext.clearRect(0, 0, canvas.width, canvas.height);

      width = gridWidth;
      height = gridHeight;
      size = gridSize;

      if (gridStyle > 0) {
        color = "#000000"
        if (gridStyle == 1) {
          color = "#e5e5e5"
        }
        for (var x = 0; x < width; x++) {
          for (var y = 0; y < height; y++) {
            gridContext.beginPath();
            gridContext.strokeStyle = color;
            gridContext.rect(x * size, y * size, size, size);
            gridContext.stroke();
            gridContext.closePath();
          }
        }
      }
    },

    getWidth: function () {
      return width;
    },

    getHeight: function () {
      return height;
    },

    getSize: function () {
      return size;
    },

    setGridStyle: function (style) {
      gridStyle = style;
      GRID.init(width, height, size);
    },

    setTrailSize: function (size) {
      trailSize = size;
    },

    draw: function () {
      context.clearRect(0, 0, canvas.width, canvas.height);

      for (var x = 0; x < width; x++) {
        for (var y = 0; y < height; y++) {
          context.beginPath();

          context.rect(x * size, y * size, size, size);
          var status = GAME.isAlive(x, y);
          if (status > 0) {
            if (status == 4) {
              context.fillStyle = "red";
            } else if (status == 3) {
              context.fillStyle = "orange";
            } else if (status == 2) {
              context.fillStyle = "yellow";
            } else {
              context.fillStyle = "#666666";
            }

            if (status >= 4 - trailSize)
              context.fill();
          }

          context.closePath();
        }
      }
    }
  }

})();

var GAME = (function () {
  var generation = 0,
    speed = 1,
    isRunning = false,
    intervalId = undefined,
    population,
    activeCells;

  return {
    init: function () {
      var gridWidth = GRID.getWidth();
      var gridHeight = GRID.getHeight();

      population = [];
      activeCells = [];

      for (var i = 0; i < gridWidth * gridHeight; i++) {
        population[i] = 0;
      }
    },

    population: function (grid) {
      return population;
    },

    isAlive: function (x, y, status) {
      var width = GRID.getWidth(),
        height = GRID.getHeight();

      // Get
      if (arguments.length < 3) {
        return population[y * width + x];
      }
      // Set
      else {
        population[y * width + x] = status;

        if (status == 4) {
          // Add changed cell with its neighbours to active cell list
          for (var i = x - 1; i <= (x + 1); i++) {
            for (var j = y - 1; j <= (y + 1); j++) {
              // Wrap around
              var a = (i + width) % width;
              var b = (j + height) % height;

              // Convert 2D coordinates to 1D
              var index = b * width + a;

              // Only add if not already in active cell
              if (activeCells.indexOf(index) < 0) {
                activeCells.push(index);
              }
            }
          }
        }
      }
    },

    getActiveCells: function () {
      return activeCells;
    },

    resetActiveCells: function () {
      activeCells = [];
    },

    currentGeneration: function () {
      return generation;
    },

    currentSpeed: function () {
      return speed;
    },

    setSpeed: function (newSpeed) {
      if (newSpeed >= 0 && newSpeed <= 3) {
        speed = newSpeed;
      } else {
        speed = 1;
      }

      if (isRunning) {
        clearInterval(intervalId);
        intervalId = setInterval(GAME.step, 32 / Math.pow(2, GAME.currentSpeed()));
      }
    },

    step: function () {
      var width = GRID.getWidth(),
        height = GRID.getHeight(),
        livingCells = [],
        activeCells = GAME.getActiveCells();

      for (var i = 0; i < width * height; i++) {
        if (population[i] > 0) {
          population[i] = population[i] - 1;
        }
      }

      // Track which cells are alive for next generation
      for (var i = 0; i < activeCells.length; i++) {
        var index = activeCells[i];
        var x = index % width;
        var y = Math.floor(index / width);

        var amountOfNeighbours = GAME.livingNeighbours(x, y);

        // If alive
        if (GAME.isAlive(x, y) == 3) {
          // Not under- or overpopulation -> keep alive
          if (amountOfNeighbours == 2 || amountOfNeighbours == 3) {
            livingCells.push(index);
          }
        }
        // If not alive, if it has exactly 3 living neighbours -> alive
        else if (amountOfNeighbours == 3) {
          livingCells.push(index);
        }
      }

      // Clear grid and redraw the living cells.
      GAME.resetActiveCells();

      for (var i = 0; i < livingCells.length; i++) {
        var index = livingCells[i];
        var x = index % width;
        var y = Math.floor(index / width);

        GAME.isAlive(x, y, 4);
      }

      GRID.draw();

      generation++;
    },

    livingNeighbours: function (x, y) {
      var amountOfNeighbours = 0,
        width = GRID.getWidth(),
        height = GRID.getHeight();

      for (var i = x - 1; i <= x + 1; i++) {
        for (var j = y - 1; j <= y + 1; j++) {
          // Check if it is itself
          if (!(i == x && j == y)) {
            // check if it is alive
            if (GAME.isAlive((i + width) % width, (j + height) % height) >= 3) {
              amountOfNeighbours++;
            }
          }
        }
      }

      return amountOfNeighbours;
    },

    toggleRun: function () {
      var button = $("#runButton");

      if (isRunning) {
        button.text("Start")
          .removeClass("btn-danger")
          .addClass("btn-success");
        clearInterval(intervalId);
      } else {
        button.text("Stop")
          .removeClass("btn-success")
          .addClass("btn-danger");
        intervalId = setInterval(GAME.step, 32 / Math.pow(2, GAME.currentSpeed()));
      }

      isRunning = !isRunning;
    },

    stop: function () {
      $("#runButton").text("Start")
        .removeClass("btn-danger")
        .addClass("btn-success");

      clearInterval(intervalId);
      isRunning = false;
    }
  }
})();<commit_msg>Trail size is updated instantaneously now<commit_after>var canvas,
  context;

$(function () {
  var gridWidth = 100,
    gridHeight = 50,
    gridSize = 10;

  canvas = $("#mainCanvas")[0];
  context = canvas.getContext('2d');

  init(gridWidth, gridHeight, gridSize);
});

function init(width, height, size) {
  GRID.init(width, height, size);
  GAME.init();
  GRID.draw();
}

function randomPop() {
  var randomX = Math.floor(Math.random() * GRID.getWidth());
  var randomY = Math.floor(Math.random() * GRID.getHeight());

  GAME.isAlive(randomX, randomY, 4);
  GRID.draw();
}

function glider() {
  var center_x = Math.floor(GRID.getWidth() / 2);
  var center_y = Math.floor(GRID.getHeight() / 2);

  GAME.isAlive(center_x, center_y - 1, 4);
  GAME.isAlive(center_x + 1, center_y, 4);
  GAME.isAlive(center_x - 1, center_y + 1, 4);
  GAME.isAlive(center_x, center_y + 1, 4);
  GAME.isAlive(center_x + 1, center_y + 1, 4);
  GRID.draw();
}

function acorn() {
  var center_x = Math.floor(GRID.getWidth() / 2);
  var center_y = Math.floor(GRID.getHeight() / 2);

  GAME.isAlive(center_x - 1, center_y - 1, 4);
  GAME.isAlive(center_x + 1, center_y, 4);
  GAME.isAlive(center_x - 2, center_y + 1, 4);
  GAME.isAlive(center_x - 1, center_y + 1, 4);
  GAME.isAlive(center_x + 2, center_y + 1, 4);
  GAME.isAlive(center_x + 3, center_y + 1, 4);
  GAME.isAlive(center_x + 4, center_y + 1, 4);
  GRID.draw();
}

function changeGridSize() {
  var size = $('#sizeSelection').val().split("x");
  console.log(size)
  GAME.stop();
  GRID.init(parseInt(size[0]), parseInt(size[1]), parseInt(size[2]));
  GAME.init();
  GRID.draw();
}

function selectSpeed() {
  var speed = parseInt($('#speedSelection').val());
  GAME.setSpeed(speed);
}

function selectGridStyle() {
  var style = parseInt($('#gridSelection').val());
  GRID.setGridStyle(style)
}

function selectTrailSize() {
  var trailSize = parseInt($('#trailSelection').val());
  GRID.setTrailSize(trailSize);
}

var GRID = (function () {
  var width,
    height,
    size,
    gridStyle = 2,
    trailSize = 3;

  return {
    init: function (gridWidth, gridHeight, gridSize) {
      var gridCanvas = $("#gridOverlay")[0],
        gridContext = gridCanvas.getContext('2d'),
        color;

      gridContext.clearRect(0, 0, canvas.width, canvas.height);

      width = gridWidth;
      height = gridHeight;
      size = gridSize;

      if (gridStyle > 0) {
        color = "#000000"
        if (gridStyle == 1) {
          color = "#e5e5e5"
        }
        for (var x = 0; x < width; x++) {
          for (var y = 0; y < height; y++) {
            gridContext.beginPath();
            gridContext.strokeStyle = color;
            gridContext.rect(x * size, y * size, size, size);
            gridContext.stroke();
            gridContext.closePath();
          }
        }
      }
    },

    getWidth: function () {
      return width;
    },

    getHeight: function () {
      return height;
    },

    getSize: function () {
      return size;
    },

    setGridStyle: function (style) {
      gridStyle = style;
      GRID.init(width, height, size);
    },

    setTrailSize: function (size) {
      trailSize = size;
      GRID.draw();
    },

    draw: function () {
      context.clearRect(0, 0, canvas.width, canvas.height);

      for (var x = 0; x < width; x++) {
        for (var y = 0; y < height; y++) {
          context.beginPath();

          context.rect(x * size, y * size, size, size);
          var status = GAME.isAlive(x, y);
          if (status > 0) {
            if (status == 4) {
              context.fillStyle = "red";
            } else if (status == 3) {
              context.fillStyle = "orange";
            } else if (status == 2) {
              context.fillStyle = "yellow";
            } else {
              context.fillStyle = "#666666";
            }

            if (status >= 4 - trailSize)
              context.fill();
          }

          context.closePath();
        }
      }
    }
  }

})();

var GAME = (function () {
  var generation = 0,
    speed = 1,
    isRunning = false,
    intervalId = undefined,
    population,
    activeCells;

  return {
    init: function () {
      var gridWidth = GRID.getWidth();
      var gridHeight = GRID.getHeight();

      population = [];
      activeCells = [];

      for (var i = 0; i < gridWidth * gridHeight; i++) {
        population[i] = 0;
      }
    },

    population: function (grid) {
      return population;
    },

    isAlive: function (x, y, status) {
      var width = GRID.getWidth(),
        height = GRID.getHeight();

      // Get
      if (arguments.length < 3) {
        return population[y * width + x];
      }
      // Set
      else {
        population[y * width + x] = status;

        if (status == 4) {
          // Add changed cell with its neighbours to active cell list
          for (var i = x - 1; i <= (x + 1); i++) {
            for (var j = y - 1; j <= (y + 1); j++) {
              // Wrap around
              var a = (i + width) % width;
              var b = (j + height) % height;

              // Convert 2D coordinates to 1D
              var index = b * width + a;

              // Only add if not already in active cell
              if (activeCells.indexOf(index) < 0) {
                activeCells.push(index);
              }
            }
          }
        }
      }
    },

    getActiveCells: function () {
      return activeCells;
    },

    resetActiveCells: function () {
      activeCells = [];
    },

    currentGeneration: function () {
      return generation;
    },

    currentSpeed: function () {
      return speed;
    },

    setSpeed: function (newSpeed) {
      if (newSpeed >= 0 && newSpeed <= 3) {
        speed = newSpeed;
      } else {
        speed = 1;
      }

      if (isRunning) {
        clearInterval(intervalId);
        intervalId = setInterval(GAME.step, 32 / Math.pow(2, GAME.currentSpeed()));
      }
    },

    step: function () {
      var width = GRID.getWidth(),
        height = GRID.getHeight(),
        livingCells = [],
        activeCells = GAME.getActiveCells();

      for (var i = 0; i < width * height; i++) {
        if (population[i] > 0) {
          population[i] = population[i] - 1;
        }
      }

      // Track which cells are alive for next generation
      for (var i = 0; i < activeCells.length; i++) {
        var index = activeCells[i];
        var x = index % width;
        var y = Math.floor(index / width);

        var amountOfNeighbours = GAME.livingNeighbours(x, y);

        // If alive
        if (GAME.isAlive(x, y) == 3) {
          // Not under- or overpopulation -> keep alive
          if (amountOfNeighbours == 2 || amountOfNeighbours == 3) {
            livingCells.push(index);
          }
        }
        // If not alive, if it has exactly 3 living neighbours -> alive
        else if (amountOfNeighbours == 3) {
          livingCells.push(index);
        }
      }

      // Clear grid and redraw the living cells.
      GAME.resetActiveCells();

      for (var i = 0; i < livingCells.length; i++) {
        var index = livingCells[i];
        var x = index % width;
        var y = Math.floor(index / width);

        GAME.isAlive(x, y, 4);
      }

      GRID.draw();

      generation++;
    },

    livingNeighbours: function (x, y) {
      var amountOfNeighbours = 0,
        width = GRID.getWidth(),
        height = GRID.getHeight();

      for (var i = x - 1; i <= x + 1; i++) {
        for (var j = y - 1; j <= y + 1; j++) {
          // Check if it is itself
          if (!(i == x && j == y)) {
            // check if it is alive
            if (GAME.isAlive((i + width) % width, (j + height) % height) >= 3) {
              amountOfNeighbours++;
            }
          }
        }
      }

      return amountOfNeighbours;
    },

    toggleRun: function () {
      var button = $("#runButton");

      if (isRunning) {
        button.text("Start")
          .removeClass("btn-danger")
          .addClass("btn-success");
        clearInterval(intervalId);
      } else {
        button.text("Stop")
          .removeClass("btn-success")
          .addClass("btn-danger");
        intervalId = setInterval(GAME.step, 32 / Math.pow(2, GAME.currentSpeed()));
      }

      isRunning = !isRunning;
    },

    stop: function () {
      $("#runButton").text("Start")
        .removeClass("btn-danger")
        .addClass("btn-success");

      clearInterval(intervalId);
      isRunning = false;
    }
  }
})();<|endoftext|>


<commit_before>// Access search box
var searchBox = document.getElementById("search-box");

// Access search button
var searchBtn = document.getElementById("search-button");

// Get JSON file via AJAX request
var xhttp = new XMLHttpRequest(),
	locations;
xhttp.onreadystatechange = function () {
	if (xhttp.readyState == 4 && xhttp.status == 200) {
		// Convert responseText to JSON and store in "locations"
		locations = JSON.parse(xhttp.responseText);
		// Load all branches
		loadMap("pb=!1m12!1m8!1m3!1d15440.032333793673!2d120.98674643710937" +
			"!3d14.655482563301007!3m2!1i1024!2i768!4f13.1!2m1!1slbc" +
			"!5e0!3m2!1sen!2sph!4v1444102396793");
	}
};
xhttp.open("GET", "js/locations.json", true);
xhttp.send(null);

// Change search box value
function setInput() {
	// Remove the strong elements before setting input
	var str = this.innerHTML.replace("", "");
	str = str.replace("", "");
	searchBox.value = str;
	document.getElementById("search-hints").innerHTML = null;
	// Reset pos to 0
	pos = 0;
}

// Call this function everytime the user input a character in search box
function displayHints(str) {
	if (window.event.which == 38 || window.event.which == 40 ||
		window.event.which == 13) return false;
	// Access search hints box, then make it empty
	// So previous searches will be cleared
	var hints = document.getElementById("search-hints");
	hints.innerHTML = null;
	// If search box value is empty, stop further execution of code
	if (str === "") return false;
	// "str" argument is the search box value
	var pattern = new RegExp(str, "i");
	// Loop throught the "locations" array
	for (var i = 0, len = locations.length; i < len; i++) {
		var currentItem = locations[i].stringLocation;
		// Search for pattern
		var match = currentItem.search(pattern);
		// If a match is found
		if (match !== -1) {
			// Create a "p" element
			var p = document.createElement("p");
			// Set "p" content equal to current item inside location array
			p.innerHTML = currentItem.substr(0, match);
			// Highlight the matched string
			p.innerHTML += "" +
				currentItem.substr(match, searchBox.value.length) +
				"";
			// Add the remaining string
			p.innerHTML += currentItem.substr(match + searchBox.value.length, currentItem.length);
			// Display the p element
			hints.appendChild(p);
		}
	}

	// Get all displayed hints
	var pHints = hints.querySelectorAll("p");
	// If there's a hint displayed, set bgcolor of the first one to light green
	if (pHints.length !== 0) pHints[0].style.background = "#efd";
	// Listen for click event to all hints displayed
	for (i = 0, len = pHints.length; i < len; i++) {
		pHints[i].addEventListener("click", setInput);
	}
}

var pos = 0; // For tracking pHints position

function highlightText() {
	// Get all displayed hints
	var pHints = document.querySelectorAll("#search-hints p");
	// If there is no hints displayed, STOP
	if (pHints === undefined || pHints.length === 0) return false;

	// Change all pHints background to white
	for (var i = 0, len = pHints.length; i < len; i++) {
		pHints[i].style.background = "#fdfdfd";
	}

	// When up arrow key (38) is press
	if (window.event.which == 38) {
		if (pos > 0) pos--; // Prevent negative numbers
		pHints[pos].style.background = "#efd";
		pHints[pos].scrollIntoView();
		// or down arrow key (40) is press
	} else if (window.event.which == 40) {
		// Prevent numbers higher than no. of displayed hints
		if (pos < pHints.length - 1) pos++;
		pHints[pos].style.background = "#efd";
		pHints[pos].scrollIntoView();
		// or enter key (13) is press
	} else if (window.event.which == 13) {
		setInput.call(pHints[pos]);
		// Add nearby branches
		addNearbyBranch();
		// Load map
		loadMap();
		// Reset pos to 0
		pos = 0;
	}

}

// Call highlightText function in each keydown
document.body.addEventListener("keydown", highlightText);

function addNearbyBranch() {
	// Loop throught locations array and check for match with searchBox content
	var content = searchBox.value;
	// Get nearby branch section
	var container = document.getElementById("nearby-branch");
	// If value of searchbox is empty
	if (content === "") {
		// Display "no nearby branches"
		container.innerHTML = "
Nearby branches
";
		container.innerHTML += "
No nearby branches
";
		return false; // Then STOP
	}
	// If search-box has input value, loop throught "locations"
	for (var i = 0, len = locations.length; i < len; i++) {
		// Check if search-box value is equal to current "locations".stringlocation
		if (content == locations[i].stringLocation) {
			// Add heading first
			container.innerHTML = "
Nearby branches
";
			// Get nearbyNum property value
			var nearbyNum = locations[i].nearbyLocations.length;
			// Loop through it
			for (var j = 0; j < nearbyNum; j++) {
				// J = nearbyNum item position
				var nearbys = locations[i].nearbyLocations[j];
				// Generate a p element containing the stringLocation
				var p = document.createElement("p");
				p.innerHTML = locations[nearbys].stringLocation;
				// listener for click event which will
				// change map src and searchBox input
				p.addEventListener("click", setInput);
				p.addEventListener("click", addNearbyBranch);
				p.addEventListener("click", loadMap);
				// Finally, append it
				container.appendChild(p);
			}
		}
	}
}

// Display nearby branches when the hint is clicked
searchBtn.onclick = addNearbyBranch;

searchBox.onkeyup = function () {
	// Store value of search box first
	// since when we call the displayHints function, "this" inside it
	// will refer to the anonymous function
	var that = this.value;
	displayHints(that);
};

// Google Map
function loadMap(url) {
	// Get map container
	var map = document.getElementById("google-map");
	// Check if url argument is not undefined, if so, set map src = url
	if (url !== undefined) map.src = "https://www.google.com/maps/embed?" + url;
	// Else, find a match between searchBox input and locations
	for (var i = 0, len = locations.length; i < len; i++) {
		if (searchBox.value == locations[i].stringLocation) {
			// When match is found, set iframe's src to current "locations" src
			// Set src
			map.src = "https://www.google.com/maps/embed?" + locations[i].src;
			break;
		}
	}
}
<commit_msg>Add another click eventlistener in searchBtn<commit_after>// Access search box
var searchBox = document.getElementById("search-box");

// Access search button
var searchBtn = document.getElementById("search-button");

// Get JSON file via AJAX request
var xhttp = new XMLHttpRequest(),
	locations;
xhttp.onreadystatechange = function () {
	if (xhttp.readyState == 4 && xhttp.status == 200) {
		// Convert responseText to JSON and store in "locations"
		locations = JSON.parse(xhttp.responseText);
		// Load all branches
		loadMap("pb=!1m12!1m8!1m3!1d15440.032333793673!2d120.98674643710937" +
			"!3d14.655482563301007!3m2!1i1024!2i768!4f13.1!2m1!1slbc" +
			"!5e0!3m2!1sen!2sph!4v1444102396793");
	}
};
xhttp.open("GET", "js/locations.json", true);
xhttp.send(null);

// Change search box value
function setInput() {
	// Remove the strong elements before setting input
	var str = this.innerHTML.replace("", "");
	str = str.replace("", "");
	searchBox.value = str;
	document.getElementById("search-hints").innerHTML = null;
	// Reset pos to 0
	pos = 0;
}

// Call this function everytime the user input a character in search box
function displayHints(str) {
	if (window.event.which == 38 || window.event.which == 40 ||
		window.event.which == 13) return false;
	// Access search hints box, then make it empty
	// So previous searches will be cleared
	var hints = document.getElementById("search-hints");
	hints.innerHTML = null;
	// If search box value is empty, stop further execution of code
	if (str === "") return false;
	// "str" argument is the search box value
	var pattern = new RegExp(str, "i");
	// Loop throught the "locations" array
	for (var i = 0, len = locations.length; i < len; i++) {
		var currentItem = locations[i].stringLocation;
		// Search for pattern
		var match = currentItem.search(pattern);
		// If a match is found
		if (match !== -1) {
			// Create a "p" element
			var p = document.createElement("p");
			// Set "p" content equal to current item inside location array
			p.innerHTML = currentItem.substr(0, match);
			// Highlight the matched string
			p.innerHTML += "" +
				currentItem.substr(match, searchBox.value.length) +
				"";
			// Add the remaining string
			p.innerHTML += currentItem.substr(match + searchBox.value.length, currentItem.length);
			// Display the p element
			hints.appendChild(p);
		}
	}

	// Get all displayed hints
	var pHints = hints.querySelectorAll("p");
	// If there's a hint displayed, set bgcolor of the first one to light green
	if (pHints.length !== 0) pHints[0].style.background = "#efd";
	// Listen for click event to all hints displayed
	for (i = 0, len = pHints.length; i < len; i++) {
		pHints[i].addEventListener("click", setInput);
	}
}

var pos = 0; // For tracking pHints position

function highlightText() {
	// Get all displayed hints
	var pHints = document.querySelectorAll("#search-hints p");
	// If there is no hints displayed, STOP
	if (pHints === undefined || pHints.length === 0) return false;

	// Change all pHints background to white
	for (var i = 0, len = pHints.length; i < len; i++) {
		pHints[i].style.background = "#fdfdfd";
	}

	// When up arrow key (38) is press
	if (window.event.which == 38) {
		if (pos > 0) pos--; // Prevent negative numbers
		pHints[pos].style.background = "#efd";
		pHints[pos].scrollIntoView();
		// or down arrow key (40) is press
	} else if (window.event.which == 40) {
		// Prevent numbers higher than no. of displayed hints
		if (pos < pHints.length - 1) pos++;
		pHints[pos].style.background = "#efd";
		pHints[pos].scrollIntoView();
		// or enter key (13) is press
	} else if (window.event.which == 13) {
		setInput.call(pHints[pos]);
		// Add nearby branches
		addNearbyBranch();
		// Load map
		loadMap();
		// Reset pos to 0
		pos = 0;
	}

}

// Call highlightText function in each keydown
document.body.addEventListener("keydown", highlightText);

function addNearbyBranch() {
	// Loop throught locations array and check for match with searchBox content
	var content = searchBox.value;
	// Get nearby branch section
	var container = document.getElementById("nearby-branch");
	// If value of searchbox is empty
	if (content === "") {
		// Display "no nearby branches"
		container.innerHTML = "
Nearby branches
";
		container.innerHTML += "
No nearby branches
";
		return false; // Then STOP
	}
	// If search-box has input value, loop throught "locations"
	for (var i = 0, len = locations.length; i < len; i++) {
		// Check if search-box value is equal to current "locations".stringlocation
		if (content == locations[i].stringLocation) {
			// Add heading first
			container.innerHTML = "
Nearby branches
";
			// Get nearbyNum property value
			var nearbyNum = locations[i].nearbyLocations.length;
			// Loop through it
			for (var j = 0; j < nearbyNum; j++) {
				// J = nearbyNum item position
				var nearbys = locations[i].nearbyLocations[j];
				// Generate a p element containing the stringLocation
				var p = document.createElement("p");
				p.innerHTML = locations[nearbys].stringLocation;
				// listener for click event which will
				// change map src and searchBox input
				p.addEventListener("click", setInput);
				p.addEventListener("click", addNearbyBranch);
				p.addEventListener("click", loadMap);
				// Finally, append it
				container.appendChild(p);
			}
		}
	}
}

// Display nearby branches and change map src based on searchbox value
// when the hint is clicked
searchBtn.addEventListener("click", addNearbyBranch);
searchBtn.addEventListener("click", loadMap);

searchBox.onkeyup = function () {
	// Store value of search box first
	// since when we call the displayHints function, "this" inside it
	// will refer to the anonymous function
	var that = this.value;
	displayHints(that);
};

// Google Map
function loadMap(url) {
	// Get map container
	var map = document.getElementById("google-map");
	// Check if url argument is not undefined, if so, set map src = url
	if (url !== undefined) map.src = "https://www.google.com/maps/embed?" + url;
	// Else, find a match between searchBox input and locations
	for (var i = 0, len = locations.length; i < len; i++) {
		if (searchBox.value == locations[i].stringLocation) {
			// When match is found, set iframe's src to current "locations" src
			// Set src
			map.src = "https://www.google.com/maps/embed?" + locations[i].src;
			break;
		}
	}
}
<|endoftext|>