<commit_before>/*global window, document */
"use strict";

/*
Your task is to create good old snake game where snake runs in a box and eats treats.

Technical requirements
•         Game must be written in pure javascript.
•         No third party libraries.
•         No canvas
•         Should work with latest Chrome. Other browsers support not required.

Game rules:
•         Each time snake eats the treat, new one will be created to random place.
          If snake wonders for too long (30 sec for instance) treat is repositioned.
•         Every now and then (interval should be configurable from code) snake gains speed,
          ie. level is increased.
•         when snake runs into a wall, game is over.
•         when snake bites itself, game is over.
•         snake starts from bottom center

Game features:
•         snake can move only one pixel at a time
•         pixel size is configurable (from code only)
•         box size is configurable (from code only)
•         game can be paused and resumed
•         progressive points - the higher the level, the higher points you get for eating
          the treat
•         display score
•         display level
*/

var Snake = {};

Snake.Point = function (x, y) {
    this.x = x;
    this.y = y;
};

Snake.Direction = {
    Up: 38,
    Down: 40,
    Left: 37,
    Right: 39,
};

Snake.Config = function () {
    this.pixelSize = 1;
    this.boxSize = 20;
};

Snake.State = function () {
    this.level = 1;
    this.score = 0;
    this.paused = false;
    this.intervalMillis = 1000;
    this.direction = Snake.Direction.Up;
};

Snake.Game = function (doc, wnd) {
    this.config = new Snake.Config();
    this.state = new Snake.State();
    doc.onkeydown = this.onkeydown;
    this.timer = wnd.setInterval(this.loop.bind(this), this.state.intervalMillis);
};

Snake.Game.prototype.update = function () {
    if (!this.box) {
        this.box = [];
        var x = 0, y = 0;
        // left
        x = 0;
        for (y = 0; y < this.config.boxSize; y = y + 1) {
            this.box.push(new Snake.Point(x, y));
            console.log(x, y);
        }
        // top
        y = this.config.boxSize - 1;
        for (x = 0; x < this.config.boxSize; x = x + 1) {
            this.box.push(new Snake.Point(x, y));
            console.log(x, y);
        }
        // right
        x = this.config.boxSize - 1;
        for (y = this.config.boxSize - 2; y >= 0; y = y - 1) {
            this.box.push(new Snake.Point(x, y));
            console.log(x, y);
        }
        // bottom
        y = 0;
        for (x = this.config.boxSize - 2; x > 0; x = x - 1) {
            this.box.push(new Snake.Point(x, y));
            console.log(x, y);
        }
    }
    if (!this.treat) {
        // FIXME: place treat
    }
    if (!this.snake) {
        // FIXME: place snake at the bottom center
    }
};

Snake.Game.prototype.draw = function () {};

Snake.Game.prototype.onkeydown = function (evt) {
    switch (evt.keyCode) {
    case Snake.Direction.Up:
    case Snake.Direction.Down:
    case Snake.Direction.Left:
    case Snake.Direction.Right:
        console.log('new direction', evt.keyCode);
        this.direction = evt.keyCode;
        break;
    }
    return true;
};

Snake.Game.prototype.loop = function () {
    this.update();
    this.draw();
};

document.game = new Snake.Game(document, window);
<commit_msg>implement pause/resume<commit_after>/*global window, document */
"use strict";

/*
Your task is to create good old snake game where snake runs in a box and eats treats.

Technical requirements
•         Game must be written in pure javascript.
•         No third party libraries.
•         No canvas
•         Should work with latest Chrome. Other browsers support not required.

Game rules:
•         Each time snake eats the treat, new one will be created to random place.
          If snake wonders for too long (30 sec for instance) treat is repositioned.
•         Every now and then (interval should be configurable from code) snake gains speed,
          ie. level is increased.
•         when snake runs into a wall, game is over.
•         when snake bites itself, game is over.
•         snake starts from bottom center

Game features:
•         snake can move only one pixel at a time
•         pixel size is configurable (from code only)
•         box size is configurable (from code only)
•         game can be paused and resumed
•         progressive points - the higher the level, the higher points you get for eating
          the treat
•         display score
•         display level
*/

var Snake = {};

Snake.Point = function (x, y) {
    this.x = x;
    this.y = y;
};

Snake.Direction = {
    Up: 38,
    Down: 40,
    Left: 37,
    Right: 39,
};

Snake.KeyCode = {
    Pause: 80,
    Resume: 82,
};

Snake.Config = function () {
    this.pixelSize = 1;
    this.boxSize = 20;
};

Snake.State = function () {
    this.level = 1;
    this.score = 0;
    this.paused = false;
    this.intervalMillis = 1000;
    this.direction = Snake.Direction.Up;
};

Snake.Game = function (doc, wnd) {
    this.config = new Snake.Config();
    this.state = new Snake.State();
    doc.onkeydown = this.onkeydown.bind(this);
    this.wnd = wnd;
    this.resume();
};

Snake.Game.prototype.update = function () {
    if (!this.box) {
        this.box = [];
        var x = 0, y = 0;
        // left
        x = 0;
        for (y = 0; y < this.config.boxSize; y = y + 1) {
            this.box.push(new Snake.Point(x, y));
            console.log(x, y);
        }
        // top
        y = this.config.boxSize - 1;
        for (x = 0; x < this.config.boxSize; x = x + 1) {
            this.box.push(new Snake.Point(x, y));
            console.log(x, y);
        }
        // right
        x = this.config.boxSize - 1;
        for (y = this.config.boxSize - 2; y >= 0; y = y - 1) {
            this.box.push(new Snake.Point(x, y));
            console.log(x, y);
        }
        // bottom
        y = 0;
        for (x = this.config.boxSize - 2; x > 0; x = x - 1) {
            this.box.push(new Snake.Point(x, y));
            console.log(x, y);
        }
    }
    if (!this.snake) {
        // FIXME: place snake at the bottom center
    }
    if (!this.treat) {
        // FIXME: check for collision
    }
};

Snake.Game.prototype.draw = function () {
    // FIXME: box
    // FIXME: snake
    // FIXME: treat
    // FIXME: level
    // FIXME: score
};

Snake.Game.prototype.onkeydown = function (evt) {
    switch (evt.keyCode) {
    case Snake.Direction.Up:
    case Snake.Direction.Down:
    case Snake.Direction.Left:
    case Snake.Direction.Right:
        console.log('new direction', evt.keyCode);
        this.direction = evt.keyCode;
        break;
    case Snake.KeyCode.Pause:
        this.pause();
        break;
    case Snake.KeyCode.Resume:
        this.resume();
        break;
    }
    return true;
};

Snake.Game.prototype.pause = function () {
    console.log('pause');
    this.wnd.clearInterval(this.timer);
    delete this.timer;
};

Snake.Game.prototype.resume = function () {
    console.log('resume');
    if (!this.timer) {
        this.timer = this.wnd.setInterval(this.loop.bind(this), this.state.intervalMillis);
    }
};

Snake.Game.prototype.loop = function () {
    console.log('loop');
    this.update();
    this.draw();
};

document.game = new Snake.Game(document, window);
<|endoftext|>


<commit_before>var game = {}; // Game Object
var up = 119, left = 97, down = 115, right = 100; // KeyCodes end
var ROWS = 100, COLS = 100;

function draw_snake_dot(location) {
    cube(location.x, location.y, false);
}

function draw_food_dot(location) {
    cube(location.x, location.y, true);
}

function is_same_dot(a, b) {
    return a.x === b.x && a.y === b.y;
}

function is_location_in_snake(loc) {
    return game.dots.filter(function (dot) {
        return is_same_dot(dot, loc);
    }).length > 0;
}

function make_location() {
    while (true) {
        var location = {
            x: Math.floor(Math.random() * (ROWS)),
            y: Math.floor(Math.random() * (COLS))
        };

        if (!is_location_in_snake(location))
            return location;
    }
}

// Limit update speed
var total_d = 0;

function is_ready_for_tick(delta) {
    total_d -= delta;
    if (total_d > 100) {
        total_d = 0;
        return true;
    }
    return false;
}

game.init = function () {
    game.keypressed = null;

    game.num_dots = 3;
    game.dots = [];

    game.direction = null;

    game.food = null;

    game.dots.push(make_location());
    game.food = make_location();

};

game.update = function (delta) {
    if (!is_ready_for_tick(delta) || game.dots.length === 0)
        return;

    var last_dot = game.dots[game.dots.length - 1];

    if (is_same_dot(last_dot, game.food)) {
        game.num_dots += 1;
        game.food = make_location();
    }

    // Movement
    if (game.direction !== null) {
        var next = {x: last_dot.x, y: last_dot.y};
        //print("Adding next dot");
        switch (game.direction) {
            case up:
                next.y += 1;
                break;
            case down:
                next.y -= 1;
                break;
            case left:
                next.x -= 1;
                break;
            case right:
                next.x += 1;
                break;
        }

        // Fail states
        if (next.x < 0 || next.x > ROWS || next.y < 0 || next.y > COLS || is_location_in_snake(next)) {
            game.init();
            return;
        }

        // If we didn't die, take this new location and push it into the snake.
        game.dots.push(next);

    }

    // Remove oldest dots from snake.
    while (game.dots.length > game.num_dots)
        game.dots.shift();
};

game.render = function () {
    // Draw the snake
    game.dots.forEach(draw_snake_dot);
    if (game.food)
        draw_food_dot(game.food)
};

game.keypress = function (key) {
    // Skip directions that don't make sense
    var is_conflicting = function (a, b) {
        return game.direction === a && key === b || game.direction === b && key === a;
    };
    if (is_conflicting(up, down) || is_conflicting(left, right))
        return;
    game.direction = key;
}
<commit_msg>Filter non-WASD keys from reaching update loop.<commit_after>var game = {}; // Game Object
var up = 119, left = 97, down = 115, right = 100; // KeyCodes end
var ROWS = 100, COLS = 100;

function draw_snake_dot(location) {
    cube(location.x, location.y, false);
}

function draw_food_dot(location) {
    cube(location.x, location.y, true);
}

function is_same_dot(a, b) {
    return a.x === b.x && a.y === b.y;
}

function is_location_in_snake(loc) {
    return game.dots.filter(function (dot) {
        return is_same_dot(dot, loc);
    }).length > 0;
}

function make_location() {
    while (true) {
        var location = {
            x: Math.floor(Math.random() * (ROWS)),
            y: Math.floor(Math.random() * (COLS))
        };

        if (!is_location_in_snake(location))
            return location;
    }
}

