<commit_before>'use strict';

var Map = require('../models/map');
const Pin = require('../models/pin');

module.exports = function (app) {
  app.route('/api/maps')
    .get(function(req, res){
      Map.find(function (error, doc) {
        res.send(doc);
      });
    })
    .post(function(req, res){
      let map = req.body;
      let locationMap = new Map(map);

      locationMap.save(function (error, data) {
        if (!error) {
          res.status(200).type('json').send(data);
        } else {
          res.status(500).type('json').send(error);
        }
      });
    });
  app.route('/api/maps/:id')
    .delete(function(req, res) {
      Map.findOne({
        _id: req.params.id
      }).remove(function (error, result){
        res.status(300).send();
      });
    })
    .patch(function(req, res) {
      Map.findById(req.params.id,
        function (error, doc) {
          for (let key in req.body) {
            if (key === '_id') { continue; }
            doc[key] = req.body[key];
          }

          doc.save();
          res.status(200).send();
        }
      );
    });
  //pins routes
  app.route('/api/pins')
    .get(function(req, res) {
      Pin.find(function (error, doc) {
        res.send(doc);
      });
    })
    .post(function(req, res){
      let pinData = req.body;
      let pin = new Pin(pinData);
      pin.save(function (error, data) {
        res.status(300).send();
      });
    });
  app.route('/api/pins/:id')
    .delete(function(req, res) {
      Pin.findOne({
        _id: req.params.id
      }).remove(function (error, result){
        res.status(300).send();
      });
    })
    .patch(function(req, res) {
      Pin.findById(req.params.id,
        function (error, doc) {
          for (let key in req.body) {
            if (key === '_id') { continue; }
            doc[key] = req.body[key];
          }

          doc.save();
          res.status(200).send();
        }
      );
    });
}
<commit_msg>update pin save route<commit_after>'use strict';

var Map = require('../models/map');
const Pin = require('../models/pin');

module.exports = function (app) {
  app.route('/api/maps')
    .get(function(req, res){
      Map.find(function (error, doc) {
        res.send(doc);
      });
    })
    .post(function(req, res){
      let map = req.body;
      let locationMap = new Map(map);

      locationMap.save(function (error, data) {
        if (!error) {
          res.status(200).type('json').send(data);
        } else {
          res.status(500).type('json').send(error);
        }
      });
    });
  app.route('/api/maps/:id')
    .delete(function(req, res) {
      Map.findOne({
        _id: req.params.id
      }).remove(function (error, result){
        res.status(300).send();
      });
    })
    .patch(function(req, res) {
      Map.findById(req.params.id,
        function (error, doc) {
          for (let key in req.body) {
            if (key === '_id') { continue; }
            doc[key] = req.body[key];
          }

          doc.save();
          res.status(200).send();
        }
      );
    });
  //pins routes
  app.route('/api/pins')
    .get(function(req, res) {
      Pin.find(function (error, doc) {
        res.send(doc);
      });
    })
    .post(function(req, res) {
      let pinData = req.body;
      let pin = new Pin(pinData);
      pin.save(function (error, data) {
      if (!error) {
        res.status(200).type('json').send(data);
      } else {
        res.status(500).type('json').send(error);
      }
      });
    });
  app.route('/api/pins/:id')
    .delete(function(req, res) {
      Pin.findOne({
        _id: req.params.id
      }).remove(function (error, result){
        res.status(300).send();
      });
    })
    .patch(function(req, res) {
      Pin.findById(req.params.id,
        function (error, doc) {
          for (let key in req.body) {
            if (key === '_id') { continue; }
            doc[key] = req.body[key];
          }

          doc.save();
          res.status(200).send();
        }
      );
    });
}
<|endoftext|>


<commit_before>/*
	The MIT License (MIT)

	Copyright (c) 2013 Fernando Bevilacqua

	Permission is hereby granted, free of charge, to any person obtaining a copy of
	this software and associated documentation files (the "Software"), to deal in
	the Software without restriction, including without limitation the rights to
	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
	the Software, and to permit persons to whom the Software is furnished to do so,
	subject to the following conditions:

	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

var CodebotFilesPanel = function() {
    var mCodebot = null;
    var mSelf = null;
    var mFocusedNode = null;
    var mRootNode = null;
    var mTree = null;
    var mContextMenu = null;

    var onClick = function(theEvent, theItem) {
        // If the currently focused node has the rename form active,
        // close it and finish the renaming process.
        if(mFocusedNode && mFocusedNode.node.isEditing()) {
            mFocusedNode.node.endEdit();
        }
        mFocusedNode = theItem;

        if(mFocusedNode.node.folder) {
            mFocusedNode.node.toggleExpanded();
        }

        console.debug('FilesPanel.click() ', theEvent, theItem);
	};

	var onDoubleClick = function(theEvent, theItem) {
		var aNode = theItem.node;

		console.debug('File panel double click: ' + theEvent + ' , folder: ' + aNode.folder);

		if(!aNode.folder) {
            mCodebot.ui.tabs.openNode(aNode);
		}
	};

    var onDragStart = function(theNode, theDragData) {
        /** This function MUST be defined to enable dragging for the tree.
         *  Return false to cancel dragging of node.
         */
        return true;
    };

    var onDragEnter = function(theDestinationNode, theDragData) {
        /** data.otherNode may be null for non-fancytree droppables.
         *  Return false to disallow dropping on node. In this case
         *  dragOver and dragLeave are not called.
         *  Return 'over', 'before, or 'after' to force a hitMode.
         *  Return ['before', 'after'] to restrict available hitModes.
         *  Any other return value will calc the hitMode from the cursor position.
         */
        // Prevent dropping a parent below another parent (only sort
        // nodes under the same parent)
        //if(node.parent !== data.otherNode.parent){
        //    return false;
        //}
        // Don't allow dropping *over* a node (would create a child)
        //return ["before", "after"];

        if(!theDestinationNode.folder) {
            return ['after', 'before'];

        } else {
            return true;
        }
    };

    /**
     * Called when a node is dropped in the files panel.
     *
     * @theDestinationNode the node used to guide the dragging process.
     * @theDragData An object containing information regarding the dragging process, e.g. node being dragged, destination, hit strategy.
     */
    var onDragDrop = function(theDestinationNode, theDragData) {
        var aNodeBeingDragged = theDragData.otherNode;

        console.debug('Drag and drop event', theDragData);

        aNodeBeingDragged.moveTo(theDestinationNode, theDragData.hitMode);

        var aOldPath = aNodeBeingDragged.data;
        var aNewPath = null;

        if(theDragData.hitMode == "over") {
            // Dragging node into a folder. In that case, the destination node (the folder)
            // already has a nice path to be used. e.g. /proj/test/folder/
            aNewPath = theDestinationNode.data.path;

        } else {
            // Dragging node after or before another node. In that case, we need to get the
            // path to this neighbour file, removing the file name.
            aNewPath = CODEBOT.utils.dirName(theDestinationNode.data.path);
        }

        aNewPath += aNodeBeingDragged.data.name;

        // TODO: only move the UI item when the IO opperation informs everything went ok.
        // TODO: fix the {path: } because it breaks IO layer.
        mCodebot.io.move(aOldPath, {path: aNewPath}, function(theError) {
            if(theError) {
                console.log('Problem with move!');
                // TODO: warn about error and reload tree.
            }
        });
    };

    var onRename = function(theEvent, theData) {
        var aNode    = theData.node;
        var aNewName = theData.value;

        if(aNewName != aNode.data.name) {
            var aNewNode = {path: CODEBOT.utils.dirName(aNode.data.path, aNode.folder ? 3 : 1) + aNewName}; // TODO: fix this, it breaks IO layer.

            mCodebot.io.move(aNode.data, aNewNode, function(theError) {
                if(theError) {
                    console.log('Problem with rename/move!');
                    // TODO: warn about error and reload tree.
                }
            });

            // TODO: update open tab containing the renamed node.
        }
    };

    var initTree = function() {
        $("#folders").fancytree({
            extensions: ['dnd', 'edit', 'awesome', 'contextMenu'],
            click: onClick,
            dblclick: onDoubleClick,
            source: [],
            checkbox: false,
            selectMode: 3,
            debugLevel: 0,

            dnd: {
                preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
                preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
                autoExpandMS: 400,
                dragStart: onDragStart,
                dragEnter: onDragEnter,
                dragDrop: onDragDrop
            },
            edit: {
                save: onRename,
                triggerCancel: ['esc', 'tab', 'click'],
                triggerStart: ['f2']
            },
            contextMenu: mContextMenu.create()
        });

        mTree = $("#folders").fancytree("getTree");
	};

    this.renameFocusedNode = function() {
        if(mFocusedNode) {
            mFocusedNode.node.startEdit();
            console.log('Open rename panel', mFocusedNode);
        }
    };

    this.refreshTree = function() {
        mCodebot.io.readDirectory(mRootNode, mSelf.populateTree);
    }

    this.populateTree = function(theNodes) {
        if(theNodes && theNodes.length > 0) {
            mTree.reload(theNodes);
            console.debug('Tree has been populated.');
        }
    };

    this.showChooseDirectoryDialog = function() {
        mCodebot.io.chooseDirectory(function(theNode) {
            mRootNode = theNode;
            mCodebot.io.readDirectory(theNode, mSelf.populateTree);
        });
    };

    this.init = function(theCodebot) {
        mCodebot     = theCodebot;
        mSelf        = this;
        mContextMenu = new CodebotContextMenu();

        mContextMenu.init(mCodebot);
        initTree();
    };
};
<commit_msg>Fix bug related to file move.<commit_after>/*
	The MIT License (MIT)

	Copyright (c) 2013 Fernando Bevilacqua

	Permission is hereby granted, free of charge, to any person obtaining a copy of
	this software and associated documentation files (the "Software"), to deal in
	the Software without restriction, including without limitation the rights to
	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
	the Software, and to permit persons to whom the Software is furnished to do so,
	subject to the following conditions:

	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

var CodebotFilesPanel = function() {
    var mCodebot = null;
    var mSelf = null;
    var mFocusedNode = null;
    var mRootNode = null;
    var mTree = null;
    var mContextMenu = null;

    var onClick = function(theEvent, theItem) {
        // If the currently focused node has the rename form active,
        // close it and finish the renaming process.
        if(mFocusedNode && mFocusedNode.node.isEditing()) {
            mFocusedNode.node.endEdit();
        }
        mFocusedNode = theItem;

        if(mFocusedNode.node.folder) {
            mFocusedNode.node.toggleExpanded();
        }

        console.debug('FilesPanel.click() ', theEvent, theItem);
	};

	var onDoubleClick = function(theEvent, theItem) {
		var aNode = theItem.node;

		console.debug('File panel double click: ' + theEvent + ' , folder: ' + aNode.folder);

		if(!aNode.folder) {
            mCodebot.ui.tabs.openNode(aNode);
		}
	};

    var onDragStart = function(theNode, theDragData) {
        /** This function MUST be defined to enable dragging for the tree.
         *  Return false to cancel dragging of node.
         */
        return true;
    };

    var onDragEnter = function(theDestinationNode, theDragData) {
        /** data.otherNode may be null for non-fancytree droppables.
         *  Return false to disallow dropping on node. In this case
         *  dragOver and dragLeave are not called.
         *  Return 'over', 'before, or 'after' to force a hitMode.
         *  Return ['before', 'after'] to restrict available hitModes.
         *  Any other return value will calc the hitMode from the cursor position.
         */
        // Prevent dropping a parent below another parent (only sort
        // nodes under the same parent)
        //if(node.parent !== data.otherNode.parent){
        //    return false;
        //}
        // Don't allow dropping *over* a node (would create a child)
        //return ["before", "after"];

        if(!theDestinationNode.folder) {
            return ['after', 'before'];

        } else {
            return true;
        }
    };

    /**
     * Called when a node is dropped in the files panel.
     *
     * @theDestinationNode the node used to guide the dragging process.
     * @theDragData An object containing information regarding the dragging process, e.g. node being dragged, destination, hit strategy.
     */
    var onDragDrop = function(theDestinationNode, theDragData) {
        var aNodeBeingDragged = theDragData.otherNode;

        console.debug('Drag and drop event', theDragData);

        aNodeBeingDragged.moveTo(theDestinationNode, theDragData.hitMode);

        var aOldPath = aNodeBeingDragged.data;
        var aNewPath = null;

        if(theDragData.hitMode == "over") {
            // Dragging node into a folder. In that case, the destination node (the folder)
            // already has a nice path to be used. e.g. /proj/test/folder/
            aNewPath = theDestinationNode.data.path + '/';

        } else {
            // Dragging node after or before another node. In that case, we need to get the
            // path to this neighbour file, removing the file name.
            aNewPath = CODEBOT.utils.dirName(theDestinationNode.data.path);
        }

        aNewPath += aNodeBeingDragged.data.name;

        // TODO: only move the UI item when the IO opperation informs everything went ok.
        // TODO: fix the {path: } because it breaks IO layer.
        mCodebot.io.move(aOldPath, {path: aNewPath}, function(theError) {
            if(theError) {
                console.log('Problem with move!');
                // TODO: warn about error and reload tree.
            }
        });
    };

    var onRename = function(theEvent, theData) {
        var aNode    = theData.node;
        var aNewName = theData.value;

        if(aNewName != aNode.data.name) {
            var aNewNode = {path: CODEBOT.utils.dirName(aNode.data.path, aNode.folder ? 3 : 1) + aNewName}; // TODO: fix this, it breaks IO layer.

            mCodebot.io.move(aNode.data, aNewNode, function(theError) {
                if(theError) {
                    console.log('Problem with rename/move!');
                    // TODO: warn about error and reload tree.
                }
            });

            // TODO: update open tab containing the renamed node.
        }
    };

    var initTree = function() {
        $("#folders").fancytree({
            extensions: ['dnd', 'edit', 'awesome', 'contextMenu'],
            click: onClick,
            dblclick: onDoubleClick,
            source: [],
            checkbox: false,
            selectMode: 3,
            debugLevel: 0,

            dnd: {
                preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
                preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
                autoExpandMS: 400,
                dragStart: onDragStart,
                dragEnter: onDragEnter,
                dragDrop: onDragDrop
            },
            edit: {
                save: onRename,
                triggerCancel: ['esc', 'tab', 'click'],
                triggerStart: ['f2']
            },
            contextMenu: mContextMenu.create()
        });

        mTree = $("#folders").fancytree("getTree");
	};

    this.renameFocusedNode = function() {
        if(mFocusedNode) {
            mFocusedNode.node.startEdit();
            console.log('Open rename panel', mFocusedNode);
        }
    };

    this.refreshTree = function() {
        mCodebot.io.readDirectory(mRootNode, mSelf.populateTree);
    }

    this.populateTree = function(theNodes) {
        if(theNodes && theNodes.length > 0) {
            mTree.reload(theNodes);
            console.debug('Tree has been populated.');
        }
    };

    this.showChooseDirectoryDialog = function() {
        mCodebot.io.chooseDirectory(function(theNode) {
            mRootNode = theNode;
            mCodebot.io.readDirectory(theNode, mSelf.populateTree);
        });
    };

    this.init = function(theCodebot) {
        mCodebot     = theCodebot;
        mSelf        = this;
        mContextMenu = new CodebotContextMenu();

        mContextMenu.init(mCodebot);
        initTree();
    };
};
<|endoftext|>


