<commit_before>const root = require('../..');
const Treap = root.DataStructures.Treap;
const assert = require('assert');

describe('Treap', () => {
  let treap;
  before(() => {
    treap = new Treap();
  });

  it('inserts elements', () => {
    treap.insert(3);
    treap.insert(2);
    treap.insert(10);
    treap.insert(-1);
    treap.insert(100);
    treap.insert(101);
    treap.insert(1);
    assert.equal(treap.root.size, 7);
    treap.insert(-100);
    assert.equal(treap.root.size, 8);
  });

  it('removes elements correctly', () => {
    // Value that not exist
    treap.remove(200);
    assert.equal(treap.root.size, 8);
    treap.remove(100);
    assert.equal(treap.root.size, 7);
    treap.remove(1);
    treap.remove(-1);
    treap.remove(-1);
    treap.remove(101);
    assert.equal(treap.root.size, 4);
  });

  it('inserts and remove elements', () => {
    // [-100, 2, 3, 10]
    treap.insert(200);
    // [-100, 2, 3, 10, 200]
    assert.equal(treap.root.size, 5);
    treap.remove(-100);
    // [2, 3, 10, 200]
    assert.equal(treap.root.size, 4);
    treap.insert(1);
    treap.remove(1);
    treap.insert(1);
    // [1, 2, 3, 10, 200]
    treap.remove(200);
    treap.insert(100);
    // [1, 2, 3, 10, 100]
    assert.equal(treap.root.size, 5);
  });

  it('checks if an element exists', () => {
    // [1, 2, 3, 10, 100]
    assert.equal(treap.find(1), true);
    assert.equal(treap.find(2), true);
    assert.equal(treap.find(3), true);
    assert.equal(treap.find(10), true);
    assert.equal(treap.find(100), true);
    assert.equal(treap.find(200), false);
    assert.equal(treap.find(-100), false);
    assert.equal(treap.find(-1), false);
    assert.equal(treap.find(101), false);
  });

  it('gets minimum element', () => {
    // [1, 2, 3, 10, 100]
    assert.equal(treap.minimum(), 1);
    treap.remove(1);
    // [2, 3, 10, 100]
    assert.equal(treap.minimum(), 2);
    treap.insert(-100);
    // [-100, 2, 3, 10, 100]
    assert.equal(treap.minimum(), -100);
    treap.remove(-100);
    // [2, 3, 10, 100]
    assert.equal(treap.minimum(), 2);
  });

  it('gets maximum element', () => {
    // [2, 3, 10, 100]
    assert.equal(treap.maximum(), 100);
    treap.remove(100);
    // [2, 3, 10]
    assert.equal(treap.maximum(), 10);
    treap.remove(10);
    // [2, 3]
    assert.equal(treap.maximum(), 3);
    treap.remove(3);
    // [2]
    assert.equal(treap.maximum(), 2);
    treap.insert(1);
    // [1, 2]
    assert.equal(treap.maximum(), 2);
    treap.remove(2);
    // [1]
    assert.equal(treap.maximum(), 1);
  });

  it('handles dumplicated elements', () => {
    treap.insert(1);
    // [1, 1]
    assert.equal(treap.size(), 2);
    treap.insert(-1);
    // [-1, 1, 1]
    assert.equal(treap.size(), 3);
    treap.remove(1);
    // [-1, 1]
    assert.equal(treap.size(), 2);
    treap.insert(-1);
    treap.insert(-1);
    treap.insert(-1);
    // [-1, -1, -1, -1, 1]
    assert.equal(treap.size(), 5);
    treap.remove(-1);
    treap.remove(1);
    treap.remove(-1);
    treap.remove(-1);
    treap.remove(-1);
    assert.equal(treap.size(), 0);
  });

  it('keeps balance', () => {
    // Insert 1023 elements randomly
    for (let i = 0; i < 1023; ++i) {
      treap.insert(Math.random());
    }
    assert.equal(treap.size(), 1023);
    // The averange height should be 23 (with an error of 5)
    assert(Math.abs(treap.height() - 23) < 5);
  });

  it('rotates correctly', () => {
    // Force clear the tree
    treap.root = null;
    treap.insert(1);
    // 1
    assert.equal(treap.height(), 1);

    // Make the tree definite
    treap.root.key = 2;
    treap.insert(2);
    /**
     *   2
     *  /
     * 1
     *
   */
    assert.equal(treap.height(), 2);

    treap.root.key = 1;
    treap.insert(3);
    /**
     *     3
     *    /
     *   2
     *  /
     * 1
     *
   */
    assert.equal(treap.height(), 3);
    assert.equal(treap.root.value, 3);

    treap.root = treap.root.rotate(0);
    /**
     *   2
     *  / \
     * 1   3
     *
   */
    assert.equal(treap.height(), 2);
    assert.equal(treap.root.value, 2);

    treap.root = treap.root.rotate(0);
    /**
     * 1
     *  \
     *   2
     *    \
     *     3
     *
   */
    assert.equal(treap.height(), 3);
    assert.equal(treap.root.value, 1);
  });
});
<commit_msg>fixed typo in treap unit test<commit_after>const root = require('../..');
const Treap = root.DataStructures.Treap;
const assert = require('assert');

describe('Treap', () => {
  let treap;
  before(() => {
    treap = new Treap();
  });

  it('inserts elements', () => {
    treap.insert(3);
    treap.insert(2);
    treap.insert(10);
    treap.insert(-1);
    treap.insert(100);
    treap.insert(101);
    treap.insert(1);
    assert.equal(treap.root.size, 7);
    treap.insert(-100);
    assert.equal(treap.root.size, 8);
  });

  it('removes elements correctly', () => {
    // Value that not exist
    treap.remove(200);
    assert.equal(treap.root.size, 8);
    treap.remove(100);
    assert.equal(treap.root.size, 7);
    treap.remove(1);
    treap.remove(-1);
    treap.remove(-1);
    treap.remove(101);
    assert.equal(treap.root.size, 4);
  });

  it('inserts and remove elements', () => {
    // [-100, 2, 3, 10]
    treap.insert(200);
    // [-100, 2, 3, 10, 200]
    assert.equal(treap.root.size, 5);
    treap.remove(-100);
    // [2, 3, 10, 200]
    assert.equal(treap.root.size, 4);
    treap.insert(1);
    treap.remove(1);
    treap.insert(1);
    // [1, 2, 3, 10, 200]
    treap.remove(200);
    treap.insert(100);
    // [1, 2, 3, 10, 100]
    assert.equal(treap.root.size, 5);
  });

  it('checks if an element exists', () => {
    // [1, 2, 3, 10, 100]
    assert.equal(treap.find(1), true);
    assert.equal(treap.find(2), true);
    assert.equal(treap.find(3), true);
    assert.equal(treap.find(10), true);
    assert.equal(treap.find(100), true);
    assert.equal(treap.find(200), false);
    assert.equal(treap.find(-100), false);
    assert.equal(treap.find(-1), false);
    assert.equal(treap.find(101), false);
  });

  it('gets minimum element', () => {
    // [1, 2, 3, 10, 100]
    assert.equal(treap.minimum(), 1);
    treap.remove(1);
    // [2, 3, 10, 100]
    assert.equal(treap.minimum(), 2);
    treap.insert(-100);
    // [-100, 2, 3, 10, 100]
    assert.equal(treap.minimum(), -100);
    treap.remove(-100);
    // [2, 3, 10, 100]
    assert.equal(treap.minimum(), 2);
  });

  it('gets maximum element', () => {
    // [2, 3, 10, 100]
    assert.equal(treap.maximum(), 100);
    treap.remove(100);
    // [2, 3, 10]
    assert.equal(treap.maximum(), 10);
    treap.remove(10);
    // [2, 3]
    assert.equal(treap.maximum(), 3);
    treap.remove(3);
    // [2]
    assert.equal(treap.maximum(), 2);
    treap.insert(1);
    // [1, 2]
    assert.equal(treap.maximum(), 2);
    treap.remove(2);
    // [1]
    assert.equal(treap.maximum(), 1);
  });

  it('handles duplicated elements', () => {
    treap.insert(1);
    // [1, 1]
    assert.equal(treap.size(), 2);
    treap.insert(-1);
    // [-1, 1, 1]
    assert.equal(treap.size(), 3);
    treap.remove(1);
    // [-1, 1]
    assert.equal(treap.size(), 2);
    treap.insert(-1);
    treap.insert(-1);
    treap.insert(-1);
    // [-1, -1, -1, -1, 1]
    assert.equal(treap.size(), 5);
    treap.remove(-1);
    treap.remove(1);
    treap.remove(-1);
    treap.remove(-1);
    treap.remove(-1);
    assert.equal(treap.size(), 0);
  });

  it('keeps balance', () => {
    // Insert 1023 elements randomly
    for (let i = 0; i < 1023; ++i) {
      treap.insert(Math.random());
    }
    assert.equal(treap.size(), 1023);
    // The averange height should be 23 (with an error of 5)
    assert(Math.abs(treap.height() - 23) < 5);
  });

  it('rotates correctly', () => {
    // Force clear the tree
    treap.root = null;
    treap.insert(1);
    // 1
    assert.equal(treap.height(), 1);

    // Make the tree definite
    treap.root.key = 2;
    treap.insert(2);
    /**
     *   2
     *  /
     * 1
     *
   */
    assert.equal(treap.height(), 2);

    treap.root.key = 1;
    treap.insert(3);
    /**
     *     3
     *    /
     *   2
     *  /
     * 1
     *
   */
    assert.equal(treap.height(), 3);
    assert.equal(treap.root.value, 3);

    treap.root = treap.root.rotate(0);
    /**
     *   2
     *  / \
     * 1   3
     *
   */
    assert.equal(treap.height(), 2);
    assert.equal(treap.root.value, 2);

    treap.root = treap.root.rotate(0);
    /**
     * 1
     *  \
     *   2
     *    \
     *     3
     *
   */
    assert.equal(treap.height(), 3);
    assert.equal(treap.root.value, 1);
  });
});
<|endoftext|>


<commit_before>import AcoustIdApiError, {ERROR_INVALID_RESPONSE_SYNTAX} from "metadata/AcoustIdApiError";

const groupTypeValue = {
    single: 0,
    album: 1
};

