<commit_before>// This is a SerGIS JSON Game Data file.
// See http://sergisproject.github.io/docs/json.html

// Since we can't load a JSON file unless running on a real web server (impractical for development),
// we're loading this as an actual JavaScript file, hence the assignment to SERGIS_JSON_DATA on the line below.

// NOTE: ArcGIS Basemap options are:
// "streets", "satellite", "hybrid", "topo", "gray", "oceans", "osm", "national-geographic"

// Also, NOTE: Comments aren't technically valid JSON. Make sure to remove all the comments in this file when making it back to JSON.

// For a production environment, get rid of these comments and the assignment below, and set the location of this file in lib/backends/local.js.
var SERGIS_JSON_DATA = {
    "jumpingBackAllowed": true,
    "onJumpBack": "hide",
    "jumpingForwardAllowed": true,
    "showActionsInUserOrder": false,

    "promptList": [
        // First prompt:
        {
            // "prompt" is a SerGIS JSON Prompt Object
            "prompt": {
                "title": "Introduction",
                // Each item in the "contents" array is a SerGIS JSON Content Object
                "contents": [
                    {"type": "html", "value": "Hello World!"},
                    {"type": "text", "value": "Note how the choice positions are randomized for this prompt. Also, each choice's content is defined in a different way."},
                    {"type": "html", "value": "Select "Choice NUMBER 1" to see an example of an explanation."}
                ],
                // "map" is a SerGIS JSON Map Object
                "map": {
                    "latitude": 55.6,
                    "longitude": 13,
                    "zoom": 5,
                    "frontendInfo": {
                        "arcgis": {
                            "basemap": "streets"
                        }
                    }
                },
                "randomizeChoices": true,
                // Each item in the "choices" array is a SerGIS JSON Content Object
                "choices": [
                    // First choice:
                    {"type": "html", "value": "Choice NUMBER 1"},
                    // Second choice:
                    {"type": "text", "value": "Choice <2>"},
                    // Third choice:
                    {"type": "image", "value": "http://www.text2image.com/user_images/text2image_R45488_20141117_035359.jpg"}
                ]
            },
            "actionList": [
                // First choice's actions:
                {
                    // Each item in the "actions" array is a SerGIS JSON Action Object
                    "actions": [
                        {
                            "name": "explain",
                            "data": [
                                {"type": "text", "value": "Good choice!"}
                            ]
                        },
                        {
                            "name": "buffer",
                            "frontend": "arcgis",
                            "data": ["first prompt, first choice"]
                        },
                        {
                            "name": "explain",
                            "data": [
                                {"type": "html", "value": "Here's another explanation after the Map Action happened!"}
                            ]
                        }
                    ],
                    "pointValue": 5
                },
                // Second choice's actions:
                {
                    // Each item in the "actions" array is a SerGIS JSON Action Object
                    "actions": [
                        {
                            "name": "buffer",
                            "frontend": "arcgis",
                            "data": ["first prompt, second choice"]
                        }
                    ],
                    "pointValue": 2
                },
                // Third choice's actions:
                {
                    // Each item in the "actions" array is a SerGIS JSON Action Object
                    "actions": [
                        {
                            "name": "buffer",
                            "frontend": "arcgis",
                            "data": ["first prompt, third choice"]
                        }
                    ],
                    "pointValue": 2
                }
            ]
        },
        // Second prompt:
        {
            // "prompt" is a SerGIS JSON Prompt Object
            "prompt": {
                "title": "Legal Crap",
                // Each item in the "contents" array is a SerGIS JSON Content Object
                "contents": [
                    {"type": "text", "value": "You must agree to this legal crap to continue."},
                    {"type": "text", "value": "(This is to test \"continue\" (\"I Agree\") and \"goto[0]\" (\"I Do Not Agree\")"}
                ],
                // "map" is a SerGIS JSON Map Object
                "map": {
                    "latitude": 30,
                    "longitude": -20,
                    "zoom": 3,
                    "frontendInfo": {
                        "arcgis": {
                            "basemap": "national-geographic"
                        }
                    }
                },
                "choices": [
                    // First choice:
                    {"type": "text", "value": "I Agree"},
                    // Second choice:
                    {"type": "text", "value": "I Disagree"}
                ]
            },
            "actionList": [
                // First choice's actions:
                {
                    // Each item in the "actions" array is a SerGIS JSON Action Object
                    "actions": [
                        {"name": "continue"}
                    ]
                },
                // Second choice's actions:
                {
                    // Each item in the "actions" array is a SerGIS JSON Action Object
                    "actions": [
                        {"name": "goto", "data": [0]}
                    ]
                }
            ]
        },
        // Third prompt:
        {
            // "prompt" is a SerGIS JSON Prompt Object
            "prompt": {
                "title": "Test Questions",
                // Each item in the "contents" array is a SerGIS JSON Content Object
                "contents": [
                    {"type": "text", "value": "Hello World! (again, menos HTML parsing)"},
                    {"type": "image", "value": "http://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Wikipedia-logo-v2.svg/70px-Wikipedia-logo-v2.svg.png"},
                    {"type": "youtube", "value": "dQw4w9WgXcQ"},
                    {"type": "text", "value": "Note the \"Continue\" button (since we didn't provide any choices and this isn't the last question)"}
                ],
                // "map" is a SerGIS JSON Map Object
                "map": {
                    "latitude": 55.6,
                    "longitude": 13,
                    "zoom": 5,
                    "frontendInfo": {
                        "arcgis": {
                            "basemap": "hybrid"
                        }
                    }
                }
            }
        },
        // Fourth prompt:
        {
            // "prompt" is a SerGIS JSON Prompt Object
            "prompt": {
                "title": "Test Questions",
                // Each item in the "contents" array is a SerGIS JSON Content Object
                "contents": [
                    {"type": "text", "value": "Hello World! (again, menos HTML parsing)"},
                    {"type": "image", "value": "http://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Wikipedia-logo-v2.svg/70px-Wikipedia-logo-v2.svg.png"},
                    {"type": "youtube", "value": "dQw4w9WgXcQ"},
                    {"type": "text", "value": "Note the lack of any choice buttons (since we didn't provide any choices and this IS the last question)"}
                ],
                // "map" is a SerGIS JSON Map Object
                "map": {
                    "latitude": 0,
                    "longitude": 0,
                    "zoom": 2,
                    "frontendInfo": {
                        "arcgis": {
                            "basemap": "gray"
                        }
                    }
                }
            }
        }
    ]
}
<commit_msg>Added test data for draw and buffer actions<commit_after>// This is a SerGIS JSON Game Data file.
// See http://sergisproject.github.io/docs/json.html

// Since we can't load a JSON file unless running on a real web server (impractical for development),
// we're loading this as an actual JavaScript file, hence the assignment to SERGIS_JSON_DATA on the line below.

// NOTE: ArcGIS Basemap options are:
// "streets", "satellite", "hybrid", "topo", "gray", "oceans", "osm", "national-geographic"

// Also, NOTE: Comments aren't technically valid JSON. Make sure to remove all the comments in this file when making it back to JSON.