<commit_before>/**
 * Convenience wrapper around XMLHttpRequest.
 *
 * @param {String} method - HTTP method to use.
 * @param {String} url - URL to send the request to.
 * @param {Object} options - Optional arguments.
 * @param {Object} options.data - Request data as an Object; keys are
 *     used as parameter names, values as parameter values.
 * @param {Object} options.headers - Headers and values to set on the
 *     request.
 * @promise {XMLHttpRequest} The request after it has succeeded.
 * @rejects {XMLHttpRequest} The request after it has failed.
 */
function xhr(method, url, options={}) {
    return new Promise((resolve, reject) => {
        let req = new XMLHttpRequest();
        req.addEventListener('load', e => {
            if (req.status >= 400) {
                reject(req);
            } else {
                resolve(req);
            }
        });
        req.open(method, url);

        let data = undefined;
        if (options.data) {
            req.setRequestHeader('Content-Type', 'application/json');
            data = JSON.stringify(data);
        }

        if (options.headers) {
            for (let key in options.headers) {
                req.setRequestHeader(key, options.headers[key]);
            }
        }

        req.send(data);
    });
}
xhr.get = xhr.bind(null, 'GET');
xhr.post = xhr.bind(null, 'POST');

let registeredActions = {};
window.Normandy = {
    registerAction(name, func) {
        registeredActions[name] = func;
    },

    heartbeatCallbacks: [],
    showHeartbeat(options) {
        return new Promise((resolve, reject) => {
            // TODO: Validate arguments and reject if some are missing.
            this.heartbeatCallbacks[options.flowId] = () => {
                resolve();
            };

            Mozilla.UITour.showHeartbeat(
                options.message,
                options.thanksMessage,
                options.flowId,
                options.postAnswerUrl,
                options.learnMoreMessage,
                options.learnMoreUrl
            );
        });

    },
};

// Trigger heartbeat callbacks when the UITour tells us that Heartbeat
// happened.
Mozilla.UITour.observe((eventName, data) => {
    if (eventName.startsWith('Heartbeat')) {
        let flowId = data.flowId;
        if (flowId in Normandy.heartbeatCallbacks) {
            Normandy.heartbeatCallbacks[flowId](data);
        }
    }
});

/**
 * Download the implementation of the given action from the server.
 *
 * @param {Action} action  - Action taken from a Recipe.
 * @promise {Function} The implementation function for the given action.
 * @rejects {Error} Rejects if the action could not be loaded or did not
 *     register itself.
 */
function loadAction(action) {
    return new Promise((resolve, reject) => {
        if (!registeredActions[action.name]) {
            let script = document.createElement('script');
            script.src = action.implementation.url;
            script.onload = () => {
                if (!registeredActions[action.name]) {
                    reject(new Error(`Could not find action with name ${action.name}.`));
                } else {
                    resolve(registeredActions[action.name]);
                }
            };
            document.head.appendChild(script);
        } else {
            resolve(registeredActions[action.name]);
        }
    });
}

/**
 * Fetch recipes from the Recipe server.
 *
 * @promise {Array<Recipe>} List of recipes.
 */
function fetchRecipes() {
    let {recipeUrl, locale} = document.documentElement.dataset;

    return xhr.post(recipeUrl, {
        data: {locale: locale},
        headers: {Accept: 'application/json'}
    }).then(request => {
        return JSON.parse(request.responseText).recipes;
    });
}

/**
 * Fetch and execute the actions for the given recipe.
 *
 * @param {Recipe} recipe - Recipe retrieved from the server.
 * @promise Resolves once all actions are complete.
 */
function runRecipe(recipe) {
    return Promise.all(recipe.actions.map(loadAction)).then((funcs) => {
        let recipePromise = Promise.resolve();

        for (let k = 0; k < recipe.actions.length; k++) {
            let action = recipe.actions[k];
            let func = funcs[k];
            recipePromise = recipePromise.then(() => {
                return func(null, action.arguments);
            });
        }

        return recipePromise;
    });
}

// Actually fetch and run the recipes.
fetchRecipes().then((recipes) => {
    let chain = Promise.resolve();

    for (let recipe of recipes) {
        chain.then(() => {
            return runRecipe(recipe);
        });
    }

    return chain;
}).catch((err) => {
    console.error(err);
});
<commit_msg>Fix a binding issue with the self-repair driver.<commit_after>/**
 * Convenience wrapper around XMLHttpRequest.
 *
 * @param {String} method - HTTP method to use.
 * @param {String} url - URL to send the request to.
 * @param {Object} options - Optional arguments.
 * @param {Object} options.data - Request data as an Object; keys are
 *     used as parameter names, values as parameter values.
 * @param {Object} options.headers - Headers and values to set on the
 *     request.
 * @promise {XMLHttpRequest} The request after it has succeeded.
 * @rejects {XMLHttpRequest} The request after it has failed.
 */
function xhr(method, url, options={}) {
    return new Promise((resolve, reject) => {
        let req = new XMLHttpRequest();
        req.addEventListener('load', e => {
            if (req.status >= 400) {
                reject(req);
            } else {
                resolve(req);
            }
        });
        req.open(method, url);

        let data = undefined;
        if (options.data) {
            req.setRequestHeader('Content-Type', 'application/json');
            data = JSON.stringify(data);
        }

        if (options.headers) {
            for (let key in options.headers) {
                req.setRequestHeader(key, options.headers[key]);
            }
        }

        req.send(data);
    });
}
xhr.get = xhr.bind(null, 'GET');
xhr.post = xhr.bind(null, 'POST');

let registeredActions = {};
window.Normandy = {
    registerAction(name, func) {
        registeredActions[name] = func;
    },

    heartbeatCallbacks: [],
    showHeartbeat(options) {
        return new Promise((resolve, reject) => {
            // TODO: Validate arguments and reject if some are missing.
            this.heartbeatCallbacks[options.flowId] = () => {
                resolve();
            };

            Mozilla.UITour.showHeartbeat(
                options.message,
                options.thanksMessage,
                options.flowId,
                options.postAnswerUrl,
                options.learnMoreMessage,
                options.learnMoreUrl
            );
        });

    },
};

// Trigger heartbeat callbacks when the UITour tells us that Heartbeat
// happened.
Mozilla.UITour.observe((eventName, data) => {
    if (eventName.startsWith('Heartbeat')) {
        let flowId = data.flowId;
        if (flowId in Normandy.heartbeatCallbacks) {
            Normandy.heartbeatCallbacks[flowId](data);
        }
    }
});