// Limit update speed
var total_d = 0;

function is_ready_for_tick(delta) {
    total_d -= delta;
    if (total_d > 100) {
        total_d = 0;
        return true;
    }
    return false;
}

game.init = function () {
    game.keypressed = null;

    game.num_dots = 3;
    game.dots = [];

    game.direction = null;

    game.food = null;

    game.dots.push(make_location());
    game.food = make_location();

};

game.update = function (delta) {
    if (!is_ready_for_tick(delta) || game.dots.length === 0)
        return;

    var last_dot = game.dots[game.dots.length - 1];

    if (is_same_dot(last_dot, game.food)) {
        game.num_dots += 1;
        game.food = make_location();
    }

    // Movement
    if (game.direction !== null) {
        var next = {x: last_dot.x, y: last_dot.y};
        //print("Adding next dot");
        switch (game.direction) {
            case up:
                next.y += 1;
                break;
            case down:
                next.y -= 1;
                break;
            case left:
                next.x -= 1;
                break;
            case right:
                next.x += 1;
                break;
        }

        // Fail states
        if (next.x < 0 || next.x > ROWS || next.y < 0 || next.y > COLS || is_location_in_snake(next)) {
            game.init();
            return;
        }

        // If we didn't die, take this new location and push it into the snake.
        game.dots.push(next);

    }

    // Remove oldest dots from snake.
    while (game.dots.length > game.num_dots)
        game.dots.shift();
};

game.render = function () {
    // Draw the snake
    game.dots.forEach(draw_snake_dot);
    if (game.food)
        draw_food_dot(game.food)
};

game.keypress = function (key) {
    // Skip directions that don't make sense
    var is_conflicting = function (a, b) {
        return game.direction === a && key === b || game.direction === b && key === a;
    };
    // Make sure this direction makes sense
    if (is_conflicting(up, down) || is_conflicting(left, right))
        return;
    // Make sure they clicked a real button
    if (up !== key && down !== key && left !== key && right !== key)
        return;

    // Update the direction
    game.direction = key;
}
<|endoftext|>


<commit_before>/*
 *   Copyright 2012 OSBI Ltd
 *
 *   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.
 */

/**
 * Workspace query
 */
var Query = Backbone.Model.extend({

    formatter: Settings.CELLSET_FORMATTER,
    properties: null,

    initialize: function(args, options) {
        // Save cube
        _.extend(this, options);

        // Bind `this`
        _.bindAll(this, "run");

        // Generate a unique query id
        this.uuid = 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
            function (c) {
                var r = Math.random() * 16 | 0,
                v = c == 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            }).toUpperCase();

        this.model = _.extend({ name: this.uuid }, SaikuOlapQueryTemplate);
        if (args.cube) {
            this.model.cube = args.cube;
        }
        this.helper = new SaikuOlapQueryHelper(this);

        // Initialize properties, action handler, and result handler
        this.action = new QueryAction({}, { query: this });
        this.result = new Result({ limit: Settings.RESULT_LIMIT }, { query: this });
        this.scenario = new QueryScenario({}, { query: this });
    },

    parse: function(response) {
        // Assign id so Backbone knows to PUT instead of POST
        this.id = this.uuid;
        if (response.name) {
            this.id = response.name;
            this.uuid = response.name;
        }
        this.model = _.extend(this.model, response);
        this.model.properties = _.extend({}, Settings.QUERY_PROPERTIES, this.model.properties);
    },

    setProperty: function(key, value) {
            this.model.properties[key] = value;
    },

    getProperty: function(key) {
        return this.model.properties[key];
    },

    run: function(force, mdx) {
        var self = this;
        // Check for automatic execution
        Saiku.ui.unblock();
        if (typeof this.model.properties != "undefined" && this.model.properties['saiku.olap.query.automatic_execution'] === false &&
			(force === false || force === undefined || force === null)) {
            return;
        }
        this.workspace.unblock();

        $(this.workspace.el).find(".workspace_results_info").empty();
        this.workspace.trigger('query:run');
        this.result.result = null;
        var validated = false;
        var errorMessage = "Query Validation failed!";

        var exModel = this.helper.model();
		for(var k in this.attributes) {
			var att = this.attributes[k];
			if(k.substring(0,5)==="PARAM"){
				var p = k.substring(5, k.size());
				exModel.parameters[p] = att;
			}

		}
        if (exModel.queryType == "OLAP") {
            if (exModel.type == "QUERYMODEL") {
                var columnsOk = Object.keys(exModel.queryModel.axes.COLUMNS.hierarchies).length > 0;
                var rowsOk = Object.keys(exModel.queryModel.axes.ROWS.hierarchies).length > 0;
                var detailsOk = exModel.queryModel.details.axis == 'COLUMNS' && exModel.queryModel.details.measures.length > 0;
                if (!rowsOk || !columnsOk || !detailsOk) {
                    errorMessage = "";
                }
                if (!columnsOk && !detailsOk) {
                    errorMessage += 'You need to include at least one measure or a level on columns for a valid query.';
                }
                if(!rowsOk) {
                    errorMessage += 'You need to include at least one level on rows for a valid query.';

                }
                if ( (columnsOk || detailsOk) && rowsOk) {
                    validated = true;
                }

            } else if (exModel.type == "MDX") {
                validated = (exModel.mdx && exModel.mdx.length > 0);
                if (!validated) {
                    errorMessage = 'You need to enter some MDX statement to execute.';
                }
            }
        }
        if (!validated) {
            this.workspace.table.clearOut();
            $(this.workspace.processing).html(errorMessage).show();
            this.workspace.adjust();
            Saiku.i18n.translate();
            return;
        }

        // Run it
        this.workspace.table.clearOut();
        $(this.workspace.processing).html('   Running query... [ Cancel ]').show();
        this.workspace.adjust();
        this.workspace.trigger('query:fetch');
		Saiku.i18n.translate();
        var message = '   Running query... [ Cancel ]';
        this.workspace.block(message);
/*
        TODO: i wonder if we should clean up the model (name and captions etc.)
        delete this.model.queryModel.axes['FILTER'].name;
*/
        this.result.save({},{ contentType: "application/json", data: JSON.stringify(exModel), error: function() {
            Saiku.ui.unblock();
            var errorMessage = 'Error executing query. Please check the server logs or contact your administrator!';
            self.workspace.table.clearOut();
            $(self.workspace.processing).html(errorMessage).show();
            self.workspace.adjust();
            Saiku.i18n.translate();
        } });
    },

    enrich: function() {
        var self = this;
        this.workspace.query.action.post("/../enrich", {
            contentType: "application/json",
            data: JSON.stringify(self.model),
            async: false,
            success: function(response, model) {
                self.model = model;
            }
        });
    },

    url: function() {
        return "api/query/" + encodeURI(this.uuid);
    }
});

<commit_msg>fix params<commit_after>/*
 *   Copyright 2012 OSBI Ltd
 *
 *   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.
 */

/**
 * Workspace query
 */
var Query = Backbone.Model.extend({

    formatter: Settings.CELLSET_FORMATTER,
    properties: null,

    initialize: function(args, options) {
        // Save cube
        _.extend(this, options);

        // Bind `this`
        _.bindAll(this, "run");

        // Generate a unique query id
        this.uuid = 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
            function (c) {
                var r = Math.random() * 16 | 0,
                v = c == 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            }).toUpperCase();

        this.model = _.extend({ name: this.uuid }, SaikuOlapQueryTemplate);
        if (args.cube) {
            this.model.cube = args.cube;
        }
        this.helper = new SaikuOlapQueryHelper(this);

        // Initialize properties, action handler, and result handler
        this.action = new QueryAction({}, { query: this });
        this.result = new Result({ limit: Settings.RESULT_LIMIT }, { query: this });
        this.scenario = new QueryScenario({}, { query: this });
    },

    parse: function(response) {
        // Assign id so Backbone knows to PUT instead of POST
        this.id = this.uuid;
        if (response.name) {
            this.id = response.name;
            this.uuid = response.name;
        }
        this.model = _.extend(this.model, response);
        this.model.properties = _.extend({}, Settings.QUERY_PROPERTIES, this.model.properties);
    },

    setProperty: function(key, value) {
            this.model.properties[key] = value;
    },

    getProperty: function(key) {
        return this.model.properties[key];
    },

    run: function(force, mdx) {
        var self = this;
        // Check for automatic execution
        Saiku.ui.unblock();
        if (typeof this.model.properties != "undefined" && this.model.properties['saiku.olap.query.automatic_execution'] === false &&
			(force === false || force === undefined || force === null)) {
            return;
        }
        this.workspace.unblock();

        $(this.workspace.el).find(".workspace_results_info").empty();
        this.workspace.trigger('query:run');
        this.result.result = null;
        var validated = false;
        var errorMessage = "Query Validation failed!";

        var exModel = this.helper.model();
		for(var k in this.attributes) {
			var att = this.attributes[k];
			if(k.substring(0,5)==="PARAM"){
				var p = k.substring(5, k.length);
				exModel.parameters[p] = att;
			}

		}
        if (exModel.queryType == "OLAP") {
            if (exModel.type == "QUERYMODEL") {
                var columnsOk = Object.keys(exModel.queryModel.axes.COLUMNS.hierarchies).length > 0;
                var rowsOk = Object.keys(exModel.queryModel.axes.ROWS.hierarchies).length > 0;
                var detailsOk = exModel.queryModel.details.axis == 'COLUMNS' && exModel.queryModel.details.measures.length > 0;
                if (!rowsOk || !columnsOk || !detailsOk) {
                    errorMessage = "";
                }
                if (!columnsOk && !detailsOk) {
                    errorMessage += 'You need to include at least one measure or a level on columns for a valid query.';
                }
                if(!rowsOk) {
                    errorMessage += 'You need to include at least one level on rows for a valid query.';

                }
                if ( (columnsOk || detailsOk) && rowsOk) {
                    validated = true;
                }

            } else if (exModel.type == "MDX") {
                validated = (exModel.mdx && exModel.mdx.length > 0);
                if (!validated) {
                    errorMessage = 'You need to enter some MDX statement to execute.';
                }
            }
        }
        if (!validated) {
            this.workspace.table.clearOut();
            $(this.workspace.processing).html(errorMessage).show();
            this.workspace.adjust();
            Saiku.i18n.translate();
            return;
        }

        // Run it
        this.workspace.table.clearOut();
        $(this.workspace.processing).html('   Running query... [ Cancel ]').show();
        this.workspace.adjust();
        this.workspace.trigger('query:fetch');
		Saiku.i18n.translate();
        var message = '   Running query... [ Cancel ]';
        this.workspace.block(message);
/*
        TODO: i wonder if we should clean up the model (name and captions etc.)
        delete this.model.queryModel.axes['FILTER'].name;
*/
        this.result.save({},{ contentType: "application/json", data: JSON.stringify(exModel), error: function() {
            Saiku.ui.unblock();
            var errorMessage = 'Error executing query. Please check the server logs or contact your administrator!';
            self.workspace.table.clearOut();
            $(self.workspace.processing).html(errorMessage).show();
            self.workspace.adjust();
            Saiku.i18n.translate();
        } });
    },

    enrich: function() {
        var self = this;
        this.workspace.query.action.post("/../enrich", {
            contentType: "application/json",
            data: JSON.stringify(self.model),
            async: false,
            success: function(response, model) {
                self.model = model;
            }
        });
    },

    url: function() {
        return "api/query/" + encodeURI(this.uuid);
    }
});