const getBestRecordingGroup = function(recordings) {
    const groups = [];

    for (let i = 0; i < recordings.length; ++i) {
        const recording = recordings[i];
        if (!recording || !recording.releasegroups) {
            continue;
        }
        const {releasegroups} = recording;
        if (!releasegroups) {
            continue;
        }
        for (let j = 0; j < releasegroups.length; ++j) {
            const releasegroup = releasegroups[j];
            if (!releasegroup) {
                continue;
            }

            if (!releasegroup.type) {
                releasegroup.type = `unknown`;
            }

            const {secondarytypes} = releasegroup;
            const type = releasegroup.type.toLowerCase();
            groups.push({
                indexI: i,
                indexJ: j,
                recording,
                type,
                typeValue: groupTypeValue[type] || 10,
                album: releasegroups[j],
                secondarytypes: secondarytypes ? secondarytypes.map(v => v.toLowerCase()) : null
            });
        }
    }

    groups.sort((aGroup, bGroup) => {
        const valueDiff = aGroup.typeValue - bGroup.typeValue;

        if (valueDiff !== 0) {
            return valueDiff;
        }

        const aSec = aGroup.secondarytypes;
        const bSec = bGroup.secondarytypes;

        if (aSec && bSec) {
            const aCompilation = aSec.indexOf(`compilation`) >= 0;
            const bCompilation = bSec.indexOf(`compilation`) >= 0;

            if (aCompilation && bCompilation) {
                const diff = aGroup.indexI - bGroup.indexI;
                if (diff !== 0) return diff;
                return aGroup.indexJ - bGroup.indexJ;
            } else if (aCompilation && !bCompilation) {
                return 1;
            } else if (!aCompilation && bCompilation) {
                return -1;
            } else {
                const diff = aGroup.indexI - bGroup.indexI;
                if (diff !== 0) return diff;
                return aGroup.indexJ - bGroup.indexJ;
            }
        } else if (aSec && !bSec) {
            return 1;
        } else if (!aSec && bSec) {
            return -1;
        } else {
            const diff = aGroup.indexI - bGroup.indexI;
            if (diff !== 0) return diff;
            return aGroup.indexJ - bGroup.indexJ;
        }
    });

    if (!groups.length) {
        return {
            recording: recordings[0],
            album: null
        };
    }

    return groups[0];
};

const formatArtist = function(artists) {
    if (artists.length === 1) {
        return artists[0].name;
    } else {
        let ret = ``;
        let i = 0;
        for (; i < artists.length - 1; ++i) {
            ret += artists[i].name + artists[i].joinphrase;
        }
        ret += artists[i].name;
        return ret;
    }
};

export default function parseAcoustId(data) {
    if (!data) {
        throw new AcoustIdApiError(`syntax error`, ERROR_INVALID_RESPONSE_SYNTAX);
    }

    if (data.status === `error`) {
        throw new AcoustIdApiError(data.error.message, data.error.code);
    }

    const result = data.results && data.results[0] || null;

    if (!result) return null;
    if (!result.recordings || result.recordings.length === 0) return null;
    const bestRecordingGroup = getBestRecordingGroup(result.recordings);
    if (!bestRecordingGroup) return null;
    const {recording} = bestRecordingGroup;

    const title = {
        name: recording.title,
        mbid: recording.id,
        type: `release`
    };
    let album = null;

    if (bestRecordingGroup.album) {
        album = {
            name: bestRecordingGroup.album.title,
            mbid: bestRecordingGroup.album.id,
            type: `release-group`
        };
    }

    let artist = null;
    if (recording.artists && recording.artists.length) {
        artist = {
            name: formatArtist(recording.artists),
            mbid: recording.artists[0].id,
            type: `artist`
        };
    }

    return {
        title,
        album,
        artist
    };
}
<commit_msg>fix wrong sort value<commit_after>import AcoustIdApiError, {ERROR_INVALID_RESPONSE_SYNTAX} from "metadata/AcoustIdApiError";

const groupTypeValue = {
    single: 0,
    album: 1
};

const getBestRecordingGroup = function(recordings) {
    const groups = [];

    for (let i = 0; i < recordings.length; ++i) {
        const recording = recordings[i];
        if (!recording || !recording.releasegroups) {
            continue;
        }
        const {releasegroups} = recording;
        if (!releasegroups) {
            continue;
        }
        for (let j = 0; j < releasegroups.length; ++j) {
            const releasegroup = releasegroups[j];
            if (!releasegroup) {
                continue;
            }

            if (!releasegroup.type) {
                releasegroup.type = `unknown`;
            }

            const {secondarytypes} = releasegroup;
            const type = releasegroup.type.toLowerCase();
            const typeValue = groupTypeValue[type];
            groups.push({
                indexI: i,
                indexJ: j,
                recording,
                type,
                typeValue: typeValue === undefined ? 10 : typeValue,
                album: releasegroups[j],
                secondarytypes: secondarytypes ? secondarytypes.map(v => v.toLowerCase()) : null
            });
        }
    }

    groups.sort((aGroup, bGroup) => {
        const valueDiff = aGroup.typeValue - bGroup.typeValue;

        if (valueDiff !== 0) {
            return valueDiff;
        }

        const aSec = aGroup.secondarytypes;
        const bSec = bGroup.secondarytypes;

        if (aSec && bSec) {
            const aCompilation = aSec.indexOf(`compilation`) >= 0;
            const bCompilation = bSec.indexOf(`compilation`) >= 0;

            if (aCompilation && bCompilation) {
                const diff = aGroup.indexI - bGroup.indexI;
                if (diff !== 0) return diff;
                return aGroup.indexJ - bGroup.indexJ;
            } else if (aCompilation && !bCompilation) {
                return 1;
            } else if (!aCompilation && bCompilation) {
                return -1;
            } else {
                const diff = aGroup.indexI - bGroup.indexI;
                if (diff !== 0) return diff;
                return aGroup.indexJ - bGroup.indexJ;
            }
        } else if (aSec && !bSec) {
            return 1;
        } else if (!aSec && bSec) {
            return -1;
        } else {
            const diff = aGroup.indexI - bGroup.indexI;
            if (diff !== 0) return diff;
            return aGroup.indexJ - bGroup.indexJ;
        }
    });

    if (!groups.length) {
        return {
            recording: recordings[0],
            album: null
        };
    }

    return groups[0];
};

const formatArtist = function(artists) {
    if (artists.length === 1) {
        return artists[0].name;
    } else {
        let ret = ``;
        let i = 0;
        for (; i < artists.length - 1; ++i) {
            ret += artists[i].name + artists[i].joinphrase;
        }
        ret += artists[i].name;
        return ret;
    }
};

export default function parseAcoustId(data) {
    if (!data) {
        throw new AcoustIdApiError(`syntax error`, ERROR_INVALID_RESPONSE_SYNTAX);
    }

    if (data.status === `error`) {
        throw new AcoustIdApiError(data.error.message, data.error.code);
    }

    const result = data.results && data.results[0] || null;

    if (!result) return null;
    if (!result.recordings || result.recordings.length === 0) return null;
    const bestRecordingGroup = getBestRecordingGroup(result.recordings);
    if (!bestRecordingGroup) return null;
    const {recording} = bestRecordingGroup;

    const title = {
        name: recording.title,
        mbid: recording.id,
        type: `release`
    };
    let album = null;

    if (bestRecordingGroup.album) {
        album = {
            name: bestRecordingGroup.album.title,
            mbid: bestRecordingGroup.album.id,
            type: `release-group`
        };
    }

    let artist = null;
    if (recording.artists && recording.artists.length) {
        artist = {
            name: formatArtist(recording.artists),
            mbid: recording.artists[0].id,
            type: `artist`
        };
    }

    return {
        title,
        album,
        artist
    };
}
<|endoftext|>


<commit_before>/*
 * This file is subject to the terms and conditions defined in
 * file 'LICENSE.txt', which is part of this source code package.
 *
 * author: emicklei
 */

// This callback is set for handling function calls in JSON from Go.
// It is called from Go using "worker.Send(...)".
// Throws a SyntaxError exception if the string to parse is not valid JSON.
//
$recv(function(msg) {
    var obj = JSON.parse(msg);
    this[obj.selector].apply(this, obj.args)
});

// javascript_dispatch is used to directly call a Javascript function by its name.
//
function javascript_dispatch(functionName, context /*, args */ ) {
    var args = [].slice.call(arguments).splice(2);
    var namespaces = functionName.split(".");
    var func = namespaces.pop();
    for (var i = 0; i < namespaces.length; i++) {
        context = context[namespaces[i]];
    }
    return context[func].apply(this, args);
}

// callback_dispatch is used from Go to call a callback function that was registered.
//
function callback_dispatch(functionRef /*, args */ ) {
	var args = [].slice.call(arguments).splice(1);
	var callback = V8D.function_registry.take(functionRef)
	if (V8D.function_registry.none == callback) {
		$print("no function for reference:"+functionRef);
		return;
	}
	callback.apply(this,args)
}

// go_dispatch is used in Javascript to call a Go function.
// if the Go function returns a non-nil value then the onReturn is called
//
function go_dispatch(onReturn, receiver, methodName /* args */ ) {
//	var iferror = function(reason) {
//		var lines = stk.split("\n");
//		$print("js: "+reason);
//		$print(lines);
//	}
    var obj = {
		"receiver": receiver,
		"method": methodName,
		"callback": onReturn,
		"stack": new Error().stack
    };
    obj["args"] = [].slice.call(arguments).splice(3);
    $send(JSON.stringify(obj));
}

<commit_msg>add request handler<commit_after>/*
 * This file is subject to the terms and conditions defined in
 * file 'LICENSE.txt', which is part of this source code package.
 *
 * author: emicklei
 */

// This callback is set for handling function calls in JSON from Go.
// It is called from Go using "worker.Send(...)".
// Throws a SyntaxError exception if the string to parse is not valid JSON.
//
$recv(function(msg) {
    var obj = JSON.parse(msg);
    this[obj.selector].apply(this, obj.args)
});

// This callback is set for handling function calls in JSON from Go.
// It is called from Go using "worker.Request(...)".
// Throws a SyntaxError exception if the string to parse is not valid JSON.
// Return the JSON representation of the return value of the handling function.
//
$request_handler(function(msg) {
    var obj = JSON.parse(msg);
    var namespaces = obj.selector.split(".");
    var func = namespaces.pop();
    for (var i = 0; i < namespaces.length; i++) {
        context = context[namespaces[i]];
    }
	// TODO handle exception
    var returnValue = context[func].apply(this, args);
	return JSON.stringify(returnValue)
});

// callback_dispatch is used from Go to call a callback function that was registered.
//
function callback_dispatch(functionRef /*, args */ ) {
	var args = [].slice.call(arguments).splice(1);
	var callback = V8D.function_registry.take(functionRef)
	if (V8D.function_registry.none == callback) {
		$print("no function for reference:"+functionRef);
		return;
	}
	callback.apply(this,args)
}

// go_dispatch is used in Javascript to call a Go function.
// if the Go function returns a non-nil value then the onReturn is called
//
function go_dispatch(onReturn, receiver, methodName /* args */ ) {
//	var iferror = function(reason) {
//		var lines = stk.split("\n");
//		$print("js: "+reason);
//		$print(lines);
//	}
    var obj = {
		"receiver": receiver,
		"method": methodName,
		"callback": onReturn,
		"stack": new Error().stack
    };
    obj["args"] = [].slice.call(arguments).splice(3);
    $send(JSON.stringify(obj));
}

<|endoftext|>


<commit_before>var Game = function (firebase, url, gameId, size) {
    this.fb = firebase;
    this.url = url;
    this.size = size;
    this.gameId = gameId;
    this.playingState = Game.PlayingState.Watching;
    this.playerNum = null;
    this.board = null;
    this.init();
};

Game.PlayingState = {Watching: 0, Joining: 1, Playing: 2};
Game.color = {BLACK: "BLACK", WHITE: "WHITE"};