/**
 * Download the implementation of the given action from the server.
 *
 * @param {Action} action  - Action taken from a Recipe.
 * @promise {Function} The implementation function for the given action.
 * @rejects {Error} Rejects if the action could not be loaded or did not
 *     register itself.
 */
function loadAction(action) {
    return new Promise((resolve, reject) => {
        if (!registeredActions[action.name]) {
            let script = document.createElement('script');
            script.src = action.implementation.url;
            script.onload = () => {
                if (!registeredActions[action.name]) {
                    reject(new Error(`Could not find action with name ${action.name}.`));
                } else {
                    resolve(registeredActions[action.name]);
                }
            };
            document.head.appendChild(script);
        } else {
            resolve(registeredActions[action.name]);
        }
    });
}

/**
 * Fetch recipes from the Recipe server.
 *
 * @promise {Array<Recipe>} List of recipes.
 */
function fetchRecipes() {
    let {recipeUrl, locale} = document.documentElement.dataset;

    return xhr.post(recipeUrl, {
        data: {locale: locale},
        headers: {Accept: 'application/json'}
    }).then(request => {
        return JSON.parse(request.responseText).recipes;
    });
}

/**
 * Fetch and execute the actions for the given recipe.
 *
 * @param {Recipe} recipe - Recipe retrieved from the server.
 * @promise Resolves once all actions are complete.
 */
function runRecipe(recipe) {
    return Promise.all(recipe.actions.map(loadAction)).then((funcs) => {
        let recipePromise = Promise.resolve();

        for (let k = 0; k < recipe.actions.length; k++) {
            let action = recipe.actions[k];
            let func = funcs[k];
            recipePromise = recipePromise.then(() => {
                return func(null, action.arguments);
            });
        }

        return recipePromise;
    });
}

// Actually fetch and run the recipes.
fetchRecipes().then((recipes) => {
    let chain = Promise.resolve();

    for (let recipe of recipes) {
        let cb = function(recipeToRun) {
            return runRecipe(recipeToRun);
        };
        chain.then(cb.bind(null, recipe));
    }

    return chain;
}).catch((err) => {
    console.error(err);
});
<|endoftext|>


<commit_before>// Copyright 2002-2013, University of Colorado Boulder

/**
 * Scene graph for the 'Matching Game' screen.
 *
 * @author Anton Ulyanov (Mlearner)
 */

define( function( require ) {
  "use strict";

  // imports
  var Bounds2 = require( 'DOT/Bounds2' ),
    inherit = require( 'PHET_CORE/inherit' ),
    ScreenView = require( 'JOIST/ScreenView' ),
    VBox = require( 'SCENERY/nodes/VBox' ),
    Text = require( 'SCENERY/nodes/Text' ),
    PhetFont = require( 'SCENERY_PHET/PhetFont' ),
    Node = require( "SCENERY/nodes/Node" ),
    matchingGameHeaderString = require( 'string!FRACTION_MATCHER/matchingGameHeader' ),
    mixedNumbersHeaderString = require( 'string!FRACTION_MATCHER/mixedNumbersHeader' ),
    mixedNumbersTitleString = require( 'string!FRACTION_MATCHER/mixedNumbersTitle' ),
    Paginator = require( 'FRACTION_MATCHER/view/Paginator' ),
    Rectangle = require( 'SCENERY/nodes/Rectangle' ),
    LevelsContainerNode = require( 'FRACTION_MATCHER/view/LevelsContainerNode' ),
    SoundToggleButton = require( 'SCENERY_PHET/SoundToggleButton' ),
    TimerToggleButton = require( 'SCENERY_PHET/TimerToggleButton' ),
    ResetAllButton = require( 'SCENERY_PHET/ResetAllButton' );

  function MatchingGameView( model ) {
    ScreenView.call( this, { renderer: 'svg' } );

    this.addChild( new Rectangle( 0, 0, 768, 504, {fill: '#eee'} ) );

    var levelsContainerNode = new LevelsContainerNode( model );

    var paginatorBox = new VBox( {centerX: model.width / 2, y: 25, spacing: 20, children: [
      // add header
      new Text( (model.game === mixedNumbersTitleString ? mixedNumbersHeaderString : matchingGameHeaderString), { font: new PhetFont( { size: 36, weight: 'bold'} )  } ),
      // add pagination
      new Paginator( model )
    ]} );
    var paginatorNode = new Node( {children: [
      paginatorBox,
      new ResetAllButton( function() {
        model.reset();
        levelsContainerNode.levelNodes.forEach( function( levelNode ) {
          levelNode.generateNewLevel();
        } );
      }, { x: model.width - 40, y: model.height - 40} ),
      new TimerToggleButton( model.isTimerProperty, {x: 20, y: model.height - 120} ),
      new SoundToggleButton( model.isSoundProperty, {x: 20, y: model.height - 60} )
    ]} );

    this.addChild( levelsContainerNode );
    this.addChild( paginatorNode );

    model.isLevelScreenActiveProperty.link( function( isActive ) {
      paginatorNode.visible = !isActive;
      levelsContainerNode.visible = isActive;
    } );

  }

  return inherit( ScreenView, MatchingGameView );
} );
<commit_msg>fixed jshint issues<commit_after>// Copyright 2002-2013, University of Colorado Boulder

/**
 * Scene graph for the 'Matching Game' screen.
 *
 * @author Anton Ulyanov (Mlearner)
 */

define( function( require ) {
  "use strict";

  // imports
  var inherit = require( 'PHET_CORE/inherit' ),
    ScreenView = require( 'JOIST/ScreenView' ),
    VBox = require( 'SCENERY/nodes/VBox' ),
    Text = require( 'SCENERY/nodes/Text' ),
    PhetFont = require( 'SCENERY_PHET/PhetFont' ),
    Node = require( "SCENERY/nodes/Node" ),
    matchingGameHeaderString = require( 'string!FRACTION_MATCHER/matchingGameHeader' ),
    mixedNumbersHeaderString = require( 'string!FRACTION_MATCHER/mixedNumbersHeader' ),
    mixedNumbersTitleString = require( 'string!FRACTION_MATCHER/mixedNumbersTitle' ),
    Paginator = require( 'FRACTION_MATCHER/view/Paginator' ),
    Rectangle = require( 'SCENERY/nodes/Rectangle' ),
    LevelsContainerNode = require( 'FRACTION_MATCHER/view/LevelsContainerNode' ),
    SoundToggleButton = require( 'SCENERY_PHET/SoundToggleButton' ),
    TimerToggleButton = require( 'SCENERY_PHET/TimerToggleButton' ),
    ResetAllButton = require( 'SCENERY_PHET/ResetAllButton' );

  function MatchingGameView( model ) {
    ScreenView.call( this, { renderer: 'svg' } );

    this.addChild( new Rectangle( 0, 0, 768, 504, {fill: '#eee'} ) );

    var levelsContainerNode = new LevelsContainerNode( model );

    var paginatorBox = new VBox( {centerX: model.width / 2, y: 25, spacing: 20, children: [
      // add header
      new Text( (model.game === mixedNumbersTitleString ? mixedNumbersHeaderString : matchingGameHeaderString), { font: new PhetFont( { size: 36, weight: 'bold'} )  } ),
      // add pagination
      new Paginator( model )
    ]} );
    var paginatorNode = new Node( {children: [
      paginatorBox,
      new ResetAllButton( function() {
        model.reset();
        levelsContainerNode.levelNodes.forEach( function( levelNode ) {
          levelNode.generateNewLevel();
        } );
      }, { x: model.width - 40, y: model.height - 40} ),
      new TimerToggleButton( model.isTimerProperty, {x: 20, y: model.height - 120} ),
      new SoundToggleButton( model.isSoundProperty, {x: 20, y: model.height - 60} )
    ]} );

    this.addChild( levelsContainerNode );
    this.addChild( paginatorNode );

    model.isLevelScreenActiveProperty.link( function( isActive ) {
      paginatorNode.visible = !isActive;
      levelsContainerNode.visible = isActive;
    } );

  }

  return inherit( ScreenView, MatchingGameView );
} );
<|endoftext|>


<commit_before>// Amara, universalsubtitles.org
//
// Copyright (C) 2013 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

(function() {

    var root = this;

    var VideoController = function($scope, SubtitleStorage) {
        /**
         * Responsible for initializing the video and all video controls.
         * @param $scope
         * @param SubtitleStorage
         * @constructor
         */

        // The Popcorn instance.
        //
        // For now, make sure we force controls.
        $scope.pop = window.Popcorn.smart('#video', SubtitleStorage.getVideoURL() + '&controls=1');

        $scope.playChunk = function(start, duration) {
            // Play a specified amount of time in a video, beginning at 'start',
            // and then pause.

            // Pause the video, first.
            $scope.pop.play();

            // Remove any existing cues that may interfere.
            $scope.removeAllTrackEvents();

            if (start < 0) {
                start = 0;
            }

            // Set the new start time.
            $scope.pop.currentTime(start);

            // Set a new cue to pause the video at the end of the chunk.
            $scope.pop.cue(start + duration, function() {
                $scope.pop.pause();
            });

            // Play the video.
            $scope.pop.play();

        };
        $scope.removeAllTrackEvents = function() {

            var trackEvents = $scope.pop.getTrackEvents();
            for (var i = 0; i < trackEvents.length; i++) {
                $scope.pop.removeTrackEvent(trackEvents[i].id);
            }

        };
        $scope.togglePlay = function() {

            // If the video is paused, play it.
            if ($scope.pop.paused()) {
                $scope.pop.play();

            // Otherwise, pause it.
            } else {
                $scope.pop.pause();
            }

        };

        $scope.$root.$on('subtitleKeyUp', function($event, options) {

            var parser = options.parser;
            var subtitle = options.subtitle;
            var value = options.value;

            // Update the Popcorn subtitle instance's text.
            $scope.pop.amarasubtitle(subtitle.popcornSubtitle.id, {
                text: parser.markdownToHTML(value)
            });

        });
        $scope.$root.$on('subtitleReady', function($event, subtitle) {
            // When a subtitle is ready, we need to create a Popcorn subtitle bound to the
            // video's Popcorn instance.

            var parser = subtitle.parser;

            var text = subtitle.parser.content(subtitle.subtitle);
            var endTimeSeconds = parser.endTime(subtitle.subtitle) / 1000;
            var startTimeSeconds = parser.startTime(subtitle.subtitle) / 1000;

            // Create the amarasubtitle instance.
            $scope.pop.amarasubtitle(subtitle.$id, {
                end:   endTimeSeconds,
                start: startTimeSeconds,
                text:  text
            });

            // Store this subtitle reference for easier retrieval later.
            subtitle.popcornSubtitle = $scope.pop.getTrackEvent(subtitle.$id);

        });
        $scope.$root.$on('subtitleSelected', function($event, subtitle) {

            var parser = subtitle.parser;
            var startTimeSeconds = parser.startTime(subtitle.subtitle) / 1000;

            // Set the current time to the start of the subtitle.
            $scope.pop.currentTime(startTimeSeconds);

        });
    };

    root.VideoController = VideoController;

}).call(this);
<commit_msg>No need to store popcorn subtitle ID.<commit_after>// Amara, universalsubtitles.org
//
// Copyright (C) 2013 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