<|endoftext|>


<commit_before>var _ = require('lodash');
var logger = require('winston');
var linkTagDef = require('../../inline-tag-defs/link');
var PartialNames = require('../../utils/partial-names').PartialNames;

describe("links inline tag handler", function() {
  var doc, links, logLevel, partialNames, linkHandler;

  it("should have name 'link'", function() {
    expect(linkTagDef.name).toEqual('link');
  });

  beforeEach(function() {
    logLevel = logger.level;
    logger.level = 'warn';
    spyOn(logger, 'warn');

    doc = {
      id: 'module:ng.directive:ngInclude',
      path: 'api/ng/directive/ngInclude',
      componentType: 'directive',
      module: 'ng',
      name: 'ngInclude',
      area: 'api',
      file: 'some/file.js',
      startingLine: 200,
      renderedContent: "Some text with a {@link some/url link} to somewhere\n" +
                       "Another text with a {@link another/url that spans\n two lines}\n" +
                       "Some example with a code link: {@link module:ngOther.directive:ngDirective}\n" +
                       "A link to reachable code: {@link ngInclude}"
    };

    partialNames = new PartialNames();
    partialNames.addDoc(doc);

    linkHandler = linkTagDef.handlerFactory(partialNames);
  });

  afterEach(function() {
    logger.level = logLevel;
  });

  it("should convert urls to HTML anchors", function() {
    expect(linkHandler(doc, 'link', 'some/url link')).toEqual('link');
  });

  it("should parse empty space within a link's title", function() {
    expect(linkHandler(doc, 'link', 'another/url link that spans\n two lines')).toEqual('link that spans\n two lines');
  });

  it("should convert code links to anchors with formatted code", function() {
    expect(linkHandler(doc, 'link', 'ngInclude')).toEqual('ngInclude');
  });

  it("should check that any links in the links property of a doc reference a valid doc", function() {
    expect(function() {
      linkHandler(doc, 'link', 'module:ngOther.directive:ngDirective');
    }).toThrow('Invalid link (does not match any doc): "module:ngOther.directive:ngDirective"');
  });
});<commit_msg>test(link inline tag): fix matching thrown error<commit_after>var _ = require('lodash');
var logger = require('winston');
var linkTagDef = require('../../inline-tag-defs/link');
var PartialNames = require('../../utils/partial-names').PartialNames;

describe("links inline tag handler", function() {
  var doc, links, logLevel, partialNames, linkHandler;

  it("should have name 'link'", function() {
    expect(linkTagDef.name).toEqual('link');
  });

  beforeEach(function() {
    logLevel = logger.level;
    logger.level = 'warn';
    spyOn(logger, 'warn');

    doc = {
      id: 'module:ng.directive:ngInclude',
      path: 'api/ng/directive/ngInclude',
      componentType: 'directive',
      module: 'ng',
      name: 'ngInclude',
      area: 'api',
      file: 'some/file.js',
      startingLine: 200,
      renderedContent: "Some text with a {@link some/url link} to somewhere\n" +
                       "Another text with a {@link another/url that spans\n two lines}\n" +
                       "Some example with a code link: {@link module:ngOther.directive:ngDirective}\n" +
                       "A link to reachable code: {@link ngInclude}"
    };

    partialNames = new PartialNames();
    partialNames.addDoc(doc);

    linkHandler = linkTagDef.handlerFactory(partialNames);
  });

  afterEach(function() {
    logger.level = logLevel;
  });

  it("should convert urls to HTML anchors", function() {
    expect(linkHandler(doc, 'link', 'some/url link')).toEqual('link');
  });

  it("should parse empty space within a link's title", function() {
    expect(linkHandler(doc, 'link', 'another/url link that spans\n two lines')).toEqual('link that spans\n two lines');
  });

  it("should convert code links to anchors with formatted code", function() {
    expect(linkHandler(doc, 'link', 'ngInclude')).toEqual('ngInclude');
  });

  it("should check that any links in the links property of a doc reference a valid doc", function() {
    expect(function() {
      linkHandler(doc, 'link', 'module:ngOther.directive:ngDirective');
    }).toThrowError(/Invalid link \(does not match any doc\): "module:ngOther\.directive:ngDirective"/);
  });
});<|endoftext|>


<commit_before>window.c.h = (function(m, moment){
  //Date Helpers
  var momentify = function(date, format){
    format = format || 'DD/MM/YYYY';
    return date ? moment(date).format(format) : 'no date';
  },

  momentFromString = function(date, format){
    var european = moment(date, format || 'DD/MM/YYYY');
    return european.isValid() ? european : moment(date);
  },

  //Number formatting helpers
  generateFormatNumber = function(s, c){
    return function(number, n, x) {
      if (number === null || number === undefined) {
        return null;
      }

      var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
          num = number.toFixed(Math.max(0, ~~n));
      return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
    };
  },
  formatNumber = generateFormatNumber('.', ','),

  //Object manipulation helpers
  toggleProp = function(defaultState, alternateState){
    var p = m.prop(defaultState);
    p.toggle = function(){
      p(((p() === alternateState) ? defaultState : alternateState));
    };

    return p;
  },

  idVM = m.postgrest.filtersVM({id: 'eq'}),

  //Templates
  loader = function(){
    return m('.u-text-center.u-margintop-30[style="margin-bottom:-110px;"]', [
      m('img[alt="Loader"][src="https://s3.amazonaws.com/catarse.files/loader.gif"]')
    ]);
  },

  fbParse = function() {
    var tryParse = function() {
      try {
        window.FB.XFBML.parse();
      } catch (e) {
        console.log(e);
      }
    };

    return window.setTimeout(tryParse, 500); //use timeout to wait async of facebook
  };

  return {
    momentify: momentify,
    momentFromString: momentFromString,
    formatNumber: formatNumber,
    idVM: idVM,
    toggleProp: toggleProp,
    loader: loader,
    fbParse: fbParse,
  };
}(window.m, window.moment));
<commit_msg>added pluralize helper<commit_after>window.c.h = (function(m, moment){
  //Date Helpers
  var momentify = function(date, format){
    format = format || 'DD/MM/YYYY';
    return date ? moment(date).format(format) : 'no date';
  },

  momentFromString = function(date, format){
    var european = moment(date, format || 'DD/MM/YYYY');
    return european.isValid() ? european : moment(date);
  },

  //Number formatting helpers
  generateFormatNumber = function(s, c){
    return function(number, n, x) {
      if (number === null || number === undefined) {
        return null;
      }

      var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
          num = number.toFixed(Math.max(0, ~~n));
      return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
    };
  },
  formatNumber = generateFormatNumber('.', ','),

  //Object manipulation helpers
  toggleProp = function(defaultState, alternateState){
    var p = m.prop(defaultState);
    p.toggle = function(){
      p(((p() === alternateState) ? defaultState : alternateState));
    };

    return p;
  },

  idVM = m.postgrest.filtersVM({id: 'eq'}),

  //Templates
  loader = function(){
    return m('.u-text-center.u-margintop-30[style="margin-bottom:-110px;"]', [
      m('img[alt="Loader"][src="https://s3.amazonaws.com/catarse.files/loader.gif"]')
    ]);
  },

  fbParse = function() {
    var tryParse = function() {
      try {
        window.FB.XFBML.parse();
      } catch (e) {
        console.log(e);
      }
    };

    return window.setTimeout(tryParse, 500); //use timeout to wait async of facebook
  },

  pluralize = function(count, s, p) {
    return (count > 1 ? count + p : count + s);
  },

  };

  return {
    momentify: momentify,
    momentFromString: momentFromString,
    formatNumber: formatNumber,
    idVM: idVM,
    toggleProp: toggleProp,
    loader: loader,
    fbParse: fbParse,
    pluralize: pluralize,
  };
}(window.m, window.moment));
<|endoftext|>


<commit_before>var request = require('request')
  , cheerio = require('cheerio');

module.exports = function (player, cb) {
  request("http://curvefever.com/users/" + player, function (err, resp, body) {
    if (!err && resp.statusCode === 200) {
      var $ = cheerio.load(body);
      var stats = $('.profile dd');
      cb(null, {
        name: player,
        ffa: $(stats[1]).text().slice(0, 4) | 0,
        team: $(stats[2]).text().slice(0, 4) | 0
      });
    }
    else {
      cb(new Error("Request for player " + player + " failed: " + resp.statusCode));
    }
  });

};
<commit_msg>add some scraping methods to get the stats from the last game<commit_after>var request = require('request')
  , cheerio = require('cheerio');

module.exports = function (player, cb) {
  request("http://curvefever.com/users/" + player, function (err, resp, body) {
    if (!err && resp.statusCode === 200) {
      var $ = cheerio.load(body);
      var stats = $('.profile dd');
      var lastMatch = $(stats[3]).find('tbody tr td a');
      if (lastMatch) {
        var matchUrl = lastMatch.first().attr('href');

      }
      console.log(lastMatch);

      cb(null, {
        name: player,
        ffa: $(stats[1]).text().slice(0, 4) | 0,
        team: $(stats[2]).text().slice(0, 4) | 0
      });
    }
    else {
      cb(new Error("Request for player " + player + " failed: " + resp.statusCode));
    }
  });

};

