<commit_before>OV.File = class
{
	constructor (file, source)
	{
		this.source = source;
		if (source === OV.FileSource.Url) {
			this.fileUrl = file;
			this.fileObject = null;
			this.name = OV.GetFileName (file);
			this.extension = OV.GetFileExtension (file);
		} else if (source === OV.FileSource.File) {
			this.fileUrl = null;
			this.fileObject = file;
			this.name = OV.GetFileName (file.name);
			this.extension = OV.GetFileExtension (file.name);
		}
		this.content = null;
	}
};

OV.FileList = class
{
	constructor (importers)
	{
		this.files = [];
		this.importers = importers;
	}

	FillFromFileUrls (fileList)
	{
		this.Fill (fileList, OV.FileSource.Url);
	}

	FillFromFileObjects (fileList)
	{
		this.Fill (fileList, OV.FileSource.File);
	}

	ExtendFromFileList (files)
	{
		for (let i = 0; i < files.length; i++) {
			let file = files[i];
			if (!this.ContainsFileByPath (file.name)) {
				this.files.push (file);
			}
		}
	}

	GetFiles ()
	{
		return this.files;
	}

	GetContent (onReady)
	{
		let obj = this;
		let taskRunner = new OV.TaskRunner ();
		taskRunner.Run (this.files.length, {
			runTask : function (index, complete) {
				obj.GetFileContent (obj.files[index], complete);
			},
			onReady : onReady
		});
	}

	ContainsFileByPath (filePath)
	{
		return this.FindFileByPath (filePath) !== null;
	}

	FindFileByPath (filePath)
	{
		let fileName = OV.GetFileName (filePath).toLowerCase ();
		for (let fileIndex = 0; fileIndex < this.files.length; fileIndex++) {
			let file = this.files[fileIndex];
			if (file.name.toLowerCase () === fileName) {
				return file;
			}
		}
		return null;
	}

	HasMainFile ()
	{
		return this.GetMainFile () !== null;
	}

	GetMainFile ()
	{
		for (let fileIndex = 0; fileIndex < this.files.length; fileIndex++) {
			let file = this.files[fileIndex];
			let importer = this.FindImporter (file);
			if (importer !== null) {
				return {
					file : file,
					importer : importer
				};
			}
		}
		return null;
	}

	IsOnlySource (source)
	{
		if (this.files.length === 0) {
			return false;
		}
		for (let i = 0; i < this.files.length; i++) {
			let file = this.files[i];
			if (file.source !== source) {
				return false;
			}
		}
		return true;
	}

	Fill (fileList, fileSource)
	{
		this.files = [];
		for (let fileIndex = 0; fileIndex < fileList.length; fileIndex++) {
			let fileObject = fileList[fileIndex];
			let file = new OV.File (fileObject, fileSource);
			this.AddFile (file);
		}
	}

	AddFile (file)
	{
		this.files.push (file);
	}

	GetFileContent (file, complete)
	{
		let callbacks = {
			success : function (content) {
				file.content = content;
			},
			error : function () {

			},
			complete : function () {
				complete ();
			}
		};
		if (file.content !== null) {
			complete ();
			return;
		}
		let format = this.GetFileFormat (file);
		if (file.source === OV.FileSource.Url) {
			OV.RequestUrl (file.fileUrl, format, callbacks);
		} else if (file.source === OV.FileSource.File) {
			OV.ReadFile (file.fileObject, format, callbacks);
		}
	}

	GetFileFormat (file)
	{
		for (let importerIndex = 0; importerIndex < this.importers.length; importerIndex++) {
			let importer = this.importers[importerIndex];
			let extension = file.extension.toLowerCase ();
			let knownFormats = importer.GetKnownFileFormats ();
			if (knownFormats[extension] !== undefined) {
				return knownFormats[extension];
			}
		}
		return OV.FileFormat.Binary;
	}

	FindImporter (file)
	{
		for (let importerIndex = 0; importerIndex < this.importers.length; importerIndex++) {
			let importer = this.importers[importerIndex];
			if (importer.CanImportExtension (file.extension.toLowerCase ())) {
				return importer;
			}
		}
		return null;
	}
};

OV.RevokeModelUrls = function (model)
{
	if (model === null) {
		return;
	}
	for (let i = 0; i < model.MaterialCount (); i++) {
		let material = model.GetMaterial (i);
		material.EnumerateTextureMaps (function (texture) {
			if (texture.url !== null) {
				OV.RevokeObjectUrl (texture.url);
			}
		});
	}
};

OV.ImportErrorCode =
{
	NoImportableFile : 1,
	ImportFailed : 2,
	UnknownError : 3
};

OV.ImportError = class
{
	constructor (code, message)
	{
		this.code = code;
		this.message = message;
	}
};

OV.ImportResult = class
{
	constructor ()
	{
		this.model = null;
		this.mainFile = null;
		this.upVector = null;
		this.usedFiles = [];
		this.missingFiles = [];
	}
};

OV.ImporterBuffers = class
{
    constructor (getBufferCallback)
    {
        this.getBufferCallback = getBufferCallback;
        this.fileBuffers = {};
        this.textureBuffers = {};
    }

    GetFileBuffer (filePath)
    {
        let fileName = OV.GetFileName (filePath);
        let buffer = this.fileBuffers[fileName];
        if (buffer === undefined) {
            buffer = this.getBufferCallback (fileName);
            this.fileBuffers[fileName] = buffer;
        }
        return buffer;
    }

    GetTextureBuffer (filePath)
    {
        let fileName = OV.GetFileName (filePath);
        let buffer = this.textureBuffers[fileName];
        if (buffer === undefined) {
            let texBuffer = this.getBufferCallback (fileName);
            if (texBuffer !== null) {
                buffer = {
                    url : OV.CreateObjectUrl (texBuffer),
                    buffer : texBuffer
                };
            } else {
                buffer = null;
            }
            this.textureBuffers[fileName] = buffer;
        }
        return buffer;
    }
};

OV.Importer = class
{
	constructor ()
	{
		this.importers = [
			new OV.ImporterObj (),
			new OV.ImporterStl (),
			new OV.ImporterOff (),
			new OV.ImporterPly (),
			new OV.Importer3ds (),
			new OV.ImporterGltf ()
		];
		this.fileList = new OV.FileList (this.importers);
		this.missingFiles = [];
	}

	LoadFilesFromUrls (fileList, onReady)
	{
		this.LoadFiles (fileList, OV.FileSource.Url, onReady);
	}

	LoadFilesFromFileObjects (fileList, onReady)
	{
		this.LoadFiles (fileList, OV.FileSource.File, onReady);
	}

	Import (callbacks)
	{
		let mainFile = this.fileList.GetMainFile ();
		if (mainFile === null || mainFile.file === null || mainFile.file.content === null) {
			callbacks.error (new OV.ImportError (OV.ImportErrorCode.NoImportableFile, null));
			return;
		}

		let result = new OV.ImportResult ();
		result.mainFile = mainFile.file.name;
		result.usedFiles.push (mainFile.file.name);

		let obj = this;
		let importer = mainFile.importer;
		let buffers = new OV.ImporterBuffers (function (fileName) {
			let fileBuffer = null;
			let file = obj.fileList.FindFileByPath (fileName);
			if (file === null || file.content === null) {
				result.missingFiles.push (fileName);
				obj.missingFiles.push (fileName);
				fileBuffer = null;
			} else {
				result.usedFiles.push (fileName);
				fileBuffer = file.content;
			}
			return fileBuffer;
		});

		importer.Import (mainFile.file.content, mainFile.file.extension, {
			getDefaultMaterial : function () {
				let material = new OV.Material ();
				material.diffuse = new OV.Color (200, 200, 200);
				return material;
			},
			getFileBuffer : function (filePath) {
				return buffers.GetFileBuffer (filePath);
			},
			getTextureBuffer : function (filePath) {
				return buffers.GetTextureBuffer (filePath);
			}
		});

		if (importer.IsError ()) {
			let message = importer.GetMessage ();
			callbacks.error (new OV.ImportError (OV.ImportErrorCode.ImportFailed, message));
			return;
		}

		result.model = importer.GetModel ();
		result.model.SetName (mainFile.file.name);
		result.upVector = importer.GetUpDirection ();
		callbacks.success (result);
	}

	LoadFiles (fileList, fileSource, onReady)
	{
		let newFileList = new OV.FileList (this.importers);
		if (fileSource === OV.FileSource.Url) {
			newFileList.FillFromFileUrls (fileList);
		} else if (fileSource === OV.FileSource.File) {
			newFileList.FillFromFileObjects (fileList);
		}
		let reset = false;
		if (newFileList.HasMainFile ()) {
			reset = true;
		} else {
			let foundMissingFile = false;
			for (let i = 0; i < this.missingFiles.length; i++) {
				let missingFile = this.missingFiles[i];
				if (newFileList.ContainsFileByPath (missingFile)) {
					foundMissingFile = true;
				}
			}
			if (!foundMissingFile) {
				reset = true;
			} else {
				let newFiles = newFileList.GetFiles ();
				this.fileList.ExtendFromFileList (newFiles);
				reset = false;
			}
		}
		if (reset) {
			this.fileList = newFileList;
		}
		this.missingFiles = [];
		this.fileList.GetContent (function () {
			onReady ();
		});
	}

	GetFileList ()
	{
		return this.fileList;
	}

	IsOnlyFileSource (source)
	{
		return this.fileList.IsOnlySource (source);
	}
};
<commit_msg>Minor modification.<commit_after>OV.File = class
{
	constructor (file, source)
	{
		this.source = source;
		if (source === OV.FileSource.Url) {
			this.fileUrl = file;
			this.fileObject = null;
			this.name = OV.GetFileName (file);
			this.extension = OV.GetFileExtension (file);
		} else if (source === OV.FileSource.File) {
			this.fileUrl = null;
			this.fileObject = file;
			this.name = OV.GetFileName (file.name);
			this.extension = OV.GetFileExtension (file.name);
		}
		this.content = null;
	}
};