// For a production environment, get rid of these comments and the assignment below, and set the location of this file in lib/backends/local.js.
var SERGIS_JSON_DATA = {
    "jumpingBackAllowed": true,
    "onJumpBack": "hide",
    "jumpingForwardAllowed": true,
    "showActionsInUserOrder": false,

    "promptList": [
        // First prompt:
        {
            // "prompt" is a SerGIS JSON Prompt Object
            "prompt": {
                "title": "Introduction",
                // Each item in the "contents" array is a SerGIS JSON Content Object
                "contents": [
                    {"type": "html", "value": "Hello World!"},
                    {"type": "text", "value": "Note how the choice positions are randomized for this prompt. Also, each choice's content is defined in a different way."},
                    {"type": "html", "value": "Select "Choice NUMBER 1" to see an example of an explanation."}
                ],
                // "map" is a SerGIS JSON Map Object
                "map": {
                    "latitude": 55.6,
                    "longitude": 13,
                    "zoom": 5,
                    "frontendInfo": {
                        "arcgis": {
                            "basemap": "streets"
                        }
                    }
                },
                "randomizeChoices": true,
                // Each item in the "choices" array is a SerGIS JSON Content Object
                "choices": [
                    // First choice:
                    {"type": "html", "value": "Choice NUMBER 1"},
                    // Second choice:
                    {"type": "text", "value": "Choice <2>"},
                    // Third choice:
                    {"type": "image", "value": "http://www.text2image.com/user_images/text2image_R45488_20141117_035359.jpg"}
                ]
            },
            "actionList": [
                // First choice's actions:
                {
                    // Each item in the "actions" array is a SerGIS JSON Action Object
                    "actions": [
                        // This is an "explain" action
                        {
                            "name": "explain",
                            "data": [
                                {"type": "text", "value": "Good choice! Once you click \"Continue\", a polygon will be drawn and a buffer will be placed around it."}
                            ]
                        },
                        // This is a "draw" action (specific to the "arcgis" frontend)
                        {
                            "name": "draw",
                            "frontend": "arcgis",
                            "data": [
                                "firstPromptDrawing",
                                "polygon",
                                [
                                    {
                                        "latitude": 55.6,
                                        "longitude": 12
                                    },
                                    {
                                        "latitude": 57,
                                        "longitude": 14
                                    },
                                    {
                                        "latitude": 55.6,
                                        "longitude": 15
                                    }
                                ]
                            ]
                        },
                        // This is an "explain" action
                        {
                            "name": "explain",
                            "data": [
                                {"type": "text", "value": "There's a polygon! Next we'll buffer it..."}
                            ]
                        },
                        // This is a "buffer" action (specific to the "arcgis" frontend)
                        {
                            "name": "buffer",
                            "frontend": "arcgis",
                            "data": [
                                50,
                                "statute_mile",
                                "firstPromptDrawing"
                            ]
                        },
                        // This is an "explain" action
                        {
                            "name": "explain",
                            "data": [
                                {"type": "html", "value": "Here's another explanation after the Map Action happened!"},
                                {"type": "text", "value": "Notice the polygon & the 50-mile buffer..."}
                            ]
                        }
                    ],
                    "pointValue": 5
                },
                // Second choice's actions:
                {
                    // Each item in the "actions" array is a SerGIS JSON Action Object
                    "actions": [],
                    "pointValue": 2
                },
                // Third choice's actions:
                {
                    // Each item in the "actions" array is a SerGIS JSON Action Object
                    "actions": [],
                    "pointValue": 2
                }
            ]
        },
        // Second prompt:
        {
            // "prompt" is a SerGIS JSON Prompt Object
            "prompt": {
                "title": "Legal Crap",
                // Each item in the "contents" array is a SerGIS JSON Content Object
                "contents": [
                    {"type": "text", "value": "You must agree to this legal crap to continue."},
                    {"type": "text", "value": "(This is to test \"continue\" (\"I Agree\") and \"goto[0]\" (\"I Do Not Agree\")"}
                ],
                // "map" is a SerGIS JSON Map Object
                "map": {
                    "latitude": 30,
                    "longitude": -20,
                    "zoom": 3,
                    "frontendInfo": {
                        "arcgis": {
                            "basemap": "national-geographic"
                        }
                    }
                },
                "choices": [
                    // First choice:
                    {"type": "text", "value": "I Agree"},
                    // Second choice:
                    {"type": "text", "value": "I Disagree"}
                ]
            },
            "actionList": [
                // First choice's actions:
                {
                    // Each item in the "actions" array is a SerGIS JSON Action Object
                    "actions": [
                        {"name": "continue"}
                    ]
                },
                // Second choice's actions:
                {
                    // Each item in the "actions" array is a SerGIS JSON Action Object
                    "actions": [
                        {"name": "goto", "data": [0]}
                    ]
                }
            ]
        },
        // Third prompt:
        {
            // "prompt" is a SerGIS JSON Prompt Object
            "prompt": {
                "title": "Test Questions",
                // Each item in the "contents" array is a SerGIS JSON Content Object
                "contents": [
                    {"type": "text", "value": "Hello World! (again, menos HTML parsing)"},
                    {"type": "image", "value": "http://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Wikipedia-logo-v2.svg/70px-Wikipedia-logo-v2.svg.png"},
                    {"type": "youtube", "value": "dQw4w9WgXcQ"},
                    {"type": "text", "value": "Note the \"Continue\" button (since we didn't provide any choices and this isn't the last question)"}
                ],
                // "map" is a SerGIS JSON Map Object
                "map": {
                    "latitude": 55.6,
                    "longitude": 13,
                    "zoom": 5,
                    "frontendInfo": {
                        "arcgis": {
                            "basemap": "hybrid"
                        }
                    }
                }
            }
        },
        // Fourth prompt:
        {
            // "prompt" is a SerGIS JSON Prompt Object
            "prompt": {
                "title": "Test Questions",
                // Each item in the "contents" array is a SerGIS JSON Content Object
                "contents": [
                    {"type": "text", "value": "Hello World! (again, menos HTML parsing)"},
                    {"type": "image", "value": "http://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Wikipedia-logo-v2.svg/70px-Wikipedia-logo-v2.svg.png"},
                    {"type": "youtube", "value": "dQw4w9WgXcQ"},
                    {"type": "text", "value": "Note the lack of any choice buttons (since we didn't provide any choices and this IS the last question)"}
                ],
                // "map" is a SerGIS JSON Map Object
                "map": {
                    "latitude": 0,
                    "longitude": 0,
                    "zoom": 2,
                    "frontendInfo": {
                        "arcgis": {
                            "basemap": "gray"
                        }
                    }
                }
            }
        }
    ]
}
<|endoftext|>


<commit_before>'use strict';

exports = module.exports = Clock;

var ClockTask = require('./clock-task');
var ClockTaskResult = require('./clock-task-result');
var util = require('util');
var Model = require('./../models/model');
var Q = require('q');

/**
 * The clock module is responsible for the clock process type. The clock process schedules tasks to run at scheduled time intervals in your worker processes. The clock module is used by e.g. the Triggers and the Scheduler module. The clock module guarantees to schedule tasks without skipping an interval.
 *
 * Because the clock process might at some point restart or crash and potentially skip a scheduled tasks, the clock process checks at startup if it skipped any task based on the date of the previous executed task. If it identifies a skipped task, it'll schedule the task immediately.
 *
 * For example, consider a task which sends a mail to all users every month at the 1st day of the month at 13:00 hour exactly. If the clock process crashes at 12:59 hour and starts again at 13:01 the time interval was skipped. The clock module recognizes this and schedules the task at 13:01 instead.
 *
 * (When the clock module starts the first time, and there are no results, it inserts a fake clock result).
 *
 * To start the clock process simply invoke the app with the `--clock` argument. For example, add the following entry to your `Procfile`:
 * ```
 * clock: node index.js --clock
 * ```
 *
 * @param {App} app
 * @constructor
 */
function Clock(app) {
	this.app = app;
	this._tasks = [];
}
Clock.prototype.ignoreDisabled = true;
Clock.prototype.enableModuleProperty = true;

Clock.prototype.migrate = function(models) {
	util.inherits(ClockTaskResult, Model);
	models.addModelConstructor(ClockTaskResult);
};

Clock.prototype.setup = function() {
	if(this.app) {
		this.app.moduleProperties.set(this);
	}

	this.migrate(this.models);
};

/**
 * Creates a task to run at a time interval. The callback is guaranteed to run. The callback should schedule a job on a worker process and not actually execute any work.
 *
 * Check the Schedule or Trigger modules instead if you want to schedule periodic tasks.
 *
 * @param {String}   timingPattern A cron-style timing pattern. For more information, see https://github.com/ncb000gt/node-cron.
 * @param {String}   taskName      The name of the task to run.
 * @param {Function} callback      The function which schedules a job on a worker process.
 */
Clock.prototype.addTask = function(timingPattern, taskName, callback) {
	var task = new ClockTask(timingPattern, taskName, callback);

	if(this.app) {
		// Makes models available on trigger task.
		this.app.moduleProperties.set(task);
	}

	this._tasks.push(task);
	return task;
};

/**
 * Starts all the tasks.
 *
 * @access private
 */
Clock.prototype.startTasks = function() {
	return Q.all(this._tasks.map(function(task) {
		return task.start();
	}));
};

/**
 * Executed when the app starts. Starts all the tasks if the app is started with the clock argument e.g. `node index.js --clock`.
 *
 * @access private
 */
Clock.prototype.start = function(argv) {
	if(argv.clock) {
		return this.startTasks();
	}
};

/**
 * Stops all the tasks. This is executed when the app is killed.
 */
Clock.prototype.stop = function() {
	return Q.all(this._tasks.map(function(task) {
		return Q.when(task.stop());
	}));
};
<commit_msg>disables ClockTaskResult model files<commit_after>'use strict';

exports = module.exports = Clock;

var ClockTask = require('./clock-task');
var ClockTaskResult = require('./clock-task-result');
var util = require('util');
var Model = require('./../models/model');
var Q = require('q');

/**
 * The clock module is responsible for the clock process type. The clock process schedules tasks to run at scheduled time intervals in your worker processes. The clock module is used by e.g. the Triggers and the Scheduler module. The clock module guarantees to schedule tasks without skipping an interval.
 *
 * Because the clock process might at some point restart or crash and potentially skip a scheduled tasks, the clock process checks at startup if it skipped any task based on the date of the previous executed task. If it identifies a skipped task, it'll schedule the task immediately.
 *
 * For example, consider a task which sends a mail to all users every month at the 1st day of the month at 13:00 hour exactly. If the clock process crashes at 12:59 hour and starts again at 13:01 the time interval was skipped. The clock module recognizes this and schedules the task at 13:01 instead.
 *
 * (When the clock module starts the first time, and there are no results, it inserts a fake clock result).
 *
 * To start the clock process simply invoke the app with the `--clock` argument. For example, add the following entry to your `Procfile`:
 * ```
 * clock: node index.js --clock
 * ```
 *
 * @param {App} app
 * @constructor
 */
function Clock(app) {
	this.app = app;
	this._tasks = [];
}
Clock.prototype.ignoreDisabled = true;
Clock.prototype.enableModuleProperty = true;

Clock.prototype.migrate = function(models) {
	util.inherits(ClockTaskResult, Model);
	ClockTaskResult.disableAutomaticModelController = true;
	models.addModelConstructor(ClockTaskResult);
};

Clock.prototype.setup = function() {
	if(this.app) {
		this.app.moduleProperties.set(this);
	}

	this.migrate(this.models);
};

/**
 * Creates a task to run at a time interval. The callback is guaranteed to run. The callback should schedule a job on a worker process and not actually execute any work.
 *
 * Check the Schedule or Trigger modules instead if you want to schedule periodic tasks.
 *
 * @param {String}   timingPattern A cron-style timing pattern. For more information, see https://github.com/ncb000gt/node-cron.
 * @param {String}   taskName      The name of the task to run.
 * @param {Function} callback      The function which schedules a job on a worker process.
 */
Clock.prototype.addTask = function(timingPattern, taskName, callback) {
	var task = new ClockTask(timingPattern, taskName, callback);

	if(this.app) {
		// Makes models available on trigger task.
		this.app.moduleProperties.set(task);
	}

	this._tasks.push(task);
	return task;
};

/**
 * Starts all the tasks.
 *
 * @access private
 */
Clock.prototype.startTasks = function() {
	return Q.all(this._tasks.map(function(task) {
		return task.start();
	}));
};

/**
 * Executed when the app starts. Starts all the tasks if the app is started with the clock argument e.g. `node index.js --clock`.
 *
 * @access private
 */
Clock.prototype.start = function(argv) {
	if(argv.clock) {
		return this.startTasks();
	}
};

/**
 * Stops all the tasks. This is executed when the app is killed.
 */