(function() {

    var root = this;

    var VideoController = function($scope, SubtitleStorage) {
        /**
         * Responsible for initializing the video and all video controls.
         * @param $scope
         * @param SubtitleStorage
         * @constructor
         */

        // The Popcorn instance.
        //
        // For now, make sure we force controls.
        $scope.pop = window.Popcorn.smart('#video', SubtitleStorage.getVideoURL() + '&controls=1');

        $scope.playChunk = function(start, duration) {
            // Play a specified amount of time in a video, beginning at 'start',
            // and then pause.

            // Pause the video, first.
            $scope.pop.play();

            // Remove any existing cues that may interfere.
            $scope.removeAllTrackEvents();

            if (start < 0) {
                start = 0;
            }

            // Set the new start time.
            $scope.pop.currentTime(start);

            // Set a new cue to pause the video at the end of the chunk.
            $scope.pop.cue(start + duration, function() {
                $scope.pop.pause();
            });

            // Play the video.
            $scope.pop.play();

        };
        $scope.removeAllTrackEvents = function() {

            var trackEvents = $scope.pop.getTrackEvents();
            for (var i = 0; i < trackEvents.length; i++) {
                $scope.pop.removeTrackEvent(trackEvents[i].id);
            }

        };
        $scope.togglePlay = function() {

            // If the video is paused, play it.
            if ($scope.pop.paused()) {
                $scope.pop.play();

            // Otherwise, pause it.
            } else {
                $scope.pop.pause();
            }

        };

        $scope.$root.$on('subtitleKeyUp', function($event, options) {

            var parser = options.parser;
            var subtitle = options.subtitle;
            var value = options.value;

            // Update the Popcorn subtitle instance's text.
            $scope.pop.amarasubtitle(subtitle.$id, {
                text: parser.markdownToHTML(value)
            });

        });
        $scope.$root.$on('subtitleReady', function($event, subtitle) {
            // When a subtitle is ready, we need to create a Popcorn subtitle bound to the
            // video's Popcorn instance.

            var parser = subtitle.parser;

            var text = subtitle.parser.content(subtitle.subtitle);
            var endTimeSeconds = parser.endTime(subtitle.subtitle) / 1000;
            var startTimeSeconds = parser.startTime(subtitle.subtitle) / 1000;

            // Create the amarasubtitle instance.
            $scope.pop.amarasubtitle(subtitle.$id, {
                end:   endTimeSeconds,
                start: startTimeSeconds,
                text:  text
            });

        });
        $scope.$root.$on('subtitleSelected', function($event, subtitle) {

            var parser = subtitle.parser;
            var startTimeSeconds = parser.startTime(subtitle.subtitle) / 1000;

            // Set the current time to the start of the subtitle.
            $scope.pop.currentTime(startTimeSeconds);

        });
    };

    root.VideoController = VideoController;

}).call(this);
<|endoftext|>


<commit_before>/*
Copyright (c) 2014 - 2017 David Meyer

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

// Config Vars
const img1            = "img/special.png";
const img2            = "img/special2.png";
const imgElement      = "awesome";        // The element id for the title image.
const audioElement    = "playitagain";
const titleSound      = "sounds/duh.mp3";
const dir             = "sounds/";        // The directory of all the audio clips.
const ext             = ".mp3";
const takes           = 3;                // There are 3 takes for each audio clip.

// Instance Vars
let ip          = "";
let sounds      = new Array();
let curSound    = null;
let START_POINT = -1;
let END_POINT   = -1;

/*
* The main init function, called upon ip retrieval
*/
let main = (json)=> {
    // Getting the IP
    ip = json.ip; //".0123456789"
    END_POINT = ip.length;

    // Set up sounds 0 - 9
    for (let i = 0; i <= 9; i++) {
        // Nested array for random sounds 1 - 3
        sounds[i.toString()] = new Array();
        for (let j = 1; j <= takes; j++) { // Add random sounds 1 - 3 for this digit
            sounds[i.toString()][j] = dir + i + "-" + j + ext;
        }
    }

    // Set up special char sounds
    sounds['.'] = new Array();
    sounds['starting'] = new Array();
    sounds['ending'] = new Array();

    for (let i = 1; i <= takes; i++) {
        sounds['.'][i] = dir + "dot-" + i + ext;
        sounds['starting'][i] = dir + "starting-" + i + ext;
        sounds['ending'][i] = dir + "ending-" + i + ext;
    }
}

/*
* Handles playing audio from specified source.
* Includes onend callback.
*/
let playAudio = (src, onend)=> {
    let audio = document.getElementById(audioElement);
    audio.src = src;
    audio.play();
    audio.onended = ()=> {
        onend();
    };
}

/*
* This function increments through the IP and plays the random associated sounds.
*/
let playIP = (i, onend)=> {
    // If past all the chars in IP, we're done.
    if (i > END_POINT) return;

    // Randomly selected sound file number.
    let rand = Math.floor(Math.random() * takes) + 1;

    // Determine current position in IP.
    switch (i) {
        case START_POINT:
            curSound = sounds['starting'][rand];
            break;
        case END_POINT:
            curSound = sounds['ending'][rand];
            onend();
            break;
        default:
            curSound = sounds[ip.charAt(i)][rand];
    }

    // Begin playing sounds. Iterate on complete.
    playAudio(curSound, playIP.bind(null, i+1, onend));
}

/*
* Switches the two title images.
*/
let switchImg = (playing)=> {
    document.getElementById(imgElement).src = (playing) ? img2 : img1;
}

/*
* Plays the title sound of the page.
*/
let playTitleSound = ()=> {
    // Is sound already playing? If so, get out of here!
    if (curSound != null && !curSound.ended) return;

    // Change title image to playing state.
    switchImg(true);

    // Play sound and change title image to default state on complete.
    playAudio(titleSound, switchImg.bind(null, false));
}

/*
* Triggered by user action on click.
* Handles switching the title image and playing the IP.
*/
let onButtonClick = ()=> {
    // Is sound already playing? If so, get out of here!
    if (curSound != null && !curSound.ended) return;

    // Change title image to playing state.
    switchImg(true);

    // Play the IP and change title image to default state on complete.
    playIP(START_POINT, switchImg.bind(null, false));
}
<commit_msg>added const to functions rather than let<commit_after>/*
Copyright (c) 2014 - 2017 David Meyer

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

// Config Vars
const img1            = "img/special.png";
const img2            = "img/special2.png";
const imgElement      = "awesome";        // The element id for the title image.
const audioElement    = "playitagain";
const titleSound      = "sounds/duh.mp3";
const dir             = "sounds/";        // The directory of all the audio clips.
const ext             = ".mp3";
const takes           = 3;                // There are 3 takes for each audio clip.

// Instance Vars
let ip          = "";
let sounds      = new Array();
let curSound    = null;
let START_POINT = -1;
let END_POINT   = -1;

/*
* The main init function, called upon ip retrieval
*/
const main = (json)=> {
    // Getting the IP
    ip = json.ip; //".0123456789"
    END_POINT = ip.length;

    // Set up sounds 0 - 9
    for (let i = 0; i <= 9; i++) {
        // Nested array for random sounds 1 - 3
        sounds[i.toString()] = new Array();
        for (let j = 1; j <= takes; j++) { // Add random sounds 1 - 3 for this digit
            sounds[i.toString()][j] = dir + i + "-" + j + ext;
        }
    }

    // Set up special char sounds
    sounds['.'] = new Array();
    sounds['starting'] = new Array();
    sounds['ending'] = new Array();

    for (let i = 1; i <= takes; i++) {
        sounds['.'][i] = dir + "dot-" + i + ext;
        sounds['starting'][i] = dir + "starting-" + i + ext;
        sounds['ending'][i] = dir + "ending-" + i + ext;
    }
}

/*
* Handles playing audio from specified source.
* Includes onend callback.
*/
const playAudio = (src, onend)=> {
    let audio = document.getElementById(audioElement);
    audio.src = src;
    audio.play();
    audio.onended = ()=> {
        onend();
    };
}

/*
* This function increments through the IP and plays the random associated sounds.
*/
const playIP = (i, onend)=> {
    // If past all the chars in IP, we're done.
    if (i > END_POINT) return;

    // Randomly selected sound file number.
    let rand = Math.floor(Math.random() * takes) + 1;

    // Determine current position in IP.
    switch (i) {
        case START_POINT:
            curSound = sounds['starting'][rand];
            break;
        case END_POINT:
            curSound = sounds['ending'][rand];
            onend();
            break;
        default:
            curSound = sounds[ip.charAt(i)][rand];
    }

    // Begin playing sounds. Iterate on complete.
    playAudio(curSound, playIP.bind(null, i+1, onend));
}

/*
* Switches the two title images.
*/
const switchImg = (playing)=> {
    document.getElementById(imgElement).src = (playing) ? img2 : img1;
}

/*
* Plays the title sound of the page.
*/
const playTitleSound = ()=> {
    // Is sound already playing? If so, get out of here!
    if (curSound != null && !curSound.ended) return;

    // Change title image to playing state.
    switchImg(true);

    // Play sound and change title image to default state on complete.
    playAudio(titleSound, switchImg.bind(null, false));
}

/*
* Triggered by user action on click.
* Handles switching the title image and playing the IP.
*/
const onButtonClick = ()=> {
    // Is sound already playing? If so, get out of here!
    if (curSound != null && !curSound.ended) return;

    // Change title image to playing state.
    switchImg(true);

    // Play the IP and change title image to default state on complete.
    playIP(START_POINT, switchImg.bind(null, false));
}
<|endoftext|>