OV.FileList = class
{
	constructor (importers)
	{
		this.files = [];
		this.importers = importers;
	}

	FillFromFileUrls (fileList)
	{
		this.Fill (fileList, OV.FileSource.Url);
	}

	FillFromFileObjects (fileList)
	{
		this.Fill (fileList, OV.FileSource.File);
	}

	ExtendFromFileList (files)
	{
		for (let i = 0; i < files.length; i++) {
			let file = files[i];
			if (!this.ContainsFileByPath (file.name)) {
				this.files.push (file);
			}
		}
	}

	GetFiles ()
	{
		return this.files;
	}

	GetContent (onReady)
	{
		let obj = this;
		let taskRunner = new OV.TaskRunner ();
		taskRunner.Run (this.files.length, {
			runTask : function (index, complete) {
				obj.GetFileContent (obj.files[index], complete);
			},
			onReady : onReady
		});
	}

	ContainsFileByPath (filePath)
	{
		return this.FindFileByPath (filePath) !== null;
	}

	FindFileByPath (filePath)
	{
		let fileName = OV.GetFileName (filePath).toLowerCase ();
		for (let fileIndex = 0; fileIndex < this.files.length; fileIndex++) {
			let file = this.files[fileIndex];
			if (file.name.toLowerCase () === fileName) {
				return file;
			}
		}
		return null;
	}

	HasMainFile ()
	{
		return this.GetMainFile () !== null;
	}

	GetMainFile ()
	{
		for (let fileIndex = 0; fileIndex < this.files.length; fileIndex++) {
			let file = this.files[fileIndex];
			let importer = this.FindImporter (file);
			if (importer !== null) {
				return {
					file : file,
					importer : importer
				};
			}
		}
		return null;
	}

	IsOnlySource (source)
	{
		if (this.files.length === 0) {
			return false;
		}
		for (let i = 0; i < this.files.length; i++) {
			let file = this.files[i];
			if (file.source !== source) {
				return false;
			}
		}
		return true;
	}

	Fill (fileList, fileSource)
	{
		this.files = [];
		for (let fileIndex = 0; fileIndex < fileList.length; fileIndex++) {
			let fileObject = fileList[fileIndex];
			let file = new OV.File (fileObject, fileSource);
			this.AddFile (file);
		}
	}

	AddFile (file)
	{
		this.files.push (file);
	}

	GetFileContent (file, complete)
	{
		let callbacks = {
			success : function (content) {
				file.content = content;
			},
			error : function () {

			},
			complete : function () {
				complete ();
			}
		};
		if (file.content !== null) {
			complete ();
			return;
		}
		let format = this.GetFileFormat (file);
		if (file.source === OV.FileSource.Url) {
			OV.RequestUrl (file.fileUrl, format, callbacks);
		} else if (file.source === OV.FileSource.File) {
			OV.ReadFile (file.fileObject, format, callbacks);
		}
	}

	GetFileFormat (file)
	{
		for (let importerIndex = 0; importerIndex < this.importers.length; importerIndex++) {
			let importer = this.importers[importerIndex];
			let extension = file.extension.toLowerCase ();
			let knownFormats = importer.GetKnownFileFormats ();
			if (knownFormats[extension] !== undefined) {
				return knownFormats[extension];
			}
		}
		return OV.FileFormat.Binary;
	}

	FindImporter (file)
	{
		for (let importerIndex = 0; importerIndex < this.importers.length; importerIndex++) {
			let importer = this.importers[importerIndex];
			if (importer.CanImportExtension (file.extension.toLowerCase ())) {
				return importer;
			}
		}
		return null;
	}
};

OV.RevokeModelUrls = function (model)
{
	if (model === null) {
		return;
	}
	for (let i = 0; i < model.MaterialCount (); i++) {
		let material = model.GetMaterial (i);
		material.EnumerateTextureMaps (function (texture) {
			if (texture.url !== null) {
				OV.RevokeObjectUrl (texture.url);
			}
		});
	}
};

OV.ImportErrorCode =
{
	NoImportableFile : 1,
	ImportFailed : 2,
	UnknownError : 3
};

OV.ImportError = class
{
	constructor (code, message)
	{
		this.code = code;
		this.message = message;
	}
};

OV.ImportResult = class
{
	constructor ()
	{
		this.model = null;
		this.mainFile = null;
		this.upVector = null;
		this.usedFiles = [];
		this.missingFiles = [];
	}
};

OV.ImporterBuffers = class
{
    constructor (getBufferCallback)
    {
        this.getBufferCallback = getBufferCallback;
        this.fileBuffers = {};
        this.textureBuffers = {};
    }

    GetFileBuffer (filePath)
    {
        let fileName = OV.GetFileName (filePath);
        let buffer = this.fileBuffers[fileName];
        if (buffer === undefined) {
            buffer = this.getBufferCallback (fileName);
            this.fileBuffers[fileName] = buffer;
        }
        return buffer;
    }

    GetTextureBuffer (filePath)
    {
        let fileName = OV.GetFileName (filePath);
        let buffer = this.textureBuffers[fileName];
        if (buffer === undefined) {
            let textureBuffer = this.getBufferCallback (fileName);
            if (textureBuffer !== null) {
                buffer = {
                    url : OV.CreateObjectUrl (textureBuffer),
                    buffer : textureBuffer
                };
            } else {
                buffer = null;
            }
            this.textureBuffers[fileName] = buffer;
        }
        return buffer;
    }
};

OV.Importer = class
{
	constructor ()
	{
		this.importers = [
			new OV.ImporterObj (),
			new OV.ImporterStl (),
			new OV.ImporterOff (),
			new OV.ImporterPly (),
			new OV.Importer3ds (),
			new OV.ImporterGltf ()
		];
		this.fileList = new OV.FileList (this.importers);
		this.missingFiles = [];
	}

	LoadFilesFromUrls (fileList, onReady)
	{
		this.LoadFiles (fileList, OV.FileSource.Url, onReady);
	}

	LoadFilesFromFileObjects (fileList, onReady)
	{
		this.LoadFiles (fileList, OV.FileSource.File, onReady);
	}

	Import (callbacks)
	{
		let mainFile = this.fileList.GetMainFile ();
		if (mainFile === null || mainFile.file === null || mainFile.file.content === null) {
			callbacks.error (new OV.ImportError (OV.ImportErrorCode.NoImportableFile, null));
			return;
		}

		let result = new OV.ImportResult ();
		result.mainFile = mainFile.file.name;
		result.usedFiles.push (mainFile.file.name);

		let obj = this;
		let importer = mainFile.importer;
		let buffers = new OV.ImporterBuffers (function (fileName) {
			let fileBuffer = null;
			let file = obj.fileList.FindFileByPath (fileName);
			if (file === null || file.content === null) {
				obj.missingFiles.push (fileName);
				result.missingFiles.push (fileName);
				fileBuffer = null;
			} else {
				fileBuffer = file.content;
				result.usedFiles.push (fileName);
			}
			return fileBuffer;
		});

		importer.Import (mainFile.file.content, mainFile.file.extension, {
			getDefaultMaterial : function () {
				let material = new OV.Material ();
				material.diffuse = new OV.Color (200, 200, 200);
				return material;
			},
			getFileBuffer : function (filePath) {
				return buffers.GetFileBuffer (filePath);
			},
			getTextureBuffer : function (filePath) {
				return buffers.GetTextureBuffer (filePath);
			}
		});

		if (importer.IsError ()) {
			let message = importer.GetMessage ();
			callbacks.error (new OV.ImportError (OV.ImportErrorCode.ImportFailed, message));
			return;
		}

		result.model = importer.GetModel ();
		result.model.SetName (mainFile.file.name);
		result.upVector = importer.GetUpDirection ();
		callbacks.success (result);
	}

	LoadFiles (fileList, fileSource, onReady)
	{
		let newFileList = new OV.FileList (this.importers);
		if (fileSource === OV.FileSource.Url) {
			newFileList.FillFromFileUrls (fileList);
		} else if (fileSource === OV.FileSource.File) {
			newFileList.FillFromFileObjects (fileList);
		}
		let reset = false;
		if (newFileList.HasMainFile ()) {
			reset = true;
		} else {
			let foundMissingFile = false;
			for (let i = 0; i < this.missingFiles.length; i++) {
				let missingFile = this.missingFiles[i];
				if (newFileList.ContainsFileByPath (missingFile)) {
					foundMissingFile = true;
				}
			}
			if (!foundMissingFile) {
				reset = true;
			} else {
				let newFiles = newFileList.GetFiles ();
				this.fileList.ExtendFromFileList (newFiles);
				reset = false;
			}
		}
		if (reset) {
			this.fileList = newFileList;
		}
		this.missingFiles = [];
		this.fileList.GetContent (function () {
			onReady ();
		});
	}

	GetFileList ()
	{
		return this.fileList;
	}

	IsOnlyFileSource (source)
	{
		return this.fileList.IsOnlySource (source);
	}
};
<|endoftext|>


<commit_before>#!/usr/bin/nodejs

'use strict';

//
// Required Modules
//

var fs = require('fs'),
	path = require('path'),
	process = require('process'),
	_ = require('lodash'),
	child_process = require('child_process');

//
// Find all images in current directory
//
var images = [];
console.log('Looking for boring images in ' + process.cwd());
_.forEach(fs.readdirSync(process.cwd()), function (node) {
	var matches = node.match(/.*\.(jpeg|jpg)$/);
	if (matches) {
		images.push(node);
	}
});

if (images.length < 2) {
	console.log('Failure! There need to be at least 2 images in the current directory');
	process.exit(50);
}

//
// Process all images, looking for "boring" images that
// have few pixel changes.
//
for (var i=1; i < images.length; i++) {
	(function () {
		var delta,
			output,
			prev = images[i-1],
			curr = images[i];

		output = child_process.spawnSync('compare', [
			'-metric', 'AE',
			'-fuzz', '50%',
			prev, curr
		]);

		delta = parseInt(output);

//		output = child_process.spawnSync('compare', {
//			'-metric', 'MAE',
//			prev, curr
//		});
//		deltaMAE = parseInt(output);

		if (delta < 1000) {
			// this image is boring, rename it as such
			var oldName = curr.match(/^(.+)\.(jpeg|jpg)$/),
				newName = oldName[1] + '-BORING.' + oldName[2];

			fs.renameSync(
				path.join(process.cwd(), curr),
				path.join(process.cwd(), newName)
			);
		}
	})();
} // for(...)
<commit_msg>Make bordem functional<commit_after>#!/usr/bin/nodejs