Clock.prototype.stop = function() {
	return Q.all(this._tasks.map(function(task) {
		return Q.when(task.stop());
	}));
};
<|endoftext|>


<commit_before>/**
 * Manipulate the fhir json object in understandable ways.
 * TODO mike@carif.io: can this module be generated from the fhir artifacts in some way?
 */

var format = require('string-format');
var JSONPath = require('jsonpath-plus');
var _ = require('underscore');

/**
 * Generate "now" as a timestamp parsable by fhir. There are several acceptible formats.
 * Using a single function throughout gives us consistent treatment.
 * @returns {string} -- the timestamp "now" as a local time.
 */
function now() {
    return new Date().toISOString();
}

/**
 * A set of predicates to recognize types of cmumps objects
 */

/**
 * Extract the *single* patient from the fhirObject using JSONPath.
 * @param {object} fhirObject
 * @returns {Patient}
 */

function extractPatient(fhirObject) {
    return JSONPath({json: fhirObject, path: '$.entry[0].resource[?(@.resourceType=="Patient")]'})[0];
}

/**
 * Fronts extractPatient because the terminology is confusing.
 * @param {object} fhirObject
 * @returns {Patient}
 */
function extractDemographics(fhirObject) {
    return [ extractPatient(fhirObject) ];
}

/**
 * Extract all medications from the fhirObject using JSONPath.
 * @param {object} fhirObject
 * @returns {Array[MedicationDispense]}
 */
function extractMedications(fhirObject) {
    return JSONPath({json: fhirObject, path: '$.entry[0].resource[?(@.resourceType=="MedicationDispense")]'});
}

/**
 * Extract all labs from the fhirObject using JSONPath.
 * @param fhirObject
 * @returns {Array[Observation]}
 */
function extractLabs(fhirObject) {
    return JSONPath({json: fhirObject, path: '$.entry[0].resource[?(@.resourceType=="DiagnosticObservation")]'});
}

/**
 * Extract all Diagnoses from the fhirObject using JSONPath.
 * @param fhirObject
 * @returns {Array[DiagosticReport]}
 */
function extractDiagnoses(fhirObject) {
    return JSONPath({json: fhirObject, path: '$.entry[0].resource[?(@.resourceType=="DiagnosticReport")]'});
}

/**
 * Extract all Procedures from the fhirObject using JSONPath.
 * @param {object} fhirObject
 * @returns {Array[Procedure]}
 */
function extractProcedures(fhirObject) {
    return JSONPath({json: fhirObject, path: '$.entry[0].resource[?(@.resourceType=="Procedure")]'});
}

/**
 * Add the cmumps participating properties, described as JSON path expressions, rooted at prefix object (if passed).
 * @param {object} fhirResult, SIDE EFFECTS fhirResult
 * @param {List[String]} participatingProperties
 * @param {String} [prefix=undefined] -- the prefix of the JSON Path expression
 */
function addParticipants(fhirResult, participatingProperties, prefix) {
    // Don't create an extension unless there are participating properties to actually report.
    if (participatingProperties.length > 0) {
        fhirResult.extension = [
            {url: 'cmumps', extension: participatingProperties.map(function(i) {
                return {url: 'cmumps', valueString: prefix ? prefix + i.substring(1) : i};
            })}
        ];
    }
}

/**
 * Add the cmumps translation warnings as strings. The strings are messages for a human reader.
 * @param {object} fhirResult, SIDE EFFECTS fhirResult
 * @param {Array[String]} warnings
 */
function addWarnings(fhirResult, warnings) {
    // Don't create or augment an extension unless there are warnings to actually report.
    if (warnings.length > 0) {
        // Array[String] => Array[{url, valueString}]
        var warningsAsExtensions = warnings.map(function(i) { return {url: 'cmumps', valueString: i}});
        if (fhirResult.extension) {
            // If there are already some extensions, add this to the list.
            fhirResult.extension.push({url: 'cmumps', extension: warningsAsExtensions});
        } else {
            // Create an extension and populate it.
            fhirResult.extension = [
                {url: 'cmumps', extension: warningsAsExtensions}
            ];
        }
    }
}

// Export the actual functions here.
[now, extractPatient, extractDemographics,
    extractMedications, extractLabs, extractDiagnoses,
    extractProcedures, extractLabs,
    addParticipants, addWarnings].forEach(function(f) { module.exports[f.name] = f; });

// Given a resourceType, e.g. 'MedicationDispense', return the function that will extract out that resource type.
// This is redundant, but can be useful if you come to this API with prior knowledge of the FHIR resourceTypes.
// Note that _.keys(module.exports.resourceTypes) will enumerate the "covered" FHIR resourceTypes.
module.exports.resourceTypes = {
    Patient: extractPatient,
    MedicationDispense: extractMedications,
    DiagnosticObservation: extractLabs,
    DiagnosticReport: extractDiagnoses,
    Procedure: extractProcedures,
    DiagnosticObservation: extractLabs
};

module.exports.returns = {};
// reverse the resourceTypes mapping, should report the FHIR return type for an extractor as a string, e.g.
// var fhir = require('fhir); fhir.returns['extractMedications'] => 'MedicationDispense'
// Useful for mocha tests.
_.pairs(module.exports.resourceTypes).forEach(function(p) { module.exports.returns[p[1]] = p[0]; });

// parts, the parts of fhir knows how to extract
module.exports.parts = {};
[extractDemographics, extractMedications, extractLabs, extractDiagnoses, extractProcedures].forEach(function(f) {
    module.exports.parts[f.name.substring('extract'.length).toLowerCase()] = f;
});
<commit_msg>placeholder for extensions function<commit_after>/**
 * Manipulate the fhir json object in understandable ways.
 * TODO mike@carif.io: can this module be generated from the fhir artifacts in some way?
 */

var format = require('string-format');
var JSONPath = require('jsonpath-plus');
var _ = require('underscore');

/**
 * Generate "now" as a timestamp parsable by fhir. There are several acceptible formats.
 * Using a single function throughout gives us consistent treatment.
 * @returns {string} -- the timestamp "now" as a local time.
 */
function now() {
    return new Date().toISOString();
}

/**
 * A set of predicates to recognize types of cmumps objects
 */

/**
 * Extract the *single* patient from the fhirObject using JSONPath.
 * @param {object} fhirObject
 * @returns {Patient}
 */

function extractPatient(fhirObject) {
    return JSONPath({json: fhirObject, path: '$.entry[0].resource[?(@.resourceType=="Patient")]'})[0];
}

/**
 * Fronts extractPatient because the terminology is confusing.
 * @param {object} fhirObject
 * @returns {Patient}
 */
function extractDemographics(fhirObject) {
    return [ extractPatient(fhirObject) ];
}

/**
 * Extract all medications from the fhirObject using JSONPath.
 * @param {object} fhirObject
 * @returns {Array[MedicationDispense]}
 */
function extractMedications(fhirObject) {
    return JSONPath({json: fhirObject, path: '$.entry[0].resource[?(@.resourceType=="MedicationDispense")]'});
}

/**
 * Extract all labs from the fhirObject using JSONPath.
 * @param fhirObject
 * @returns {Array[Observation]}
 */
function extractLabs(fhirObject) {
    return JSONPath({json: fhirObject, path: '$.entry[0].resource[?(@.resourceType=="DiagnosticObservation")]'});
}

/**
 * Extract all Diagnoses from the fhirObject using JSONPath.
 * @param fhirObject
 * @returns {Array[DiagosticReport]}
 */
function extractDiagnoses(fhirObject) {
    return JSONPath({json: fhirObject, path: '$.entry[0].resource[?(@.resourceType=="DiagnosticReport")]'});
}

/**
 * Extract all Procedures from the fhirObject using JSONPath.
 * @param {object} fhirObject
 * @returns {Array[Procedure]}
 */
function extractProcedures(fhirObject) {
    return JSONPath({json: fhirObject, path: '$.entry[0].resource[?(@.resourceType=="Procedure")]'});
}

/**
 * Add the cmumps participating properties, described as JSON path expressions, rooted at prefix object (if passed).
 * @param {object} fhirResult, SIDE EFFECTS fhirResult
 * @param {List[String]} participatingProperties
 * @param {String} [prefix=undefined] -- the prefix of the JSON Path expression
 */
function addParticipants(fhirResult, participatingProperties, prefix) {
    // Don't create an extension unless there are participating properties to actually report.
    if (participatingProperties.length > 0) {
        fhirResult.extension = [
            {url: 'cmumps', extension: participatingProperties.map(function(i) {
                return {url: 'cmumps', valueString: prefix ? prefix + i.substring(1) : i};
            })}
        ];
    }
}

/**
 * Add the cmumps translation warnings as strings. The strings are messages for a human reader.
 * @param {object} fhirResult, SIDE EFFECTS fhirResult
 * @param {Array[String]} warnings
 */
function addWarnings(fhirResult, warnings) {
    // Don't create or augment an extension unless there are warnings to actually report.
    if (warnings.length > 0) {
        // Array[String] => Array[{url, valueString}]
        var warningsAsExtensions = warnings.map(function(i) { return {url: 'cmumps', valueString: i}});
        if (fhirResult.extension) {
            // If there are already some extensions, add this to the list.
            fhirResult.extension.push({url: 'cmumps', extension: warningsAsExtensions});
        } else {
            // Create an extension and populate it.
            fhirResult.extension = [
                {url: 'cmumps', extension: warningsAsExtensions}
            ];
        }
    }
}

/**
 * Given an arbitrary javascript Object, encoded it as a list of fhirExtensions using
 * the directions at https://hl7-fhir.github.io/extensibility.html
 * @param jsObject
 * @returns {null}
 */
function js2fhirExtension(jsObject) {
    return jsObject.map(_.pairs(jsObject), js2fhir)
}

function js2fhir(key, value) {

}

// Export the actual functions here.
[now, extractPatient, extractDemographics,
    extractMedications, extractLabs, extractDiagnoses,
    extractProcedures, extractLabs,
    addParticipants, addWarnings].forEach(function(f) { module.exports[f.name] = f; });