Game.prototype.init = function () {
    this.board = new Board(this.fb, this.size, this.gameId);
    this.addShareLink();
    this.waitToJoin();

    var $gameAlertToplay = $('#game-alert-toplay');
    var $welcomeLogin = $('#welcome-login');

    this.fb.ref().onAuth(function (authData) {
        if (authData) {
            $gameAlertToplay.addClass('is-hidden');
            $welcomeLogin.addClass('is-hidden');
        } else {
            $gameAlertToplay.removeClass('is-hidden');
            $welcomeLogin.removeClass('is-hidden');
        }
    });

    this.watchForNewStones();
};

Game.prototype.addShareLink = function () {
    var link = $("#share-link");
    if (link !== null) {
        link.text(window.location.href).attr('href', window.location.href);
    }
};

Game.prototype.getColor = function () {
    if (this.playerNum === null) {
        return null;
    }
    return (this.playerNum === 0) ? Game.color.BLACK : Game.color.WHITE;
};

Game.prototype.waitToJoin = function () {
    var self = this;

    var players = self.fb.ref('games/' + self.gameId + '/players/');

    this.fb.ref().onAuth(function (authData) {
        if (authData && _.isEqual(self.playingState, Game.PlayingState.Watching)) {
            players.once('value', function (snap) {
                var players = snap.val();

                if (_.isNull(players) || !_.has(players, "player0") || _.isEqual(players.player0.uid, authData.uid)) {
                    self.tryToJoin(0, authData.uid);
                    return;
                }

                if (!_.has(players, "player1") || _.isEqual(players.player1.uid, authData.uid)) {
                    self.tryToJoin(1, authData.uid);
                    return;
                }

                self.watchForUser();
                $('#skip').addClass('is-hidden');
            });
        } else {
            self.watchForUser();
            console.log(" waitToJoin watching");
        }
    });
};

Game.prototype.tryToJoin = function (playerNum, uid) {
    console.log('tryToJoin start', playerNum, uid);
    this.playerNum = playerNum;

    // Set ourselves as joining to make sure we don't try to join as both players. :-)
    this.playingState = Game.PlayingState.Joining;

    // Use a transaction to make sure we don't conflict with other people trying to join.
    var self = this;
    this.fb.ref('games/' + self.gameId + '/players/player' + playerNum + '/uid').transaction(function (snap) {

        if (snap !== null) {
            return; // Somebody must have beat us.  Abort the transaction.
        }

        self.playingState = Game.PlayingState.Playing;
        self.startPlaying(playerNum, uid);

        self.fb.initToken(playerNum);
        return uid; // Try to set user with uid current

    }, function (error, committed, snapshot) {
        console.log("tryToJoin transaction error");
        if (error) {
            console.log('Transaction failed abnormally!', error);
        } else if (!committed) {
            console.log('We aborted the transaction (because value already exists).');
        } else {
            console.log('Value added!');
        }
        console.log("Value data: ", snapshot.val());
    });
};

/**
 * Once we've joined, enable controlling our player.
 */
Game.prototype.startPlaying = function (playerNum, uid) {
    var playerRef = this.fb.ref('games/' + this.gameId + '/players/player' + playerNum + '/online');

    playerRef.set(true, function (error) {
        if (error) {
            console.error('startPlaying online failed');
        }
    });

    // Clear our 'online' status when we disconnect so somebody else can join.
    playerRef.onDisconnect().remove();

    this.watchForUser();

    var $board = $('#board');

    if (playerNum === 0) {
        $board.addClass('black');
    } else if (playerNum === 1){
        $board.addClass('white');
    }

    var $picPlayer0 = $('#player0');
    var $picPlayer1 = $('#player1');
    var tokenRef = this.fb.ref('games/' + this.gameId + '/players/token');
    tokenRef.on('value', function (snap) {
        if (snap.val() === 0) {
            $picPlayer0.removeClass('waitForTurn');
            $picPlayer1.addClass('waitForTurn');
        } else {
            $picPlayer0.addClass('waitForTurn');
            $picPlayer1.removeClass('waitForTurn');
        }
    });

    var self = this;
    $(".cell").on("click", function (event) {
        var ids = event.target.id.split("-"),
            x = ids[0],
            y = ids[1];

        var color = self.board.get(x, y);
        if (color !== undefined && !_.isEqual(color, self.getColor())) {
            self.board.removeStone(x, y, playerNum);
            return;
        }

        self.board.setStoneFirebase(x, y, self.getColor(), playerNum);
    });

    $("#skip").on("click", function (event) {
        self.board.skipTurnFirebase(playerNum);
    });
};

/**
 * Detect when our opponent pushes extra rows to us.
 */
Game.prototype.watchForNewStones = function () {
    var self = this;

    this.fb.once('games/' + this.gameId + '/goban', 'value').then(function (snaps) {
        snaps.forEach(function (snap) {
            var coord = snap.key().split("-");
            var stone = snap.val();
            self.board.setStone(parseInt(coord[0]), parseInt(coord[1]), stone);
        });
    });

    this.fb.on('games/' + this.gameId + '/goban', 'child_added').progress(function (snap) {
        var coord = snap.key().split("-");
        var stone = snap.val();
        self.board.setStone(parseInt(coord[0]), parseInt(coord[1]), stone);
    });

    this.fb.on('games/' + this.gameId + '/goban', 'child_removed').progress(function (snap) {
        var coord = snap.key().split("-");
        self.board.removeStone(parseInt(coord[0]), parseInt(coord[1]));
    });
};

Game.prototype.watchForUser = function () {
    var self = this;
    var player0Avatar = "", player1Avatar = "";
    var players = this.fb.ref('games/' + this.gameId + '/players/');

    // Listen location for player0 and player1.
    players.child('player0').on('value', function (snap) {
        var player = snap.val();
        if (!_.isNull(player)) {
            if (_.has(player, "score")) {
                $('#scorePlayer0').text(player.score);
            }
            self.presence(0, player.online);

            if (_.isEmpty(player0Avatar)) {
                self.fb.ref('users/' + player.uid).once('value', function (snapUser) {
                    if (!_.isNull(snapUser.val())) {
                        $('#player0').find('img:first-child')[0].src = snapUser.val().picture;
                    }
                });
            }
        }
    });

    players.child('player1').on('value', function (snap) {
        var player = snap.val();
        if (!_.isNull(player)) {
            if (_.has(player, "score")) {
                $('#scorePlayer1').text(player.score);
            }
            self.presence(1, player.online);

            if (_.isEmpty(player1Avatar)) {
                self.fb.ref('users/' + player.uid).once('value', function (snapUser) {
                    if (!_.isNull(snapUser.val())) {
                        $('#player1').find('img:first-child')[0].src = snapUser.val().picture;
                    }
                });
            }
        }
    });
};

Game.prototype.presence = function (playerNum, online) {
    var $player = $("#player" + playerNum);

    if (online) {
        $player.addClass('online');
    } else {
        $player.removeClass('online');
    }
};
<commit_msg>to prevent the added of a stone<commit_after>var Game = function (firebase, url, gameId, size) {
    this.fb = firebase;
    this.url = url;
    this.size = size;
    this.gameId = gameId;
    this.playingState = Game.PlayingState.Watching;
    this.playerNum = null;
    this.board = null;
    this.init();
};

Game.PlayingState = {Watching: 0, Joining: 1, Playing: 2};
Game.color = {BLACK: "BLACK", WHITE: "WHITE"};

Game.prototype.init = function () {
    this.board = new Board(this.fb, this.size, this.gameId);
    this.addShareLink();
    this.waitToJoin();

    var $gameAlertToplay = $('#game-alert-toplay');
    var $welcomeLogin = $('#welcome-login');

    this.fb.ref().onAuth(function (authData) {
        if (authData) {
            $gameAlertToplay.addClass('is-hidden');
            $welcomeLogin.addClass('is-hidden');
        } else {
            $gameAlertToplay.removeClass('is-hidden');
            $welcomeLogin.removeClass('is-hidden');
        }
    });

    this.watchForNewStones();
};

Game.prototype.addShareLink = function () {
    var link = $("#share-link");
    if (link !== null) {
        link.text(window.location.href).attr('href', window.location.href);
    }
};

Game.prototype.getColor = function () {
    if (this.playerNum === null) {
        return null;
    }
    return (this.playerNum === 0) ? Game.color.BLACK : Game.color.WHITE;
};

Game.prototype.waitToJoin = function () {
    var self = this;

    var players = self.fb.ref('games/' + self.gameId + '/players/');

    this.fb.ref().onAuth(function (authData) {
        if (authData && _.isEqual(self.playingState, Game.PlayingState.Watching)) {
            players.once('value', function (snap) {
                var players = snap.val();

                if (_.isNull(players) || !_.has(players, "player0") || _.isEqual(players.player0.uid, authData.uid)) {
                    self.tryToJoin(0, authData.uid);
                    return;
                }

                if (!_.has(players, "player1") || _.isEqual(players.player1.uid, authData.uid)) {
                    self.tryToJoin(1, authData.uid);
                    return;
                }

                self.watchForUser();
                $('#skip').addClass('is-hidden');
            });
        } else {
            self.watchForUser();
            console.log(" waitToJoin watching");
        }
    });
};

Game.prototype.tryToJoin = function (playerNum, uid) {
    console.log('tryToJoin start', playerNum, uid);
    this.playerNum = playerNum;

    // Set ourselves as joining to make sure we don't try to join as both players. :-)
    this.playingState = Game.PlayingState.Joining;

    // Use a transaction to make sure we don't conflict with other people trying to join.
    var self = this;
    this.fb.ref('games/' + self.gameId + '/players/player' + playerNum + '/uid').transaction(function (snap) {

        if (snap !== null) {
            return; // Somebody must have beat us.  Abort the transaction.
        }

        self.playingState = Game.PlayingState.Playing;
        self.startPlaying(playerNum, uid);

        self.fb.initToken(playerNum);
        return uid; // Try to set user with uid current

    }, function (error, committed, snapshot) {
        console.log("tryToJoin transaction error");
        if (error) {
            console.log('Transaction failed abnormally!', error);
        } else if (!committed) {
            console.log('We aborted the transaction (because value already exists).');
        } else {
            console.log('Value added!');
        }
        console.log("Value data: ", snapshot.val());
    });
};

/**
 * Once we've joined, enable controlling our player.
 */
Game.prototype.startPlaying = function (playerNum, uid) {
    var playerRef = this.fb.ref('games/' + this.gameId + '/players/player' + playerNum + '/online');

    playerRef.set(true, function (error) {
        if (error) {
            console.error('startPlaying online failed');
        }
    });

    // Clear our 'online' status when we disconnect so somebody else can join.
    playerRef.onDisconnect().remove();

    this.watchForUser();

    var $board = $('#board');

    if (playerNum === 0) {
        $board.addClass('black');
    } else if (playerNum === 1){
        $board.addClass('white');
    }

    var $picPlayer0 = $('#player0');
    var $picPlayer1 = $('#player1');
    var tokenRef = this.fb.ref('games/' + this.gameId + '/players/token');
    tokenRef.on('value', function (snap) {
        if (snap.val() === 0) {
            $picPlayer0.removeClass('waitForTurn');
            $picPlayer1.addClass('waitForTurn');
        } else {
            $picPlayer0.addClass('waitForTurn');
            $picPlayer1.removeClass('waitForTurn');
        }
    });

    var self = this;
    $(".cell").on("click", function (event) {
        var ids = event.target.id.split("-"),
            x = ids[0],
            y = ids[1];

        var color = self.board.get(x, y);

        if (color === undefined || _.isEqual(color, self.getColor())) {
            return;
        }

        if (!_.isEqual(color, self.getColor())) {
            self.board.removeStone(x, y, playerNum);
            return;
        }

        self.board.setStoneFirebase(x, y, self.getColor(), playerNum);
    });

    $("#skip").on("click", function (event) {
        self.board.skipTurnFirebase(playerNum);
    });
};