'use strict';

//
// Required Modules
//

var fs = require('fs'),
	path = require('path'),
	process = require('process'),
	_ = require('lodash'),
	child_process = require('child_process');

//
// Find all images in current directory
//
var images = [];
console.log('Looking for boring images in ' + process.cwd());
_.forEach(fs.readdirSync(process.cwd()), function (node) {
	var matches = node.match(/.*\.(jpeg|jpg)$/);
	if (matches) {
		images.push(node);
	}
});

if (images.length < 2) {
	console.log('Failure! There need to be at least 2 images in the current directory');
	process.exit(50);
}

var TOTAL_IMAGES = images.length;

//
// Process all images, looking for "boring" images that
// have few pixel changes.
//
var boringImages = [],
		prevImage = images[0];
for (var i=1; i < TOTAL_IMAGES; i++) {
	(function () {
		console.log('Analyzing ' + (i+1) + '/' + TOTAL_IMAGES + '...');

		var delta,
			result,
			output,
			curr = images[i];

		result = child_process.spawnSync('compare', [
			'-metric', 'AE',
			'-fuzz', '35%',
			prevImage, curr, '/dev/null'
		], {
			'encoding': 'utf8'
		});

		output = result.output;
		delta = parseInt(output[2]);

		console.log(prevImage + ' -> ' + curr + ' delta: ', delta);

		if (delta < 50) {
			boringImages.push(curr);
		} else {
			// save this image as the previously updated image
			prevImage = curr;
		}

	})();
} // for(...)

//
// Rename all boring images
//
console.log('Found ' + boringImages.length + ' boring images');
_.forEach(boringImages, function (boringImage) {
	var oldName = boringImage.match(/^(.+)\.(jpeg|jpg)$/),
		newName = oldName[1] + '-BORING.' + oldName[2];

	fs.renameSync(
		path.join(process.cwd(), boringImage),
		path.join(process.cwd(), newName)
	);
});
<|endoftext|>


<commit_before>var apiAccess = require('../config/apiAccess');

/*var apiAccess = {};
apiAccess.callUrl = function(url, funct){

	var request = new XMLHttpRequest();
	request.onreadystatechange = function(){
		if(request.readyState == 4 && request.status == 200){
			funct(request.responseText);
		}
	}
	request.open("GET", url, true);
	request.send(null);
}*/

/*
 * How to use -
 * First, use datesSet(); to check if the starting dates for the Pre and Reg season have been set
 * If false, call getFirstWeeks(Int curYear) to set them, where curYear is an integer representing the year of the season. That is, if the season starts in 2016, it would be the int 2015
 * To ensure that the dates have been set, due to asyncronity, ensure that datesSet() returns true before moving on
 *
 * Setup is now completed.
 * To get a set of games, call getGamesOnDate(Date date, boolean includeAllForWeek), where the date is a Date object representing the day which you want to retrieve games for, and includeAllForWeek is true only if you want to return all games for that week, instead of just for that day
 * This will populate GamesForWeek with the output data in an object of the form {date:The date supplied for retrieval, data:an array of game items}
 * You can retrieve what is stored in GamesForWeek using getRetrievedGameData(), but again due to asyncronity, verify that the date is accurate before proceeding with use.
 *
 * For now, don't trust the scores, also the scores are strings. Game object is as such:
 * {date:a Date representing the game day,
 * 	awayTeam:String represnting team nick(name),
 * 	awayScore:String representing whatever was stored on the page for the score,
 * 	homeTeam,
 * 	homeScore}
 *
 */

var PRE0Date;
var evalDate;
var REG1Date;
var GamesForWeek = {};
var TeamsForWeek = [];

//NOTE: WEEK ENDS ON MONDAY!
function constructScoreURI(season, part, week){
	//http://www.nfl.com/scores/2016/PRE0
	//season is year, part is PRE, REG, POST
	return "http://www.nfl.com/scores/"+season+"/"+part+week;
}

function constructYahooURI(url, element, attrType, attrValue){

	//http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url=%22http://www.nfl.com/schedules%22%20and%20
	//	xpath=%27//div[@class=%22schedules-list%22]%27&format=json

	var head = "http://query.yahooapis.com/v1/public/yql?q=select * from html where url=\"" + url + "\"";
	var xpath = constructXpath(element, attrType, attrValue);
	var jsonTail = '&format=json';

	return head + " and " + xpath + jsonTail;
}

function constructXpath(elementType, attributeType, attributeValue){
	return "xpath='//" + elementType + "[@" + attributeType + "=\"" + attributeValue + "\"]'";
}

function getFirstWeeks(currentYearInt){
	var queryFirstPRE = constructYahooURI("http://www.nfl.com/scores/2016/PRE0", "span", "title", "Date Airing");
	var queryFirstREG = constructYahooURI("http://www.nfl.com/scores/2016/REG1", "span", "title", "Date Airing");

	return Promise.all([apiAccess.callUrl(queryFirstPRE),apiAccess.callUrl(queryFirstREG)])
    .then(function(response){ preResponse(response[0]); regResponse(response[1]);});

    function preResponse(response){
      var json = JSON.parse(response);
      var spans = json.query.results.span;
      var item = spans[spans.length-1] || spans;
      var date = item.content

      date += " " + currentYearInt;

      date = new Date(date);
      //sets the date to be the next Monday, staying the same if it's already a monday
      date.setDate( date.getDate() + ((Math.abs( date.getDay() - 7 ) + 1)%7) );
      PRE0Date = date;
    }

    function regResponse(response){
      var json = JSON.parse(response);
      var spans = json.query.results.span;
      var item = spans[spans.length-1] || spans;
      var date = item.content;

      date += " " + currentYearInt;

      date = new Date(date);
      //sets the date to be the next Monday, staying the same if it's already a monday
      date.setDate( date.getDate() + ((Math.abs( date.getDay() - 7 ) + 1)%7) );
      REG1Date = date;//end of first week of Reg season
      evalDate = new Date(date);
      evalDate.setDate(evalDate.getDate()-7);//end of last week of presesason
    }

}

function datesSet(){
	return PRE0Date != null && REG1Date != null;
}

function getGamesOnDate(date, includeAllGamesForWeek){
	var oneDay = 24*60*60*1000; // hours*minutes*seconds*milliseconds
	var season = date.getYear() + 1900; //stupid epochs
	var part;
	var dateOfPart;
	var week;

	if(date <= evalDate){//Preseason
		part = "PRE";
		dateOfPart = PRE0Date;
	} else {
		part = "REG";
		dateOfPart = REG1Date;
	}
	//which week is it in?

	if(date <= dateOfPart){
		if(part=="PRE"){
			week = 1;
		} else {
			week = 1;
		}
	} else {
		//http://stackoverflow.com/questions/2627473/how-to-calculate-the-number-of-days-between-two-dates-using-javascript
		var diffDays = Math.round(Math.abs((date.getTime() - dateOfPart.getTime())/(oneDay)));
		var numWeeks = Math.round(diffDays / 7);
		week = 1+numWeeks;
	}

	var baseURI = constructScoreURI(season, part, week);
	var fullURI = constructYahooURI(baseURI, "div", "class", "scorebox-wrapper pre");

	return apiAccess.callUrl(fullURI)
    .then(function(response){

		var results = JSON.parse(response).query.results;

		output = results.div[0] ;
		//Date span is output.div[0].div.div[0].p.span[0];
		//TeamAway Nick is output.div[0].div.div[1].div[0].div.div.div.p[1].a.content
		//TeamAway totalScore is output.div[0].div.div[1].div[0].div.div.p.content
		//TeamHome Nick is output.div[0].div.div[1].div[1].div.div.div.p[1].a.content

		var gamesOnDay = [];

		for ( i in results.div ){
			var game = {};

			game.date = new Date( results.div[i].div[0].div.div[0].p.span[0].content + " " + (date.getYear() + 1900) )
			game.awayTeam = results.div[i].div[0].div.div[1].div[0].div.div.div.p[1].a.content;
			game.awayScore = results.div[i].div[0].div.div[1].div[0].div.div.p.content;
			game.homeTeam = results.div[i].div[0].div.div[1].div[1].div.div.div.p[1].a.content;
			game.homeScore = results.div[i].div[0].div.div[1].div[1].div.div.p.content

			if(!includeAllGamesForWeek){
				if(game.date == date){
					gamesOnDay.push(game);
          TeamsForWeek.push(game.awayTeam, game.homeTeam);
				}
			} else {
        if(!(game.date.getDay() == 4 || game.date.getDay() == 4)) {
          gamesOnDay.push(game);
          TeamsForWeek.push(game.awayTeam, game.homeTeam);
        }
			}
		}

		GamesForWeek.date = date;
		GamesForWeek.data = gamesOnDay;
    return Promise.resolve(GamesForWeek);
	});

}

function getRetrievedGameData(){
	return GamesForWeek;
}

function getTeams() {
  return TeamsForWeek;
}

module.exports = {
  datesSet: datesSet,
  getFirstWeeks: getFirstWeeks,
  getGamesOnDate: getGamesOnDate,
  getRetrievedGameData: getRetrievedGameData,
  getTeams: getTeams
};
<commit_msg>adding code to make it so we can get the winners<commit_after>var apiAccess = require('../config/apiAccess');

/*var apiAccess = {};
apiAccess.callUrl = function(url, funct){

	var request = new XMLHttpRequest();
	request.onreadystatechange = function(){
		if(request.readyState == 4 && request.status == 200){
			funct(request.responseText);
		}
	}
	request.open("GET", url, true);
	request.send(null);
}*/