<commit_before>game.GameTimerManager = Object.extend({
	//initializes the function
	init: function(x, y, settings){
		//the time that we want to use
		this.now = new Date().getTime();
		//keep track of the last time we made a creep happen
		this.lastCreep = new Date().getTime();
		this.paused = false;
		//makes sure it is always updating
		this.alwaysUpdate = true;

	},
	//updates the function
	update: function(){
		//keep track of our timer
		this.now = new Date().getTime();
		this.goldTimerCheck();
		this.creepTimerCheck();

		return true;
	},
	goldTimerCheck: function(){
		if(Math.round(this.now/1000)%20 ===0 && (this.now - this.lastCreep >= 1000)){
			//adds one gold for a creep kill
			game.data.gold +=1;
			//keeps track of our gold
			console.log("Current gold: " + game.data.gold);
		}
	},
	creepTimerCheck: function(){
		//keeps track on whether we should be making creeps
		//checks to see if we have a multiple of 10
		if(Math.round(this.now/1000)%10 ===0 && (this.now - this.lastCreep >= 1000)){
			this.lastCreep = this.now;
			var creepe = me.pool.pull("EnemyCreep", 1000, 0, {});
			//creates a creep
 			//adds the creep to the world
			me.game.world.addChild(creepe, 5);
			var creepe2 = me.pool.pull("Player2", 200, 0, {});
			//creates a creep
 			//adds the creep to the world
			me.game.world.addChild(creepe2, 5);
		}
	}
});
game.HeroDeathManager = Object.extend({
	init: function(x, y, settings){
		//makes sure it is always updating
		this.alwaysUpdate = true;
	},
	update: function(){
		//checks if our player is dead
		//we are asking if he is dead
		//if so we will execute some stuff
		if(game.data.player.dead){
			me.game.world.removeChild(game.data.player);
			me.state.current().resetPlayer(10, 0);
		}
		//makes the code run
		return true;
	}
});
game.ExperienceManager = Object.extend({
	init: function(x, y, settings){
		//makes sure it is always updating
		this.alwaysUpdate = true;
		//sets gameover to false
		this.gameOver = false;
	},
	update: function(){
		//if you win the game is not over
		if(game.data.win === true && !this.gameOver){
			this.gameOver(true);
		}
		else if(game.data.win === false && !this.gameOver){

			this.gameOver(false);
		}
		//makes the code run
		return true;
	},
	gameOver: function(win){
		if(win){
			//adds ten points to the experience variable
			game.data.exp += 10;
		}
		else{
			//adds 1 point to the experience variable
			game.data.exp += 1;
		}
		//makes the game be over
		this.gameOver = true;

		me.save.exp = game.data.exp;
	}
});<commit_msg>commented on video 38<commit_after>game.GameTimerManager = Object.extend({
	//initializes the function
	init: function(x, y, settings){
		//the time that we want to use
		this.now = new Date().getTime();
		//keep track of the last time we made a creep happen
		this.lastCreep = new Date().getTime();
		this.paused = false;
		//makes sure it is always updating
		this.alwaysUpdate = true;

	},
	//updates the function
	update: function(){
		//keep track of our timer
		this.now = new Date().getTime();
		this.goldTimerCheck();
		this.creepTimerCheck();

		return true;
	},
	goldTimerCheck: function(){
		if(Math.round(this.now/1000)%20 ===0 && (this.now - this.lastCreep >= 1000)){
			//adds one gold for a creep kill
			game.data.gold +=1;
			//keeps track of our gold
			console.log("Current gold: " + game.data.gold);
		}
	},
	creepTimerCheck: function(){
		//keeps track on whether we should be making creeps
		//checks to see if we have a multiple of 10
		if(Math.round(this.now/1000)%10 ===0 && (this.now - this.lastCreep >= 1000)){
			this.lastCreep = this.now;
			var creepe = me.pool.pull("EnemyCreep", 1000, 0, {});
			//creates a creep
 			//adds the creep to the world
			me.game.world.addChild(creepe, 5);
			var creepe2 = me.pool.pull("Player2", 200, 0, {});
			//creates a creep
 			//adds the creep to the world
			me.game.world.addChild(creepe2, 5);
		}
	}
});
game.HeroDeathManager = Object.extend({
	init: function(x, y, settings){
		//makes sure it is always updating
		this.alwaysUpdate = true;
	},
	update: function(){
		//checks if our player is dead
		//we are asking if he is dead
		//if so we will execute some stuff
		if(game.data.player.dead){
			me.game.world.removeChild(game.data.player);
			me.state.current().resetPlayer(10, 0);
		}
		//makes the code run
		return true;
	}
});
game.ExperienceManager = Object.extend({
	init: function(x, y, settings){
		//makes sure it is always updating
		this.alwaysUpdate = true;
		//sets gameover to false
		this.gameOver = false;
	},
	update: function(){
		//if you win the game is not over
		if(game.data.win === true && !this.gameOver){
			//sets the gameOver to true
			this.gameOver(true);
		}
		//you gain no points
		else if(game.data.win === false && !this.gameOver){
			//makes the game be over
			this.gameOver(false);
		}
		//makes the code run
		return true;
	},
	//made a gameOver function
	gameOver: function(win){
		//if you win,
		if(win){
			//adds ten points to the experience variable
			game.data.exp += 10;
		}
		//if else you gain 1 point
		else{
			//adds 1 point to the experience variable
			game.data.exp += 1;
		}
		//makes the game be over
		this.gameOver = true;
		//saves the experience
		me.save.exp = game.data.exp;
	}
});<|endoftext|>


<commit_before><commit_msg>fix resource forms didn't transfer settings to pdf<commit_after><|endoftext|>


<commit_before>'use strict';