var findLastMatchId = function (player, cb) {
  request("http://curvefever.com/users/" + player, function (err, resp, body) {
    if (!err && resp.statusCode === 200) {
      var $ = cheerio.load(body);
      var stats = $('.profile dd');
      var lastMatch, id;
      try {
        lastMatch = $(stats[3]).find('tbody tr td a');
        id = lastMatch.first().attr('href').match(/\match\/(\d*)/)[1] | 0;
      }
      catch (e) {
        cb(e);
        return;
      }
      cb(null, id);
    }
    else {
      cb(new Error("Request for player " + player + " failed: " + resp.statusCode));
    }
  });
};

var getLastMatch = function (id, cb) {
  request('http://curvefever.com/achtung/match/' + id, function (err, resp, body) {
    if (!err && resp.statusCode === 200) {
      var $ = cheerio.load(body);
      var stats = $('.content').find('table tbody tr');

      // sorted by players position in FFA
      // sorted by team, then by individual score within team (if teams)
      var scores = [];

      var scoreReg = /(\d*) \((\d*)\)/;
      for (var i = 0; i < stats.length; i += 1) {
        var player = $(stats[i]);
        var scoreString = $(player.children()[1]).text(); // if teams: '10 (65)'
        var isTeam = scoreReg.test(scoreString);
        var rankChange = $(player.children()[4]).text();
        var obj = { name: player.find('a').text() };
        if (isTeam) {
          var match = scoreString.match(scoreReg);
          obj.score = match[2] | 0;
          obj.teamScore = match[1] | 0;
        }
        else {
          obj.score = scoreString | 0;
        }
        obj.rankChange = rankChange;
        scores.push(obj);
      }
      cb(null, scores);
    }
    else {
      cb(new Error("Request for match " + id + " failed: " + resp.statusCode));
    }
  });
};

if (module === require.main) {
  //module.exports('ealbrigt', console.log);
  //findLastMatchId('ealbrigt', console.log)
  getLastMatch(9496358, console.log); // team game
  //getLastMatch(9469502, console.log); // ffa gam
}
<|endoftext|>