// Given a resourceType, e.g. 'MedicationDispense', return the function that will extract out that resource type.
// This is redundant, but can be useful if you come to this API with prior knowledge of the FHIR resourceTypes.
// Note that _.keys(module.exports.resourceTypes) will enumerate the "covered" FHIR resourceTypes.
module.exports.resourceTypes = {
    Patient: extractPatient,
    MedicationDispense: extractMedications,
    DiagnosticObservation: extractLabs,
    DiagnosticReport: extractDiagnoses,
    Procedure: extractProcedures,
    DiagnosticObservation: extractLabs
};

module.exports.returns = {};
// reverse the resourceTypes mapping, should report the FHIR return type for an extractor as a string, e.g.
// var fhir = require('fhir); fhir.returns['extractMedications'] => 'MedicationDispense'
// Useful for mocha tests.
_.pairs(module.exports.resourceTypes).forEach(function(p) { module.exports.returns[p[1]] = p[0]; });

// parts, the parts of fhir knows how to extract
module.exports.parts = {};
[extractDemographics, extractMedications, extractLabs, extractDiagnoses, extractProcedures].forEach(function(f) {
    module.exports.parts[f.name.substring('extract'.length).toLowerCase()] = f;
});
<|endoftext|>


<commit_before>'use strict';

var bitcore = require('..'),
    MerkleBlock = bitcore.MerkleBlock,
    BufferReader = bitcore.encoding.BufferReader,
    BufferWriter = bitcore.encoding.BufferWriter,
    data = require('./data/merkleblocks.js');

describe('MerkleBlock', function() {
  var blockhex  = data.HEX[0];
  var blockbuf  = new Buffer(blockhex,'hex');
  var blockJSON = JSON.stringify(data.JSON[0]);
  var blockObject = JSON.parse(JSON.stringify(data.JSON[0]));

  describe('#constructor', function() {
    it('should make a new merkleblock from buffer', function() {
      var b = MerkleBlock(blockbuf);
      b.toBuffer().toString('hex').should.equal(blockhex);
    });

    it('should make a new merkleblock from object', function() {
      var b = MerkleBlock(blockObject);
      b.toObject().should.deep.equal(blockObject);
    });

    it('should make a new merkleblock from JSON', function() {
      var b = MerkleBlock(blockJSON);
      b.toJSON().should.equal(blockJSON);
    });

    it('should not make an empty block', function() {
      (function() {
        return new MerkleBlock();
      }).should.throw('Unrecognized argument for Block');
    });
  });

  describe('#fromJSON', function() {

    it('should set these known values', function() {
      var block = MerkleBlock.fromJSON(blockJSON);
      should.exist(block.header);
      should.exist(block.numTransactions);
      should.exist(block.hashes);
      should.exist(block.flags);
    });

    it('should set these known values', function() {
      var block = MerkleBlock(blockJSON);
      should.exist(block.header);
      should.exist(block.numTransactions);
      should.exist(block.hashes);
      should.exist(block.flags);
    });

    it('accepts an object as argument', function() {
      var block = MerkleBlock(blockbuf);
      MerkleBlock.fromJSON(block.toObject()).should.exist();
    });

  });

  describe('#toJSON', function() {

    it('should recover these known values', function() {
      var block = MerkleBlock.fromJSON(blockJSON);
      var b = JSON.parse(block.toJSON());
      should.exist(block.header);
      should.exist(block.numTransactions);
      should.exist(block.hashes);
      should.exist(block.flags);
      should.exist(b.header);
      should.exist(b.numTransactions);
      should.exist(b.hashes);
      should.exist(b.flags);
    });

  });

  // TODO
  //describe('#fromString/#toString', function() {

    //it('should output/input a block hex string', function() {
      //var b = MerkleBlock.fromString(blockhex);
      //b.toString().should.equal(blockhex);
    //});

  //});

  describe('#fromBuffer', function() {

    it('should make a block from this known buffer', function() {
      var block = MerkleBlock.fromBuffer(blockbuf);
      block.toBuffer().toString('hex').should.equal(blockhex);
    });

  });

  describe('#fromBufferReader', function() {

    it('should make a block from this known buffer', function() {
      var block = MerkleBlock.fromBufferReader(BufferReader(blockbuf));
      block.toBuffer().toString('hex').should.equal(blockhex);
    });

  });

  describe('#toBuffer', function() {

    it('should recover a block from this known buffer', function() {
      var block = MerkleBlock.fromBuffer(blockbuf);
      block.toBuffer().toString('hex').should.equal(blockhex);
    });

  });

  describe('#toBufferWriter', function() {

    it('should recover a block from this known buffer', function() {
      var block = MerkleBlock.fromBuffer(blockbuf);
      block.toBufferWriter().concat().toString('hex').should.equal(blockhex);
    });

    it('doesn\'t create a bufferWriter if one provided', function() {
      var writer = new BufferWriter();
      var block = MerkleBlock.fromBuffer(blockbuf);
      block.toBufferWriter(writer).should.equal(writer);
    });

  });

});

<commit_msg>One variable per var statement<commit_after>'use strict';

var bitcore = require('..');
var MerkleBlock = bitcore.MerkleBlock;
var BufferReader = bitcore.encoding.BufferReader;
var BufferWriter = bitcore.encoding.BufferWriter;
var data = require('./data/merkleblocks.js');

describe('MerkleBlock', function() {
  var blockhex  = data.HEX[0];
  var blockbuf  = new Buffer(blockhex,'hex');
  var blockJSON = JSON.stringify(data.JSON[0]);
  var blockObject = JSON.parse(JSON.stringify(data.JSON[0]));

  describe('#constructor', function() {
    it('should make a new merkleblock from buffer', function() {
      var b = MerkleBlock(blockbuf);
      b.toBuffer().toString('hex').should.equal(blockhex);
    });

    it('should make a new merkleblock from object', function() {
      var b = MerkleBlock(blockObject);
      b.toObject().should.deep.equal(blockObject);
    });

    it('should make a new merkleblock from JSON', function() {
      var b = MerkleBlock(blockJSON);
      b.toJSON().should.equal(blockJSON);
    });

    it('should not make an empty block', function() {
      (function() {
        return new MerkleBlock();
      }).should.throw('Unrecognized argument for Block');
    });
  });

  describe('#fromJSON', function() {

    it('should set these known values', function() {
      var block = MerkleBlock.fromJSON(blockJSON);
      should.exist(block.header);
      should.exist(block.numTransactions);
      should.exist(block.hashes);
      should.exist(block.flags);
    });

    it('should set these known values', function() {
      var block = MerkleBlock(blockJSON);
      should.exist(block.header);
      should.exist(block.numTransactions);
      should.exist(block.hashes);
      should.exist(block.flags);
    });

    it('accepts an object as argument', function() {
      var block = MerkleBlock(blockbuf);
      MerkleBlock.fromJSON(block.toObject()).should.exist();
    });

  });

  describe('#toJSON', function() {

    it('should recover these known values', function() {
      var block = MerkleBlock.fromJSON(blockJSON);
      var b = JSON.parse(block.toJSON());
      should.exist(block.header);
      should.exist(block.numTransactions);
      should.exist(block.hashes);
      should.exist(block.flags);
      should.exist(b.header);
      should.exist(b.numTransactions);
      should.exist(b.hashes);
      should.exist(b.flags);
    });

  });

  // TODO
  //describe('#fromString/#toString', function() {

    //it('should output/input a block hex string', function() {
      //var b = MerkleBlock.fromString(blockhex);
      //b.toString().should.equal(blockhex);
    //});

  //});

  describe('#fromBuffer', function() {

    it('should make a block from this known buffer', function() {
      var block = MerkleBlock.fromBuffer(blockbuf);
      block.toBuffer().toString('hex').should.equal(blockhex);
    });

  });

  describe('#fromBufferReader', function() {

    it('should make a block from this known buffer', function() {
      var block = MerkleBlock.fromBufferReader(BufferReader(blockbuf));
      block.toBuffer().toString('hex').should.equal(blockhex);
    });

  });

  describe('#toBuffer', function() {

    it('should recover a block from this known buffer', function() {
      var block = MerkleBlock.fromBuffer(blockbuf);
      block.toBuffer().toString('hex').should.equal(blockhex);
    });

  });

  describe('#toBufferWriter', function() {

    it('should recover a block from this known buffer', function() {
      var block = MerkleBlock.fromBuffer(blockbuf);
      block.toBufferWriter().concat().toString('hex').should.equal(blockhex);
    });

    it('doesn\'t create a bufferWriter if one provided', function() {
      var writer = new BufferWriter();
      var block = MerkleBlock.fromBuffer(blockbuf);
      block.toBufferWriter(writer).should.equal(writer);
    });

  });

});

<|endoftext|>


<commit_before><commit_msg>Added some comments to file<commit_after><|endoftext|>


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

var assert = require("assert");
var dJSON = require("../dirty-json");

function compareResults(json, done) {
	dJSON.parse(json).then(function (res) {
		jeq(res, JSON.parse(json));
	}).then(done, done);
}

function compareResultsToValid(invalid, valid, done) {
	// confirm that the invalid json is invalid
	try {
		var j = JSON.parse(invalid);
		// it didn't fail!
		done("json was valid!");
	} catch (e) {
		dJSON.parse(invalid).then(function (res) {
			jeq(res, JSON.parse(valid));
		}).then(done, done);
	}

}

function jeq(obj1, obj2) {
	assert.equal(JSON.stringify(obj1), JSON.stringify(obj2));
}