/*
 * How to use -
 * First, use datesSet(); to check if the starting dates for the Pre and Reg season have been set
 * If false, call getFirstWeeks(Int curYear) to set them, where curYear is an integer representing the year of the season. That is, if the season starts in 2016, it would be the int 2015
 * To ensure that the dates have been set, due to asyncronity, ensure that datesSet() returns true before moving on
 *
 * Setup is now completed.
 * To get a set of games, call getGamesOnDate(Date date, boolean includeAllForWeek), where the date is a Date object representing the day which you want to retrieve games for, and includeAllForWeek is true only if you want to return all games for that week, instead of just for that day
 * This will populate GamesForWeek with the output data in an object of the form {date:The date supplied for retrieval, data:an array of game items}
 * You can retrieve what is stored in GamesForWeek using getRetrievedGameData(), but again due to asyncronity, verify that the date is accurate before proceeding with use.
 *
 * For now, don't trust the scores, also the scores are strings. Game object is as such:
 * {date:a Date representing the game day,
 * 	awayTeam:String represnting team nick(name),
 * 	awayScore:String representing whatever was stored on the page for the score,
 * 	homeTeam,
 * 	homeScore}
 *
 */

var PRE0Date;
var evalDate;
var REG1Date;
var GamesForWeek = {};
var TeamsForWeek = [];

//NOTE: WEEK ENDS ON MONDAY!
function constructScoreURI(season, part, week){
	//http://www.nfl.com/scores/2016/PRE0
	//season is year, part is PRE, REG, POST
	return "http://www.nfl.com/scores/"+season+"/"+part+week;
}

function constructYahooURI(url, element, attrType, attrValue){

	//http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url=%22http://www.nfl.com/schedules%22%20and%20
	//	xpath=%27//div[@class=%22schedules-list%22]%27&format=json

	var head = "http://query.yahooapis.com/v1/public/yql?q=select * from html where url=\"" + url + "\"";
	var xpath = constructXpath(element, attrType, attrValue);
	var jsonTail = '&format=json';

	return head + " and " + xpath + jsonTail;
}

function constructXpath(elementType, attributeType, attributeValue){
	return "xpath='//" + elementType + "[@" + attributeType + "=\"" + attributeValue + "\"]'";
}

function getFirstWeeks(currentYearInt){
	var queryFirstPRE = constructYahooURI("http://www.nfl.com/scores/2016/PRE0", "span", "title", "Date Airing");
	var queryFirstREG = constructYahooURI("http://www.nfl.com/scores/2016/REG1", "span", "title", "Date Airing");

	return Promise.all([apiAccess.callUrl(queryFirstPRE),apiAccess.callUrl(queryFirstREG)])
    .then(function(response){ preResponse(response[0]); regResponse(response[1]);});

    function preResponse(response){
      var json = JSON.parse(response);
      var spans = json.query.results.span;
      var item = spans[spans.length-1] || spans;
      var date = item.content

      date += " " + currentYearInt;

      date = new Date(date);
      //sets the date to be the next Monday, staying the same if it's already a monday
      date.setDate( date.getDate() + ((Math.abs( date.getDay() - 7 ) + 1)%7) );
      PRE0Date = date;
    }

    function regResponse(response){
      var json = JSON.parse(response);
      var spans = json.query.results.span;
      var item = spans[spans.length-1] || spans;
      var date = item.content;

      date += " " + currentYearInt;

      date = new Date(date);
      //sets the date to be the next Monday, staying the same if it's already a monday
      date.setDate( date.getDate() + ((Math.abs( date.getDay() - 7 ) + 1)%7) );
      REG1Date = date;//end of first week of Reg season
      evalDate = new Date(date);
      evalDate.setDate(evalDate.getDate()-7);//end of last week of presesason
    }

}

function datesSet(){
	return PRE0Date != null && REG1Date != null;
}

function getGamesOnDate(date, includeAllGamesForWeek, returnWinners){
	var oneDay = 24*60*60*1000; // hours*minutes*seconds*milliseconds
	var season = date.getYear() + 1900; //stupid epochs
	var part;
	var dateOfPart;
	var week;

	if(date <= evalDate){//Preseason
		part = "PRE";
		dateOfPart = PRE0Date;
	} else {
		part = "REG";
		dateOfPart = REG1Date;
	}
	//which week is it in?

	if(date <= dateOfPart){
		if(part=="PRE"){
			week = 1;
		} else {
			week = 1;
		}
	} else {
		//http://stackoverflow.com/questions/2627473/how-to-calculate-the-number-of-days-between-two-dates-using-javascript
		var diffDays = Math.round(Math.abs((date.getTime() - dateOfPart.getTime())/(oneDay)));
		var numWeeks = Math.round(diffDays / 7);
		week = 1+numWeeks;
	}

	var baseURI = constructScoreURI(season, part, week);
	var fullURI = constructYahooURI(baseURI, "div", "class", "scorebox-wrapper pre");

	return apiAccess.callUrl(fullURI)
    .then(function(response){

		var results = JSON.parse(response).query.results;

		output = results.div[0] ;
		//Date span is output.div[0].div.div[0].p.span[0];
		//TeamAway Nick is output.div[0].div.div[1].div[0].div.div.div.p[1].a.content
		//TeamAway totalScore is output.div[0].div.div[1].div[0].div.div.p.content
		//TeamHome Nick is output.div[0].div.div[1].div[1].div.div.div.p[1].a.content

		var gamesOnDay = [];
    var winningTeams = [];

		for ( i in results.div ){
			var game = {};

			game.date = new Date( results.div[i].div[0].div.div[0].p.span[0].content + " " + (date.getYear() + 1900) )
			game.awayTeam = results.div[i].div[0].div.div[1].div[0].div.div.div.p[1].a.content;
			game.awayScore = results.div[i].div[0].div.div[1].div[0].div.div.p.content;
			game.homeTeam = results.div[i].div[0].div.div[1].div[1].div.div.div.p[1].a.content;
			game.homeScore = results.div[i].div[0].div.div[1].div[1].div.div.p.content

      if(returnWinners) {

        winningTeams.push(getWinner(game));
      }

			if(!includeAllGamesForWeek){
				if(game.date == date){
					gamesOnDay.push(game);
          TeamsForWeek.push(game.awayTeam, game.homeTeam);
				}
			} else {
        if(!(game.date.getDay() == 4 || game.date.getDay() == 4)) {
          gamesOnDay.push(game);
          TeamsForWeek.push(game.awayTeam, game.homeTeam);
        }
			}
		}

		GamesForWeek.date = date;
		GamesForWeek.data = gamesOnDay;
    if(returnWinners) {
      GamesForWeek.data = winningTeams;
    }
    return Promise.resolve(GamesForWeek);
	});

}

function getWinner(game) {
  return (game.homeScore > game.awayScore) ? game.homeTeam : game.awayTeam;
}

function getRetrievedGameData(){
	return GamesForWeek;
}

function getTeams() {
  return TeamsForWeek;
}

module.exports = {
  datesSet: datesSet,
  getFirstWeeks: getFirstWeeks,
  getGamesOnDate: getGamesOnDate,
  getRetrievedGameData: getRetrievedGameData,
  getTeams: getTeams
};
<|endoftext|>


<commit_before>import React from 'react';
import { expect } from 'chai';
import { spy } from 'sinon';
import { shallow } from 'enzyme';
import { JSDOM } from 'jsdom';

import DomainTier from '../../../src/components/Character/DomainTier';
import Ability from '../../../src/components/Character/Ability';

const window = (new JSDOM('<!doctype html>')).window;
global.window = window;
global.document = window.document;
global.navigator = {
  userAgent: 'node.js',
};

function copyProps(src, target) {
  const props = Object.getOwnPropertyNames(src)
    .filter(prop => typeof target[prop] === 'undefined')
    .map(prop => Object.getOwnPropertyDescriptor(src, prop));
  Object.defineProperties(target, props);
}
copyProps(window, global);

describe('<DomainTier />', () => {
  it('renders a div with a span and an Ability component for each object in the abilities prop', () => {
    const view = spy(), update = spy();
    let list = [{
      id: 42,
      name: 'test'
    }];
    const wrapper = shallow(<DomainTier domain='test' tier={1} abilities={list} viewDescription={view} updateCharacterAbility={update}/>);
    expect(wrapper.find('div')).to.have.length(1);
    expect(wrapper.find('div').childAt(0).type()).to.equal('span');
    expect(wrapper.find('span')).to.have.length(1);
    expect(wrapper.find('div').childAt(1).type()).to.equal(Ability);
    expect(wrapper.find(Ability)).to.have.length(list.length);
    list = list.concat([{
      id: 7,
      name: 'lucky',
      display: 'checkbox',
      count: 11
    }, {
      id: 0,
      name: 'choice',
      display: 'tiers',
      count: 1
    }]);
    wrapper.setProps({abilities: list});
    expect(wrapper.find(Ability)).to.have.length(list.length);
  });

  it('renders a Ability component with the color prop based on the passed stones prop', () => {
    const view = spy(), update = spy();
    const list = [{
      id: 42,
      name: 'test'
    }, {
      id: 7,
      name: 'lucky',
      display: 'checkbox',
      count: 11
    }];
    const wrapper = shallow(<DomainTier domain='test' tier={1} abilities={list} viewDescription={view} updateCharacterAbility={update}/>);
    expect(wrapper.find(Ability).at(0).prop('id')).to.equal(list[0].id);
    expect(wrapper.find(Ability).at(0).prop('name')).to.equal(list[0].name);
    expect(wrapper.find(Ability).at(0).prop('display')).to.equal(undefined);
    expect(wrapper.find(Ability).at(0).prop('count')).to.equal(0);
    expect(wrapper.find(Ability).at(0).prop('viewDescription')).to.equal(view);
    expect(wrapper.find(Ability).at(0).prop('updateCharacterAbility')).to.equal(update);
    expect(wrapper.find(Ability).at(1).prop('id')).to.equal(list[1].id);
    expect(wrapper.find(Ability).at(1).prop('name')).to.equal(list[1].name);
    expect(wrapper.find(Ability).at(1).prop('display')).to.equal(list[1].display);
    expect(wrapper.find(Ability).at(1).prop('count')).to.equal(list[1].count);
    expect(wrapper.find(Ability).at(1).prop('viewDescription')).to.equal(view);
    expect(wrapper.find(Ability).at(1).prop('updateCharacterAbility')).to.equal(update);
  });
});
<commit_msg>corrected wording on a test<commit_after>import React from 'react';
import { expect } from 'chai';
import { spy } from 'sinon';
import { shallow } from 'enzyme';
import { JSDOM } from 'jsdom';