<commit_before>window.c.h = ((m, moment) => {
    //Date Helpers
    const hashMatch = (str) => {return window.location.hash === str;},

          paramByName = (name) => {
              const normalName = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'),
                    regex = new RegExp('[\\?&]' + normalName + '=([^&#]*)'),
                    results = regex.exec(location.search);
              return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
          },

          setMomentifyLocale = () => {
              moment.locale('pt', {
                  monthsShort: 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_')
              });
          },

          existy = (x) => {
              return x != null;
          },

          momentify = (date, format) => {
              format = format || 'DD/MM/YYYY';
              return date ? moment(date).locale('pt').format(format) : 'no date';
          },

          storeAction = (action) => {
              if (!sessionStorage.getItem(action)) {
                  return sessionStorage.setItem(action, action);
              }
          },

          callStoredAction = (action, func) => {
              if (sessionStorage.getItem(action)) {
                  func.call();
                  return sessionStorage.removeItem(action);
              }
          },

          discuss = (page, identifier) => {
              const d = document,
                    s = d.createElement('script');
              window.disqus_config = function() {
                  this.page.url = page;
                  this.page.identifier = identifier;
              };
              s.src = '//catarseflex.disqus.com/embed.js';
              s.setAttribute('data-timestamp', +new Date());
              (d.head || d.body).appendChild(s);
              return m('');
          },

          momentFromString = (date, format) => {
              const european = moment(date, format || 'DD/MM/YYYY');
              return european.isValid() ? european : moment(date);
          },

          translatedTimeUnits = {
              days: 'dias',
              minutes: 'minutos',
              hours: 'horas',
              seconds: 'segundos'
          },
          //Object manipulation helpers
          translatedTime = (time) => {
              const translatedTime = translatedTimeUnits,
                    unit = () => {
                        const projUnit = translatedTime[time.unit || 'seconds'];

                        return (time.total <= 1) ? projUnit.slice(0, -1) : projUnit;
                    };

              return {
                  unit: unit(),
                  total: time.total
              };
          },

          //Number formatting helpers
          generateFormatNumber = (s, c) => {
              return (number, n, x) => {
                  if (!_.isNumber(number)) {
                      return null;
                  }

                  const re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
                        num = number.toFixed(Math.max(0, ~~n));
                  return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
              };
          },
          formatNumber = generateFormatNumber('.', ','),

          toggleProp = (defaultState, alternateState) => {
              const p = m.prop(defaultState);
              p.toggle = () => {
                  p(((p() === alternateState) ? defaultState : alternateState));
              };

              return p;
          },

          idVM = m.postgrest.filtersVM({
              id: 'eq'
          }),

          getUser = () => {
              const body = document.getElementsByTagName('body'),
                    data = _.first(body).getAttribute('data-user');
              if (data) {
                  return JSON.parse(data);
              } else {
                  return false;
              }
          },

          locationActionMatch = (action) => {
              const act = window.location.pathname.split('/').slice(-1)[0];
              return action === act;
          },

          useAvatarOrDefault = (avatarPath) => {
              return avatarPath || '/assets/catarse_bootstrap/user.jpg';
          },

          //Templates
          loader = () => {
              return m('.u-text-center.u-margintop-30 u-marginbottom-30', [
                  m('img[alt="Loader"][src="https://s3.amazonaws.com/catarse.files/loader.gif"]')
              ]);
          },

          fbParse = () => {
              const tryParse = () => {
                  try {
                      window.FB.XFBML.parse();
                  } catch (e) {
                      console.log(e);
                  }
              };

              return window.setTimeout(tryParse, 500); //use timeout to wait async of facebook
          },

          pluralize = (count, s, p) => {
              return (count > 1 ? count + p : count + s);
          },

          simpleFormat = (str = '') => {
              str = str.replace(/\r\n?/, '\n');
              if (str.length > 0) {
                  str = str.replace(/\n\n+/g, '

');
                  str = str.replace(/\n/g, '
');
                  str = '
' + str + '
';
              }
              return str;
          },

          rewardSouldOut = (reward) => {
              return (reward.maximum_contributions > 0 ?
                      (reward.paid_count + reward.waiting_payment_count >= reward.maximum_contributions) : false);
          },

          rewardRemaning = (reward) => {
              return reward.maximum_contributions - (reward.paid_count + reward.waiting_payment_count);
          },

          parseUrl = (href) => {
              const l = document.createElement('a');
              l.href = href;
              return l;
          },

          mixpanelTrack = () => {
              return (el, isInitialized) => {
                  if (!isInitialized) {
                      window.CatarseMixpanel.activate();
                  }
              };
          },

          UIHelper = () => {
              return (el, isInitialized) => {
                  if (!isInitialized && $) {
                      window.UIHelper.setupResponsiveIframes($(el));
                  }
              };
          },

          toAnchor = () => {
              return (el, isInitialized) => {
                  if (!isInitialized){
                      const hash = window.location.hash.substr(1);
                      if (hash === el.id) {
                          window.location.hash = '';
                          setTimeout(function(){
                              window.location.hash = el.id;
                          });
                      }
                  }
              };
          },

          validateEmail = (email) => {
              const re = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
              return re.test(email);
          },

          navigateToDevise = () => {
              window.location.href = '/pt/login';
              return false;
          },

          cumulativeOffset = (element) => {
              let top = 0, left = 0;
              do {
                  top += element.offsetTop  || 0;
                  left += element.offsetLeft || 0;
                  element = element.offsetParent;
              } while (element);

              return {
                  top: top,
                  left: left
              };
          },

          closeFlash = () => {
              let el = document.getElementsByClassName('icon-close')[0];
              if (_.isElement(el)){
                  el.onclick = (event) => {
                      event.preventDefault();

                      el.parentElement.remove();
                  };
              };
          };

    setMomentifyLocale();
    closeFlash();

    return {
        cumulativeOffset: cumulativeOffset,
        discuss: discuss,
        existy: existy,
        validateEmail: validateEmail,
        momentify: momentify,
        momentFromString: momentFromString,
        formatNumber: formatNumber,
        idVM: idVM,
        getUser: getUser,
        toggleProp: toggleProp,
        loader: loader,
        fbParse: fbParse,
        pluralize: pluralize,
        simpleFormat: simpleFormat,
        translatedTime: translatedTime,
        rewardSouldOut: rewardSouldOut,
        rewardRemaning: rewardRemaning,
        parseUrl: parseUrl,
        hashMatch: hashMatch,
        useAvatarOrDefault: useAvatarOrDefault,
        locationActionMatch: locationActionMatch,
        mixpanelTrack: mixpanelTrack,
        navigateToDevise: navigateToDevise,
        storeAction: storeAction,
        callStoredAction: callStoredAction,
        UIHelper: UIHelper,
        toAnchor: toAnchor,
        paramByName: paramByName
    };
}(window.m, window.moment));
<commit_msg>Adds helper to provide I18n scoping inside components<commit_after>window.c.h = ((m, moment) => {
    //Date Helpers

    const hashMatch = (str) => {return window.location.hash === str;},
        paramByName = (name) => {
          const normalName = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'),
                regex = new RegExp('[\\?&]' + normalName + '=([^&#]*)'),
                results = regex.exec(location.search);
          return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
        },
        setMomentifyLocale = () => {
            moment.locale('pt', {
                    monthsShort: 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_')
                });
        },
        existy = (x) => {
            return x != null;
        },

        momentify = (date, format) => {
            format = format || 'DD/MM/YYYY';
            return date ? moment(date).locale('pt').format(format) : 'no date';
        },

        storeAction = (action) => {
            if (!sessionStorage.getItem(action)) {
                return sessionStorage.setItem(action, action);
            }
        },

        callStoredAction = (action, func) => {
            if (sessionStorage.getItem(action)) {
                func.call();
                return sessionStorage.removeItem(action);
            }
        },

        discuss = (page, identifier) => {
            const d = document,
                s = d.createElement('script');
            window.disqus_config = function() {
                this.page.url = page;
                this.page.identifier = identifier;
            };
            s.src = '//catarseflex.disqus.com/embed.js';
            s.setAttribute('data-timestamp', +new Date());
            (d.head || d.body).appendChild(s);
            return m('');
        },

        momentFromString = (date, format) => {
            const european = moment(date, format || 'DD/MM/YYYY');
            return european.isValid() ? european : moment(date);
        },

        translatedTimeUnits = {
            days: 'dias',
            minutes: 'minutos',
            hours: 'horas',
            seconds: 'segundos'
        },
        //Object manipulation helpers
        translatedTime = (time) => {
            const translatedTime = translatedTimeUnits,
                unit = () => {
                    const projUnit = translatedTime[time.unit || 'seconds'];

                    return (time.total <= 1) ? projUnit.slice(0, -1) : projUnit;
                };

            return {
                unit: unit(),
                total: time.total
            };
        },

        //Number formatting helpers
        generateFormatNumber = (s, c) => {
            return (number, n, x) => {
                if (!_.isNumber(number)) {
                    return null;
                }

                const re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
                    num = number.toFixed(Math.max(0, ~~n));
                return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
            };
        },
        formatNumber = generateFormatNumber('.', ','),

        toggleProp = (defaultState, alternateState) => {
            const p = m.prop(defaultState);
            p.toggle = () => {
                p(((p() === alternateState) ? defaultState : alternateState));
            };

            return p;
        },

        idVM = m.postgrest.filtersVM({
            id: 'eq'
        }),

        getUser = () => {
            const body = document.getElementsByTagName('body'),
                data = _.first(body).getAttribute('data-user');
            if (data) {
                return JSON.parse(data);
            } else {
                return false;
            }
        },

        hashMatch = (str) => {
            return window.location.hash === str;
        },

        locationActionMatch = (action) => {
            const act = window.location.pathname.split('/').slice(-1)[0];
            return action === act;
        },

        useAvatarOrDefault = (avatarPath) => {
            return avatarPath || '/assets/catarse_bootstrap/user.jpg';
        },

        //Templates
        loader = () => {
            return m('.u-text-center.u-margintop-30 u-marginbottom-30', [
                m('img[alt="Loader"][src="https://s3.amazonaws.com/catarse.files/loader.gif"]')
            ]);
        },

        fbParse = () => {
            const tryParse = () => {
                try {
                    window.FB.XFBML.parse();
                } catch (e) {
                    console.log(e);
                }
            };

            return window.setTimeout(tryParse, 500); //use timeout to wait async of facebook
        },

        pluralize = (count, s, p) => {
            return (count > 1 ? count + p : count + s);
        },

        simpleFormat = (str = '') => {
            str = str.replace(/\r\n?/, '\n');
            if (str.length > 0) {
                str = str.replace(/\n\n+/g, '

');
                str = str.replace(/\n/g, '
');
                str = '
' + str + '
';
            }
            return str;
        },

        rewardSouldOut = (reward) => {
            return (reward.maximum_contributions > 0 ?
                (reward.paid_count + reward.waiting_payment_count >= reward.maximum_contributions) : false);
        },

        rewardRemaning = (reward) => {
            return reward.maximum_contributions - (reward.paid_count + reward.waiting_payment_count);
        },

        parseUrl = (href) => {
            const l = document.createElement('a');
            l.href = href;
            return l;
        },

        mixpanelTrack = () => {
            return (el, isInitialized) => {
                if (!isInitialized) {
                    window.CatarseMixpanel.activate();
                }
            };
        },

        UIHelper = () => {
            return (el, isInitialized) => {
                if (!isInitialized && $) {
                    window.UIHelper.setupResponsiveIframes($(el));
                }
            };
        },

        toAnchor = () => {
            return (el, isInitialized) => {
                if (!isInitialized){
                    const hash = window.location.hash.substr(1);
                    if (hash === el.id) {
                        window.location.hash = '';
                        setTimeout(function(){
                            window.location.hash = el.id;
                        });
                    }
                }
            };
        },

        validateEmail = (email) => {
            const re = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
            return re.test(email);
        },

        navigateToDevise = () => {
            window.location.href = '/pt/login';
            return false;
        },

        cumulativeOffset = (element) => {
            let top = 0, left = 0;
            do {
                top += element.offsetTop  || 0;
                left += element.offsetLeft || 0;
                element = element.offsetParent;
            } while (element);

            return {
                top: top,
                left: left
            };
        },

        closeFlash = () => {
            let el = document.getElementsByClassName('icon-close')[0];
            if (_.isElement(el)){
                el.onclick = (event) => {
                    event.preventDefault();

                    el.parentElement.remove();
                };
            };
        },

        i18nScope = (scope, obj) => {
            obj = obj || {};
            return _.extend({}, obj, {scope: scope});
        };

    setMomentifyLocale();
    closeFlash();

    return {
        cumulativeOffset: cumulativeOffset,
        discuss: discuss,
        existy: existy,
        validateEmail: validateEmail,
        momentify: momentify,
        momentFromString: momentFromString,
        formatNumber: formatNumber,
        idVM: idVM,
        getUser: getUser,
        toggleProp: toggleProp,
        loader: loader,
        fbParse: fbParse,
        pluralize: pluralize,
        simpleFormat: simpleFormat,
        translatedTime: translatedTime,
        rewardSouldOut: rewardSouldOut,
        rewardRemaning: rewardRemaning,
        parseUrl: parseUrl,
        hashMatch: hashMatch,
        useAvatarOrDefault: useAvatarOrDefault,
        locationActionMatch: locationActionMatch,
        mixpanelTrack: mixpanelTrack,
        navigateToDevise: navigateToDevise,
        storeAction: storeAction,
        callStoredAction: callStoredAction,
        UIHelper: UIHelper,
        toAnchor: toAnchor,
        paramByName: paramByName
        i18nScope: i18nScope
    };
}(window.m, window.moment));
<|endoftext|>


<commit_before>(function (exports) {
	'use strict';
	/*jshint node:true */

	var request, fs, hub, scrape, writer, Writer, ROOT_URL, getKnownEntities, types, logger,
		uuid, knownEntities, Sync, SPARQLURL, Query, query, NOW, diseaseFiles, getDiseaseFiles;

	ROOT_URL = process.env.ROOT_URL;
	SPARQLURL = process.env.SPARQLURL;
	request = require('request');
	hub = require('node-pubsub');
	fs = require('fs');
	NOW = (new Date()).toISOString(); //add .slice(0,10) to get date only.

	// Generate a UUID
	uuid = function uuid(a){
		//Function from https://gist.github.com/982883 (@jed)
		return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,uuid);
	};

	// Semaphore from https://gist.github.com/1296828
	Sync = function Sync(syncCount, callback, preventInstantCallbackExecution) {
		this.syncCount = syncCount;
		this.callback = callback;
		if(preventInstantCallbackExecution === false && this.syncCount === 0) {
			this.executeCallback();
		}
		Sync.prototype.decrement = function() {
			--this.syncCount;
			if(this.syncCount === 0) {
				this.executeCallback();
			}
		};
		Sync.prototype.increment = function() {
			++this.syncCount;
		};
		Sync.prototype.executeCallback = function() {
			if (typeof this.callback === "function") this.callback();
		};
	};

	// Writer Singleton
	Writer = (function (){
		var instantiated, init;

		init = function () {

			var writer = {}, fileName;

			fileName = "/tcgascrape"+Date.now()+".nt";

			writer.stream = fs.createWriteStream(process.cwd()+fileName);

			writer.listen = function (msg) {
				var triples = msg.triples;
				//triples = triples.split(" . ").join(" .\n");
				writer.stream.write(triples);
			};

			writer.close = function () {
				writer.stream.end();
			};

			return writer;

		};

		return {
			getInstance : function () {
				if (!instantiated) instantiated = init();
				return instantiated;
			}
		};
	})();

	// Query Singleton
	Query = (function (){
		var instantiated, init;

		init = function () {

			var query = {}, url, triples;

			url = process.env.SPARQLURL;
			triples = [];

			query.url = function (_) {
				if (!_) return url;
				else url = _;
				return query;
			};

			query.listen = function (msg) {
				triples.push(msg.triples);
				if (triples.length > 100) query.write();
			};

			query.write = function (){
				var insertQuery;
				insertQuery = 'INSERT DATA {\n'+triples.join("")+'\n}';
				triples = [];
				query.execute(insertQuery, function (error, response, body) {
					if (error || response.statusCode >= 300) {
						console.log("Unable to load triples:", insertQuery, error);
						console.log(response.statusCode, response.body);
						return;
					}
				});
			};

			query.flush = function () {
				query.write();
			};

			query.execute = function (query, callback) {
				request({
					url : url+encodeURIComponent(query),
					method : "POST"
				}, callback);
			};

			return query;
		};

		return {
			getInstance : function () {
				if (!instantiated) instantiated = init();
				return instantiated;
			}
		};

	})();

	types = {
		9 : "DiseaseStudy",
		diseaseStudy : "DiseaseStudy",
		10 : "CenterType",
		11 : "CenterDomain",
		12 : "Platform",
		13 : "DataType",
		14 : "Archive",
		archive : "Archive",
		15 : "File",
		file : "File"
	};

	knownEntities = {};

	diseaseFiles = {};

	getKnownEntities = function (callback) {
		var query;

		query = [
			'prefix rdfs:<http://www.w3.org/2000/01/rdf-schema#>',
			'prefix tcga:<http://purl.org/tcga/core#>',
			'select distinct ?url ?id where {',
			'	?id tcga:url ?url .',
			'}'
		].join(' ');

		request({
				url : SPARQLURL+encodeURIComponent(query),
				headers : { "Accept" : "application/sparql-results+json" }
			}, function ( error, response, body ) {

				if (error || response.statusCode !== 200) {
					console.log("Unable to query SPARQL endpoint");
					return;
				}

				var bindings;

				bindings = JSON.parse(body).results.bindings;

				bindings.forEach(function (binding) {
					knownEntities[binding.url.value] = binding;
				});

				console.log('Found', bindings.length, 'entities.');

				callback();
		});
	};

	getDiseaseFiles = function (disease, callback) {
		var query;

		diseaseFiles = {};

		query = [
			'prefix rdfs:<http://www.w3.org/2000/01/rdf-schema#>',
			'prefix tcga:<http://purl.org/tcga/core#>',
			'select distinct ?url ?id where {',
			'	?id tcga:url ?url .',
			'	?id tcga:diseaseStudy ?d .',
			'	?d rdfs:label "'+disease+'" .',
			'}'
		].join(' ');

		request({
				url : SPARQLURL+encodeURIComponent(query),
				headers : { "Accept" : "application/sparql-results+json" }
			}, function ( error, response, body ) {

				if (error || response.statusCode !== 200) {
					console.log("Unable to query SPARQL endpoint for",disease,"files.");
					return;
				}

				var bindings;

				bindings = JSON.parse(body).results.bindings;

				bindings.forEach(function (binding) {
					diseaseFiles[binding.url.value] = binding;
				});

				console.log('Found', bindings.length, 'entities for', disease,'.');

				callback();
		});

	};

	scrape = function (options) {
		var opts, target, parent, callback, start, callCallback;

		opts = options || {};
		target = opts.target || ROOT_URL;
		parent = opts.parent || {};

		callCallback = function () {
			if (callback && typeof callback === 'function') callback();
		};
		callback = opts.callback;

		request(target, function (error, response, body) {

			if (error || response.statusCode !== 200) {
				console.log("Failed to get", target);
				return callCallback();
			}

			else {

				var pre, rows, children = [], tcga, literal;

				tcga = function (name) { return "<http://purl.org/tcga/core#"+name+">"; };
				literal = function (value) { return '"'+value+'"'; };
				pre = body.match(/<pre>([\s\S]*)<\/pre>/);
				if (!pre) {
					console.log("Could not parse (pre)", target);
					return callCallback();
				} else pre = pre[1];
				rows = pre.match(/<a[^>]+>[^<]+<\/a>\s+\d{2}-\w{3}-\d{4}/g);

				if (rows) rows.forEach(function (row) {

					var name, id, url, type, tripleString, lastModified, subject, scrapeChildren = true, level;

					name = row.match(/>([\s\S]*)</);
					if (!name) console.log("Could not parse (name)", row); else name = name[1];
					id = uuid();
					url = target + row.match(/href="(.*)"/)[1];
					level = target.split('/').length;
					type = types[level];
					lastModified = (new Date(row.match(/\d{2}-\w{3}-\d{4}/)[0])).toISOString().slice(0,10);
					tripleString = "";

					if ((process.env.TESTING && level === 10) || level >= 15) {
						scrapeChildren = false;
						if (target.match(/ucec|thca|stad/)) scrapeChildren = true;
					}

					if (name === 'lost+found/') return;

					name = name.trim();

					// Things with extensions are files (e.g. reallylong_name.tiff)
					// TODO Use MIME types to determine files.
					if (name.match(/^.*\.[^\/]+$/)) {
						type = types.file;
						scrapeChildren = false;
					}

					// Remove the trailing "/"
					if (name.charAt(name.length-1) === "/") name = name.slice(0,-1);

					// If a file ends in .tar.gz or .tar.gz.md5, type it as an archive
					if (type === types.file && name.match(/\.tar\.gz($|\.md5$)/)) {
						type = types.archive;
					}

					// If a file is of the form
					// <domain>_<disease study>.<platform>.<archive type>.<serial index>.<revision>.<series>
					// type it as an archive
					if (name.match(/.*?_(.*?\.){5}\d$/)) {
						type = types.archive;
					}

					// Either insert or update, based on whether this item exists in the known entities.
					if (!knownEntities[url] && !diseaseFiles[url]) {
						var entity = {
							id : { value : id },
							newEntity : true
						};
						if (type !== types.file) knownEntities[url] = entity;
						else diseaseFiles[url] = entity;
						subject = id.length === 36 ? tcga(id) : "<" + id + ">";
						tripleString = [
							subject, tcga("lastSeen"), literal(NOW), ".\n",
							subject, tcga("firstSeen"), literal(NOW), ".\n",
							subject, "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>",  tcga(type), ".\n",
							subject, "<http://www.w3.org/2000/01/rdf-schema#label>", literal(name), ".\n",
							subject, tcga("url"), literal(url), ".\n"
						];

						if (type === types.file || types === types.archive) {
							tripleString.push(subject, tcga("lastModified"), literal(lastModified), ".\n");
						}

						if (type === types.file) {
							var ancestor;
							Object.keys(parent).forEach(function (ancestor) {
								// Make the first letter lowercase
								var property = ancestor.charAt(0).toLowerCase() + ancestor.slice(1);
								tripleString.push(subject, tcga(property), parent[ancestor], ".\n");
							});
						}
					}
					else {
						if (knownEntities[url]) id = knownEntities[url].id.value;
						else id = diseaseFiles[url].id.value;
						subject = id.length === 36 ? tcga(id) : "<" + id + ">";
						tripleString = [
							subject, tcga("lastSeen"), literal(NOW), ".\n"
						];

						// Additional URLS may need to be added for new entities, such as center types.
						if (knownEntities[url].newEntity) {
							tripleString.push(subject, tcga("url"), literal(url), ".\n");
						}
					}

					hub.publish('/triples', [{
						triples : tripleString.join(" "),
						type : type,
						name : name
					}]);

					if (scrapeChildren){
						var child;
						parent[type] = subject;
						child = {target:url, parent:JSON.parse(JSON.stringify(parent))};
						if (type == types.diseaseStudy) {
							child.type = type;
							child.name = name;
						}
						children.push(child);
					}

				});

				if (children.length > 0) {
					var counter = new Sync(children.length, callback);
					var nextChild = function nextChild(children){
						var child = children.pop();
						if (child){
							child.callback = function(){
								counter.decrement();
								nextChild(children);
							};
							if (child.type === types.diseaseStudy) {
								getDiseaseFiles(child.name, function () {
									scrape(child);
								});
							} else {
								scrape(child);
							}
						}
					};
					nextChild(children);
				}
				else callCallback();

			}

		});
	};

	//writer = Writer.getInstance();

	query = Query.getInstance().url(process.env.SPARQLURL);

	hub.subscribe('/triples', query.listen);

	//hub.subscribe('/triples', writer.listen);

	console.log('Getting known entities from hub.');

	getKnownEntities(function (err) {
		if (err) console.log(err);
		console.log('Beginning scrape of', ROOT_URL);
		scrape({
			target : ROOT_URL,
			callback : function () {
				Query.getInstance().flush();
				// writer.close();
				console.log("Scrape finished");
			}
		});
	});

})( exports );
<commit_msg>Put the query in the body of the POST request, rather than in the URL.<commit_after>(function (exports) {
	'use strict';
	/*jshint node:true */

	var request, fs, hub, scrape, writer, Writer, ROOT_URL, getKnownEntities, types, logger,
		uuid, knownEntities, Sync, SPARQLURL, Query, query, NOW, diseaseFiles, getDiseaseFiles;

	ROOT_URL = process.env.ROOT_URL;
	SPARQLURL = process.env.SPARQLURL;
	request = require('request');
	hub = require('node-pubsub');
	fs = require('fs');
	NOW = (new Date()).toISOString(); //add .slice(0,10) to get date only.

	// Generate a UUID
	uuid = function uuid(a){
		//Function from https://gist.github.com/982883 (@jed)
		return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,uuid);
	};

	// Semaphore from https://gist.github.com/1296828
	Sync = function Sync(syncCount, callback, preventInstantCallbackExecution) {
		this.syncCount = syncCount;
		this.callback = callback;
		if(preventInstantCallbackExecution === false && this.syncCount === 0) {
			this.executeCallback();
		}
		Sync.prototype.decrement = function() {
			--this.syncCount;
			if(this.syncCount === 0) {
				this.executeCallback();
			}
		};
		Sync.prototype.increment = function() {
			++this.syncCount;
		};
		Sync.prototype.executeCallback = function() {
			if (typeof this.callback === "function") this.callback();
		};
	};

	// Writer Singleton
	Writer = (function (){
		var instantiated, init;

		init = function () {

			var writer = {}, fileName;

			fileName = "/tcgascrape"+Date.now()+".nt";

			writer.stream = fs.createWriteStream(process.cwd()+fileName);

			writer.listen = function (msg) {
				var triples = msg.triples;
				//triples = triples.split(" . ").join(" .\n");
				writer.stream.write(triples);
			};

			writer.close = function () {
				writer.stream.end();
			};

			return writer;

		};

		return {
			getInstance : function () {
				if (!instantiated) instantiated = init();
				return instantiated;
			}
		};
	})();

	// Query Singleton
	Query = (function (){
		var instantiated, init;

		init = function () {

			var query = {}, url, triples;

			url = process.env.SPARQLURL;
			triples = [];

			query.url = function (_) {
				if (!_) return url;
				else url = _;
				return query;
			};

			query.listen = function (msg) {
				triples.push(msg.triples);
				if (triples.length > 100) query.write();
			};

			query.write = function (){
				var insertQuery;
				insertQuery = 'INSERT DATA {\n'+triples.join("")+'\n}';
				triples = [];
				query.execute(insertQuery, function (error, response, body) {
					if (error || response.statusCode >= 300) {
						console.log("Unable to load triples:", insertQuery, error);
						console.log(response.statusCode, response.body);
						return;
					}
				});
			};

			query.flush = function () {
				query.write();
			};

			query.execute = function (query, callback) {
				request({
					url : url,//+encodeURIComponent(query),
					method : "POST",
					body : query
				}, callback);
			};

			return query;
		};

		return {
			getInstance : function () {
				if (!instantiated) instantiated = init();
				return instantiated;
			}
		};

	})();

	types = {
		9 : "DiseaseStudy",
		diseaseStudy : "DiseaseStudy",
		10 : "CenterType",
		11 : "CenterDomain",
		12 : "Platform",
		13 : "DataType",
		14 : "Archive",
		archive : "Archive",
		15 : "File",
		file : "File"
	};

	knownEntities = {};

	diseaseFiles = {};

	getKnownEntities = function (callback) {
		var query;

		query = [
			'prefix rdfs:<http://www.w3.org/2000/01/rdf-schema#>',
			'prefix tcga:<http://purl.org/tcga/core#>',
			'select distinct ?url ?id where {',
			'	?id tcga:url ?url .',
			'}'
		].join(' ');

		request({
				url : SPARQLURL+encodeURIComponent(query),
				headers : { "Accept" : "application/sparql-results+json" }
			}, function ( error, response, body ) {

				if (error || response.statusCode !== 200) {
					console.log("Unable to query SPARQL endpoint");
					return;
				}

				var bindings;

				bindings = JSON.parse(body).results.bindings;

				bindings.forEach(function (binding) {
					knownEntities[binding.url.value] = binding;
				});

				console.log('Found', bindings.length, 'entities.');

				callback();
		});
	};

	getDiseaseFiles = function (disease, callback) {
		var query;

		diseaseFiles = {};

		query = [
			'prefix rdfs:<http://www.w3.org/2000/01/rdf-schema#>',
			'prefix tcga:<http://purl.org/tcga/core#>',
			'select distinct ?url ?id where {',
			'	?id tcga:url ?url .',
			'	?id tcga:diseaseStudy ?d .',
			'	?d rdfs:label "'+disease+'" .',
			'}'
		].join(' ');

		request({
				url : SPARQLURL+encodeURIComponent(query),
				headers : { "Accept" : "application/sparql-results+json" }
			}, function ( error, response, body ) {

				if (error || response.statusCode !== 200) {
					console.log("Unable to query SPARQL endpoint for",disease,"files.");
					return;
				}

				var bindings;

				bindings = JSON.parse(body).results.bindings;

				bindings.forEach(function (binding) {
					diseaseFiles[binding.url.value] = binding;
				});

				console.log('Found', bindings.length, 'entities for', disease,'.');

				callback();
		});

	};

	scrape = function (options) {
		var opts, target, parent, callback, start, callCallback;

		opts = options || {};
		target = opts.target || ROOT_URL;
		parent = opts.parent || {};

		callCallback = function () {
			if (callback && typeof callback === 'function') callback();
		};
		callback = opts.callback;

		request(target, function (error, response, body) {

			if (error || response.statusCode !== 200) {
				console.log("Failed to get", target);
				return callCallback();
			}

			else {

				var pre, rows, children = [], tcga, literal;

				tcga = function (name) { return "<http://purl.org/tcga/core#"+name+">"; };
				literal = function (value) { return '"'+value+'"'; };
				pre = body.match(/<pre>([\s\S]*)<\/pre>/);
				if (!pre) {
					console.log("Could not parse (pre)", target);
					return callCallback();
				} else pre = pre[1];
				rows = pre.match(/<a[^>]+>[^<]+<\/a>\s+\d{2}-\w{3}-\d{4}/g);

				if (rows) rows.forEach(function (row) {

					var name, id, url, type, tripleString, lastModified, subject, scrapeChildren = true, level;

					name = row.match(/>([\s\S]*)</);
					if (!name) console.log("Could not parse (name)", row); else name = name[1];
					id = uuid();
					url = target + row.match(/href="(.*)"/)[1];
					level = target.split('/').length;
					type = types[level];
					lastModified = (new Date(row.match(/\d{2}-\w{3}-\d{4}/)[0])).toISOString().slice(0,10);
					tripleString = "";

					if ((process.env.TESTING && level === 10) || level >= 15) {
						scrapeChildren = false;
						if (target.match(/ucec|thca|stad/)) scrapeChildren = true;
					}

					if (name === 'lost+found/') return;

					name = name.trim();

					// Things with extensions are files (e.g. reallylong_name.tiff)
					// TODO Use MIME types to determine files.
					if (name.match(/^.*\.[^\/]+$/)) {
						type = types.file;
						scrapeChildren = false;
					}

					// Remove the trailing "/"
					if (name.charAt(name.length-1) === "/") name = name.slice(0,-1);

					// If a file ends in .tar.gz or .tar.gz.md5, type it as an archive
					if (type === types.file && name.match(/\.tar\.gz($|\.md5$)/)) {
						type = types.archive;
					}

					// If a file is of the form
					// <domain>_<disease study>.<platform>.<archive type>.<serial index>.<revision>.<series>
					// type it as an archive
					if (name.match(/.*?_(.*?\.){5}\d$/)) {
						type = types.archive;
					}

					// Either insert or update, based on whether this item exists in the known entities.
					if (!knownEntities[url] && !diseaseFiles[url]) {
						var entity = {
							id : { value : id },
							newEntity : true
						};
						if (type !== types.file) knownEntities[url] = entity;
						else diseaseFiles[url] = entity;
						subject = id.length === 36 ? tcga(id) : "<" + id + ">";
						tripleString = [
							subject, tcga("lastSeen"), literal(NOW), ".\n",
							subject, tcga("firstSeen"), literal(NOW), ".\n",
							subject, "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>",  tcga(type), ".\n",
							subject, "<http://www.w3.org/2000/01/rdf-schema#label>", literal(name), ".\n",
							subject, tcga("url"), literal(url), ".\n"
						];

						if (type === types.file || types === types.archive) {
							tripleString.push(subject, tcga("lastModified"), literal(lastModified), ".\n");
						}

						if (type === types.file) {
							var ancestor;
							Object.keys(parent).forEach(function (ancestor) {
								// Make the first letter lowercase
								var property = ancestor.charAt(0).toLowerCase() + ancestor.slice(1);
								tripleString.push(subject, tcga(property), parent[ancestor], ".\n");
							});
						}
					}
					else {
						if (knownEntities[url]) id = knownEntities[url].id.value;
						else id = diseaseFiles[url].id.value;
						subject = id.length === 36 ? tcga(id) : "<" + id + ">";
						tripleString = [
							subject, tcga("lastSeen"), literal(NOW), ".\n"
						];

						// Additional URLS may need to be added for new entities, such as center types.
						if (knownEntities[url].newEntity) {
							tripleString.push(subject, tcga("url"), literal(url), ".\n");
						}
					}

					hub.publish('/triples', [{
						triples : tripleString.join(" "),
						type : type,
						name : name
					}]);

					if (scrapeChildren){
						var child;
						parent[type] = subject;
						child = {target:url, parent:JSON.parse(JSON.stringify(parent))};
						if (type == types.diseaseStudy) {
							child.type = type;
							child.name = name;
						}
						children.push(child);
					}

				});

				if (children.length > 0) {
					var counter = new Sync(children.length, callback);
					var nextChild = function nextChild(children){
						var child = children.pop();
						if (child){
							child.callback = function(){
								counter.decrement();
								nextChild(children);
							};
							if (child.type === types.diseaseStudy) {
								getDiseaseFiles(child.name, function () {
									scrape(child);
								});
							} else {
								scrape(child);
							}
						}
					};
					nextChild(children);
				}
				else callCallback();

			}

		});
	};

	//writer = Writer.getInstance();

	query = Query.getInstance().url(process.env.SPARQLURL);

	hub.subscribe('/triples', query.listen);

	//hub.subscribe('/triples', writer.listen);

	console.log('Getting known entities from hub.');

	getKnownEntities(function (err) {
		if (err) console.log(err);
		console.log('Beginning scrape of', ROOT_URL);
		scrape({
			target : ROOT_URL,
			callback : function () {
				Query.getInstance().flush();
				// writer.close();
				console.log("Scrape finished");
			}
		});
	});

})( exports );
<|endoftext|>


<commit_before>var ConfigModel = require('../../../../../../javascripts/cartodb3/data/config-model');
var BasemapInnerView = require('../../../../../../javascripts/cartodb3/editor/layers/basemap-content-views/basemap-inner-view');
var BasemapsCollection = require('../../../../../../javascripts/cartodb3/editor/layers/basemap-content-views/basemaps-collection');
var CarouselCollection = require('../../../../../../javascripts/cartodb3/components/custom-carousel/custom-carousel-collection');

describe('editor/layers/basemap-content-views/basemap-inner-view', function () {
  beforeEach(function () {
    var configModel = new ConfigModel({
      base_url: '/u/pepe'
    });

    this.analysisDefinitionNodesCollection = new AnalysisDefinitionNodesCollection(null, {
      configModel: configModel
    });

    this.layerDefinitionsCollection = new LayerDefinitionsCollection(null, {
      configModel: configModel,
      analysisDefinitionNodesCollection: this.analysisDefinitionNodesCollection,
      mapId: 'm-123'
    });

    this.layerDefinitionsCollection.add({
      id: 'l-1',
      kind: 'carto',
      options: {
        table_name: 'foo',
        className: 'positron_rainbow',
        category: 'CARTO'
      }
    });

    this.categoriesCollection = new CarouselCollection([]);

    this.view = new BasemapInnerView({
      categoriesCollection: this.categoriesCollection,
      layerDefinitionsCollection: this.layerDefinitionsCollection,
      basemapsCollection: new BasemapsCollection(),
      selectedCategoryVal: 'CARTO',
      model: {}
    });

    this.view.render();
  });

  it('should render properly', function () {
    expect(_.size(this.view._subviews)).toBe(2); // categories, select
  });

  it('should update disabled if model changes', function () {
    expect(this.view.$el.hasClass('is-disabled')).toEqual(false);
    this.view.model.set('disabled', true);
    expect(this.view.$el.hasClass('is-disabled')).toEqual(true);
    this.view.model.set('disabled', false);
    expect(this.view.$el.hasClass('is-disabled')).toEqual(false);
  });

  it('should have no leaks', function () {
    expect(this.view).toHaveNoLeaks();
  });
});
<commit_msg>basemaps: specs<commit_after>var Backbone = require('backbone');
var ConfigModel = require('../../../../../../javascripts/cartodb3/data/config-model');
var BasemapInnerView = require('../../../../../../javascripts/cartodb3/editor/layers/basemap-content-views/basemap-inner-view');
var BasemapsCollection = require('../../../../../../javascripts/cartodb3/editor/layers/basemap-content-views/basemaps-collection');
var CarouselCollection = require('../../../../../../javascripts/cartodb3/components/custom-carousel/custom-carousel-collection');
var AnalysisDefinitionNodesCollection = require('../../../../../../javascripts/cartodb3/data/analysis-definition-nodes-collection');
var LayerDefinitionsCollection = require('../../../../../../javascripts/cartodb3/data/layer-definitions-collection');

describe('editor/layers/basemap-content-views/basemap-inner-view', function () {
  beforeEach(function () {
    var configModel = new ConfigModel({
      base_url: '/u/pepe'
    });

    this.analysisDefinitionNodesCollection = new AnalysisDefinitionNodesCollection(null, {
      configModel: configModel
    });

    this.layerDefinitionsCollection = new LayerDefinitionsCollection(null, {
      configModel: configModel,
      analysisDefinitionNodesCollection: this.analysisDefinitionNodesCollection,
      mapId: 'm-123'
    });

    this.layerDefinitionsCollection.add({
      id: 'l-1',
      kind: 'carto',
      options: {
        table_name: 'foo',
        className: 'positron_rainbow',
        category: 'CARTO'
      }
    });

    this.categoriesCollection = new CarouselCollection([]);

    this.view = new BasemapInnerView({
      categoriesCollection: this.categoriesCollection,
      layerDefinitionsCollection: this.layerDefinitionsCollection,
      basemapsCollection: new BasemapsCollection(),
      selectedCategoryVal: 'CARTO',
      model: new Backbone.Model()
    });

    this.view.render();
  });

  it('should render properly', function () {
    expect(_.size(this.view._subviews)).toBe(2); // categories, select
  });

  it('should update disabled if model changes', function () {
    expect(this.view.$el.hasClass('is-disabled')).toEqual(false);
    this.view.model.set('disabled', true);
    expect(this.view.$el.hasClass('is-disabled')).toEqual(true);
    this.view.model.set('disabled', false);
    expect(this.view.$el.hasClass('is-disabled')).toEqual(false);
  });

  it('should have no leaks', function () {
    expect(this.view).toHaveNoLeaks();
  });
});
<|endoftext|>


<commit_before>'use strict';
const DataHub = require("/data-hub/5/datahub.sjs");
const datahub = new DataHub();

function transform(context, params, content) {

  let flowName = params['flow-name'] ? xdmp.urlDecode(params['flow-name']) : "default-ingestion";
  let flow = datahub.flow.getFlow(flowName);
  if (!flow) {
    datahub.debug.log({message: params, type: 'error'});
    fn.error(null, "RESTAPI-SRVEXERR", "The specified flow " + flowName + " is missing.");
  }

  let step = params['step'] ? xdmp.urlDecode(params['step']) : null;
  let stepObj = flow.steps[step];
  if(!stepObj) {
    datahub.debug.log({message: params, type: 'error'});
    fn.error(null, "RESTAPI-SRVEXERR", "The specified step "+ step + "is missing in  " + flowName);
  }
  if(! stepObj.stepDefinitionType.toLowerCase() === "ingestion"){
    datahub.debug.log({message: params, type: 'error'});
    fn.error(null, "RESTAPI-SRVEXERR", "The specified step "+ step + "is not an ingestion step");
  }

  let jobId = params["job-id"];
  let options = params.options ? JSON.parse(params.options) : {};

  options.noWrite = true;
  options.fullOutput = true;
  options.noBatchWrite=true;

  let newContent = {};
  newContent.uri=context.uri;
  newContent.value=content;

  let flowContent = [];
  flowContent.push(newContent);

  let flowResponse = datahub.flow.runFlow(flowName, jobId, flowContent, options, step);
    if (flowResponse.errors && flowResponse.errors.length) {
      datahub.debug.log(flowResponse.errors[0]);
      fn.error(null, flowResponse.errors[0].message, flowResponse.errors[0].stack);
    }
    let documents = flowResponse.documents;
    if (documents && documents.length) {
      Object.assign(context, documents[0].context);
    }
    let docs = [];
    for (let doc of documents) {
      delete doc.context;
      if (doc.type && doc.type === 'error' && doc.message) {
        datahub.debug.log(doc);
        fn.error(null, "RESTAPI-SRVEXERR", doc.message);
      } else if (!doc.value) {
        datahub.debug.log({message: params, type: 'error'});
        fn.error(null, "RESTAPI-SRVEXERR", "The content was null in the flow " + flowName + " for " + doc.uri + ".");
      }
      else {
        docs.push(doc.value);
      }
    }
   return Sequence.from(docs);
}

exports.transform = transform;
<commit_msg>DHFPROD-2308: fix the typo, but also the invalid casting part<commit_after>'use strict';
const DataHub = require("/data-hub/5/datahub.sjs");
const datahub = new DataHub();

function transform(context, params, content) {

  let flowName = params['flow-name'] ? xdmp.urlDecode(params['flow-name']) : "default-ingestion";
  let flow = datahub.flow.getFlow(flowName);
  if (!flow) {
    datahub.debug.log({message: params, type: 'error'});
    fn.error(null, "RESTAPI-SRVEXERR", "The specified flow " + flowName + " is missing.");
  }

  let step = params['step'] ? xdmp.urlDecode(params['step']) : null;
  let stepObj = flow.steps[step];
  if(!stepObj) {
    datahub.debug.log({message: params, type: 'error'});
    fn.error(null, "RESTAPI-SRVEXERR", "The specified step "+ step + " is missing in  " + flowName);
  }
  if(! stepObj.stepDefinitionType.toLowerCase() === "ingestion"){
    datahub.debug.log({message: params, type: 'error'});
    fn.error(null, "RESTAPI-SRVEXERR", "The specified step "+ step + " is not an ingestion step");
  }

  let jobId = params["job-id"];
  let options = params.options ? JSON.parse(params.options) : {};

  options.noWrite = true;
  options.fullOutput = true;
  options.noBatchWrite=true;

  let newContent = {};
  newContent.uri=context.uri;
  newContent.value=content;

  let flowContent = [];
  flowContent.push(newContent);

  let flowResponse = datahub.flow.runFlow(flowName, jobId, flowContent, options, step);
    if (flowResponse.errors && flowResponse.errors.length) {
      datahub.debug.log(flowResponse.errors[0]);
      fn.error(null, flowResponse.errors[0].message, flowResponse.errors[0].stack);
    }
    let documents = flowResponse.documents;
    if (documents && documents.length) {
      Object.assign(context, documents[0].context);
    }
    let docs = [];
    for (let doc of documents) {
      delete doc.context;
      if (doc.type && doc.type === 'error' && doc.message) {
        datahub.debug.log(doc);
        fn.error(null, "RESTAPI-SRVEXERR", doc.message);
      } else if (!doc.value) {
        datahub.debug.log({message: params, type: 'error'});
        fn.error(null, "RESTAPI-SRVEXERR", "The content was null in the flow " + flowName + " for " + doc.uri + ".");
      }
      else {
        docs.push(doc.value);
      }
    }
   return Sequence.from(docs);
}

exports.transform = transform;
<|endoftext|>


<commit_before>// split a string to get text between before & after characters
//var i = 0;

function between(input, before, after) {
  i = input.indexOf(before);
  if (i >= 0) {
    input = input.substring(i + before.length);
  }
  else {
    return '';
  }
  if (after) {
    i = input.indexOf(after);
    if (i >= 0) {
      input = input.substring(0, i);
    }
    else {
      return '';
    }
  }
  return input;
}

//folderStructure object we want to get
var folderStructure = {
    files: null,
    subDirs: {
      dir1: {
        files: ['file1', 'file2'],
        subDirs: {
          'subDirA': {
            files: ['file3', 'file4'],
            subDirs: null
          },
          'subDirB': {
            files: ['file5'],
            subDirs: null
          }
        }
      },
      dir2: {
        files: ['hello'],
        subDirs: {
          'subdirC': {
            files: ['file6'],
            subDirs: {
              'moreA': {
                files: ['file3', 'file4'],
                subDirs: null
              },
              'moreB': {
                files: ['file5'],
                subDirs: null
              }
            }
          }
        }
      },
    dir3: {
      files: null,
      subDirs: {
        'subDirD': {
          files: ['file7'],
          subDirs: null
        }
      }
    }
  }
};

var depthCount = 0;
var thisItem, lastDir;

function readFiles(obj) {
  for( var item in obj ) {
    if( typeof obj[item] === 'object' ) { //its a subDir, keep going
      if ( item !== 'subDirs' && item !== 'files') {
        //if its the last prop, cd back again
        lastDir = Object.keys(obj)[Object.keys(obj).length - 1]; //this is the last directory in the cluster
        thisItem = item;
        console.log('mkdir & cd into', item);
        depthCount++;
      }
      if( Array.isArray(obj[item]) ) { //if its an array, its the files
        for (var i = 0; i < obj[item].length; i++) {
          console.log('touch ', obj[item][i]);
        }
        if( obj.subDirs == null ) { //you hit the end of the tree
          depthCount--;
          console.log('cd ../', depthCount);
          if(lastDir === thisItem) { //if its the last dir in the dir we're looping
            depthCount--;
            console.log('cd ../', depthCount);

            for(i=0; i<depthCount; i++) {
              depthCount--;
              console.log('cd ../', depthCount);
            }
          }
        }
      }
      readFiles(obj[item]); // recurse!
    }
    // else {
    //   for (i=0; i<depthCount; i++) {
    //     // console.log('other cd ../');
    //   }
    // }
  }
}

//console.log( readFiles( folderStructure ) );

readFiles(folderStructure);

<commit_msg>converted all console logs into finalOutput<commit_after>// split a string to get text between before & after characters
//var i = 0;

function between(input, before, after) {
  i = input.indexOf(before);
  if (i >= 0) {
    input = input.substring(i + before.length);
  }
  else {
    return '';
  }
  if (after) {
    i = input.indexOf(after);
    if (i >= 0) {
      input = input.substring(0, i);
    }
    else {
      return '';
    }
  }
  return input;
}

//folderStructure object we want to get
var folderStructure = {
    files: null,
    subDirs: {
      dir1: {
        files: ['file1', 'file2'],
        subDirs: {
          'subDirA': {
            files: ['file3', 'file4'],
            subDirs: null
          },
          'subDirB': {
            files: ['file5'],
            subDirs: null
          }
        }
      },
      dir2: {
        files: ['hello'],
        subDirs: {
          'subdirC': {
            files: ['file6'],
            subDirs: {
              'moreA': {
                files: ['file3', 'file4'],
                subDirs: null
              },
              'moreB': {
                files: ['file5'],
                subDirs: null
              }
            }
          }
        }
      },
    dir3: {
      files: null,
      subDirs: {
        'subDirD': {
          files: ['file7'],
          subDirs: null
        }
      }
    }
  }
};

var depthCount = 0;
var thisItem, lastDir;
var finalText = '';

function readFiles(obj) {
  for( var item in obj ) {
    if( typeof obj[item] === 'object' ) { //its a subDir, keep going
      if ( item !== 'subDirs' && item !== 'files') {
        //if its the last prop, cd back again
        lastDir = Object.keys(obj)[Object.keys(obj).length - 1]; //this is the last directory in the cluster
        thisItem = item;
        finalText += 'mkdir ' +  item + ';cd ' + item +';';
        depthCount++;
      }
      if( Array.isArray(obj[item]) ) { //if its an array, its the files
        for (var i = 0; i < obj[item].length; i++) {
          finalText += 'touch ' + obj[item][i] + ';';
        }
        if( obj.subDirs == null ) { //you hit the end of the tree
          depthCount--;
          finalText += 'cd ../;';
          if(lastDir === thisItem) { //if its the last dir in the dir we're looping
            depthCount--;
            finalText += 'cd ../;'

            for(i=0; i<depthCount; i++) {
              depthCount--;
              finalText += 'cd ../;'
            }
          }
        }
      }
      readFiles(obj[item]); // recurse!
    }
  }
}

readFiles(folderStructure);
console.log(finalText);

<|endoftext|>