describe("parser", function () {
	describe("parse() on valid JSON", function (done) {
		it('should handle an empty object', function (done) {
			compareResults("{}", done);
		});

		it('should handle an empty list', function (done) {
			compareResults("[]", done);
		});

		it('should handle an single-item list', function (done) {
			compareResults("[4]", done);
		});

		it('should handle an single-item object', function (done) {
			compareResults("{ \"test\": 4 }", done);
		});

		it('should handle a list of numbers', function (done) {
			compareResults("[3, 4, -2, 5.5, 0.5, 0.32]", done);
		});

		it('should handle a list of numbers and strings', function (done) {
			compareResults("[3, 4, -2, \"5.5\", 0.5, 0.32]", done);
		});

		it('should handle a list of numbers, strings, and booleans', function (done) {
			compareResults("[3, 4, -2, \"5.5\", 0.5, false]", done);
		});

		it('should handle a list of numbers, strings, and booleans', function (done) {
			compareResults('["some text", 4, "some more text", "text"]', done);
		});

		it('should handle a list of numbers, strings, and booleans', function (done) {
			compareResults('["[],4,5", "false", ","]', done);
		});

		it('should handle an object with mixed values', function (done) {
			compareResults('{ "test": 56, "test2": "hello!", "test3": false }', done);
		});

		it('should handle an object with list values', function (done) {
			compareResults('{ "test": [3, "str", false, 0.5], "test2": [1, 2, "str2"] }', done);
		});

		it('should handle embedded objects', function (done) {
			compareResults('{ "test": { "test": [1, 2, 3] } }', done);
		});

		it('should handle embedded lists', function (done) {
			compareResults('[1, 2, [3, 4], 5]', done);
		});

		it('should handle embedded lists when the first item is a list', function (done) {
			compareResults('[[1, false], 2, [3, 4], 5]', done);
		});

		it('should handle objects embedded in lists', function (done) {
			compareResults('[2, {"test": "str"}]', done);
		});

		it('should handle objects embedded in lists', function (done) {
			compareResults('[{"test": "str"}, 2, [3, {"test2": "str2"}], 5]', done);
		});

		it('should handle a complex JSON structure', function (done) {
			compareResults('[{"test": "str"}, [2, false, 0.4], [3, {"test2": ["str2", 6]}], 5]', done);
		});

		it('should handle a complex JSON structure', function (done) {
			compareResults('[{"test": "str"}, [2, false, ",", 0.4, "[val]"], [3, {"test2": ["str2", 6]}], 5]', done);
		});

		it('should handle nulls in lists', function (done) {
			compareResults("[null]", done);
		});

		it('should handle nulls in objects', function (done) {
			compareResults("{ \"test\": null}", done);
		});

	});

	describe("parse() on invalid JSON", function () {
		it('should handle non-quoted object keys', function(done) {
			compareResultsToValid('{test: 5}', '{"test": 5}', done);
		});

		it('should handle single-quoted object keys', function(done) {
			compareResultsToValid('{\'test\': 5}', '{"test": 5}', done);
		});

		it('should handle single-quoted object values', function(done) {
			compareResultsToValid('{\'test\': \'5\'}', '{"test": "5"}', done);
		});

		it('should handle quotes-in-quotes (list)', function(done) {
			compareResultsToValid('["some "quoted" text"]', '["some \\"quoted\\" text"]', done);
		});

		it('should handle quotes-in-quotes (list)', function(done) {
			compareResultsToValid('[3, "some "quoted" text", 2]', '[3, "some \\"quoted\\" text", 2]', done);
		});

		it('should handle quotes-in-quotes (object)', function(done) {
			compareResultsToValid('{"test": "some "quoted" text"}', '{"test": "some \\"quoted\\" text"}', done);
		});

		it('should handle quotes-in-quotes (object)', function(done) {
			compareResultsToValid('{"test0": false, "test": "some "quoted" text", "test1": 5}', '{"test0": false, "test": "some \\"quoted\\" text", "test1": 5}', done);
		});

		describe("with new lines", function() {
			it ('should handle a newline in a string in object', function(done) {

				dJSON.parse('{ "test0": "a '+"\n"+'string" }').then(function (r) {
					assert.equal(r.test0, 'a '+"\n"+'string');
				}).then(done, done);
			});

			it ('should handle a newline in a string in a list', function(done) {

				dJSON.parse('["a '+"\n"+'string"]').then(function (r) {
					assert.equal(r[0], 'a '+"\n"+'string');
				}).then(done, done);
			});

			it('should handle newline in misquoted string in object', function(done) {
				var str = 'this\n"quote"\ntext';
				dJSON.parse('{ "test0": "' + str + '"}').then(function (r) {
					assert.equal(r.test0, str);
				}).then(done, done);
			});

			it('should handle newline in misquoted string in object', function(done) {
				var str = 'this\n"quote"\ntext';
				dJSON.parse('{ "test1": false, "test0": "' + str + '", test2: 5.5}').then(function (r) {
					assert.equal(r.test0, str);
					assert.equal(r.test1, false);
					assert.equal(r.test2, 5.5);
				}).then(done, done);
			});

			it('should handle newline in misquoted string in list', function(done) {
				var str = 'this\n"quote"\ntext';
				dJSON.parse('["' + str + '"]').then(function (r) {
					assert.equal(r[0], str);
				}).then(done, done);
			});

			it('should handle newline in misquoted string in list', function(done) {
				var str = 'this\n"quote"\ntext';
				dJSON.parse('[5, 6, "' + str + '", "test"]').then(function (r) {
					assert.equal(r[2], str);
					assert.equal(r[0], 5);
					assert.equal(r[1], 6);
					assert.equal(r[3], "test");
				}).then(done, done);
			});
		});

		describe("with embedded HTML", function() {
			it('should handle an embedded DIV tag', function(done) {
				dJSON.parse('["
some text
"]').then(function (r) {
					assert.equal(r[0], '
some text
');
					assert.equal(r.length, 1);
				}).then(done, done);
			});
		});

	});
});
<commit_msg>Added more test<commit_after>// Copyright 2014 Ryan Marcus
// This file is part of dirty-json.
//
// dirty-json is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// dirty-json is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with dJSON.  If not, see <http://www.gnu.org/licenses/>.

var assert = require("assert");
var dJSON = require("../dirty-json");

function compareResults(json, done) {
	dJSON.parse(json).then(function (res) {
		jeq(res, JSON.parse(json));
	}).then(done, done);
}

function compareResultsToValid(invalid, valid, done) {
	// confirm that the invalid json is invalid
	try {
		var j = JSON.parse(invalid);
		// it didn't fail!
		done("json was valid!");
	} catch (e) {
		dJSON.parse(invalid).then(function (res) {
			jeq(res, JSON.parse(valid));
		}).then(done, done);
	}

}

function jeq(obj1, obj2) {
	assert.equal(JSON.stringify(obj1), JSON.stringify(obj2));
}

describe("parser", function () {
	describe("parse() on valid JSON", function (done) {
		it('should handle an empty object', function (done) {
			compareResults("{}", done);
		});

		it('should handle an empty list', function (done) {
			compareResults("[]", done);
		});

		it('should handle an single-item list', function (done) {
			compareResults("[4]", done);
		});

		it('should handle an single-item object', function (done) {
			compareResults("{ \"test\": 4 }", done);
		});

		it('should handle a list of numbers', function (done) {
			compareResults("[3, 4, -2, 5.5, 0.5, 0.32]", done);
		});

		it('should handle a list of numbers and strings', function (done) {
			compareResults("[3, 4, -2, \"5.5\", 0.5, 0.32]", done);
		});

		it('should handle a list of numbers, strings, and booleans', function (done) {
			compareResults("[3, 4, -2, \"5.5\", 0.5, false]", done);
		});

		it('should handle a list of numbers, strings, and booleans', function (done) {
			compareResults('["some text", 4, "some more text", "text"]', done);
		});

		it('should handle a list of numbers, strings, and booleans', function (done) {
			compareResults('["[],4,5", "false", ","]', done);
		});

		it('should handle an object with mixed values', function (done) {
			compareResults('{ "test": 56, "test2": "hello!", "test3": false }', done);
		});

		it('should handle an object with list values', function (done) {
			compareResults('{ "test": [3, "str", false, 0.5], "test2": [1, 2, "str2"] }', done);
		});

		it('should handle embedded objects', function (done) {
			compareResults('{ "test": { "test": [1, 2, 3] } }', done);
		});

		it('should handle embedded lists', function (done) {
			compareResults('[1, 2, [3, 4], 5]', done);
		});

		it('should handle embedded lists when the first item is a list', function (done) {
			compareResults('[[1, false], 2, [3, 4], 5]', done);
		});

		it('should handle objects embedded in lists', function (done) {
			compareResults('[2, {"test": "str"}]', done);
		});

		it('should handle objects embedded in lists', function (done) {
			compareResults('[{"test": "str"}, 2, [3, {"test2": "str2"}], 5]', done);
		});

		it('should handle a complex JSON structure', function (done) {
			compareResults('[{"test": "str"}, [2, false, 0.4], [3, {"test2": ["str2", 6]}], 5]', done);
		});

		it('should handle a complex JSON structure', function (done) {
			compareResults('[{"test": "str"}, [2, false, ",", 0.4, "[val]"], [3, {"test2": ["str2", 6]}], 5]', done);
		});

		it('should handle nulls in lists', function (done) {
			compareResults("[null]", done);
		});

		it('should handle nulls in objects', function (done) {
			compareResults("{ \"test\": null}", done);
		});

	});

	describe("parse() on invalid JSON", function () {
		it('should handle non-quoted object keys', function(done) {
			compareResultsToValid('{test: 5}', '{"test": 5}', done);
		});

		it('should handle single-quoted object keys', function(done) {
			compareResultsToValid('{\'test\': 5}', '{"test": 5}', done);
		});

		it('should handle single-quoted object values', function(done) {
			compareResultsToValid('{\'test\': \'5\'}', '{"test": "5"}', done);
		});

		it('should handle quotes-in-quotes (list)', function(done) {
			compareResultsToValid('["some "quoted" text"]', '["some \\"quoted\\" text"]', done);
		});

		it('should handle quotes-in-quotes (list)', function(done) {
			compareResultsToValid('[3, "some "quoted" text", 2]', '[3, "some \\"quoted\\" text", 2]', done);
		});

		it('should handle quotes-in-quotes (object)', function(done) {
			compareResultsToValid('{"test": "some "quoted" text"}', '{"test": "some \\"quoted\\" text"}', done);
		});

		it('should handle quotes-in-quotes (object)', function(done) {
			compareResultsToValid('{"test0": false, "test": "some "quoted" text", "test1": 5}', '{"test0": false, "test": "some \\"quoted\\" text", "test1": 5}', done);
		});

		describe("with new lines", function() {
			it ('should handle a newline in a string in object', function(done) {

				dJSON.parse('{ "test0": "a '+"\n"+'string" }').then(function (r) {
					assert.equal(r.test0, 'a '+"\n"+'string');
				}).then(done, done);
			});

			it ('should handle a newline in a string in a list', function(done) {

				dJSON.parse('["a '+"\n"+'string"]').then(function (r) {
					assert.equal(r[0], 'a '+"\n"+'string');
				}).then(done, done);
			});

			it('should handle newline in misquoted string in object', function(done) {
				var str = 'this\n"quote"\ntext';
				dJSON.parse('{ "test0": "' + str + '"}').then(function (r) {
					assert.equal(r.test0, str);
				}).then(done, done);
			});

			it('should handle newline in misquoted string in object', function(done) {
				var str = 'this\n"quote"\ntext';
				dJSON.parse('{ "test1": false, "test0": "' + str + '", test2: 5.5}').then(function (r) {
					assert.equal(r.test0, str);
					assert.equal(r.test1, false);
					assert.equal(r.test2, 5.5);
				}).then(done, done);
			});

			it('should handle newline in misquoted string in list', function(done) {
				var str = 'this\n"quote"\ntext';
				dJSON.parse('["' + str + '"]').then(function (r) {
					assert.equal(r[0], str);
				}).then(done, done);
			});

			it('should handle newline in misquoted string in list', function(done) {
				var str = 'this\n"quote"\ntext';
				dJSON.parse('[5, 6, "' + str + '", "test"]').then(function (r) {
					assert.equal(r[2], str);
					assert.equal(r[0], 5);
					assert.equal(r[1], 6);
					assert.equal(r[3], "test");
				}).then(done, done);
			});
		});

		describe("with embedded HTML", function() {
			it('should handle an embedded DIV tag', function(done) {
				dJSON.parse('["
some text
"]').then(function (r) {
					assert.equal(r[0], '
some text
');
					assert.equal(r.length, 1);
				}).then(done, done);
			});

			it('should handle an embedded span tag', function(done) {
				dJSON.parse('["some text"]').then(function (r) {
					assert.equal(r[0], 'some text');
					assert.equal(r.length, 1);
				}).then(done, done);
			});

			it('should handle an embedded span tag in a div tag', function(done) {
				dJSON.parse('["
some text
"]').then(function (r) {
					assert.equal(r[0], '
some text
');
					assert.equal(r.length, 1);
				}).then(done, done);
			});
		});

	});
});
<|endoftext|>