import DomainTier from '../../../src/components/Character/DomainTier';
import Ability from '../../../src/components/Character/Ability';

const window = (new JSDOM('<!doctype html>')).window;
global.window = window;
global.document = window.document;
global.navigator = {
  userAgent: 'node.js',
};

function copyProps(src, target) {
  const props = Object.getOwnPropertyNames(src)
    .filter(prop => typeof target[prop] === 'undefined')
    .map(prop => Object.getOwnPropertyDescriptor(src, prop));
  Object.defineProperties(target, props);
}
copyProps(window, global);

describe('<DomainTier />', () => {
  it('renders a div with a span and an Ability component for each object in the abilities prop', () => {
    const view = spy(), update = spy();
    let list = [{
      id: 42,
      name: 'test'
    }];
    const wrapper = shallow(<DomainTier domain='test' tier={1} abilities={list} viewDescription={view} updateCharacterAbility={update}/>);
    expect(wrapper.find('div')).to.have.length(1);
    expect(wrapper.find('div').childAt(0).type()).to.equal('span');
    expect(wrapper.find('span')).to.have.length(1);
    expect(wrapper.find('div').childAt(1).type()).to.equal(Ability);
    expect(wrapper.find(Ability)).to.have.length(list.length);
    list = list.concat([{
      id: 7,
      name: 'lucky',
      display: 'checkbox',
      count: 11
    }, {
      id: 0,
      name: 'choice',
      display: 'tiers',
      count: 1
    }]);
    wrapper.setProps({abilities: list});
    expect(wrapper.find(Ability)).to.have.length(list.length);
  });

  it('renders an Ability component with the propper props from the array object', () => {
    const view = spy(), update = spy();
    const list = [{
      id: 42,
      name: 'test'
    }, {
      id: 7,
      name: 'lucky',
      display: 'checkbox',
      count: 11
    }];
    const wrapper = shallow(<DomainTier domain='test' tier={1} abilities={list} viewDescription={view} updateCharacterAbility={update}/>);
    expect(wrapper.find(Ability).at(0).prop('id')).to.equal(list[0].id);
    expect(wrapper.find(Ability).at(0).prop('name')).to.equal(list[0].name);
    expect(wrapper.find(Ability).at(0).prop('display')).to.equal(undefined);
    expect(wrapper.find(Ability).at(0).prop('count')).to.equal(0);
    expect(wrapper.find(Ability).at(0).prop('viewDescription')).to.equal(view);
    expect(wrapper.find(Ability).at(0).prop('updateCharacterAbility')).to.equal(update);
    expect(wrapper.find(Ability).at(1).prop('id')).to.equal(list[1].id);
    expect(wrapper.find(Ability).at(1).prop('name')).to.equal(list[1].name);
    expect(wrapper.find(Ability).at(1).prop('display')).to.equal(list[1].display);
    expect(wrapper.find(Ability).at(1).prop('count')).to.equal(list[1].count);
    expect(wrapper.find(Ability).at(1).prop('viewDescription')).to.equal(view);
    expect(wrapper.find(Ability).at(1).prop('updateCharacterAbility')).to.equal(update);
  });
});
<|endoftext|>


<commit_before>/**
 * @fileOverview
 * Slides player.
 */
modules.define('shower.Player', [
    'event.Emitter',
    'util.extend',
    'util.bind'
], function (provide, EventEmitter, extend, bind) {

    /**
     * @name shower.Player
     * @constructor
     * @param {Shower} shower
     */
    function Player (shower) {
        this.events = new EventEmitter();

        this._shower = shower;
        this._currentSlideNumber = 0;
        this._currentSlide = null;
        this._playerLoop = null;

        this._init();
    }

    extend(Player.prototype, /** @lends shower.Player.prototype */ {
        /**
         * Next slide.
         * @returns {shower.Player}
         */
        next: function () {
            this._changeSlide(this._currentSlideNumber + 1);
            this.events.fire('next');

            return this;
        },

        /**
         * Prev slide.
         * @returns {shower.Player}
         */
        prev: function () {
            this._changeSlide(this._currentSlideNumber - 1);
            this.events.fire('prev');

            return this;
        },

        /**
         * Play slideshow.
         * @param {Object} [options] Play options.
         * @param {Number} [options.timeout = 2000]
         * @param {Number} [options.startIndex = 0]
         * @param {Number} [options.stopIndex]
         */
        play: function (options) {
            options = extend({
                timeout: 2000,
                startIndex: 0,
                stopIndex: this._shower.getSlidesCount()
            }, options || {});

            if (this._playerLoop) {
                this.stop();
            }
            this.setActive(options.startIndex);
            this._playerLoop = setInterval(bind(function () {
                if (this._currentSlideNumber == options.stopIndex) {
                    this.stop();
                } else {
                    this.next();
                }
            }, this), options.timeout);

            this.events.fire('play');
        },

        /**
         * Stop slideshow.
         */
        stop: function () {
            if (this._playerLoop) {
                stopInterval(this._playerLoop);
                this._playerLoop = null;
            }
            this.events.fire('stop');
        },

        /**
         * @param {Number} index Slide index to activate.
         * @returns {shower.Player}
         */
        setActive: function (index) {
            var slidesCount = this._shower.getSlidesCount();
            if (index < slidesCount && index >= 0) {
                if (this._currentSlide) {
                    this.setInavtive(this._currentSlideNumber);
                }
                this._currentSlide = this._shower.get(index);
                this._currentSlide.setActive();
                this._currentSlideNumber = index;

                this.events.fire('activate', {
                    index: index
                });
            }

            return this;
        },

        /**
         * @returns {Slide} Current slide.
         */
        getCurrentSlide: function () {
            return this._currentSlide;
        },

        /**
         * @returns {Number} Current slide index.
         */
        getCurrentSlideIndex: function () {
            return this._currentSlideNumber;
        },

        /**
         * @ignore
         * Init player state.
         */
        _init: function () {
            // get active slide
            // check init data
        },

        /**
         * @ignore
         * @param {Number} index Slide index.
         */
        _changeSlide: function (index) {
            this.setActive(index);
            this._currentSlideNUmber = index;
            this.events.fire('slidechange');
        },

        _playSlides: function () {
            this.next();
        }
    });

    provide(Player);
});
<commit_msg>[Player] fix bugs: .play, .setActive<commit_after>/**
 * @fileOverview
 * Slides player.
 */
modules.define('shower.Player', [
    'event.Emitter',
    'util.extend',
    'util.bind'
], function (provide, EventEmitter, extend, bind) {

    /**
     * @class
     * @name shower.Player
     * @param {Shower} shower
     */
    function Player (shower) {
        this.events = new EventEmitter();

        this._shower = shower;
        this._currentSlideNumber = 0;
        this._currentSlide = null;
        this._playerLoop = null;

        this._init();
    }

    extend(Player.prototype, /** @lends shower.Player.prototype */ {
        /**
         * Next slide.
         * @returns {shower.Player}
         */
        next: function () {
            if (this._shower.getSlidesCount() < index) {
                this._changeSlide(this._currentSlideNumber + 1);
                this.events.fire('next');
            } else {
                if (this._playerLoop) {
                    this.stop();
                }
            }

            return this;
        },

        /**
         * Prev slide.
         * @returns {shower.Player}
         */
        prev: function () {
            this._changeSlide(this._currentSlideNumber - 1);
            this.events.fire('prev');

            return this;
        },

        /**
         * Play slideshow.
         * @param {Object} [options] Play options.
         * @param {Number} [options.timeout = 2000]
         * @param {Number} [options.startIndex = 0]
         * @param {Number} [options.stopIndex]
         */
        play: function (options) {
            options = extend({
                timeout: 2000,
                startIndex: 0,
                stopIndex: this._shower.getSlidesCount()
            }, options || {});

            if (this._playerLoop) {
                this.stop();
            }
            this.setActive(options.startIndex);
            this._playerLoop = setInterval(bind(this._playSlides, this), options.timeout);

            this.events.fire('play');
        },

        /**
         * Stop slideshow.
         */
        stop: function () {
            if (this._playerLoop) {
                clearInterval(this._playerLoop);
                this._playerLoop = null;
            }
            this.events.fire('stop');
        },

        /**
         * @param {Number} index Slide index to activate.
         * @returns {shower.Player}
         */
        setActive: function (index) {
            var slidesCount = this._shower.getSlidesCount(),
                currentSlide = this._currentSlide;

            if (index < slidesCount && index >= 0) {
                if (currentSlide) {
                    currentSlide.setInactive();
                }
                currentSlide = this._shower.get(index);
                currentSlide.setActive();

                this._currentSlide = currentSlide;
                this._currentSlideNumber = index;

                this.events.fire('activate', {
                    index: index
                });
            }

            return this;
        },

        /**
         * @returns {Slide} Current slide.
         */
        getCurrentSlide: function () {
            return this._currentSlide;
        },

        /**
         * @returns {Number} Current slide index.
         */
        getCurrentSlideIndex: function () {
            return this._currentSlideNumber;
        },

        /**
         * @ignore
         * Init player state.
         */
        _init: function () {
            // get active slide
            // check init data
        },

        /**
         * @ignore
         * @param {Number} index Slide index.
         */
        _changeSlide: function (index) {
            this.setActive(index);
            this.events.fire('slidechange');
        },

        _playSlides: function () {
            if (this._currentSlideNumber == options.stopIndex) {
                this.stop();
            } else {
                this.next();
            }
        },

        _deactivate: function (slideNumber) {

        }
    });

    provide(Player);
});
<|endoftext|>


<commit_before>//= require mice
//= require mice/jquery
//= require_tree .

// ZeroClipboard
ZeroClipboard.config( { moviePath: '/images/ZeroClipboard.swf' } );

$(function(){

});<commit_msg>Update doc.js<commit_after>//= require mice/jquery
//= require mice
//= require_tree .

// ZeroClipboard
ZeroClipboard.config( { moviePath: '/images/ZeroClipboard.swf' } );

$(function(){

  if($("body.mobile").size()){
    $(document).scroll(function() {
      console.log('scroll')
      //$('#window').contents().find('body').html($('#typography').next().next().text())
    });
  }
  //

});<|endoftext|>