function Game(data) {
  if (data) {
    this.data = data;
  } else {
    this.data = {
      winner: null,
      whoseTurn: null,
      player1: null,
      player2: null,
      player3: null,
      player4: null,
      disconnected: {},
      title: "Awaiting players ...",
      board: [['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ]]
    };
  }
}

Game.prototype = {
  addPlayer: function(player) {
    if (this.data.player1 != null && this.data.player2 != null && this.data.player3 != null && this.data.player4 != null) return;
    if (this.data.player1 == null) {
      this.data.player1 = player;
      this.data.whoseTurn = this.data.player1;
    } else if (this.data.player2 == null) {
      this.data.player2 = player;
    } else if (this.data.player3 == null) {
      this.data.player3 = player;
    } else if (this.data.player3 == null) {
      this.data.player3 = player;
    }
  },
  title: function() {
    if ( this.isTie() ) {
      this.data.title = "It's a tie!"
    } else if (this.data.winner) {
      this.data.title = this.data.winner + " won!";
    } else {
      if (this.data.player1 != null) {
        this.data.title = this.data.player1 + " vs. ";
        if (this.data.player2 != null) {
          this.data.title = this.data.title + this.data.player2;
        } else {
          this.data.title = this.data.title + "(awaiting 2nd player)";
        }
        if (this.data.player3 != null) {
          this.data.title = this.data.title + this.data.player3;
        } else {
          this.data.title = this.data.title + "(awaiting 3nd player)";
        }
        if (this.data.player4 != null) {
          this.data.title = this.data.title + this.data.player4;
        } else {
          this.data.title = this.data.title + "(awaiting 4th player)";
        }
      }
    }
    return this.data.title;
  },
  board: function() {
    return this.data.board;
  },
  setConnected: function(player) {
    if (!this.data.disconnected) {
      this.data.disconnected = {};
    }
    this.data.disconnected[player] = false;
  },
  isAbandoned: function() {
    if (!this.data.disconnected) return false;
    var numPlayers = 0;
    if (this.data.player1) numPlayers++;
    if (this.data.player2) numPlayers++;
    if (this.data.player3) numPlayers++;
    if (this.data.player4) numPlayers++;
    var numDisconnected = 0;
    for (var k in this.data.disconnected) {
      if (this.data.disconnected[k]) numDisconnected++;
    }
    return (numDisconnected == numPlayers);
  },
  isTie: function() {
    for (var row in [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]) {
      for (var col in [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]) {
        if (this.data.board[row][col] === '') return false;
      }
    }
    return true;
  },
  isOver: function() {
    return (this.isTie() || this.data.winner != null);
  },
  isPlayersTurn: function(player) {
    return this.data.whoseTurn === player;
  },
  playerForMark: function(mark) {
    if (mark === 'A') {
      return this.data.player1;
    } else if (mark === 'B') {
      return this.data.player2;
    }
    else if (mark === 'C'){
      return this.data.player3;
    } else if (mark === 'D') {
      return this.data.player4;
    }
  },
  markForPlayer: function(player) {
    if (player == this.data.player1) {
      return 'A';
    } else if (player == this.data.player2) {
      return 'B';
    } else if (player == this.data.player3) {
      return 'C';
    } else if (player == this.data.player4) {
      return 'D';
    }
  },
  nextPlayerToMove: function(player) {
    if (player == this.data.player1) {
      return this.data.player2;
    } else if (player == this.data.player2) {
      return this.data.player3;
    }
     else if (player == this.data.player3) {
      return this.data.player4;

    } else if (player == this.data.player4) {
      return this.data.player1;
    }

  },
  move: function(player, row, col) {
    if ( this.isOver() ) return;
    if ( !this.isPlayersTurn(player) ) return;
    if (row < 0 || row > 2 || col < 0 || col > 2) return;
    if (this.data.board[row][col] != '') return;

    this.data.board[row][col] = this.markForPlayer(player);
    this.data.whoseTurn = this.nextPlayerToMove(player);
    this.data.winner = this.checkForWinner();
  },
  checkForWinner: function() {
    var b = this.data.board;
    //--------------
    // ROW WINS:
    //--------------
    // 0,0  0,1  0,2
    // 1,0  1,1  1,2
    // 2,0  2,1  2,2
    //--------------

    var name = "";
    var ocurrences = new Array(3);
    var letters = "ABCD";

    firstForLoop: for(var i = 0;i < b.length;i++){
      for(var j = 0;j < b[0].length;j++){
        //Left to Right
        if (i>=(b.length-3) || j>=(b.length-3)) {break firstForLoop;};
        for (var k = 0; i < 3; i++) {
           name+=b[i+k][j];
        };

        for (var n = 0; n <= name.length; n++) {
          if (name.length != 4) {
            name = "";
            break;
          }
          else {
            if (name.charAt(n) === 'A') {
              ocurrences[0]++;
            }
            if (name.charAt(n) === 'B') {
              ocurrences[1]++;
            }
            if (name.charAt(n) === 'C') {
              ocurrences[2]++;
            }
            if (name.charAt(n) === 'D') {
              ocurrences[3]++;
            }
          }
          for (var g = 0; g < ocurrences.length;g++) {
            if(ocurrences[g] == 4){
             return playerForMark(letters.charAt(g));
            }
          };
        }

        //Up to Down
        for (var k = 0; i < 3; i++) {
           name+=b[i][j+k];
        }

        for (var n = 0; n <= name.length; n++) {
          if (name.length != 4) {
            name = "";
            break;
          }
          else {
            if (name.charAt(n) === 'A') {
              ocurrences[0]++;
            }
            if (name.charAt(n) === 'B') {
              ocurrences[1]++;
            }
            if (name.charAt(n) === 'C') {
              ocurrences[2]++;
            }
            if (name.charAt(n) === 'D') {
              ocurrences[3]++;
            }
          }
          for (var g = 0; g < ocurrences.length;g++) {
            if(ocurrences[g] == 4){
             return playerForMark(letters.charAt(g));
            }
          };
        }

        //Diagonal
        for (var k = 0; i < 3; i++) {
           name+=b[i+k][j+k];
        }

        for (var n = 0; n <= name.length; n++) {
          if (name.length != 4) {
            name = "";
            break;
          }
          else {
            if (name.charAt(n) === 'A') {
              ocurrences[0]++;
            }
            if (name.charAt(n) === 'B') {
              ocurrences[1]++;
            }
            if (name.charAt(n) === 'C') {
              ocurrences[2]++;
            }
            if (name.charAt(n) === 'D') {
              ocurrences[3]++;
            }
          }
          for (var g = 0; g < ocurrences.length;g++) {
            if(ocurrences[g] == 4){
             return playerForMark(letters.charAt(g));
            }
          };
        }
      }
    }

    // if (b[0][0] != '' && b[0][0] === b[0][1] && b[0][1] === b[0][2]) {
    //   return this.playerForMark(b[0][0]);
    // } else if (b[1][0] != '' && b[1][0] === b[1][1] && b[1][1] === b[1][2]) {
    //   return this.playerForMark(b[1][0]);
    // } else if (b[2][0] != '' && b[2][0] === b[2][1] && b[2][1] === b[2][2]) {
    //   return this.playerForMark(b[2][0]);
    // }

    // //--------------
    // // COL WINS:
    // //--------------
    // // 0,0  1,0  2,0
    // // 0,1  1,1  2,1
    // // 0,2  1,2  2,2
    // //--------------
    // if (b[0][0] != '' && b[0][0] === b[1][0] && b[1][0] === b[2][0]) {
    //   return this.playerForMark(b[0][0]);
    // } else if (b[0][1] != '' && b[0][1] === b[1][1] && b[1][1] === b[2][1]) {
    //   return this.playerForMark(b[0][1]);
    // } else if (b[0][2] != '' && b[0][2] === b[1][2] && b[1][2] === b[2][2]) {
    //   return this.playerForMark(b[0][2]);
    // }

    // //--------------
    // // DIAG WINS:
    // //--------------
    // // 0,0  1,1  2,2
    // // 0,2  1,1  2,0
    // //--------------
    // if (b[0][0] != '' && b[0][0] === b[1][1] && b[1][1] === b[2][2]) {
    //   return this.playerForMark(b[0][0]);
    // } else if (b[0][2] != '' && b[0][2] === b[1][1] && b[1][1] === b[2][0]) {
    //   return this.playerForMark(d);
    // } else {
    //   // NO WINNER
    //   return null;
    // }
  }
}

angular.module('ticTacToe.controllers.game', ['firebase', 'ngCookies'])
  .controller('GameCtrl',
    ['$scope', '$routeParams', '$location', '$cookies', 'angularFire', 'angularFireCollection',
    function($scope, $routeParams, $location, $cookies, angularFire, angularFireCollection) {
      $scope.username = $cookies.username;

      var gameUrl = 'https://radiant-fire-7849.firebaseio.com/games/' + $routeParams.gameId;
      var disconnectedRef = new Firebase(gameUrl + "/disconnected/" + $scope.username);
      disconnectedRef.onDisconnect().set(true);
      var promise = angularFire(gameUrl, $scope, 'gameData', {});
      promise.then(function(game) {
        watchGame($scope, $routeParams, angularFire, angularFireCollection);
      });
    }]
  );

function watchGame($scope, $routeParams, angularFire, angularFireCollection) {
  $scope.$watch('gameData', function() {
    $scope.game = new Game($scope.gameData);
    $scope.game.setConnected($scope.username);
  });

  $scope.mouseOver = function(player, row, col, $event) {
    if (! $scope.game.isPlayersTurn(player) ) return;

    if ($scope.game.board()[row][col] == '') {
      $event.target.style.cursor = 'pointer';
    }
  };

  $scope.mouseOut = function($event) {
    $event.target.style.cursor = 'default';
  };
}
<commit_msg>grid fo the full thang<commit_after>'use strict';

function Game(data) {
  if (data) {
    this.data = data;
  } else {
    this.data = {
      winner: null,
      whoseTurn: null,
      player1: null,
      player2: null,
      player3: null,
      player4: null,
      disconnected: {},
      title: "Awaiting players ...",
      board: [['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ], ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ]]
    };
  }
}

Game.prototype = {
  addPlayer: function(player) {
    if (this.data.player1 != null && this.data.player2 != null && this.data.player3 != null && this.data.player4 != null) return;
    if (this.data.player1 == null) {
      this.data.player1 = player;
      this.data.whoseTurn = this.data.player1;
    } else if (this.data.player2 == null) {
      this.data.player2 = player;
    } else if (this.data.player3 == null) {
      this.data.player3 = player;
    } else if (this.data.player3 == null) {
      this.data.player3 = player;
    }
  },
  title: function() {
    if ( this.isTie() ) {
      this.data.title = "It's a tie!"
    } else if (this.data.winner) {
      this.data.title = this.data.winner + " won!";
    } else {
      if (this.data.player1 != null) {
        this.data.title = this.data.player1 + " vs. ";
        if (this.data.player2 != null) {
          this.data.title = this.data.title + this.data.player2;
        } else {
          this.data.title = this.data.title + "(awaiting 2nd player)";
        }
        if (this.data.player3 != null) {
          this.data.title = this.data.title + this.data.player3;
        } else {
          this.data.title = this.data.title + "(awaiting 3nd player)";
        }
        if (this.data.player4 != null) {
          this.data.title = this.data.title + this.data.player4;
        } else {
          this.data.title = this.data.title + "(awaiting 4th player)";
        }
      }
    }
    return this.data.title;
  },
  board: function() {
    return this.data.board;
  },
  setConnected: function(player) {
    if (!this.data.disconnected) {
      this.data.disconnected = {};
    }
    this.data.disconnected[player] = false;
  },
  isAbandoned: function() {
    if (!this.data.disconnected) return false;
    var numPlayers = 0;
    if (this.data.player1) numPlayers++;
    if (this.data.player2) numPlayers++;
    if (this.data.player3) numPlayers++;
    if (this.data.player4) numPlayers++;
    var numDisconnected = 0;
    for (var k in this.data.disconnected) {
      if (this.data.disconnected[k]) numDisconnected++;
    }
    return (numDisconnected == numPlayers);
  },
  isTie: function() {
    for (var row in [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]) {
      for (var col in [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]) {
        if (this.data.board[row][col] === '') return false;
      }
    }
    return true;
  },
  isOver: function() {
    return (this.isTie() || this.data.winner != null);
  },
  isPlayersTurn: function(player) {
    return this.data.whoseTurn === player;
  },
  playerForMark: function(mark) {
    if (mark === 'A') {
      return this.data.player1;
    } else if (mark === 'B') {
      return this.data.player2;
    }
    else if (mark === 'C'){
      return this.data.player3;
    } else if (mark === 'D') {
      return this.data.player4;
    }
  },
  markForPlayer: function(player) {
    if (player == this.data.player1) {
      return 'A';
    } else if (player == this.data.player2) {
      return 'B';
    } else if (player == this.data.player3) {
      return 'C';
    } else if (player == this.data.player4) {
      return 'D';
    }
  },
  nextPlayerToMove: function(player) {
    if (player == this.data.player1) {
      return this.data.player2;
    } else if (player == this.data.player2) {
      return this.data.player3;
    }
     else if (player == this.data.player3) {
      return this.data.player4;

    } else if (player == this.data.player4) {
      return this.data.player1;
    }

  },
  move: function(player, row, col) {
    if ( this.isOver() ) return;
    if ( !this.isPlayersTurn(player) ) return;
    if (row < 0 || row > 19 || col < 0 || col > 19) return;
    if (this.data.board[row][col] != '') return;

    this.data.board[row][col] = this.markForPlayer(player);
    this.data.whoseTurn = this.nextPlayerToMove(player);
    this.data.winner = this.checkForWinner();
  },
  checkForWinner: function() {
    var b = this.data.board;
    //--------------
    // ROW WINS:
    //--------------
    // 0,0  0,1  0,2
    // 1,0  1,1  1,2
    // 2,0  2,1  2,2
    //--------------

    var name = "";
    var ocurrences = new Array(3);
    var letters = "ABCD";

    firstForLoop: for(var i = 0;i < b.length;i++){
      for(var j = 0;j < b[0].length;j++){
        //Left to Right
        if (i>=(b.length-3) || j>=(b.length-3)) {break firstForLoop;};
        for (var k = 0; i < 3; i++) {
           name+=b[i+k][j];
        };

        for (var n = 0; n <= name.length; n++) {
          if (name.length != 4) {
            name = "";
            break;
          }
          else {
            if (name.charAt(n) === 'A') {
              ocurrences[0]++;
            }
            if (name.charAt(n) === 'B') {
              ocurrences[1]++;
            }
            if (name.charAt(n) === 'C') {
              ocurrences[2]++;
            }
            if (name.charAt(n) === 'D') {
              ocurrences[3]++;
            }
          }
          for (var g = 0; g < ocurrences.length;g++) {
            if(ocurrences[g] == 4){
             return playerForMark(letters.charAt(g));
            }
          };
        }

        //Up to Down
        for (var k = 0; i < 3; i++) {
           name+=b[i][j+k];
        }

        for (var n = 0; n <= name.length; n++) {
          if (name.length != 4) {
            name = "";
            break;
          }
          else {
            if (name.charAt(n) === 'A') {
              ocurrences[0]++;
            }
            if (name.charAt(n) === 'B') {
              ocurrences[1]++;
            }
            if (name.charAt(n) === 'C') {
              ocurrences[2]++;
            }
            if (name.charAt(n) === 'D') {
              ocurrences[3]++;
            }
          }
          for (var g = 0; g < ocurrences.length;g++) {
            if(ocurrences[g] == 4){
             return playerForMark(letters.charAt(g));
            }
          };
        }

        //Diagonal
        for (var k = 0; i < 3; i++) {
           name+=b[i+k][j+k];
        }

        for (var n = 0; n <= name.length; n++) {
          if (name.length != 4) {
            name = "";
            break;
          }
          else {
            if (name.charAt(n) === 'A') {
              ocurrences[0]++;
            }
            if (name.charAt(n) === 'B') {
              ocurrences[1]++;
            }
            if (name.charAt(n) === 'C') {
              ocurrences[2]++;
            }
            if (name.charAt(n) === 'D') {
              ocurrences[3]++;
            }
          }
          for (var g = 0; g < ocurrences.length;g++) {
            if(ocurrences[g] == 4){
             return playerForMark(letters.charAt(g));
            }
          };
        }
      }
    }

    // if (b[0][0] != '' && b[0][0] === b[0][1] && b[0][1] === b[0][2]) {
    //   return this.playerForMark(b[0][0]);
    // } else if (b[1][0] != '' && b[1][0] === b[1][1] && b[1][1] === b[1][2]) {
    //   return this.playerForMark(b[1][0]);
    // } else if (b[2][0] != '' && b[2][0] === b[2][1] && b[2][1] === b[2][2]) {
    //   return this.playerForMark(b[2][0]);
    // }

    // //--------------
    // // COL WINS:
    // //--------------
    // // 0,0  1,0  2,0
    // // 0,1  1,1  2,1
    // // 0,2  1,2  2,2
    // //--------------
    // if (b[0][0] != '' && b[0][0] === b[1][0] && b[1][0] === b[2][0]) {
    //   return this.playerForMark(b[0][0]);
    // } else if (b[0][1] != '' && b[0][1] === b[1][1] && b[1][1] === b[2][1]) {
    //   return this.playerForMark(b[0][1]);
    // } else if (b[0][2] != '' && b[0][2] === b[1][2] && b[1][2] === b[2][2]) {
    //   return this.playerForMark(b[0][2]);
    // }

    // //--------------
    // // DIAG WINS:
    // //--------------
    // // 0,0  1,1  2,2
    // // 0,2  1,1  2,0
    // //--------------
    // if (b[0][0] != '' && b[0][0] === b[1][1] && b[1][1] === b[2][2]) {
    //   return this.playerForMark(b[0][0]);
    // } else if (b[0][2] != '' && b[0][2] === b[1][1] && b[1][1] === b[2][0]) {
    //   return this.playerForMark(d);
    // } else {
    //   // NO WINNER
    //   return null;
    // }
  }
}

angular.module('ticTacToe.controllers.game', ['firebase', 'ngCookies'])
  .controller('GameCtrl',
    ['$scope', '$routeParams', '$location', '$cookies', 'angularFire', 'angularFireCollection',
    function($scope, $routeParams, $location, $cookies, angularFire, angularFireCollection) {
      $scope.username = $cookies.username;

      var gameUrl = 'https://radiant-fire-7849.firebaseio.com/games/' + $routeParams.gameId;
      var disconnectedRef = new Firebase(gameUrl + "/disconnected/" + $scope.username);
      disconnectedRef.onDisconnect().set(true);
      var promise = angularFire(gameUrl, $scope, 'gameData', {});
      promise.then(function(game) {
        watchGame($scope, $routeParams, angularFire, angularFireCollection);
      });
    }]
  );

function watchGame($scope, $routeParams, angularFire, angularFireCollection) {
  $scope.$watch('gameData', function() {
    $scope.game = new Game($scope.gameData);
    $scope.game.setConnected($scope.username);
  });

  $scope.mouseOver = function(player, row, col, $event) {
    if (! $scope.game.isPlayersTurn(player) ) return;

    if ($scope.game.board()[row][col] == '') {
      $event.target.style.cursor = 'pointer';
    }
  };

  $scope.mouseOut = function($event) {
    $event.target.style.cursor = 'default';
  };
}
<|endoftext|>


<commit_before>(function() {

// Monkey-patch to use a dict instead of a list, which allows for faster
// removal of entries.

MochiKit.DragAndDrop.Droppables._drops = {};
MochiKit.DragAndDrop.Droppables._drop_id = 0;

MochiKit.DragAndDrop.Droppables.register = function(drop) {
    this.drops.push(drop);
    this._drop_id += 1;
    this._drops[this._drop_id] = drop;
    drop._id = this._drop_id;
};

MochiKit.DragAndDrop.Droppables.unregister = function(drop) {
    delete this._drops[drop._id];
    this.drops = [];
    var keys = Object.keys(this._drops);
    for (var i = 0; i < keys.length; i++) {
        this.drops.push(this._drops[keys[i]]);
    }
};

MochiKit.DragAndDrop.Droppables.remove = function(element) {
    element = MochiKit.DOM.getElement(element);
    var remove_keys = [];
    var keys = Object.keys(this._drops);
    for (var i = 0; i < keys.length; i++) {
        if (this._drops[keys[i]].element == element) {
            remove_keys.push(keys[i]);
        }
    }

    for (i = 0; i < remove_keys.length; i++) {
        this.unregister(this._drops[remove_keys[i]]);
    }
};

MochiKit.DragAndDrop.Draggables._drags = {};
MochiKit.DragAndDrop.Draggables._drag_id = 0;

MochiKit.DragAndDrop.Draggables.register = function(draggable) {
    if (this.drags.length === 0) {
        var conn = MochiKit.Signal.connect;
        this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag);
        this.eventMouseMove = conn(document, 'onmousemove', this,
                                   this.updateDrag);
        this.eventKeypress = conn(document, 'onkeypress', this,
                                  this.keyPress);
    }
    this.drags.push(draggable);
    this._drag_id += 1;
    this._drags[this._drag_id] = draggable;
    draggable._id = this._drag_id;
};

MochiKit.DragAndDrop.Draggables.unregister = function(draggable) {
    delete this._drags[draggable._id];
    this.drags = [];
    var keys = Object.keys(this._drags);
    for (var i = 0; i < keys.length; i++) {
        this.drags.push(this._drags[keys[i]]);
    }

    if (this.drags.length === 0) {
        var disc = MochiKit.Signal.disconnect;
        disc(this.eventMouseUp);
        disc(this.eventMouseMove);
        disc(this.eventKeypress);
    }
};

// Monkey-patch to deactivate last active droppable only if it is not affected
// anymore (this allows landing zones to enlarge on hover and stay that way
// until mouseout, for example).

MochiKit.DragAndDrop.Droppables.show = function (point, element) {
    if (!this.drops.length) {
        return;
    }
    var affected = [];

    // This is the only changed line, everything else is copy&paste, sigh.
    if (this.last_active && !this.last_active.isAffected(point, element)) {
        this.last_active.deactivate();
    }
    MochiKit.Iter.forEach(this.drops, function (drop) {
        if (drop.isAffected(point, element)) {
            affected.push(drop);
        }
    });
    if (affected.length > 0) {
        drop = this.findDeepestChild(affected);
        MochiKit.Position.within(drop.element, point.page.x, point.page.y);
        drop.options.onhover(element, drop.element,
            MochiKit.Position.overlap(drop.options.overlap, drop.element));
        drop.activate();
    }
};

}());
<commit_msg>Fix JSLint error.<commit_after>(function() {

// Monkey-patch to use a dict instead of a list, which allows for faster
// removal of entries.

MochiKit.DragAndDrop.Droppables._drops = {};
MochiKit.DragAndDrop.Droppables._drop_id = 0;

MochiKit.DragAndDrop.Droppables.register = function(drop) {
    this.drops.push(drop);
    this._drop_id += 1;
    this._drops[this._drop_id] = drop;
    drop._id = this._drop_id;
};

MochiKit.DragAndDrop.Droppables.unregister = function(drop) {
    delete this._drops[drop._id];
    this.drops = [];
    var keys = Object.keys(this._drops);
    for (var i = 0; i < keys.length; i++) {
        this.drops.push(this._drops[keys[i]]);
    }
};

MochiKit.DragAndDrop.Droppables.remove = function(element) {
    element = MochiKit.DOM.getElement(element);
    var remove_keys = [];
    var keys = Object.keys(this._drops);
    for (var i = 0; i < keys.length; i++) {
        if (this._drops[keys[i]].element == element) {
            remove_keys.push(keys[i]);
        }
    }

    for (i = 0; i < remove_keys.length; i++) {
        this.unregister(this._drops[remove_keys[i]]);
    }
};

MochiKit.DragAndDrop.Draggables._drags = {};
MochiKit.DragAndDrop.Draggables._drag_id = 0;

MochiKit.DragAndDrop.Draggables.register = function(draggable) {
    if (this.drags.length === 0) {
        var conn = MochiKit.Signal.connect;
        this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag);
        this.eventMouseMove = conn(document, 'onmousemove', this,
                                   this.updateDrag);
        this.eventKeypress = conn(document, 'onkeypress', this,
                                  this.keyPress);
    }
    this.drags.push(draggable);
    this._drag_id += 1;
    this._drags[this._drag_id] = draggable;
    draggable._id = this._drag_id;
};

MochiKit.DragAndDrop.Draggables.unregister = function(draggable) {
    delete this._drags[draggable._id];
    this.drags = [];
    var keys = Object.keys(this._drags);
    for (var i = 0; i < keys.length; i++) {
        this.drags.push(this._drags[keys[i]]);
    }

    if (this.drags.length === 0) {
        var disc = MochiKit.Signal.disconnect;
        disc(this.eventMouseUp);
        disc(this.eventMouseMove);
        disc(this.eventKeypress);
    }
};

// Monkey-patch to deactivate last active droppable only if it is not affected
// anymore (this allows landing zones to enlarge on hover and stay that way
// until mouseout, for example).

MochiKit.DragAndDrop.Droppables.show = function (point, element) {
    if (!this.drops.length) {
        return;
    }
    var affected = [];

    // This is the only changed line, everything else is copy&paste, sigh.
    if (this.last_active && !this.last_active.isAffected(point, element)) {
        this.last_active.deactivate();
    }
    MochiKit.Iter.forEach(this.drops, function (drop) {
        if (drop.isAffected(point, element)) {
            affected.push(drop);
        }
    });
    if (affected.length > 0) {
        var drop = this.findDeepestChild(affected);
        MochiKit.Position.within(drop.element, point.page.x, point.page.y);
        drop.options.onhover(element, drop.element,
            MochiKit.Position.overlap(drop.options.overlap, drop.element));
        drop.activate();
    }
};

}());
<|endoftext|>


<commit_before>//
//   Copyright 2009-2014 Ilkka Oksanen <iao@iki.fi>
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing,
//   software distributed under the License is distributed on an "AS
//   IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
//   express or implied.  See the License for the specific language
//   governing permissions and limitations under the License.
//

'use strict';

const path = require('path');
const router = require('koa-router')();
const serve = require('koa-static');
const mount = require('koa-mount');
const bodyParser = require('koa-bodyparser');
const koaBody = require('koa-body');
const conf = require('../lib/conf');
const passport = require('../lib/passport');
const cacheFilter = require('../lib/cacheFilter');
const registerController = require('../controllers/register');
const loginController = require('../controllers/login');
const websiteController = require('../controllers/website');
const uploadController = require('../controllers/upload');
const userFilesController = require('../controllers/userFiles');
const forgotPasswordController = require('../controllers/forgotPassword');
const confirmEmailController = require('../controllers/confirmEmail');

exports.register = function register(app) {
    app.use(cacheFilter);

    // Passport authentication routes
    if (conf.get('googleauth:enabled') && conf.get('googleauth:openid_realm')) {
        router.get('/auth/google', passport.authenticate('google', {
            scope: 'email profile',
            openIDRealm: conf.get('googleauth:openid_realm')
        }));
        router.get('/auth/google/oauth2callback', loginController.googleLogin);
    }

    if (conf.get('yahooauth:enabled')) {
        router.get('/auth/yahoo', passport.authenticate('yahoo'));
        router.get('/auth/yahoo/callback', loginController.yahooLogin);
    }

    if (conf.get('cloudronauth:enabled')) {
        router.get('/auth/cloudron', passport.authenticate('cloudron'));
        router.get('/auth/cloudron/callback', loginController.cloudronLogin);
    }

    router.post('/login', bodyParser(), loginController.localLogin);

    // File upload endpoint
    router.post('/api/v1/upload', koaBody({ multipart: true }), uploadController);

    // Registration routes
    router.get('/register', registerController.index);
    router.post('/register', bodyParser(), registerController.create);
    router.post('/register-ext', registerController.createExt);
    router.post('/register-reset', registerController.createReset);

    // Forgot password
    router.post('/forgot-password', bodyParser(), forgotPasswordController.create);
    router.get('/reset-password/:token', registerController.indexReset);

    // Confirm email
    router.get('/confirm-email/:token', confirmEmailController.show);

    // Web site pages route
    router.get('/', websiteController);
    router.get('/:page', websiteController);

    // Public assets
    router.get('/files/:uuid/:slug*', userFilesController);

    app.use(router.routes()).use(router.allowedMethods());

    // Ember CLI Live Reload redirect hack
    if (conf.get('common:dev_mode')) {
        router.get('/ember-cli-live-reload.js', function *redirect() { // eslint-disable-line require-yield, max-len
            this.redirect('http://localhost:4200/ember-cli-live-reload.js');
        });
    }

    app.use(serve(path.join(__dirname, '..', 'website'), {
        maxage: 1000 * 60 * 60 * 24 * 365 // 1 year
    }));

    // Ember client assets
    app.use(mount('/app', serve(path.join(__dirname, '../../client/dist'))));
};
<commit_msg>Add route for the new client<commit_after>//
//   Copyright 2009-2014 Ilkka Oksanen <iao@iki.fi>
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing,
//   software distributed under the License is distributed on an "AS
//   IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
//   express or implied.  See the License for the specific language
//   governing permissions and limitations under the License.
//

'use strict';

const path = require('path');
const router = require('koa-router')();
const serve = require('koa-static');
const mount = require('koa-mount');
const bodyParser = require('koa-bodyparser');
const koaBody = require('koa-body');
const conf = require('../lib/conf');
const passport = require('../lib/passport');
const cacheFilter = require('../lib/cacheFilter');
const registerController = require('../controllers/register');
const loginController = require('../controllers/login');
const websiteController = require('../controllers/website');
const uploadController = require('../controllers/upload');
const userFilesController = require('../controllers/userFiles');
const forgotPasswordController = require('../controllers/forgotPassword');
const confirmEmailController = require('../controllers/confirmEmail');

const ONE_YEAR_IN_MS = 1000 * 60 * 60 * 24 * 365;

exports.register = function register(app) {
    app.use(cacheFilter);

    // Passport authentication routes
    if (conf.get('googleauth:enabled') && conf.get('googleauth:openid_realm')) {
        router.get('/auth/google', passport.authenticate('google', {
            scope: 'email profile',
            openIDRealm: conf.get('googleauth:openid_realm')
        }));
        router.get('/auth/google/oauth2callback', loginController.googleLogin);
    }

    if (conf.get('yahooauth:enabled')) {
        router.get('/auth/yahoo', passport.authenticate('yahoo'));
        router.get('/auth/yahoo/callback', loginController.yahooLogin);
    }

    if (conf.get('cloudronauth:enabled')) {
        router.get('/auth/cloudron', passport.authenticate('cloudron'));
        router.get('/auth/cloudron/callback', loginController.cloudronLogin);
    }

    router.post('/login', bodyParser(), loginController.localLogin);

    // File upload endpoint
    router.post('/api/v1/upload', koaBody({ multipart: true }), uploadController);

    // Registration routes
    router.get('/register', registerController.index);
    router.post('/register', bodyParser(), registerController.create);
    router.post('/register-ext', registerController.createExt);
    router.post('/register-reset', registerController.createReset);

    // Forgot password
    router.post('/forgot-password', bodyParser(), forgotPasswordController.create);
    router.get('/reset-password/:token', registerController.indexReset);

    // Confirm email
    router.get('/confirm-email/:token', confirmEmailController.show);

    // Web site pages route
    router.get('/', websiteController);
    router.get('/:page', websiteController);

    // Public assets
    router.get('/files/:uuid/:slug*', userFilesController);

    app.use(router.routes()).use(router.allowedMethods());

    // Ember CLI Live Reload redirect hack
    if (conf.get('common:dev_mode')) {
        router.get('/ember-cli-live-reload.js', function *redirect() { // eslint-disable-line require-yield, max-len
            this.redirect('http://localhost:4200/ember-cli-live-reload.js');
        });
    }

    app.use(serve(path.join(__dirname, '..', 'website'), {
        maxage: ONE_YEAR_IN_MS
    }));

    app.use(mount('/sector17/', serve(path.join(__dirname, '../../newclient/dist'), {
        maxage: ONE_YEAR_IN_MS // TODO: Bad for index.html
    })));

    // Ember client assets, cacheFilter handles caching
    app.use(mount('/app', serve(path.join(__dirname, '../../client/dist'))));
};
<|endoftext|>


<commit_before>var Whisper = Whisper || {};

(function () {
  'use strict';

  var destroyer = Backbone.View.extend({
    tagName: 'button',
    className: 'btn btn-square btn-sm destroy',
    events: {
      'click': 'destroy'
    },
    initialize: function() {
      this.$el.html('×');
    },

    destroy: function() {
      this.model.messages().each(function(message) { message.destroy(); });
      this.model.set('active', false);
      this.model.save();
      this.model.trigger('destroy');
    }
  });

  var menu = Backbone.View.extend({
    tagName: 'ul',
    className: 'menu',
    initialize: function() {
      this.$el.html("
delete
");
    }
  });

  Whisper.ConversationView = Backbone.View.extend({
    tagName: 'li',
    className: 'conversation',

    events: {
      'click': 'toggle',
      'submit form': 'sendMessage'
    },
    initialize: function() {
      this.listenTo(this.model, 'change', this.render); // auto update
      this.listenTo(this.model, 'message', this.addMessage); // auto update
      this.listenTo(this.model, 'destroy', this.remove); // auto update
      this.listenTo(Whisper.Messages, 'reset', this.addAllMessages); // auto update

      this.$el.addClass('closed');
      this.$destroy = (new destroyer({model: this.model})).$el;

      this.$image  = $('
');
      this.$name   = $('');
      this.$header = $('
').append(this.$image, this.$name);

      this.$button = $('<button class="btn">').append($('').text('Send'));
      this.$input  = $('<input type="text">').attr('autocomplete','off');
      this.$form   = $("<form class=''>").append(this.$input);

      this.$messages    = $('
');
      this.$collapsable = $('
').hide();
      this.$collapsable.append(this.$messages, this.$form);

      this.$el.append(this.$destroy, this.$header, this.$collapsable);
    },

    sendMessage: function(e) {
      if (!this.$input.val().length) { return false; }
      this.model.sendMessage(this.$input.val());
      this.$input.val("");
      e.preventDefault();
    },

    remove: function() {
      this.$el.remove();
    },

    close: function() {
      if (!this.$el.hasClass('closed')) {
        this.$el.addClass('closed').find('.collapsable').slideUp(600);
      }
    },

    open: function(e) {
      if (this.$el.hasClass('closed')) {
        this.$el.removeClass('closed');
        this.$collapsable.slideDown(600);
      }
      this.$input.focus();
    },

    toggle: function() {
      if (this.$el.hasClass('closed')) {
        this.open();
      } else {
        this.close();
      }
    },

    addMessage: function (message) {
      var view = new Whisper.MessageView({ model: message });
      this.$messages.append(view.render().el);
    },

    addAllMessages: function () {
      this.model.messages().each(this.addMessage, this);
      this.render();
    },

    render: function() {
      this.$name.text(this.model.get('name'));
      this.$image.css('background-image: ' + this.model.get('image') + ';');
      return this;
    }
  });
})();
<commit_msg>Use $.find so these locals can go away<commit_after>var Whisper = Whisper || {};

(function () {
  'use strict';

  var destroyer = Backbone.View.extend({
    tagName: 'button',
    className: 'btn btn-square btn-sm destroy',
    events: {
      'click': 'destroy'
    },
    initialize: function() {
      this.$el.html('×');
    },

    destroy: function() {
      this.model.messages().each(function(message) { message.destroy(); });
      this.model.set('active', false);
      this.model.save();
      this.model.trigger('destroy');
    }
  });

  var menu = Backbone.View.extend({
    tagName: 'ul',
    className: 'menu',
    initialize: function() {
      this.$el.html("
delete
");
    }
  });

  Whisper.ConversationView = Backbone.View.extend({
    tagName: 'li',
    className: 'conversation',

    events: {
      'click': 'toggle',
      'submit form': 'sendMessage'
    },
    initialize: function() {
      this.listenTo(this.model, 'change', this.render); // auto update
      this.listenTo(this.model, 'message', this.addMessage); // auto update
      this.listenTo(this.model, 'destroy', this.remove); // auto update
      this.listenTo(Whisper.Messages, 'reset', this.addAllMessages); // auto update

      this.$el.addClass('closed');
      this.$destroy = (new destroyer({model: this.model})).$el;

      this.$image  = $('
');
      this.$name   = $('');
      this.$header = $('
').append(this.$image, this.$name);

      this.$button = $('<button class="btn">').append($('').text('Send'));
      this.$input  = $('<input type="text">').attr('autocomplete','off');
      this.$form   = $("<form class=''>").append(this.$input);

      this.$messages    = $('
');
      this.$collapsable = $('
').hide();
      this.$collapsable.append(this.$messages, this.$form);

      this.$el.append(this.$destroy, this.$header, this.$collapsable);
    },

    sendMessage: function(e) {
      if (!this.$input.val().length) { return false; }
      this.model.sendMessage(this.$input.val());
      this.$input.val("");
      e.preventDefault();
    },

    remove: function() {
      this.$el.remove();
    },

    close: function() {
      if (!this.$el.hasClass('closed')) {
        this.$el.addClass('closed').find('.collapsable').slideUp(600);
      }
    },

    open: function(e) {
      if (this.$el.hasClass('closed')) {
        this.$el.removeClass('closed');
        this.$el.find('.collapsable').slideDown(600);
      }
      this.$el.find('input').focus();
    },

    toggle: function() {
      if (this.$el.hasClass('closed')) {
        this.open();
      } else {
        this.close();
      }
    },

    addMessage: function (message) {
      var view = new Whisper.MessageView({ model: message });
      this.$messages.append(view.render().el);
    },

    addAllMessages: function () {
      this.model.messages().each(this.addMessage, this);
      this.render();
    },

    render: function() {
      this.$name.text(this.model.get('name'));
      this.$image.css('background-image: ' + this.model.get('image') + ';');
      return this;
    }
  });
})();
<|endoftext|>