/**
 * Detect when our opponent pushes extra rows to us.
 */
Game.prototype.watchForNewStones = function () {
    var self = this;

    this.fb.once('games/' + this.gameId + '/goban', 'value').then(function (snaps) {
        snaps.forEach(function (snap) {
            var coord = snap.key().split("-");
            var stone = snap.val();
            self.board.setStone(parseInt(coord[0]), parseInt(coord[1]), stone);
        });
    });

    this.fb.on('games/' + this.gameId + '/goban', 'child_added').progress(function (snap) {
        var coord = snap.key().split("-");
        var stone = snap.val();
        self.board.setStone(parseInt(coord[0]), parseInt(coord[1]), stone);
    });

    this.fb.on('games/' + this.gameId + '/goban', 'child_removed').progress(function (snap) {
        var coord = snap.key().split("-");
        self.board.removeStone(parseInt(coord[0]), parseInt(coord[1]));
    });
};

Game.prototype.watchForUser = function () {
    var self = this;
    var player0Avatar = "", player1Avatar = "";
    var players = this.fb.ref('games/' + this.gameId + '/players/');

    // Listen location for player0 and player1.
    players.child('player0').on('value', function (snap) {
        var player = snap.val();
        if (!_.isNull(player)) {
            if (_.has(player, "score")) {
                $('#scorePlayer0').text(player.score);
            }
            self.presence(0, player.online);

            if (_.isEmpty(player0Avatar)) {
                self.fb.ref('users/' + player.uid).once('value', function (snapUser) {
                    if (!_.isNull(snapUser.val())) {
                        $('#player0').find('img:first-child')[0].src = snapUser.val().picture;
                    }
                });
            }
        }
    });

    players.child('player1').on('value', function (snap) {
        var player = snap.val();
        if (!_.isNull(player)) {
            if (_.has(player, "score")) {
                $('#scorePlayer1').text(player.score);
            }
            self.presence(1, player.online);

            if (_.isEmpty(player1Avatar)) {
                self.fb.ref('users/' + player.uid).once('value', function (snapUser) {
                    if (!_.isNull(snapUser.val())) {
                        $('#player1').find('img:first-child')[0].src = snapUser.val().picture;
                    }
                });
            }
        }
    });
};

Game.prototype.presence = function (playerNum, online) {
    var $player = $("#player" + playerNum);

    if (online) {
        $player.addClass('online');
    } else {
        $player.removeClass('online');
    }
};
<|endoftext|>


<commit_before>var fs = require('fs')
var url = require('url')
var http = require('http')
var https = require('https')
var level = require('level')
var asyncMap = require('slide').asyncMap
var multilevel = require('multilevel')
var formidable = require('formidable')
var browserify = require('browserify')
var livestream = require('level-live-stream')
var engineServer = require('engine.io-stream')
var newhmac = require('crypto').createhmac

// RUN -- process  next tick or self calling function !?!
process.nextTick(function () {
  server.listen(config.port, config.host, function () {
    fs.watch(config.files.modules, compileModules)
    compileModules()
    console.log('server running on port: '+config.port+' host: '+config.host)
  })
})

// CONFIG -- if no dir then make one!
var config = (process.argv[2]) // also check db for config if no file found
  ? config = require(process.argv[2])
  : config = require('./config.json')

if (config.files.modules.slice(-1) !== '/') config.files.modules += '/'
if (config.files.static.slice(-1) !== '/') config.files.static += '/'

var db = level('./' + config.host)
livestream.install(db)
multilevel.writeManifest(db, './static/manifest.json')

var modes = {} // remove this

if (config.brico) { // handle configuration
  var conf = config.brico
  for (m in conf.modes) {
    if (conf.modes[m].pass) {
      var token = conf.modes[m].pass
      delete conf.modes[m].pass
      gethmac({token:token,user:m}, function (d) { modes[d.key] = d.val })
    }
  }
  db.put('config', JSON.stringify(conf))
}

// SERVER
fs.writeFileSync(config.files.static+'index.html', '<!doctype html>'+
''+
'<meta charset="utf-8">'+
''+
'<title>Untitiled</title>'+
'<link rel="stylesheet" href="/style.css">'+
''+
''+
'
'+
'
'+
''+
''+
'')

var fileserver = require('node-static').Server

if (!config.crypto) {
  var file = new fileserver(config.files.static)
  var server = http.createServer(handleHttp)
} else {
  var hsts = {'Strict-Transport-Security':'max-age=31536000'}
  var file = new fileServer(config.files.static, hsts)
  var server = https.createServer({
    honorCipherOrder : true,
    key : fs.readFileSync(config.crypto.key),
    cert : fs.readFileSync(config.crypto.cert),
    cipher : 'ecdh+aesgcm:dh+aesgcm:ecdh+aes256:dh+aes256:'+
             'ecdh+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:'+
             'RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'
  }, handleHttp)
}

function handleHttp (req, res) {
  if (req.url === '/upload' && req.method === 'post') fileupload(req, res)
  file.serve(req, res, function noFile (e) {
    if (e) {
      var path = url.parse(req.url).pathname.slice(1)
      file.serveFile('/index.html', 200, {}, req, res)
      console.log(path)
    }
  })
}

var engine = engineServer(function (wss) {
  wss.pipe(multiLevel.server(db, {
    auth: function (user, cb) {
      getHmac({token:user.pass,user:user.user}, function handleHmac (d) {
        if (modes[user.user] === pass) cb(null, { name: user.user, token: d.val })
        if (modes[user.user] !== pass) cb(new Error('wrong pass!'), null)
        if (e) cb(e, null)
      })
    },
    access: function (user, db, method, args) {}
  })).pipe(wss)
  wss.on('error', console.error)
}, {cookie:false})
  .attach(server, '/ws')

// UTILS
function getHmac (d, cb) {
  var hmac = newHmac(config.hmac.algo, config.hmac.key)
  hmac.setEncoding('hex')
  hmac.write(d.token)
  hmac.end()
  cb({key:'users:'+d.user, val:hmac.read().toString()})
}

function handleUpload (req, res) {
  var form = new formidable.IncomingForm()
  form.parse(req, function(err, fields, files) {
    res.writeHead(200, {'content-type': 'text/plain'})
    res.write('received upload:\n\n')
    res.end()
    var blob = fields.blob.split(',')[1]
    fs.writeFileSync(config.files.uploads+fields.file, blob, {encoding:'base64'})
  })
}

function compileModules (event, file) {// replace this ! -- steal old map fn
  var library  = {}
  var inBun = config.files.bundleIn
  var outBun = config.files.bundleOut
  var b = browserify(inBun)

  var modulesFolder = fs.readdirSync(config.files.modules)

  asyncMap(modulesFolder, function (moduleFolder, next) {
    var pkgPath = config.files.modules + moduleFolder + '/package.json'
    if (!fs.existsSync(pkgPath)) { next(); return null }
    var pkg = JSON.parse(fs.readFileSync(pkgPath, {encoding:'utf8'}))
    if (!pkg.nimoy) { next(); return null }
    var key = 'modules:'+pkg.name
    library[key] = pkg.nimoy
    b.require(config.files.modules+moduleFolder+'/'+pkg.main, {expose: moduleFolder})
    next()
    // add pkg to library
  }, function end () {
    db.put('library', JSON.stringify(library))
    var bun = fs.createWriteStream(config.files.bundleOut)
    bun.on('finish',function () {console.log('compiled '+inBun+' to '+outBun)})
    b.bundle().pipe(bun)
  })
}
<commit_msg>fixed multiLevel var typo<commit_after>var fs = require('fs')
var url = require('url')
var http = require('http')
var https = require('https')
var level = require('level')
var asyncMap = require('slide').asyncMap
var multiLevel = require('multilevel')
var formidable = require('formidable')
var browserify = require('browserify')
var livestream = require('level-live-stream')
var engineServer = require('engine.io-stream')
var newhmac = require('crypto').createhmac

// RUN -- process  next tick or self calling function !?!
process.nextTick(function () {
  server.listen(config.port, config.host, function () {
    fs.watch(config.files.modules, compileModules)
    compileModules()
    console.log('server running on port: '+config.port+' host: '+config.host)
  })
})

// CONFIG -- if no dir then make one!
var config = (process.argv[2]) // also check db for config if no file found
  ? config = require(process.argv[2])
  : config = require('./config.json')

if (config.files.modules.slice(-1) !== '/') config.files.modules += '/'
if (config.files.static.slice(-1) !== '/') config.files.static += '/'

var db = level('./' + config.host)
livestream.install(db)
multiLevel.writeManifest(db, './static/manifest.json')

var modes = {} // remove this

if (config.brico) { // handle configuration
  var conf = config.brico
  for (m in conf.modes) {
    if (conf.modes[m].pass) {
      var token = conf.modes[m].pass
      delete conf.modes[m].pass
      gethmac({token:token,user:m}, function (d) { modes[d.key] = d.val })
    }
  }
  db.put('config', JSON.stringify(conf))
}

// SERVER
fs.writeFileSync(config.files.static+'index.html', '<!doctype html>'+
''+
'<meta charset="utf-8">'+
''+
'<title>Untitiled</title>'+
'<link rel="stylesheet" href="/style.css">'+
''+
''+
'
'+
'
'+
''+
''+
'')

var fileserver = require('node-static').Server

if (!config.crypto) {
  var file = new fileserver(config.files.static)
  var server = http.createServer(handleHttp)
} else {
  var hsts = {'Strict-Transport-Security':'max-age=31536000'}
  var file = new fileServer(config.files.static, hsts)
  var server = https.createServer({
    honorCipherOrder : true,
    key : fs.readFileSync(config.crypto.key),
    cert : fs.readFileSync(config.crypto.cert),
    cipher : 'ecdh+aesgcm:dh+aesgcm:ecdh+aes256:dh+aes256:'+
             'ecdh+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:'+
             'RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'
  }, handleHttp)
}

function handleHttp (req, res) {
  if (req.url === '/upload' && req.method === 'post') fileupload(req, res)
  file.serve(req, res, function noFile (e) {
    if (e) {
      var path = url.parse(req.url).pathname.slice(1)
      file.serveFile('/index.html', 200, {}, req, res)
      console.log(path)
    }
  })
}

var engine = engineServer(function (wss) {
  wss.pipe(multiLevel.server(db, {
    auth: function (user, cb) {
      getHmac({token:user.pass,user:user.user}, function handleHmac (d) {
        if (modes[user.user] === pass) cb(null, { name: user.user, token: d.val })
        if (modes[user.user] !== pass) cb(new Error('wrong pass!'), null)
        if (e) cb(e, null)
      })
    },
    access: function (user, db, method, args) {}
  })).pipe(wss)
  wss.on('error', console.error)
}, {cookie:false})
  .attach(server, '/ws')