<commit_before>define(['controllers/projects/taskRunner'], function () {
	app.registerController('ProjectTemplatesCtrl', ['$scope', '$http', '$uibModal', 'Project', '$rootScope', '$window', function ($scope, $http, $modal, Project, $rootScope, $window) {
		$http.get(Project.getURL() + '/keys?type=ssh').success(function (keys) {
			$scope.sshKeys = keys;

			$scope.sshKeysAssoc = {};
			keys.forEach(function (k) {
				if (k.removed) k.name = '[removed] - ' + k.name;
				$scope.sshKeysAssoc[k.id] = k;
			});
		});
		$http.get(Project.getURL() + '/inventory').success(function (inv) {
			$scope.inventory = inv;

			$scope.inventoryAssoc = {};
			inv.forEach(function (i) {
				if (i.removed) i.name = '[removed] - ' + i.name;
				$scope.inventoryAssoc[i.id] = i;
			});
		});
		$http.get(Project.getURL() + '/repositories').success(function (repos) {
			$scope.repos = repos;

			$scope.reposAssoc = {};
			repos.forEach(function (i) {
				if (i.removed) i.name = '[removed] - ' + i.name;

				$scope.reposAssoc[i.id] = i;
			});
		});
		$http.get(Project.getURL() + '/environment').success(function (env) {
			$scope.environment = env;

			$scope.environmentAssoc = {};
			env.forEach(function (i) {
				if (i.removed) i.name = '[removed] - ' + i.name;

				$scope.environmentAssoc[i.id] = i;
			});
		});

		function getHiddenTemplates() {
			try {
				return JSON.parse($window.localStorage.getItem('hidden-templates') || '[]');
			} catch(e) {
				return [];
			}
		}

		function setHiddenTemplates(hiddenTemplates) {
			$window.localStorage.setItem('hidden-templates', JSON.stringify(hiddenTemplates));
		}

    $scope.hasHiddenTemplates = function() {
      return getHiddenTemplates().length > 0;
    }

		$scope.reload = function () {
			$http.get(Project.getURL() + '/templates?sort=alias&order=asc').success(function (templates) {
				var hiddenTemplates = getHiddenTemplates();
				for (var i = 0; i < templates.length; i++) {
					var template = templates[i];
					if (hiddenTemplates.indexOf(template.id) !== -1) {
						template.hidden = true;
					}
				}
				$scope.templates = templates;
			});
		}

		$scope.remove = function (template) {
			$http.delete(Project.getURL() + '/templates/' + template.id).success(function () {
				$scope.reload();
			}).error(function () {
				swal('error', 'could not delete template..', 'error');
			});
		}

		$scope.add = function () {
			var scope = $rootScope.$new();
			scope.keys = $scope.sshKeys;
			scope.inventory = $scope.inventory;
			scope.repositories = $scope.repos;
			scope.environment = $scope.environment;

			$modal.open({
				templateUrl: '/tpl/projects/templates/add.html',
				scope: scope
			}).result.then(function (opts) {
				var tpl = opts.template;
				$http.post(Project.getURL() + '/templates', tpl).success(function () {
					$scope.reload();
				}).error(function (_, status) {
					swal('error', 'could not add template:' + status, 'error');
				});
			});
		}

		$scope.update = function (template) {
			var scope = $rootScope.$new();
			scope.tpl = template;
			scope.keys = $scope.sshKeys;
			scope.inventory = $scope.inventory;
			scope.repositories = $scope.repos;
			scope.environment = $scope.environment;

			$modal.open({
				templateUrl: '/tpl/projects/templates/add.html',
				scope: scope
			}).result.then(function (opts) {
				if (opts.remove) {
					return $scope.remove(template);
				}

				var tpl = opts.template;
				$http.put(Project.getURL() + '/templates/' + template.id, tpl).success(function () {
					$scope.reload();
				}).error(function (_, status) {
					swal('error', 'could not add template:' + status, 'error');
				});
			}).closed.then(function () {
				$scope.reload();
			});
		}

		$scope.run = function (tpl) {
			$modal.open({
				templateUrl: '/tpl/projects/createTaskModal.html',
				controller: 'CreateTaskCtrl',
				resolve: {
					Project: function () {
						return Project;
					},
					Template: function () {
						return tpl;
					}
				}
			}).result.then(function (task) {
				var scope = $rootScope.$new();
				scope.task = task;
				scope.project = Project;

				$modal.open({
					templateUrl: '/tpl/projects/taskModal.html',
					controller: 'TaskCtrl',
					scope: scope,
					size: 'lg'
				});
			})
		}

		$scope.showAll = function() {
			$scope.allShown = true;
		}

		$scope.hideHidden = function() {
			$scope.allShown = false;
		}

		$scope.hideTemplate = function(template) {
			var hiddenTemplates = getHiddenTemplates();
			if (hiddenTemplates.indexOf(template.id) === -1) {
				hiddenTemplates.push(template.id);
			}
			setHiddenTemplates(hiddenTemplates);
			template.hidden = true;
		}

		$scope.showTemplate = function(template) {
			var hiddenTemplates = getHiddenTemplates();
			var i = hiddenTemplates.indexOf(template.id);
			if (i !== -1) {
				hiddenTemplates.splice(i, 1);
			}
			setHiddenTemplates(hiddenTemplates);
			delete template.hidden;
		}

		$scope.copy = function (template) {
			var tpl = angular.copy(template);
			tpl.id = null;

			var scope = $rootScope.$new();
			scope.tpl = tpl;
			scope.keys = $scope.sshKeys;
			scope.inventory = $scope.inventory;
			scope.repositories = $scope.repos;
			scope.environment = $scope.environment;

			$modal.open({
				templateUrl: '/tpl/projects/templates/add.html',
				scope: scope
			}).result.then(function (opts) {
				var tpl = opts.template;
				$http.post(Project.getURL() + '/templates', tpl).success(function () {
					$scope.reload();
				}).error(function (_, status) {
					swal('error', 'could not add template:' + status, 'error');
				});
			});
		}

		$scope.reload();
	}]);
});
<commit_msg>style(template): use tabs instead of spaces<commit_after>define(['controllers/projects/taskRunner'], function () {
	app.registerController('ProjectTemplatesCtrl', ['$scope', '$http', '$uibModal', 'Project', '$rootScope', '$window', function ($scope, $http, $modal, Project, $rootScope, $window) {
		$http.get(Project.getURL() + '/keys?type=ssh').success(function (keys) {
			$scope.sshKeys = keys;

			$scope.sshKeysAssoc = {};
			keys.forEach(function (k) {
				if (k.removed) k.name = '[removed] - ' + k.name;
				$scope.sshKeysAssoc[k.id] = k;
			});
		});
		$http.get(Project.getURL() + '/inventory').success(function (inv) {
			$scope.inventory = inv;

			$scope.inventoryAssoc = {};
			inv.forEach(function (i) {
				if (i.removed) i.name = '[removed] - ' + i.name;
				$scope.inventoryAssoc[i.id] = i;
			});
		});
		$http.get(Project.getURL() + '/repositories').success(function (repos) {
			$scope.repos = repos;

			$scope.reposAssoc = {};
			repos.forEach(function (i) {
				if (i.removed) i.name = '[removed] - ' + i.name;

				$scope.reposAssoc[i.id] = i;
			});
		});
		$http.get(Project.getURL() + '/environment').success(function (env) {
			$scope.environment = env;

			$scope.environmentAssoc = {};
			env.forEach(function (i) {
				if (i.removed) i.name = '[removed] - ' + i.name;

				$scope.environmentAssoc[i.id] = i;
			});
		});

		function getHiddenTemplates() {
			try {
				return JSON.parse($window.localStorage.getItem('hidden-templates') || '[]');
			} catch(e) {
				return [];
			}
		}

		function setHiddenTemplates(hiddenTemplates) {
			$window.localStorage.setItem('hidden-templates', JSON.stringify(hiddenTemplates));
		}

		$scope.hasHiddenTemplates = function() {
			return getHiddenTemplates().length > 0;
		}

		$scope.reload = function () {
			$http.get(Project.getURL() + '/templates?sort=alias&order=asc').success(function (templates) {
				var hiddenTemplates = getHiddenTemplates();
				for (var i = 0; i < templates.length; i++) {
					var template = templates[i];
					if (hiddenTemplates.indexOf(template.id) !== -1) {
						template.hidden = true;
					}
				}
				$scope.templates = templates;
			});
		}

		$scope.remove = function (template) {
			$http.delete(Project.getURL() + '/templates/' + template.id).success(function () {
				$scope.reload();
			}).error(function () {
				swal('error', 'could not delete template..', 'error');
			});
		}

		$scope.add = function () {
			var scope = $rootScope.$new();
			scope.keys = $scope.sshKeys;
			scope.inventory = $scope.inventory;
			scope.repositories = $scope.repos;
			scope.environment = $scope.environment;

			$modal.open({
				templateUrl: '/tpl/projects/templates/add.html',
				scope: scope
			}).result.then(function (opts) {
				var tpl = opts.template;
				$http.post(Project.getURL() + '/templates', tpl).success(function () {
					$scope.reload();
				}).error(function (_, status) {
					swal('error', 'could not add template:' + status, 'error');
				});
			});
		}

		$scope.update = function (template) {
			var scope = $rootScope.$new();
			scope.tpl = template;
			scope.keys = $scope.sshKeys;
			scope.inventory = $scope.inventory;
			scope.repositories = $scope.repos;
			scope.environment = $scope.environment;

			$modal.open({
				templateUrl: '/tpl/projects/templates/add.html',
				scope: scope
			}).result.then(function (opts) {
				if (opts.remove) {
					return $scope.remove(template);
				}

				var tpl = opts.template;
				$http.put(Project.getURL() + '/templates/' + template.id, tpl).success(function () {
					$scope.reload();
				}).error(function (_, status) {
					swal('error', 'could not add template:' + status, 'error');
				});
			}).closed.then(function () {
				$scope.reload();
			});
		}

		$scope.run = function (tpl) {
			$modal.open({
				templateUrl: '/tpl/projects/createTaskModal.html',
				controller: 'CreateTaskCtrl',
				resolve: {
					Project: function () {
						return Project;
					},
					Template: function () {
						return tpl;
					}
				}
			}).result.then(function (task) {
				var scope = $rootScope.$new();
				scope.task = task;
				scope.project = Project;

				$modal.open({
					templateUrl: '/tpl/projects/taskModal.html',
					controller: 'TaskCtrl',
					scope: scope,
					size: 'lg'
				});
			})
		}

		$scope.showAll = function() {
			$scope.allShown = true;
		}

		$scope.hideHidden = function() {
			$scope.allShown = false;
		}

		$scope.hideTemplate = function(template) {
			var hiddenTemplates = getHiddenTemplates();
			if (hiddenTemplates.indexOf(template.id) === -1) {
				hiddenTemplates.push(template.id);
			}
			setHiddenTemplates(hiddenTemplates);
			template.hidden = true;
		}

		$scope.showTemplate = function(template) {
			var hiddenTemplates = getHiddenTemplates();
			var i = hiddenTemplates.indexOf(template.id);
			if (i !== -1) {
				hiddenTemplates.splice(i, 1);
			}
			setHiddenTemplates(hiddenTemplates);
			delete template.hidden;
		}

		$scope.copy = function (template) {
			var tpl = angular.copy(template);
			tpl.id = null;

			var scope = $rootScope.$new();
			scope.tpl = tpl;
			scope.keys = $scope.sshKeys;
			scope.inventory = $scope.inventory;
			scope.repositories = $scope.repos;
			scope.environment = $scope.environment;

			$modal.open({
				templateUrl: '/tpl/projects/templates/add.html',
				scope: scope
			}).result.then(function (opts) {
				var tpl = opts.template;
				$http.post(Project.getURL() + '/templates', tpl).success(function () {
					$scope.reload();
				}).error(function (_, status) {
					swal('error', 'could not add template:' + status, 'error');
				});
			});
		}

		$scope.reload();
	}]);
});
<|endoftext|>