<commit_before>module.exports = (function(){

    var jcon = require('../src/jcon');

    var p1 = jcon.string('1');
    var p2 = jcon.string('2');
    var p3 = jcon.string('3');
    var p4 = jcon.string('4');

    return {
        seq: function(test){

            test.deepEqual(p1.seq(p2).parse('12').value, ['1','2'], 'seq ok!');
            test.deepEqual(p1.seq(p2, p3).parse('123').value, ['1', '2', '3'], 'seq ok!');
            test.deepEqual(p1.seq(p2, p3).seq(p4).parse('1234').value, ['1', '2', '3', '4'], 'seq ok!');

            test.done();
        },
        or: function(test){

            test.equal(p1.or(p2, p3).parse('3').value, '3', 'or ok!');
            test.equal(p1.or(p2,p3).or(p4).parse('4').value, '4', 'or ok!');

            test.done();

        },
        times: function(test){
        },
        least: function(test){
        },
        most: function(test){
        },
        many: function(test){
        },
        process: function(test){
        },
        joinValue: function(test){
        }
    };
}());
<commit_msg>调整seq的测试用例代码，暂时不调整seq组合子中的代码为对被组合解析器的结果进行平坦化<commit_after>module.exports = (function(){

    var jcon = require('../src/jcon');

    var p1 = jcon.string('1');
    var p2 = jcon.string('2');
    var p3 = jcon.string('3');
    var p4 = jcon.string('4');

    return {
        seq: function(test){

            test.deepEqual(p1.seq(p2).parse('12').value, ['1','2'], 'seq ok!');
            test.deepEqual(p1.seq(p2, p3).parse('123').value, ['1', '2', '3'], 'seq ok!');

            //seq创建的parser，会创建一层数组结构，将被连接的多个parser的result.value置为数组成员
            //所以每次对seq的调用，都会创建一层数组结构，形成多层深的数组
            test.deepEqual(p1.seq(p2, p3).seq(p4).parse('1234').value, [['1', '2', '3'], '4'], 'seq ok!');

            test.done();
        },
        or: function(test){

            test.equal(p1.or(p2, p3).parse('3').value, '3', 'or ok!');
            test.equal(p1.or(p2,p3).or(p4).parse('4').value, '4', 'or ok!');

            test.done();

        },
        times: function(test){
            test.done();
        },
        least: function(test){
        },
        most: function(test){
        },
        many: function(test){
        },
        process: function(test){
        },
        joinValue: function(test){
        }
    };
}());
<|endoftext|>


<commit_before>const sinon = require('sinon')
const expect = require('chai').expect
const passthrough = require('../lib/passthrough')

suite('passthrough', function () {
  const passes = passthrough.passes

  function restore() {
    passthrough.passes = passes
  }

  test('sequentially', function (done) {
    var delay = Date.now() - 10

    function pass(text, next) {
      var now = Date.now()
      expect(text).to.be.equal('hello')
      expect((now - delay) >= 10).to.be.true
      delay = Date.now()
      setTimeout(next, 10)
    }

    const args = [ 'hello' ]
    passthrough.passes = [ pass, pass, pass ]
    passthrough.sequentially(args, done)
  })

  test('concurrently', function (done) {
    var start = Date.now()

    function pass(text, next) {
      expect(text).to.be.equal('hello')
      setTimeout(next, 5)
    }

    const args = [ 'hello' ]
    passthrough.passes = [ pass, pass, pass ]
    passthrough.concurrently(args, function (err) {
      expect((Date.now() - start) <= 10).to.be.true
      restore()
      done(err)
    })
  })
})
<commit_msg>fix(test): increase timer delay<commit_after>const sinon = require('sinon')
const expect = require('chai').expect
const passthrough = require('../lib/passthrough')

suite('passthrough', function () {
  const passes = passthrough.passes

  function restore() {
    passthrough.passes = passes
  }

  test('sequentially', function (done) {
    var delay = Date.now() - 10

    function pass(text, next) {
      var now = Date.now()
      expect(text).to.be.equal('hello')
      expect((now - delay) >= 10).to.be.true
      delay = Date.now()
      setTimeout(next, 10)
    }

    const args = [ 'hello' ]
    passthrough.passes = [ pass, pass, pass ]
    passthrough.sequentially(args, done)
  })

  test('concurrently', function (done) {
    var start = Date.now()

    function pass(text, next) {
      expect(text).to.be.equal('hello')
      setTimeout(next, 5)
    }

    const args = [ 'hello' ]
    passthrough.passes = [ pass, pass, pass ]
    passthrough.concurrently(args, function (err) {
      expect((Date.now() - start)).to.lower(12)
      restore()
      done(err)
    })
  })
})
<|endoftext|>


<commit_before><commit_msg>chore(eslint): accepts the usage of bitwise<commit_after><|endoftext|>


<commit_before>// For every change on inputs and select with attr data-refreshOnChange
$(document).on(
    'change',
    'select[data-refreshOnChange="true"], ' +
    'input:checkbox[data-refreshOnChange="true"], ' +
    'input:radio[data-refreshOnChange="true"]',
    function(event) {
        var form = $(this).parents('form');
        var formdata = (window.FormData) ? new FormData(form[0]) : null;
        var data = (formdata !== null) ? formdata : form.serialize();
        var ignoredChanges = {};
        $(form).find('[data-ignoreonchange]').each(function (idx, elem) {
            var $elem = $(elem);
            ignoredChanges[$elem.attr('data-ignoreonchange')] = $elem;
        });
        $.ajax({
            url         : form.attr('action') + (form.attr('action').split('?')[1] ? '&' : '?') + 'novalidate',
            data        : data,
            type        : $(form).attr('method'),
            contentType : false,
            dataType    : 'json',
            processData : false,
        }).done(function(response){
            if (typeof response === 'object' && response.hasOwnProperty("html")) {
                form.html(response.html);
            } else {
                form.html(response);
            }
            $.each(ignoredChanges, function(index, elem){
                $('[data-ignoreonchange="' + index + '"]').replaceWith(elem);
            });
        }).fail(function(response) {
            console.log(response);
        });
    }
);
<commit_msg>deal with update strategy and use complete instead of done and fail which are not working properly<commit_after>// For every change on inputs and select with attr data-refreshOnChange
$(document).on(
    'change',
    'select[data-refreshOnChange="true"], ' +
    'input:checkbox[data-refreshOnChange="true"], ' +
    'input:radio[data-refreshOnChange="true"]',
    function(event) {
        var form = $(this).parents('form');
        var formdata = (window.FormData) ? new FormData(form[0]) : null;
        var data = (formdata !== null) ? formdata : form.serialize();
        var ignoredChanges = {};
        var updateStrategy = "html";
        if ($(this).data('update-strategy')) {
            updateStrategy = $(this).data('update-strategy');
        }
        $(form).find('[data-ignoreonchange]').each(function (idx, elem) {
            var $elem = $(elem);
            ignoredChanges[$elem.attr('data-ignoreonchange')] = $elem;
        });
        $.ajax({
            url         : form.attr('action') + (form.attr('action').split('?')[1] ? '&' : '?') + 'novalidate',
            data        : data,
            type        : $(form).attr('method'),
            contentType : false,
            dataType    : 'json',
            processData : false
        }).complete(function(response){
            if (typeof response === 'object' && response.hasOwnProperty("html")) {
                newForm = response.html;
            } else {
                newForm = response.responseText;
            }
            eval('form.' + updateStrategy + '(newForm)');
            $.each(ignoredChanges, function(index, elem){
                $('[data-ignoreonchange="' + index + '"]').replaceWith(elem);
            });
        });
    }
);
<|endoftext|>