// UTILS
function getHmac (d, cb) {
  var hmac = newHmac(config.hmac.algo, config.hmac.key)
  hmac.setEncoding('hex')
  hmac.write(d.token)
  hmac.end()
  cb({key:'users:'+d.user, val:hmac.read().toString()})
}

function handleUpload (req, res) {
  var form = new formidable.IncomingForm()
  form.parse(req, function(err, fields, files) {
    res.writeHead(200, {'content-type': 'text/plain'})
    res.write('received upload:\n\n')
    res.end()
    var blob = fields.blob.split(',')[1]
    fs.writeFileSync(config.files.uploads+fields.file, blob, {encoding:'base64'})
  })
}

function compileModules (event, file) {// replace this ! -- steal old map fn
  var library  = {}
  var inBun = config.files.bundleIn
  var outBun = config.files.bundleOut
  var b = browserify(inBun)
  var modulesFolder = fs.readdirSync(config.files.modules)
  asyncMap(modulesFolder, function (moduleFolder, next) {
    var pkgPath = config.files.modules + moduleFolder + '/package.json'
    if (!fs.existsSync(pkgPath)) { next(); return null }
    var pkg = JSON.parse(fs.readFileSync(pkgPath, {encoding:'utf8'}))
    if (!pkg.nimoy) { next(); return null }
    var key = 'modules:'+pkg.name
    library[key] = pkg.nimoy
    b.require(config.files.modules+moduleFolder+'/'+pkg.main, {expose: moduleFolder})
    next()
  }, function end () {
    db.put('library', JSON.stringify(library))
    var bun = fs.createWriteStream(config.files.bundleOut)
    bun.on('finish',function () {console.log('compiled '+inBun+' to '+outBun)})
    b.bundle().pipe(bun)
  })
}
<|endoftext|>


<commit_before>/**
 * Copyright 2016 F5 Networks, Inc.
 *
 * 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.
 */
var fs = require('fs');
var childProcess = require("child_process");
var options = require("commander");
var q = require("q");
var BigIp = require('./lib/bigIp');
var globalSettings = {
    guiSetup: 'disabled'
};
var dbVars = {};
var modules = {};
var passwords = {};
var rootPasswords = {};

var logFileName = '/tmp/setup.log';
var logFile;

var bigIp;

var args;
var myChild;

var i;

var PASSWORD_OPTION_KEYS = ['-p', '--password', '--set-password', '--set-root-password'];
/**
 * Adds value to an array
 *
 * Typically used by the option parser for collecting
 * multiple values for a command line option
 */
var collect = function(val, collection) {
    collection.push(val);
    return collection;
};

/**
 * Parses a ':' deliminated key-value pair and stores them
 * in a container.
 *   - Key is the part before the first ':',
 *   - Value is everything after.
 *   - Leading and trailing spaces are removed from keys and values
 *
 * Typically used by the option parser for collecting
 * multiple key-value pairs for a command line option
 */
var map = function(pair, container) {
    var nameVal = pair.split(/:(.+)/);
    container[nameVal[0].trim()] = nameVal[1].trim();
};

/**
 * Special case of map. Used to parse root password options in the form of
 *     old:oldRootPassword,new:newRootPassword
 * Since passwords can contain any character, a delimiter is difficult to find.
 * Compromise by looking for ',new:' as a delimeter
 */
var parseRootPasswords = function(passwordsValue, container) {
    var set = passwordsValue.split(",new:");

    if (set.length == 2) {
        container.old = set[0].split("old:")[1];
        container.new = set[1];
    }
};

var writeResponse = function(response) {
    if (response && options.verbose) {
        console.log((typeof response === 'object' ? JSON.stringify(response, null, 4) : "  " + response));
    }
};

options
    .option('--host <ip_address>', 'BIG-IP management IP.')
    .option('-u, --user <user>', 'BIG-IP admin user.')
    .option('-p, --password <password>', 'BIG-IP admin user password.')
    .option('--ntp <ntp-server>', 'NTP server. For multiple NTP servers, use multiple --ntp entries', collect, [])
    .option('--tz <timezone>', 'Timezone for NTP setting')
    .option('--dns <DNS server>', 'DNS server. For multiple DNS severs, use multiple --dns entries', collect, [])
    .option('-l, --license <license_key>', 'BIG-IP license key.')
    .option('-a, --add-on <add-on keys>', 'Add on license key. For multiple keys, use multiple -a entries', collect, [])
    .option('-n, --host-name <hostname>', 'Set BIG-IP hostname')
    .option('-g, --global-settings <name:value>', 'A global setting name/value pair. For multiple settings, use multiple -g entries', map, globalSettings)
    .option('-d, --db <name:value>', 'A db variable name/value pair. For multiple settings, use multiple -d entries', map, dbVars)
    .option('--set-password <user:newPassword>', 'Set user password to newPassword. For multiple users, use multiple --set-password entries.', map, passwords)
    .option('--set-root-password <old:oldPassword,new:newPassword>', 'Set the password for the root user from oldPassword to newPassword', parseRootPasswords, rootPasswords)
    .option('-m, --module <name:value>', 'A module provisioning module/level pair. For multiple modules, use multiple -m entries', map, modules)
    .option('-f, --foreground', 'Do the work - otherwise spawn a background process to do the work. If you are running in cloud init, you probably do not want this option.')
    .option('-o, --output <file>', 'Full path for log file if background process is spawned. Default is ' + logFileName)
    .option('--verbose', 'Turn on verbose output')
    .parse(process.argv);

logFileName = options.output || logFileName;