<commit_before>/*
 * TODO: colors
 * TODO: rotation
 * TODO: line clearing
 * TODO: end state
 *
 */

const GRID = {
    DIMENSION: 30,
    WIDTH:     10,
    HEIGHT:    20
};

const COLORS = {
    RED:       "#e74c3c",
    ORANGE:    "#e67e22",
    GREEN:     "#2ecc71",
    BLUE:      "#3498db",
    PURPLE:    "#9b59b6",
    TURQUOISE: "#1abc9c",
    YELLOW:    "#f1c40f",
};

function Space(x, y, color = COLORS.BLUE) {
    return {
        x: x,
        y: y,
        color: color
    };
}

class Piece {
    constructor (shape, orientation, layout, color, x = 0, y = 0) {
        this.shape = shape;
        this.orientation = orientation;
        this.x = x;
        this.y = y;
        this.layout = layout;
        this.color = color;
    }

    get spaces() {
        return this.layout.map(
            space => Space(space.x + this.x, space.y + this.y, this.color)
        );
    }

    shifted(dx, dy) {
        return new Piece(this.shape, this.orientation, this.layout, this.color, this.x + dx, this.y + dy);
    }

    rotated(dx, dy) {
        let newOrientation = (this.orientation + 1) % 4;
        let newLayout = SHAPES[this.shape].orientations[newOrientation];
        return new Piece(this.shape, newOrientation, newLayout, this.color, this.x, this.y);
    }
}

const SHAPES = {
    O: {
        orientations: [
            [Space(0,0), Space(0,1), Space(1,0), Space(1,1)],
            [Space(0,0), Space(0,1), Space(1,0), Space(1,1)],
            [Space(0,0), Space(0,1), Space(1,0), Space(1,1)],
            [Space(0,0), Space(0,1), Space(1,0), Space(1,1)]
        ],
        color: COLORS.RED
    },
    J: {
        orientations: [
            [Space(0,0), Space(1,0), Space(2,0), Space(2,1)],
            [Space(1,0), Space(1,1), Space(1,2), Space(0,2)],
            [Space(0,0), Space(0,1), Space(1,1), Space(2,1)],
            [Space(0,0), Space(1,0), Space(0,1), Space(0,2)]
        ],
        color: COLORS.ORANGE
    },
    L: {
        orientations: [
            [Space(0,0), Space(1,0), Space(2,0), Space(0,1)],
            [Space(0,0), Space(1,0), Space(1,1), Space(1,2)],
            [Space(2,0), Space(0,1), Space(1,1), Space(2,1)],
            [Space(0,0), Space(0,1), Space(0,2), Space(1,2)]
        ],
        color: COLORS.GREEN
    },
    T: {
        orientations: [
            [Space(0,0), Space(0,1), Space(0,2), Space(1,1)],
            [Space(0,0), Space(1,0), Space(2,0), Space(1,1)],
            [Space(1,0), Space(1,1), Space(1,2), Space(0,1)],
            [Space(1,0), Space(0,1), Space(1,1), Space(2,1)]
        ],
        color: COLORS.YELLOW
    },
    Z: {
        orientations: [
            [Space(0,0), Space(1,0), Space(1,1), Space(2,1)],
            [Space(1,0), Space(0,1), Space(1,1), Space(0,2)],
            [Space(0,0), Space(1,0), Space(1,1), Space(2,1)],
            [Space(1,0), Space(0,1), Space(1,1), Space(0,2)]
        ],
        color: COLORS.PURPLE
    },
    S: {
        orientations: [
            [Space(0,0), Space(0,1), Space(1,1), Space(1,2)],
            [Space(1,0), Space(2,0), Space(0,1), Space(1,1)],
            [Space(0,0), Space(0,1), Space(1,1), Space(1,2)],
            [Space(1,0), Space(2,0), Space(0,1), Space(1,1)]
        ],
        color: COLORS.TURQUOISE
    },
    I: {
        orientations: [
            [Space(0,0), Space(1,0), Space(2,0), Space(3,0)],
            [Space(1,0), Space(1,1), Space(1,2), Space(1,3)],
            [Space(0,0), Space(1,0), Space(2,0), Space(3,0)],
            [Space(1,0), Space(1,1), Space(1,2), Space(1,3)],
        ],
        color: COLORS.BLUE
    },
};

function makeInitialState() {
    return {
        board: [],
        current: randomPiece(),
        next: randomPiece()
    };
}

function inXBounds(piece, gridwidth) {
    let bools = piece.spaces.map(square => 0 <= square.x && square.x < gridwidth);
    return bools.indexOf(false) == -1;
}

function colliding(piece, board) {
    let colliding = space => boardsquare => boardsquare.x == space.x && boardsquare.y == space.y;
    for (let i in piece.spaces) {
        let space = piece.spaces[i];
        // check for square collision
        let collision = board.find(colliding(space));
        if (collision) return true;
        // check for floor collision
        if (space.y >= GRID.HEIGHT) return true;
    }
    return false;
}

function randomPiece() {
    let keys = Object.keys(SHAPES);
    let idx = Math.floor(Math.random() * keys.length);
    let shape = SHAPES[keys[idx]];
    return new Piece(keys[idx], 0, shape.orientations[0], shape.color, 3, 0);
}

function validPiece(piece, board) {
    return inXBounds(piece, GRID.WIDTH) && !colliding(piece, board);
}

function shiftPiece(piece, board, dx, dy) {
    let newPiece = piece.shifted(dx, dy);
    if (!validPiece(newPiece, board)) {
        return piece;
    }
    return newPiece;
}

function clearRows(board) {
    let rowcounts = {};
    for (let i in board) {
        let space = board[i];
        rowcounts[space.y] = rowcounts[space.y] + 1 || 1;
    }
    let notInRow = row => space => space.y != row;
    let bumpSpaceDown = row => space => space.y < row ? new Space(space.x, space.y + 1, space.color) : space;
    for (let row in rowcounts) {
        if (rowcounts[row] >= GRID.WIDTH) {
            board = board.filter(notInRow(row));
            board = board.map(bumpSpaceDown(row));
        }
    }

    return board;
}

function validRotation(piece, board) {
    let rotated = piece.rotated();
    if (!validPiece(rotated, board)) {
        rotated = rotated.shifted(1, 0);
        if (!validPiece(rotated, board)) {
            rotated = rotated.shifted(-2, 0);
            if (!validPiece(rotated, board)) {
                rotated = state.current;
            }
        }
    }
    return rotated;
}

function mainState(state = makeInitialState(), action) {
    switch (action.type) {
        case 'TICK':
            let current = state.current;
            let newCurrent = new Piece(current.shape, current.orientation, current.layout, current.color, current.x, current.y + 1);
            if (colliding(newCurrent, state.board)) {
                let newboard = state.current.spaces.concat(state.board);
                newboard = clearRows(newboard);
                return Object.assign({}, state, {current: state.next, next: randomPiece(), board: newboard});
            }
            return Object.assign({}, state, {current: newCurrent});
        case 'MOVE_RIGHT':
            return Object.assign({}, state, {
                current: shiftPiece(state.current, state.board, 1, 0)
            });
        case 'MOVE_LEFT':
            return Object.assign({}, state, {
                current: shiftPiece(state.current, state.board, -1, 0)
            });
        case 'MOVE_DOWN':
            return Object.assign({}, state, {
                current: shiftPiece(state.current, state.board, 0, 1)
            });
        case 'ROTATE':
            return Object.assign({}, state, {
                current: validRotation(state.current, state.board)
            });
        default:
            return state;
    }
}

let store = Redux.createStore(mainState);

let canvas = document.getElementById("myCanvas");
canvas.width = GRID.DIMENSION * GRID.WIDTH;
canvas.height = GRID.DIMENSION * GRID.HEIGHT;
let ctx = canvas.getContext("2d");

document.addEventListener("keydown", keyDownHandler, false);

function keyDownHandler(event) {
    if (event.keyCode == 39) {
        store.dispatch({type: 'MOVE_RIGHT'});
    }
    else if (event.keyCode == 37) {
        store.dispatch({type: 'MOVE_LEFT'});
    }
    else if (event.keyCode == 40) {
        store.dispatch({type: 'MOVE_DOWN'});
    }
    else if (event.keyCode == 38) {
        store.dispatch({type: 'ROTATE'});
    }
}