<commit_before>const debug = require('debug')('hops:development-proxy');
const {
  Mixin,
  strategies: {
    sync: { sequence },
  },
} = require('hops-mixin');
const proxy = require('http-proxy-middleware');

class ProxyMixin extends Mixin {
  configureServer(app, middlewares) {
    const proxyConfig = this.config.proxy;

    if (process.env.NODE_ENV === 'production' || !proxyConfig) {
      return;
    }

    const options = {
      changeOrigin: true,
      logLevel: 'warn',
      onProxyReq: this.onProxyReq,
      onProxyRes: this.onProxyRes,
      onError: this.onProxyError,
    };

    if (typeof proxyConfig === 'string') {
      if (proxyConfig === '') {
        console.warn('The proxy target is empty, disabling feature');

        return;
      }

      debug('Using proxy string version: ', proxyConfig);

      middlewares.initial.push(
        proxy(
          (pathName, req) => {
            return (
              req.headers.accept && !req.headers.accept.includes('text/html')
            );
          },
          {
            ...options,
            target: proxyConfig,
          }
        )
      );
    }

    if (typeof proxyConfig === 'object') {
      debug('Using proxy object version', proxyConfig);

      Object.entries(proxyConfig).forEach(([path, config]) => {
        const { target, routes } =
          typeof config === 'string' ? { target: config } : config;

        if (target === '') {
          console.warn('The proxy target is empty, ignoring path', path);

          return;
        }

        middlewares.initial.push(
          proxy(path, {
            ...options,
            target,
            routes,
          })
        );
      });
    }
  }
}

ProxyMixin.strategies = {
  onProxyReq: sequence,
  onProxyRes: sequence,
  onProxyError: sequence,
};
module.exports = ProxyMixin;
<commit_msg>feat(development-proxy): check for full URLs<commit_after>const debug = require('debug')('hops:development-proxy');
const {
  Mixin,
  strategies: {
    sync: { sequence },
  },
} = require('hops-mixin');
const proxy = require('http-proxy-middleware');

const checkUrl = url => /^https?:\/\//.test(url);

class ProxyMixin extends Mixin {
  configureServer(app, middlewares) {
    const proxyConfig = this.config.proxy;

    if (process.env.NODE_ENV === 'production' || !proxyConfig) {
      return;
    }

    const options = {
      changeOrigin: true,
      logLevel: 'warn',
      onProxyReq: this.onProxyReq,
      onProxyRes: this.onProxyRes,
      onError: this.onProxyError,
    };

    if (typeof proxyConfig === 'string') {
      if (!checkUrl(proxyConfig)) {
        console.warn(
          `The proxy target '${proxyConfig}' is invalid, disabling feature`
        );

        return;
      }

      debug('Using proxy string version', proxyConfig);

      middlewares.initial.push(
        proxy(
          (pathName, req) => {
            return (
              req.headers.accept && !req.headers.accept.includes('text/html')
            );
          },
          {
            ...options,
            target: proxyConfig,
          }
        )
      );
    }

    if (typeof proxyConfig === 'object') {
      debug('Using proxy object version', proxyConfig);

      Object.entries(proxyConfig).forEach(([path, config]) => {
        const { target, routes } =
          typeof config === 'string' ? { target: config } : config;

        if (target === '') {
          console.warn(
            `The proxy target '${target}' is invalid, ignoring path`,
            path
          );

          return;
        }

        middlewares.initial.push(
          proxy(path, {
            ...options,
            target,
            routes,
          })
        );
      });
    }
  }
}

ProxyMixin.strategies = {
  onProxyReq: sequence,
  onProxyRes: sequence,
  onProxyError: sequence,
};
module.exports = ProxyMixin;
<|endoftext|>


<commit_before>//based on and inspired by https://github.com/andris9/pubsubhubbub
// customised to work with Meteor and within Simple_RSS app

var Stream = Npm.require( 'stream').Stream,
  PubSubHubbub = Npm.require("pubsubhubbub"),
  resumer = Npm.require("resumer"),
  urlParse = Npm.require( 'url' ).parse,
  Future = Npm.require( 'fibers/future');

// a PuSH subcription manager that wraps
FeedSubscriber = class FeedSubscriber extends Stream {
  constructor ( options ) {
    var self = this;

    // The 'pubsubhubbub' module only exports createServer().
    // Otherwise the manager could inherit from it.
    // With inheritence no need for own subscribe and unsubscribe methods.
    self.server = PubSubHubbub.createServer( options );
    var server = self.server;

    if ( ! (self instanceof FeedSubscriber) )
      throw new Error('use "new" to construct a FeedSubscriber');

    self.subscriptions = new Map([]);

    WebApp.connectHandlers.use(
      urlParse( server.callbackUrl ).pathname,
      function (req, res, next) {
        if(req.method === 'POST')
          return  server._onPostRequest(req, res);
        if(req.method === 'GET')
          return server._onGetRequest(req, res);

        return server._sendError(req, res, 405, "Method Not Allowed");
      }
    );
    self.startEventListeners();
  }

  startEventListeners() {
    var self = this;
    var server = self.server;

    server.on( 'feed', data => {
      var stream = resumer().queue( data.feed ).end();
      self.emit( 'feedStream', stream, data.topic );
    });

    // check that subscribe events match our requests and manage subscriptions object
    // create resubscription event 6 hours before expected expiry
    server.on ( 'subscribe' ,  data => {
      var interval,
      fn,
      sub = self.subscriptions.get( data.topic );

      if ( sub ){
        sub.expiry = new Date( data.lease * 1000 );
        sub.resub && clearTimeout( sub.resub );
        console.log (["subscribed to : ", data.hub, " : ", data.topic, " : ", sub.expiry].join());
        //  interval in ms with plan to resubscribe 6 hours before expiry
        interval =  sub.expiry - new Date().getTime() - 6 * 60 * 60 * 1000;
        sub.resub = setTimeout( () => {
          sub.unsub = new Future();
          server.unsubscribe( data.topic, data.hub );
          server.subscribe( data.topic, data.hub );
        }, interval );
      } else {
        console.error("unmatched subscription: " + data.topic);
      }
    });

    // check that unsubscribe events match our requests and manage subscriptions object
    self.on ( 'unsubscribe' ,  data => {
      var sub = self.subscriptions.get( data.topic );
      if ( sub && sub.unsub ){
        if (sub.unsub instanceof Future)
          sub.unsub.return( data );
        console.log(" unsubscribed from : " + data.topic);
        self.subscriptions.delete( data.topic );
      } else {
        console.error("resubscribing to: " + data.topic);
        server.subscribe( data.topic, data.hub );
      }
    });
  }

  // stop all subscriptions with one synchronous call
  stopAllSubscriptions() {
    var self = this;
    self.subscriptions.forEach( (sub) => {
      sub.unsub =  new Future();
      self.server.unsubscribe( sub.url, sub.hub );
    });
    self.subscriptions.forEach( (sub) => sub.unsub.wait());
  }

  subscribe( url, hub, _id ) {
    var self = this;
    self.subscriptions.set(url,{url, hub, _id});
    self.server.subscribe( url, hub );
  }

  unsubscribe( url, hub ) {
    var self = this;
    var sub = self.subscriptions.get(url);
    if ( sub ) sub.unsub = new Future;
    self.server.unsubscribe( url, hub );
  }
}
<commit_msg>super error<commit_after>//based on and inspired by https://github.com/andris9/pubsubhubbub
// customised to work with Meteor and within Simple_RSS app

var Stream = Npm.require( 'stream').Stream,
  PubSubHubbub = Npm.require("pubsubhubbub"),
  resumer = Npm.require("resumer"),
  urlParse = Npm.require( 'url' ).parse,
  Future = Npm.require( 'fibers/future');

// a PuSH subcription manager that wraps
FeedSubscriber = class FeedSubscriber extends Stream {
  constructor ( options ) {
    super.call(this);
    var self = this;

    // The 'pubsubhubbub' module only exports createServer().
    // Otherwise the manager could inherit from it.
    // With inheritence no need for own subscribe and unsubscribe methods.
    self.server = PubSubHubbub.createServer( options );
    var server = self.server;

    if ( ! (self instanceof FeedSubscriber) )
      throw new Error('use "new" to construct a FeedSubscriber');

    self.subscriptions = new Map([]);

    WebApp.connectHandlers.use(
      urlParse( server.callbackUrl ).pathname,
      function (req, res, next) {
        if(req.method === 'POST')
          return  server._onPostRequest(req, res);
        if(req.method === 'GET')
          return server._onGetRequest(req, res);

        return server._sendError(req, res, 405, "Method Not Allowed");
      }
    );
    self.startEventListeners();
  }

  startEventListeners() {
    var self = this;
    var server = self.server;

    server.on( 'feed', data => {
      var stream = resumer().queue( data.feed ).end();
      self.emit( 'feedStream', stream, data.topic );
    });

    // check that subscribe events match our requests and manage subscriptions object
    // create resubscription event 6 hours before expected expiry
    server.on ( 'subscribe' ,  data => {
      var interval,
      fn,
      sub = self.subscriptions.get( data.topic );

      if ( sub ){
        sub.expiry = new Date( data.lease * 1000 );
        sub.resub && clearTimeout( sub.resub );
        console.log (["subscribed to : ", data.hub, " : ", data.topic, " : ", sub.expiry].join());
        //  interval in ms with plan to resubscribe 6 hours before expiry
        interval =  sub.expiry - new Date().getTime() - 6 * 60 * 60 * 1000;
        sub.resub = setTimeout( () => {
          sub.unsub = new Future();
          server.unsubscribe( data.topic, data.hub );
          server.subscribe( data.topic, data.hub );
        }, interval );
      } else {
        console.error("unmatched subscription: " + data.topic);
      }
    });

    // check that unsubscribe events match our requests and manage subscriptions object
    self.on ( 'unsubscribe' ,  data => {
      var sub = self.subscriptions.get( data.topic );
      if ( sub && sub.unsub ){
        if (sub.unsub instanceof Future)
          sub.unsub.return( data );
        console.log(" unsubscribed from : " + data.topic);
        self.subscriptions.delete( data.topic );
      } else {
        console.error("resubscribing to: " + data.topic);
        server.subscribe( data.topic, data.hub );
      }
    });
  }

  // stop all subscriptions with one synchronous call
  stopAllSubscriptions() {
    var self = this;
    self.subscriptions.forEach( (sub) => {
      sub.unsub =  new Future();
      self.server.unsubscribe( sub.url, sub.hub );
    });
    self.subscriptions.forEach( (sub) => sub.unsub.wait());
  }

  subscribe( url, hub, _id ) {
    var self = this;
    self.subscriptions.set(url,{url, hub, _id});
    self.server.subscribe( url, hub );
  }

  unsubscribe( url, hub ) {
    var self = this;
    var sub = self.subscriptions.get(url);
    if ( sub ) sub.unsub = new Future;
    self.server.unsubscribe( url, hub );
  }
}
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import IconColorful from '../../content/IconColorful/IconColorful'