try {
    logFile = fs.openSync(logFileName, 'a');

    // When running in cloud init, we need to exit so that cloud init can complete and
    // allow the BIG-IP services to start
    if (!options.foreground) {

        if (process.argv.length > 100) {
            console.log("Too many arguments - maybe we're stuck in a restart loop?");
        }
        else {
            console.log("Spawning child process to do the work. Output will be in " + logFileName);
            args = process.argv.slice(1);
            args.push('--foreground');
            myChild = childProcess.spawn(
                process.argv[0],
                args,
                {
                    detached: true,
                    stdio: ['ignore', logFile, logFile]
                }
            );
            myChild.unref();
        }

        process.exit();
    }

    // Log the input, but don't log the password
    if (options.password || Object.keys(passwords).lentgh > 0 || Object.keys(rootPasswords).length > 0) {
        for (i = 0; i < process.argv.length; ++i) {
            if (PASSWORD_OPTION_KEYS.indexOf(process.argv[i]) !== -1) {
                process.argv[i + 1] = "*******";
            }
        }
    }
    console.log(process.argv[1] + " called with " + process.argv.slice().join(" "));

    bigIp = new BigIp(options.host, options.user, options.password);

    // Use hostName if both hostName and global-settings hostName are set
    if (globalSettings && options.hostName) {
        if (globalSettings.hostname || globalSettings.hostName) {
            console.log("Using host-name option to override global-settings host name");
            delete globalSettings.hostName;
            delete globalSettings.hostname;
        }
    }

    console.log("Setup starting at: " + new Date().toUTCString());
    console.log("Waiting for BIG-IP to be ready...");
    bigIp.ready(60, 10000) // 10 minutes
        .then(function() {
            var promises = [];
            var user;

            console.log("BIG-IP is ready.");

            if (Object.keys(passwords).length > 0) {
                console.log("Setting password(s).");
                for (user in passwords) {
                    promises.push(bigIp.password(user, passwords[user]));
                }

                return q.all(promises);
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            if (Object.keys(rootPasswords).length > 0) {
                if (!rootPasswords.old || !rootPasswords.new) {
                    return q.reject("Old or new password missing for root user. Specify with --set-root-password old:old_root_password,new:new_root_password");
                }

                console.log("Setting rootPassword.");
                return bigIp.password('root', rootPasswords.new, rootPasswords.old);
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            var ntpBody;

            writeResponse(response);

            if (options.ntp.length > 0 || options.tz) {
                console.log("Setting up NTP.");

                ntpBody = {};

                if (options.ntp) {
                    ntpBody.servers = options.ntp;
                }

                if (options.tz) {
                    ntpBody.timezone = options.tz;
                }

                return bigIp.modify(
                    '/tm/sys/ntp',
                    ntpBody
                );
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            if (options.dns.length > 0) {
                console.log("Setting up DNS.");

                return bigIp.modify(
                    '/tm/sys/dns',
                    {
                        'name-servers': options.dns
                    }
                );
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            if (options.hostName) {
                console.log("Setting host name.");
                return bigIp.hostName(options.hostName);
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            if (globalSettings) {
                console.log("Setting global settings.");
                return bigIp.globalSettings(globalSettings);
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            if (Object.keys(dbVars).length > 0) {
                console.log("Setting DB vars");
                return bigIp.setDbVars(dbVars);
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            var registrationKey = options.license;
            var addOnKeys = options.addOn;

            if (registrationKey || addOnKeys.length > 0) {
                console.log("Licensing...");

                return bigIp.license(
                    {
                        registrationKey: registrationKey,
                        addOnKeys: addOnKeys
                    }
                );
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            if (Object.keys(modules).length > 0) {
                console.log("Provisioning modules: " + JSON.stringify(modules, null, 4));
                return bigIp.provision(modules);
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            console.log("BIG-IP setup complete.");
        })
        .catch(function(err) {
            console.log("BIG-IP setup failed: " + (typeof err === 'object' ? err.message : err));
        })
        .done(function() {
            console.log("Setup finished at: " + new Date().toUTCString());
        });
}
finally {
    fs.closeSync(logFile);
}

<commit_msg>Save config at end<commit_after>/**
 * Copyright 2016 F5 Networks, Inc.
 *
 * 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.
 */
var fs = require('fs');
var childProcess = require("child_process");
var options = require("commander");
var q = require("q");
var BigIp = require('./lib/bigIp');
var globalSettings = {
    guiSetup: 'disabled'
};
var dbVars = {};
var modules = {};
var passwords = {};
var rootPasswords = {};

var logFileName = '/tmp/setup.log';
var logFile;

var bigIp;

var args;
var myChild;

var i;

var PASSWORD_OPTION_KEYS = ['-p', '--password', '--set-password', '--set-root-password'];
/**
 * Adds value to an array
 *
 * Typically used by the option parser for collecting
 * multiple values for a command line option
 */
var collect = function(val, collection) {
    collection.push(val);
    return collection;
};

/**
 * Parses a ':' deliminated key-value pair and stores them
 * in a container.
 *   - Key is the part before the first ':',
 *   - Value is everything after.
 *   - Leading and trailing spaces are removed from keys and values
 *
 * Typically used by the option parser for collecting
 * multiple key-value pairs for a command line option
 */
var map = function(pair, container) {
    var nameVal = pair.split(/:(.+)/);
    container[nameVal[0].trim()] = nameVal[1].trim();
};

/**
 * Special case of map. Used to parse root password options in the form of
 *     old:oldRootPassword,new:newRootPassword
 * Since passwords can contain any character, a delimiter is difficult to find.
 * Compromise by looking for ',new:' as a delimeter
 */
var parseRootPasswords = function(passwordsValue, container) {
    var set = passwordsValue.split(",new:");

    if (set.length == 2) {
        container.old = set[0].split("old:")[1];
        container.new = set[1];
    }
};

var writeResponse = function(response) {
    if (response && options.verbose) {
        console.log((typeof response === 'object' ? JSON.stringify(response, null, 4) : "  " + response));
    }
};

options
    .option('--host <ip_address>', 'BIG-IP management IP.')
    .option('-u, --user <user>', 'BIG-IP admin user.')
    .option('-p, --password <password>', 'BIG-IP admin user password.')
    .option('--ntp <ntp-server>', 'NTP server. For multiple NTP servers, use multiple --ntp entries', collect, [])
    .option('--tz <timezone>', 'Timezone for NTP setting')
    .option('--dns <DNS server>', 'DNS server. For multiple DNS severs, use multiple --dns entries', collect, [])
    .option('-l, --license <license_key>', 'BIG-IP license key.')
    .option('-a, --add-on <add-on keys>', 'Add on license key. For multiple keys, use multiple -a entries', collect, [])
    .option('-n, --host-name <hostname>', 'Set BIG-IP hostname')
    .option('-g, --global-settings <name:value>', 'A global setting name/value pair. For multiple settings, use multiple -g entries', map, globalSettings)
    .option('-d, --db <name:value>', 'A db variable name/value pair. For multiple settings, use multiple -d entries', map, dbVars)
    .option('--set-password <user:newPassword>', 'Set user password to newPassword. For multiple users, use multiple --set-password entries.', map, passwords)
    .option('--set-root-password <old:oldPassword,new:newPassword>', 'Set the password for the root user from oldPassword to newPassword', parseRootPasswords, rootPasswords)
    .option('-m, --module <name:value>', 'A module provisioning module/level pair. For multiple modules, use multiple -m entries', map, modules)
    .option('-f, --foreground', 'Do the work - otherwise spawn a background process to do the work. If you are running in cloud init, you probably do not want this option.')
    .option('-o, --output <file>', 'Full path for log file if background process is spawned. Default is ' + logFileName)
    .option('--verbose', 'Turn on verbose output')
    .parse(process.argv);

logFileName = options.output || logFileName;

try {
    logFile = fs.openSync(logFileName, 'a');

    // When running in cloud init, we need to exit so that cloud init can complete and
    // allow the BIG-IP services to start
    if (!options.foreground) {

        if (process.argv.length > 100) {
            console.log("Too many arguments - maybe we're stuck in a restart loop?");
        }
        else {
            console.log("Spawning child process to do the work. Output will be in " + logFileName);
            args = process.argv.slice(1);
            args.push('--foreground');
            myChild = childProcess.spawn(
                process.argv[0],
                args,
                {
                    detached: true,
                    stdio: ['ignore', logFile, logFile]
                }
            );
            myChild.unref();
        }

        process.exit();
    }

    // Log the input, but don't log the password
    if (options.password || Object.keys(passwords).lentgh > 0 || Object.keys(rootPasswords).length > 0) {
        for (i = 0; i < process.argv.length; ++i) {
            if (PASSWORD_OPTION_KEYS.indexOf(process.argv[i]) !== -1) {
                process.argv[i + 1] = "*******";
            }
        }
    }
    console.log(process.argv[1] + " called with " + process.argv.slice().join(" "));

    bigIp = new BigIp(options.host, options.user, options.password);

    // Use hostName if both hostName and global-settings hostName are set
    if (globalSettings && options.hostName) {
        if (globalSettings.hostname || globalSettings.hostName) {
            console.log("Using host-name option to override global-settings host name");
            delete globalSettings.hostName;
            delete globalSettings.hostname;
        }
    }

    console.log("Setup starting at: " + new Date().toUTCString());
    console.log("Waiting for BIG-IP to be ready...");
    bigIp.ready(60, 10000) // 10 minutes
        .then(function() {
            var promises = [];
            var user;

            console.log("BIG-IP is ready.");

            if (Object.keys(passwords).length > 0) {
                console.log("Setting password(s).");
                for (user in passwords) {
                    promises.push(bigIp.password(user, passwords[user]));
                }

                return q.all(promises);
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            if (Object.keys(rootPasswords).length > 0) {
                if (!rootPasswords.old || !rootPasswords.new) {
                    return q.reject("Old or new password missing for root user. Specify with --set-root-password old:old_root_password,new:new_root_password");
                }

                console.log("Setting rootPassword.");
                return bigIp.password('root', rootPasswords.new, rootPasswords.old);
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            var ntpBody;

            writeResponse(response);

            if (options.ntp.length > 0 || options.tz) {
                console.log("Setting up NTP.");

                ntpBody = {};

                if (options.ntp) {
                    ntpBody.servers = options.ntp;
                }

                if (options.tz) {
                    ntpBody.timezone = options.tz;
                }

                return bigIp.modify(
                    '/tm/sys/ntp',
                    ntpBody
                );
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            if (options.dns.length > 0) {
                console.log("Setting up DNS.");

                return bigIp.modify(
                    '/tm/sys/dns',
                    {
                        'name-servers': options.dns
                    }
                );
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            if (options.hostName) {
                console.log("Setting host name.");
                return bigIp.hostName(options.hostName);
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            if (globalSettings) {
                console.log("Setting global settings.");
                return bigIp.globalSettings(globalSettings);
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            if (Object.keys(dbVars).length > 0) {
                console.log("Setting DB vars");
                return bigIp.setDbVars(dbVars);
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            var registrationKey = options.license;
            var addOnKeys = options.addOn;

            if (registrationKey || addOnKeys.length > 0) {
                console.log("Licensing...");

                return bigIp.license(
                    {
                        registrationKey: registrationKey,
                        addOnKeys: addOnKeys
                    }
                );
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);

            if (Object.keys(modules).length > 0) {
                console.log("Provisioning modules: " + JSON.stringify(modules, null, 4));
                return bigIp.provision(modules);
            }
            else {
                return q();
            }
        })
        .then(function(response) {
            writeResponse(response);
            console.log("Saving config.");
            return bigIp.save();
        })
        .then(function(response) {
            writeResponse(response);
            console.log("BIG-IP setup complete.");
        })
        .catch(function(err) {
            console.log("BIG-IP setup failed: " + (typeof err === 'object' ? err.message : err));
        })
        .done(function() {
            console.log("Setup finished at: " + new Date().toUTCString());
        });
}
finally {
    fs.closeSync(logFile);
}

<|endoftext|>


<commit_before>var Game = {};
var light = false;
var timerset = false;
var timersetflash = false;
var fading = false;
var currContext = "#1F3D5C";
Game.fps = 50;

Game.initialize = function() {
  this.entities = [];
  this.context = document.getElementById("viewport").getContext("2d");

};

Game.draw = function() {

  this.context.clearRect(0, 0, 512, 288);

  this.context.fillStyle = currContext;
  this.context.fillRect(0, 0, 512, 288);

  if(light == true && fading == false){
    fading = true; // we're starting to fade, so don't run this function more than once
    var r = 255, g = 255, b = 255; // starting color (white)
    var steps = 50;
    var dr = (31 - r) / steps; // how much red should be added each time
    var dg = (61 - g) / steps; // green
    var db = (92 - b) / steps; // blue
    var count = 0; // step counter
    var interval = setInterval(function() {
      currContext = 'rgb(' + Math.round(r + dr * count) + ','
                  + Math.round(g + dg * count) + ','
                  + Math.round(b + db * count) + ')';
      count++;
      if(count === steps) { // stop if done
          clearInterval(interval);
          fading = false; // we're done fading
          light = false; // light is now off
      }
    }, 30);
  }

  var lightTime = Math.floor(Math.random() * (7000 - 1000 + 1)) + 1000; // random amount of time between 3 and 7 seconds
  if(light == false && timerset == false){ //if the light is off, set a timer to light it after 5 sec
    setTimeout(function(){
      light = true;
      timerset = false;
    }, lightTime);
    timerset = true;
  }

  for (var i=0; i < this.entities.length; i++) {
    this.entities[i].draw(this.context);
  }
};

Game.update = function() {
  for (var i=0; i < this.entities.length; i++) {
    this.entities[i].update();
  }
};

Game.addRect = function(initX) {
  Game.entities.push(new Rect(initX));
};
Game.addRain = function() {
  Game.entities.push(new Rain());
};

Game.addPlayer = function(){
  Game.entites.push(new Player());
};
<commit_msg>Update game.js<commit_after>var Game = {};
var light = false;
var timerset = false;
var timersetflash = false;
var fading = false;
var currContext = "#1F3D5C";
Game.fps = 50;

Game.initialize = function() {
  this.entities = [];
  this.context = document.getElementById("viewport").getContext("2d");

  for(i =0; i< 17; i++){
    Game.addRect(i*32);
  }

  for(i =0; i< 800; i++){
    Game.addRain();
  }

};

Game.draw = function() {

  this.context.clearRect(0, 0, 512, 288);

  this.context.fillStyle = currContext;
  this.context.fillRect(0, 0, 512, 288);

  if(light == true && fading == false){
    fading = true; // we're starting to fade, so don't run this function more than once
    var r = 255, g = 255, b = 255; // starting color (white)
    var steps = 50;
    var dr = (31 - r) / steps; // how much red should be added each time
    var dg = (61 - g) / steps; // green
    var db = (92 - b) / steps; // blue
    var count = 0; // step counter
    var interval = setInterval(function() {
      currContext = 'rgb(' + Math.round(r + dr * count) + ','
                  + Math.round(g + dg * count) + ','
                  + Math.round(b + db * count) + ')';
      count++;
      if(count === steps) { // stop if done
          clearInterval(interval);
          fading = false; // we're done fading
          light = false; // light is now off
      }
    }, 30);
  }

  var lightTime = Math.floor(Math.random() * (7000 - 1000 + 1)) + 1000; // random amount of time between 3 and 7 seconds
  if(light == false && timerset == false){ //if the light is off, set a timer to light it after 5 sec
    setTimeout(function(){
      light = true;
      timerset = false;
    }, lightTime);
    timerset = true;
  }

  for (var i=0; i < this.entities.length; i++) {
    this.entities[i].draw(this.context);
  }
};

Game.update = function() {
  for (var i=0; i < this.entities.length; i++) {
    this.entities[i].update();
  }
};

Game.addRect = function(initX) {
  Game.entities.push(new Rect(initX));
};
Game.addRain = function() {
  Game.entities.push(new Rain());
};

Game.addPlayer = function(){
  Game.entites.push(new Player());
};
<|endoftext|>


<commit_before>define(['app'], function() {

    return {

        app: null,
        ctx: null,
        NROWS: 5,
        NCOLS: 27,
        BRICKWIDTH: 0,
        BRICKHEIGHT: 18,
        PADDING: 1,
        bricks: [],
        drawIntervalId: null,
        ballRadius: 9,
        rowcolors: ["#f2665e", "#fcb040", "#6ac071", "#57cbf5", "#f2665e"],
        paddlecolor: "#656565",
        ballcolor: "#f2665e",
        backcolor: "#f4f0ed",
        paddlePosition: {
            x: 0,
            y: 0
        },
        ballPosition: {
            x: 25,
            y: 250,
        },
        ballSpeed: {
            x: 1.5,
            y: -4,
        },
        // Used to calculate where the ball is going/what it's hitting
        tempBallPosition: {
            x: 0,
            y: 0,
        },

        init: function(app) {
            this.app = app;
            this.app.init();
            this.ctx = this.app.ctx;
            drawIntervalId = setInterval($.proxy(function() {
                this.draw();
            }, this), 10);
            this.BRICKWIDTH = (this.app.WIDTH / this.NCOLS) - 1;
            this.initBricks();
            this.addListeners();
        },

        addListeners: function() {
            $(window).on('game.over', function() {
                console.log('Game over man, game over');
                clearInterval(drawIntervalId);
            });
        },

        draw: function() {
            this.ctx.fillStyle = this.backcolor;
            this.clear();
            this.ctx.fillStyle = this.ballcolor;
            this.circle(this.ballPosition.x, this.ballPosition.y, this.ballRadius);

            this.paddlePosition = {
                x: this.app.paddlex + this.app.PADDLE_POSITION_OFFSET.x,
                y: this.app.HEIGHT - this.app.paddleh + this.app.PADDLE_POSITION_OFFSET.y
            };

            this.tempBallPosition = {
                x: this.ballPosition.x + this.ballSpeed.x,
                y: this.ballPosition.y + this.ballSpeed.y
            };

            this.drawPaddle();
            this.drawBricks();
            this.updateBricks();

            if (this.isBallOutOfBounds()) {
                $(window).trigger('player.died');
                return this.restart();
            }

            // If the ball has hit the wall
            if (this.hasBallHitWall()) {
                this.ballSpeed.x *= -1;
            }

            if (this.isBallNearPaddle()) {
                // Ball has hit paddle
                if (this.hasBallHitPaddle()) {
                    //move the ball differently based on where it hit the paddle
                    this.ballSpeed.x = 8 * ((this.ballPosition.x - (this.app.paddlex + this.app.paddlew / 2)) / this.app.paddlew);
                    this.ballSpeed.y *= -1;
                }
            } else if (this.hasBallHitTop()) {
                this.ballSpeed.y *= -1;
            }

            this.ballPosition = this.tempBallPosition;
        },

        restart: function() {
            this.ballPosition = {
                x: 25,
                y: 250,
            };
            this.ballSpeed = {
                x: 1.5,
                y: -4,
            };
        },

        initBricks: function() {
            this.bricks = new Array(this.NROWS);
            for (i=0; i < this.NROWS; i++) {
                this.bricks[i] = new Array(this.NCOLS);
                for (j=0; j < this.NCOLS; j++) {
                    this.bricks[i][j] = 1;
                }
            }
        },

        drawBricks: function() {
            for (i=0; i < this.NROWS; i++) {
                this.ctx.fillStyle = this.rowcolors[i];
                for (j=0; j < this.NCOLS; j++) {
                    if (this.bricks[i][j] == 1) {
                        this.rect((j * (this.BRICKWIDTH + this.PADDING)) + this.PADDING,
                                (i * (this.BRICKHEIGHT + this.PADDING)) + this.PADDING,
                                this.BRICKWIDTH, this.BRICKHEIGHT);
                    }
                }
            }
        },

        updateBricks: function() {
            //want to learn about real collision detection? go read
            // http://www.harveycartel.org/metanet/tutorials/tutorialA.html
            var rowheight = this.BRICKHEIGHT + this.PADDING;
            var colwidth = this.BRICKWIDTH + this.PADDING;
            var row = Math.floor(this.ballPosition.y / rowheight);
            var col = Math.floor(this.ballPosition.x / colwidth);
            //reverse the ball and mark the brick as broken
            if (this.ballPosition.y < this.NROWS * rowheight && row >= 0 && col >= 0 && this.bricks[row][col] == 1) {
                this.ballSpeed.y *= -1;
                this.bricks[row][col] = 0;
                $(window).trigger('brick.destroyed');
            }
        },

        drawPaddle: function() {

            // Move paddle
            if (this.app.rightDown && this.canPaddleMoveRight()) {
                this.app.paddlex += 5;
            } else if (this.app.leftDown && this.canPaddleMoveLeft()) {
                this.app.paddlex -= 5;
            }
            this.ctx.fillStyle = this.paddlecolor;

            // Draw paddle
            this.rect(this.paddlePosition.x, this.paddlePosition.y, this.app.paddlew, this.app.paddleh);
        },

        canPaddleMoveLeft: function() {
            return (this.paddlePosition.x > 0);
        },

        canPaddleMoveRight: function() {
            return (this.paddlePosition.x + this.app.paddlew < this.app.WIDTH);
        },

        hasBallHitWall: function() {
            return (this.tempBallPosition.x + this.ballRadius > this.app.WIDTH
                    || this.tempBallPosition.x - this.ballRadius < 0);
        },

        hasBallHitTop: function() {
            return (this.ballPosition.y + this.ballSpeed.y - this.ballRadius < 0);
        },

        /**
         * Is the ball about to hit the paddle. Check whether the ball is currently hittable
         * or whether it's too late/early
         */
        isBallNearPaddle: function() {
            return (this.tempBallPosition.y + this.ballRadius >= this.app.HEIGHT - this.app.paddleh + this.app.PADDLE_POSITION_OFFSET.y);
        },

        hasBallHitPaddle: function() {
            return (this.ballPosition.x > this.paddlePosition.x && this.ballPosition.x < this.paddlePosition.x + this.app.paddlew);
        },

        isBallOutOfBounds: function() {
            return (this.tempBallPosition.y + this.ballRadius >= this.app.HEIGHT);
        },

        circle: function(x,y,r) {
            this.ctx.beginPath();
            this.ctx.arc(x, y, r, 0, Math.PI*2, true);
            this.ctx.closePath();
            this.ctx.fill();
        },

        rect: function(x,y,w,h) {
            this.ctx.beginPath();
            this.ctx.rect(x, y, w, h);
            this.ctx.closePath();
            this.ctx.fill();
        },

        clear: function() {
            this.ctx.clearRect(0, 0, this.app.WIDTH, this.app.HEIGHT);
            this.rect(0, 0, this.app.WIDTH, this.app.HEIGHT);
        }
    }
});
<commit_msg>Amending initBricks to use array literals<commit_after>define(['app'], function() {

    return {

        app: null,
        ctx: null,
        NROWS: 5,
        NCOLS: 27,
        BRICKWIDTH: 0,
        BRICKHEIGHT: 18,
        PADDING: 1,
        bricks: [],
        drawIntervalId: null,
        addRowIntervalId: null,
        ballRadius: 9,
        rowcolors: ["#f2665e", "#fcb040", "#6ac071", "#57cbf5", "#f2665e"],
        paddlecolor: "#656565",
        ballcolor: "#f2665e",
        backcolor: "#f4f0ed",
        paddlePosition: {
            x: 0,
            y: 0
        },
        ballPosition: {
            x: 25,
            y: 250,
        },
        ballSpeed: {
            x: 1.5,
            y: -4,
        },
        // Used to calculate where the ball is going/what it's hitting
        tempBallPosition: {
            x: 0,
            y: 0,
        },

        init: function(app) {
            this.app = app;
            this.app.init();
            this.ctx = this.app.ctx;
            drawIntervalId = setInterval($.proxy(function() {
                this.draw();
            }, this), 10);
            this.BRICKWIDTH = (this.app.WIDTH / this.NCOLS) - 1;
            this.initBricks();
            this.startAddRowInterval();
            this.addListeners();
        },

        addListeners: function() {
            $(window).on('game.over', function() {
                console.log('Game over man, game over');
                clearInterval(drawIntervalId);
            });
        },

        draw: function() {
            this.ctx.fillStyle = this.backcolor;
            this.clear();
            this.ctx.fillStyle = this.ballcolor;
            this.circle(this.ballPosition.x, this.ballPosition.y, this.ballRadius);

            this.paddlePosition = {
                x: this.app.paddlex + this.app.PADDLE_POSITION_OFFSET.x,
                y: this.app.HEIGHT - this.app.paddleh + this.app.PADDLE_POSITION_OFFSET.y
            };

            this.tempBallPosition = {
                x: this.ballPosition.x + this.ballSpeed.x,
                y: this.ballPosition.y + this.ballSpeed.y
            };

            this.drawPaddle();
            this.drawBricks();
            this.updateBricks();

            if (this.isBallOutOfBounds()) {
                $(window).trigger('player.died');
                return this.restart();
            }

            // If the ball has hit the wall
            if (this.hasBallHitWall()) {
                this.ballSpeed.x *= -1;
            }

            if (this.isBallNearPaddle()) {
                // Ball has hit paddle
                if (this.hasBallHitPaddle()) {
                    //move the ball differently based on where it hit the paddle
                    this.ballSpeed.x = 8 * ((this.ballPosition.x - (this.app.paddlex + this.app.paddlew / 2)) / this.app.paddlew);
                    this.ballSpeed.y *= -1;
                }
            } else if (this.hasBallHitTop()) {
                this.ballSpeed.y *= -1;
            }

            this.ballPosition = this.tempBallPosition;
        },

        restart: function() {
            this.ballPosition = {
                x: 25,
                y: 250,
            };
            this.ballSpeed = {
                x: 1.5,
                y: -4,
            };
        },

        initBricks: function() {
            for (i=0; i < this.NROWS; i++) {
                this.bricks[i] = [];
                for (j=0; j < this.NCOLS; j++) {
                    this.bricks[i][j] = 1;
                }
            }
        },

        startAddRowInterval: function() {
            this.addRowIntervalId = setInterval($.proxy(function() {
                this.addRow();
            }, this), 10000);
        },

        addRow: function() {
            this.NROWS++;
            this.initBricks();
            this.drawBricks();
        },

        drawBricks: function() {
            for (i=0; i < this.NROWS; i++) {
                this.ctx.fillStyle = this.rowcolors[i];
                for (j=0; j < this.NCOLS; j++) {
                    if (this.bricks[i][j] == 1) {
                        this.rect((j * (this.BRICKWIDTH + this.PADDING)) + this.PADDING,
                                (i * (this.BRICKHEIGHT + this.PADDING)) + this.PADDING,
                                this.BRICKWIDTH, this.BRICKHEIGHT);
                    }
                }
            }
        },

        updateBricks: function() {
            //want to learn about real collision detection? go read
            // http://www.harveycartel.org/metanet/tutorials/tutorialA.html
            var rowheight = this.BRICKHEIGHT + this.PADDING;
            var colwidth = this.BRICKWIDTH + this.PADDING;
            var row = Math.floor(this.ballPosition.y / rowheight);
            var col = Math.floor(this.ballPosition.x / colwidth);
            //reverse the ball and mark the brick as broken
            if (this.ballPosition.y < this.NROWS * rowheight && row >= 0 && col >= 0 && this.bricks[row][col] == 1) {
                this.ballSpeed.y *= -1;
                this.bricks[row][col] = 0;
                $(window).trigger('brick.destroyed');
            }
        },

        drawPaddle: function() {

            // Move paddle
            if (this.app.rightDown && this.canPaddleMoveRight()) {
                this.app.paddlex += 5;
            } else if (this.app.leftDown && this.canPaddleMoveLeft()) {
                this.app.paddlex -= 5;
            }
            this.ctx.fillStyle = this.paddlecolor;

            // Draw paddle
            this.rect(this.paddlePosition.x, this.paddlePosition.y, this.app.paddlew, this.app.paddleh);
        },

        canPaddleMoveLeft: function() {
            return (this.paddlePosition.x > 0);
        },

        canPaddleMoveRight: function() {
            return (this.paddlePosition.x + this.app.paddlew < this.app.WIDTH);
        },

        hasBallHitWall: function() {
            return (this.tempBallPosition.x + this.ballRadius > this.app.WIDTH
                    || this.tempBallPosition.x - this.ballRadius < 0);
        },

        hasBallHitTop: function() {
            return (this.ballPosition.y + this.ballSpeed.y - this.ballRadius < 0);
        },

        /**
         * Is the ball about to hit the paddle. Check whether the ball is currently hittable
         * or whether it's too late/early
         */
        isBallNearPaddle: function() {
            return (this.tempBallPosition.y + this.ballRadius >= this.app.HEIGHT - this.app.paddleh + this.app.PADDLE_POSITION_OFFSET.y);
        },

        hasBallHitPaddle: function() {
            return (this.ballPosition.x > this.paddlePosition.x && this.ballPosition.x < this.paddlePosition.x + this.app.paddlew);
        },

        isBallOutOfBounds: function() {
            return (this.tempBallPosition.y + this.ballRadius >= this.app.HEIGHT);
        },

        circle: function(x,y,r) {
            this.ctx.beginPath();
            this.ctx.arc(x, y, r, 0, Math.PI*2, true);
            this.ctx.closePath();
            this.ctx.fill();
        },

        rect: function(x,y,w,h) {
            this.ctx.beginPath();
            this.ctx.rect(x, y, w, h);
            this.ctx.closePath();
            this.ctx.fill();
        },

        clear: function() {
            this.ctx.clearRect(0, 0, this.app.WIDTH, this.app.HEIGHT);
            this.rect(0, 0, this.app.WIDTH, this.app.HEIGHT);
        }
    }
});
<|endoftext|>


<commit_before>var nmbug_server = 'http://localhost:5000';

nmbug = {
	show: function (message_id) {
		this._get_tags(message_id, this._edit_tags.bind(this, message_id));
	},
	_get_tags: function (message_id, callback) {
		var url = [
			nmbug_server,
			'mid',
			encodeURIComponent(message_id),
			].join('/');
		console.log('nmbug: get tags from ' + url);
		var request = new XMLHttpRequest();
		request.onload = function () {
			if (this.status == 200) {
				var tags = JSON.parse(this.response);
				console.log('nmbug: got tags', tags);
				callback(tags);
			} else {
				throw 'Error fetching ' + url + ' (status ' + this.status + ')';
			}
		};
		request.open('get', url, true);
		request.send();
	},
	_edit_tags: function (message_id, tags) {
		if (document.createElement('dialog').show) {
			this._x_edit_tags(message_id, tags);
		} else {
			var _this = this;
			var dialog_polyfill_loaded = 0;

			function onload () {
				dialog_polyfill_loaded++;
				if (dialog_polyfill_loaded == 2) {
					_this._x_edit_tags(message_id, tags);
				}
			}

			var script = document.createElement('script');
			script.type = 'text/javascript';
			script.src = nmbug_server + '/static/dialog-polyfill/dialog-polyfill.js';
			script.onload = onload;
			document.head.appendChild(script);

			var link = document.createElement('link');
			link.rel = 'stylesheet';
			link.type = 'text/css';
			link.href = nmbug_server + '/static/dialog-polyfill/dialog-polyfill.css';
			link.onload = onload;
			document.head.appendChild(link);
		}
	},
	_x_edit_tags: function (message_id, tags) {
		var dialog = document.createElement('dialog');
		if (!document.createElement('dialog').show) {
			dialogPolyfill.registerDialog(dialog);
		}

		dialog.style.border = '1px solid rgba(0, 0, 0, 0.3)';
		dialog.style.borderRadius = '6px';
		dialog.style.boxShadow = '0 3px 7px rgba(0, 0, 0, 0.3)';

		var content = document.createElement('p');
		content.innerHTML = 'Edit tags for ' + message_id;
		dialog.appendChild(content);

		var ul = document.createElement('ul');
		dialog.appendChild(ul);
		for (var i = 0; i < tags.length; i++) {
			var li = document.createElement('li');
			li.innerHTML = tags[i];
			ul.appendChild(li);
		}
		var close = document.createElement('button');
		close.innerHTML = 'Close';
		close.onclick = function () {
			dialog.close();
		};
		dialog.appendChild(close);

		document.body.appendChild(dialog);

		dialog.show();
	},
};

var _gmane_handler = {
	regexp: /gmane[.]org/,
	handle: function (callback) {
		var article = this._get_article();
		this._get_message_id(article, callback);
	},
	_article_from_url: function (url) {
		var regexp = new RegExp('http://article.gmane.org/([^/]+)/([0-9]+)');
		var match = regexp.exec(url);
		console.log('nmbug: get article from ' + url, match);
		if (match) {
			return {'group': match[1], 'id': parseInt(match[2])};
		}
	},
	_get_article: function () {
		var article = this._article_from_url(document.URL);
		var i = 0;
		for (var i = 0; !article && i < window.frames.length; i++) {
			article = this._article_from_url(window.frames[i].document.URL);
		}
		if (!article) {
			throw "Cannot extract an article from Gmane's " + document.URL;
		}
		return article;
	},
	_get_message_id: function (article, callback) {
		var url = [
			nmbug_server,
			'gmane',
			article.group,
			article.id,
		].join('/');
		console.log('nmbug: get Message-ID from ' + url);
		var request = new XMLHttpRequest();
		request.onload = function () {
			var message_id = this.responseText;
			callback(message_id);
		};
		request.open('get', url, true);
		request.send();
	},
};

var handlers = [
	_gmane_handler,
];

function _check_handler(handler) {
	var match = handler.regexp.test(document.URL);
	console.log('nmbug: testing', handler, match);
	if (match) {
		console.log('nmbug: matched', handler);
		handler.handle(nmbug.show.bind(nmbug));
	}
	return match;  /* break after the first match */
}

function run() {
	var matched = handlers.some(_check_handler);
	if (!matched) {
		throw 'No handler for ' + document.URL;
	}
}
<commit_msg>nmbug.js: Add available-tags fetcher and highlight selected tags<commit_after>var nmbug_server = 'http://localhost:5000';

nmbug = {
	show: function (message_id) {
		var _this = this;
		this._get_available_tags(function (available_tags) {
			_this._get_tags(
				message_id,
				_this._edit_tags.bind(_this, available_tags, message_id));
		});
	},
	_get_available_tags: function (callback) {
		var url = [
			nmbug_server,
			'tags',
			].join('/');
		console.log('nmbug: get available tags from ' + url);
		var request = new XMLHttpRequest();
		request.onload = function () {
			if (this.status == 200) {
				var available_tags = JSON.parse(this.response);
				console.log('nmbug: got available tags', available_tags);
				callback(available_tags);
			} else {
				throw 'Error fetching ' + url + ' (status ' + this.status + ')';
			}
		};
		request.open('get', url, true);
		request.send();
	},
	_get_tags: function (message_id, callback) {
		var url = [
			nmbug_server,
			'mid',
			encodeURIComponent(message_id),
			].join('/');
		console.log('nmbug: get tags from ' + url);
		var request = new XMLHttpRequest();
		request.onload = function () {
			if (this.status == 200) {
				var tags = JSON.parse(this.response);
				console.log('nmbug: got tags', tags);
				callback(tags);
			} else {
				throw 'Error fetching ' + url + ' (status ' + this.status + ')';
			}
		};
		request.open('get', url, true);
		request.send();
	},
	_edit_tags: function (available_tags, message_id, tags) {
		if (document.createElement('dialog').show) {
			this._x_edit_tags(available_tags, message_id, tags);
		} else {
			var _this = this;
			var dialog_polyfill_loaded = 0;

			function onload () {
				dialog_polyfill_loaded++;
				if (dialog_polyfill_loaded == 2) {
					_this._x_edit_tags(available_tags, message_id, tags);
				}
			}

			var script = document.createElement('script');
			script.type = 'text/javascript';
			script.src = nmbug_server + '/static/dialog-polyfill/dialog-polyfill.js';
			script.onload = onload;
			document.head.appendChild(script);

			var link = document.createElement('link');
			link.rel = 'stylesheet';
			link.type = 'text/css';
			link.href = nmbug_server + '/static/dialog-polyfill/dialog-polyfill.css';
			link.onload = onload;
			document.head.appendChild(link);
		}
	},
	_x_edit_tags: function (available_tags, message_id, tags) {
		var dialog = document.createElement('dialog');
		if (!document.createElement('dialog').show) {
			dialogPolyfill.registerDialog(dialog);
		}

		dialog.style.border = '1px solid rgba(0, 0, 0, 0.3)';
		dialog.style.borderRadius = '6px';
		dialog.style.boxShadow = '0 3px 7px rgba(0, 0, 0, 0.3)';

		var content = document.createElement('p');
		content.innerHTML = 'Edit tags for ' + message_id;
		dialog.appendChild(content);

		var ul = document.createElement('ul');
		dialog.appendChild(ul);
		for (var i = 0; i < available_tags.length; i++) {
			var li = document.createElement('li');
			li.innerHTML = available_tags[i];
			if (tags.indexOf(available_tags[i]) >= 0) {
				li.style.backgroundColor = 'lime';
			}
			ul.appendChild(li);
		}
		var close = document.createElement('button');
		close.innerHTML = 'Close';
		close.onclick = function () {
			dialog.close();
		};
		dialog.appendChild(close);

		document.body.appendChild(dialog);

		dialog.show();
	},
};

var _gmane_handler = {
	regexp: /gmane[.]org/,
	handle: function (callback) {
		var article = this._get_article();
		this._get_message_id(article, callback);
	},
	_article_from_url: function (url) {
		var regexp = new RegExp('http://article.gmane.org/([^/]+)/([0-9]+)');
		var match = regexp.exec(url);
		console.log('nmbug: get article from ' + url, match);
		if (match) {
			return {'group': match[1], 'id': parseInt(match[2])};
		}
	},
	_get_article: function () {
		var article = this._article_from_url(document.URL);
		var i = 0;
		for (var i = 0; !article && i < window.frames.length; i++) {
			article = this._article_from_url(window.frames[i].document.URL);
		}
		if (!article) {
			throw "Cannot extract an article from Gmane's " + document.URL;
		}
		return article;
	},
	_get_message_id: function (article, callback) {
		var url = [
			nmbug_server,
			'gmane',
			article.group,
			article.id,
		].join('/');
		console.log('nmbug: get Message-ID from ' + url);
		var request = new XMLHttpRequest();
		request.onload = function () {
			var message_id = this.responseText;
			callback(message_id);
		};
		request.open('get', url, true);
		request.send();
	},
};

var handlers = [
	_gmane_handler,
];

function _check_handler(handler) {
	var match = handler.regexp.test(document.URL);
	console.log('nmbug: testing', handler, match);
	if (match) {
		console.log('nmbug: matched', handler);
		handler.handle(nmbug.show.bind(nmbug));
	}
	return match;  /* break after the first match */
}

function run() {
	var matched = handlers.some(_check_handler);
	if (!matched) {
		throw 'No handler for ' + document.URL;
	}
}
<|endoftext|>