function drawSpace(context, space) {
    let dim = GRID.DIMENSION;
    context.beginPath();
    context.rect(space.x*dim, space.y*dim, dim, dim);
    context.fillStyle = space.color;
    context.fill();
    context.closePath();
}
function drawPiece(context, shape) {
     let spaces = shape.spaces.map(space => drawSpace(context, space));
}
function drawState(context, state) {
    state.board.map(space => drawSpace(context, space));
    drawPiece(context, state.current);
}
function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawState(ctx, store.getState());
}
store.subscribe(draw);
setInterval(() => store.dispatch({type: 'TICK'}), 1000);
<commit_msg>Added scoring and score rendering<commit_after>/*
 * TODO: colors
 * TODO: rotation
 * TODO: line clearing
 * TODO: end state
 *
 */

const GRID = {
    DIMENSION: 30,
    WIDTH:     10,
    HEIGHT:    20
};

const COLORS = {
    RED:       "#e74c3c",
    ORANGE:    "#e67e22",
    GREEN:     "#2ecc71",
    BLUE:      "#3498db",
    PURPLE:    "#9b59b6",
    TURQUOISE: "#1abc9c",
    YELLOW:    "#f1c40f",
};

const POINT_VALUES = [0, 40, 100, 300, 1200];

function Space(x, y, color = COLORS.BLUE) {
    return {
        x: x,
        y: y,
        color: color
    };
}

class Piece {
    constructor (shape, orientation, layout, color, x = 0, y = 0) {
        this.shape = shape;
        this.orientation = orientation;
        this.x = x;
        this.y = y;
        this.layout = layout;
        this.color = color;
    }

    get spaces() {
        return this.layout.map(
            space => Space(space.x + this.x, space.y + this.y, this.color)
        );
    }

    shifted(dx, dy) {
        return new Piece(this.shape, this.orientation, this.layout, this.color, this.x + dx, this.y + dy);
    }

    rotated(dx, dy) {
        let newOrientation = (this.orientation + 1) % 4;
        let newLayout = SHAPES[this.shape].orientations[newOrientation];
        return new Piece(this.shape, newOrientation, newLayout, this.color, this.x, this.y);
    }
}

const SHAPES = {
    O: {
        orientations: [
            [Space(0,0), Space(0,1), Space(1,0), Space(1,1)],
            [Space(0,0), Space(0,1), Space(1,0), Space(1,1)],
            [Space(0,0), Space(0,1), Space(1,0), Space(1,1)],
            [Space(0,0), Space(0,1), Space(1,0), Space(1,1)]
        ],
        color: COLORS.RED
    },
    J: {
        orientations: [
            [Space(0,0), Space(1,0), Space(2,0), Space(2,1)],
            [Space(1,0), Space(1,1), Space(1,2), Space(0,2)],
            [Space(0,0), Space(0,1), Space(1,1), Space(2,1)],
            [Space(0,0), Space(1,0), Space(0,1), Space(0,2)]
        ],
        color: COLORS.ORANGE
    },
    L: {
        orientations: [
            [Space(0,0), Space(1,0), Space(2,0), Space(0,1)],
            [Space(0,0), Space(1,0), Space(1,1), Space(1,2)],
            [Space(2,0), Space(0,1), Space(1,1), Space(2,1)],
            [Space(0,0), Space(0,1), Space(0,2), Space(1,2)]
        ],
        color: COLORS.GREEN
    },
    T: {
        orientations: [
            [Space(0,0), Space(0,1), Space(0,2), Space(1,1)],
            [Space(0,0), Space(1,0), Space(2,0), Space(1,1)],
            [Space(1,0), Space(1,1), Space(1,2), Space(0,1)],
            [Space(1,0), Space(0,1), Space(1,1), Space(2,1)]
        ],
        color: COLORS.YELLOW
    },
    Z: {
        orientations: [
            [Space(0,0), Space(1,0), Space(1,1), Space(2,1)],
            [Space(1,0), Space(0,1), Space(1,1), Space(0,2)],
            [Space(0,0), Space(1,0), Space(1,1), Space(2,1)],
            [Space(1,0), Space(0,1), Space(1,1), Space(0,2)]
        ],
        color: COLORS.PURPLE
    },
    S: {
        orientations: [
            [Space(0,0), Space(0,1), Space(1,1), Space(1,2)],
            [Space(1,0), Space(2,0), Space(0,1), Space(1,1)],
            [Space(0,0), Space(0,1), Space(1,1), Space(1,2)],
            [Space(1,0), Space(2,0), Space(0,1), Space(1,1)]
        ],
        color: COLORS.TURQUOISE
    },
    I: {
        orientations: [
            [Space(0,0), Space(1,0), Space(2,0), Space(3,0)],
            [Space(1,0), Space(1,1), Space(1,2), Space(1,3)],
            [Space(0,0), Space(1,0), Space(2,0), Space(3,0)],
            [Space(1,0), Space(1,1), Space(1,2), Space(1,3)],
        ],
        color: COLORS.BLUE
    },
};

function makeInitialState() {
    return {
        board: [],
        current: randomPiece(),
        next: randomPiece(),
        score: 0
    };
}

function inXBounds(piece, gridwidth) {
    let bools = piece.spaces.map(square => 0 <= square.x && square.x < gridwidth);
    return bools.indexOf(false) == -1;
}

function colliding(piece, board) {
    let colliding = space => boardsquare => boardsquare.x == space.x && boardsquare.y == space.y;
    for (let i in piece.spaces) {
        let space = piece.spaces[i];
        // check for square collision
        let collision = board.find(colliding(space));
        if (collision) return true;
        // check for floor collision
        if (space.y >= GRID.HEIGHT) return true;
    }
    return false;
}

function randomPiece() {
    let keys = Object.keys(SHAPES);
    let idx = Math.floor(Math.random() * keys.length);
    let shape = SHAPES[keys[idx]];
    return new Piece(keys[idx], 0, shape.orientations[0], shape.color, 3, 0);
}

function validPiece(piece, board) {
    return inXBounds(piece, GRID.WIDTH) && !colliding(piece, board);
}

function shiftPiece(piece, board, dx, dy) {
    let newPiece = piece.shifted(dx, dy);
    if (!validPiece(newPiece, board)) {
        return piece;
    }
    return newPiece;
}

function clearRows(board) {
    let rowcounts = {};
    for (let i in board) {
        let space = board[i];
        rowcounts[space.y] = rowcounts[space.y] + 1 || 1;
    }
    let notInRow = row => space => space.y != row;
    let bumpSpaceDown = row => space => space.y < row ? new Space(space.x, space.y + 1, space.color) : space;

    let rowscleared = 0;
    for (let row in rowcounts) {
        if (rowcounts[row] >= GRID.WIDTH) {
            board = board.filter(notInRow(row));
            board = board.map(bumpSpaceDown(row));
            rowscleared += 1;
        }
    }

    let points = rowscleared <= 4 ? POINT_VALUES[rowscleared] : POINT_VALUES[4];

    return {
        board: board,
        points: points
    };
}

function validRotation(piece, board) {
    let rotated = piece.rotated();
    if (!validPiece(rotated, board)) {
        rotated = rotated.shifted(1, 0);
        if (!validPiece(rotated, board)) {
            rotated = rotated.shifted(-2, 0);
            if (!validPiece(rotated, board)) {
                rotated = state.current;
            }
        }
    }
    return rotated;
}

function mainState(state = makeInitialState(), action) {
    switch (action.type) {
        case 'TICK':
            let current = state.current;
            let newCurrent = new Piece(current.shape, current.orientation, current.layout, current.color, current.x, current.y + 1);
            if (colliding(newCurrent, state.board)) {
                let newboard = state.current.spaces.concat(state.board);
                let result = clearRows(newboard);
                let newscore = state.score + result.points;
                return Object.assign({}, state,
                     {current: state.next, next: randomPiece(), board: result.board, score: newscore}
                );
            }
            return Object.assign({}, state, {current: newCurrent});
        case 'MOVE_RIGHT':
            return Object.assign({}, state, {
                current: shiftPiece(state.current, state.board, 1, 0)
            });
        case 'MOVE_LEFT':
            return Object.assign({}, state, {
                current: shiftPiece(state.current, state.board, -1, 0)
            });
        case 'MOVE_DOWN':
            return Object.assign({}, state, {
                current: shiftPiece(state.current, state.board, 0, 1)
            });
        case 'ROTATE':
            return Object.assign({}, state, {
                current: validRotation(state.current, state.board)
            });
        default:
            return state;
    }
}

let store = Redux.createStore(mainState);

let canvas = document.getElementById("myCanvas");
canvas.width = GRID.DIMENSION * GRID.WIDTH;
canvas.height = GRID.DIMENSION * GRID.HEIGHT;
let ctx = canvas.getContext("2d");
ctx.font = "30px Arial";

document.addEventListener("keydown", keyDownHandler, false);

function keyDownHandler(event) {
    if (event.keyCode == 39) {
        store.dispatch({type: 'MOVE_RIGHT'});
    }
    else if (event.keyCode == 37) {
        store.dispatch({type: 'MOVE_LEFT'});
    }
    else if (event.keyCode == 40) {
        store.dispatch({type: 'MOVE_DOWN'});
    }
    else if (event.keyCode == 38) {
        store.dispatch({type: 'ROTATE'});
    }
}

function drawSpace(context, space) {
    let dim = GRID.DIMENSION;
    context.beginPath();
    context.rect(space.x*dim, space.y*dim, dim, dim);
    context.fillStyle = space.color;
    context.fill();
    context.closePath();
}
function drawPiece(context, shape) {
     let spaces = shape.spaces.map(space => drawSpace(context, space));
}

function drawScore(context, score) {
    context.fillStyle = "#777";
    context.fillText(score, 10, 30);
}

function drawState(context, state) {
    state.board.map(space => drawSpace(context, space));
    drawPiece(context, state.current);
    drawScore(context, state.score);
}
function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawState(ctx, store.getState());
}
store.subscribe(draw);
setInterval(() => store.dispatch({type: 'TICK'}), 1000);
<|endoftext|>