const FooterContent = styled.div`
  flex-grow: 1;
  padding: 0 0 0 84.7px;

  & a {
    font-family: 'Nunito Sans', sans-serif;
    font-size: 13px;
    font-weight: 800;
    text-transform: uppercase;
    text-decoration: none;
    margin-right: 35px;
    color: #fff;

    &:hover {
      text-decoration: underline;
    }
  }
`

const Footer = styled(({ children, className, btnHelpLabel, btnHelpClick }) => (

    <IconColorful name='bonde' size={115} inverted />
    <FooterContent>
    {children}
    </FooterContent>

))`
  ${props => props.fixed && `
    position: absolute;
    bottom: 0;
  `}
  display: flex;
  align-items: center;
  height: 94px;
  background: #000;
  padding: 0 150px;
  overflow: hidden;
  width: auto;
`

const { oneOfType, node, func, string } = PropTypes

Footer.propTypes = {
  /** The content of the footer. */
  children: oneOfType([node, func]),
  /** The help button label text. */
  btnHelpLabel: string,
  /** The help button onClick event handler function. */
  btnHelpClick: func
}

Footer.displayName = 'Footer'

/** @component */
export default Footer
<commit_msg>fix(styleguide): full size when fixed footer<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import IconColorful from '../../content/IconColorful/IconColorful'

const FooterContent = styled.div`
  flex-grow: 1;
  padding: 0 0 0 84.7px;

  & a {
    font-family: 'Nunito Sans', sans-serif;
    font-size: 13px;
    font-weight: 800;
    text-transform: uppercase;
    text-decoration: none;
    margin-right: 35px;
    color: #fff;

    &:hover {
      text-decoration: underline;
    }
  }
`

const Footer = styled(({ children, className, btnHelpLabel, btnHelpClick }) => (

    <IconColorful name='bonde' size={115} inverted />
    <FooterContent>
    {children}
    </FooterContent>

))`
  ${props => props.fixed && `
    position: absolute;
    bottom: 0;
  `}
  display: flex;
  align-items: center;
  height: 94px;
  background: #000;
  padding: 0 150px;
  overflow: hidden;
  width: ${props => props.fixed ? '100%' : 'auto'};
`

const { oneOfType, node, func, string } = PropTypes

Footer.propTypes = {
  /** The content of the footer. */
  children: oneOfType([node, func]),
  /** The help button label text. */
  btnHelpLabel: string,
  /** The help button onClick event handler function. */
  btnHelpClick: func
}

Footer.displayName = 'Footer'

/** @component */
export default Footer
<|endoftext|>


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

FilooFiloo.creditsPage = SC.Page.design(
  {

  mainView: SC.LabelView.design({
    layout: FilooFiloo.Layout.MAIN_VIEW,
    classNames: ['main-view', 'information'],
    escapeHTML: NO,
    value: "
Contributors

This game was done by Philippe Bourgau, 2008-2010.

Licence

GNU Affero General Public License, the code can be found here.

Main third parties

Sproutcore

Rails

POV Ray

"
  })
});
<commit_msg>Updated the credit page<commit_after>// ==========================================================================
// Project:   FilooFiloo - credits page
// Copyright: ©2008-2010 Philippe Bourgau, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
//
// ==========================================================================
/*globals FilooFiloo */

FilooFiloo.creditsPage = SC.Page.design(
  {

  mainView: SC.LabelView.design({
    layout: FilooFiloo.Layout.MAIN_VIEW,
    classNames: ['main-view', 'information'],
    escapeHTML: NO,
    value: "
Contributors

This game was done by Philippe Bourgau, 2008-2010.

Licence

GNU Affero general Public License v3, the code can be found on github.

Main third parties

Sproutcore

Sinatra

POV Ray

Feedback

filoo-filoo@gmail.com
"
  })
});
<|endoftext|>


<commit_before>(function(){
    'use strict';

    describe('angular-queue', function() {

        var $queue,
            $timeout,
            myQueue,
            result,
            myCallback = function(item) {
                //console.log('Callback: ', item);
                result.push(item);
            };

        beforeEach(function() {
            result = [];
            module('ngQueue');
            inject(function($injector) {
                $queue = $injector.get('$queue');
                $timeout = $injector.get('$timeout');
                myQueue = $queue.queue({
                    callback: myCallback
                });
            });
        });

        describe('#queue', function() {
            it('Should throw exception when no callback is specified',
                function() {
                    expect($queue.queue).toThrow();
                }
            );

            it('Should make a new Queue', function() {
                var aQueue = $queue.queue({callback: myCallback});
                expect(aQueue).not.toBe(null);
            });
        });

        it('should work', function() {

            var names = ['james', 'tom', 'joe', 'mike', 'ryan'];
            myQueue.addEach(names);
            for (var i = 0; i < names.length; i++) {
                //Must call flush once per delay
                $timeout.flush();
            }

            expect(result.length).toEqual(5);

            // myQueue.add('james');
            // myQueue.add('tom');
            // myQueue.add('taylor');
            // myQueue.add('patrick');
            // myQueue.add('joe');
            // for (var j = 0; j < names.length; j++) {
            //     $timeout.flush();
            // }
        });
    });
})();<commit_msg>Finished test coverage<commit_after>(function() {
    'use strict';

    describe('angular-queue', function() {

        var $queue,
            $timeout,
            myQueue,
            result,
            myCallback = function(item) {
                result.push(item);
            };

        beforeEach(function() {
            result = [];
            module('ngQueue');
            inject(function($injector) {
                $queue = $injector.get('$queue');
                $timeout = $injector.get('$timeout');
                myQueue = $queue.queue(myCallback);
            });
        });

        describe('Constructor', function() {
            it('Should throw exception when no callback is specified',
                function() {
                    expect($queue.queue).toThrow();
                }
            );

            it('Should make a new Queue', function() {
                var aQueue = $queue.queue(myCallback);
                expect(aQueue).toBeDefined();
                expect(aQueue.queue).toBeDefined();
            });
        });

        describe('#pause', function() {
            it('Should pause the queue', function() {
                myQueue.pause();
                expect(myQueue.paused).toBeTruthy();
            });
        });

        describe('#start', function() {
            it('Should unpause the queue', function() {
                myQueue.pause();
                expect(myQueue.paused).toBeTruthy();
                myQueue.start();
                expect(myQueue.paused).toBeFalsy();
            });
        });

        describe('#add', function() {
            it('Should add an item to the queue', function() {
                myQueue.pause();
                expect(myQueue.queue.length).toEqual(0);
                expect(myQueue.add('item')).toEqual(1);
                expect(myQueue.queue.length).toEqual(1);
                expect(myQueue.queue[0]).toEqual('item');
            });
        });

        describe('#size', function() {
            it('Should return the number of items in the queue', function() {
                myQueue.pause();
                expect(myQueue.size()).toEqual(0);
                myQueue.add('an item');
                expect(myQueue.size()).toEqual(1);
                myQueue.add('another item');
                expect(myQueue.size()).toEqual(2);
            });
        });

        describe('#addEach', function() {
            it('Should add an array of items to the queue', function() {
                myQueue.pause();
                myQueue.addEach(['tom', 'joe', 'mike']);
                expect(myQueue.size()).toEqual(3);
                expect(myQueue.queue[1]).toEqual('joe');
            });
        });

        describe('#clear', function() {
            it('Should clear the queue', function() {
                myQueue.pause();
                myQueue.add('item');
                myQueue.clear();
                expect(myQueue.size()).toEqual(0);
            });
        });

        describe('Queue processing', function() {
            it('Should process items via the provided callback', function() {
                expect(result.length).toEqual(0);
                var names = ['james', 'tom', 'joe', 'mike', 'ryan'];
                myQueue.addEach(names);
                for (var i = 0; i < names.length; i++) {
                    //Must call flush once per delay
                    $timeout.flush();
                    //Result is pushed items via myCallback
                    expect(result[i]).toEqual(names[i]);
                }
            });

            it('Should call the complete callback when finished', function() {

                var hasCompleted = false,
                    onComplete = function() {
                        hasCompleted = true;
                    },
                    aQueue = $queue.queue(myCallback, {complete: onComplete});

                aQueue.add('item');
                $timeout.flush();
                expect(hasCompleted).toBeTruthy();
            });
        });

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


<commit_before>'use strict';

import dom from 'bower:metal/src/dom/dom';
import Scrollspy from '../src/Scrollspy';

var spy;
var element;
var scrollElement;

describe('Scrollspy', function() {
	before(function() {
		dom.enterDocument('