<commit_before>var slug               = require('slug');
var models             = require('../../models');
var imagesTypes        = require('../../models/image/imageTypes.json');
var sortTypes          = require('../../models/customSort/sortTypes.json');
var forbiddenUsernames = require('../../helpers/user/forbiddenUsernames.json');
var imageUpdloader     = require('../../helpers/image-uploader');
var updateEmail        = require('../../helpers/user/updateEmail');

var createUser = function(req, profile, accessToken, strategy, callback){
    var sess = req.session;
    var newUser = new models.User();
    var profileEmail = profile.emails[0].value;

    //check if email alreday used
    models.User.findOne({email: profileEmail.toLowerCase()}, function(err, user){
        if(err) {console.log(err); return callback(err)}
        if(user) return callback("email already used");

        newUser[strategy].id = profile.id;
        newUser[strategy].token = accessToken;

        if(profile.displayName){
            var slugDdisplayName = slug(profile.displayName, '-');
            newUser.unsafeUsername = (forbiddenUsernames.indexOf(slugDdisplayName.toLowerCase()) > -1 ) ? 'forbidden-name' : slugDdisplayName;
        }else{
            newUser.unsafeUsername = 'anonyme';
        }
        newUser.name = (profile.displayName || 'anonyme');
        newUser.roles = ['ROLE_USER'];
        newUser.language = (sess.language || 'en');

        createAvatar(newUser, profile, function(image){
            var avatar = image;
            newUser._avatar = avatar._id;

            newUser.save(function(err){
                if (err) { return callback(err); }
                updateEmail.update(newUser, profileEmail, function(err, newUser){
                    if (err) { return callback(err); }
                    avatar.save(function(err){
                        if (err) { return callback(err); }
                        newUser._avatar = avatar;
                        createMyCollectionSort(newUser, function(err){
                            if (err) { return callback(err); }
                            callback(null, newUser);
                        })
                    });
                });
            })
        });

    })
}

function createMyCollectionSort(newUser, callback){
    var myCollectionSort = new models.CustomSort();
    myCollectionSort.type = sortTypes.MY_COLLECTIONS.id;
    myCollectionSort._user = newUser._id;
    myCollectionSort.save(function(err){
        callback(err)
    });
}

function createAvatar(newUser, profile, callback){
    var image = new models.Image();
    image.type = imagesTypes.AVATAR.name;
    image.mime = 'jpg';
    image._user = newUser._id;
    if(profile.photos[0]){
        imageUpdloader.getSocialNetworkAvatar(image, profile.photos[0].value,function(err){
            callback(image);
        });
    }else{
        callback(image);
    }
}

module.exports = {
  createUser: createUser,
};
<commit_msg>server side: fix user create from social when no email<commit_after>var slug               = require('slug');
var models             = require('../../models');
var imagesTypes        = require('../../models/image/imageTypes.json');
var sortTypes          = require('../../models/customSort/sortTypes.json');
var forbiddenUsernames = require('../../helpers/user/forbiddenUsernames.json');
var imageUpdloader     = require('../../helpers/image-uploader');
var updateEmail        = require('../../helpers/user/updateEmail');

var createUser = function(req, profile, accessToken, strategy, callback){
    var sess = req.session;
    var newUser = new models.User();
    var emailArray = profile.emails;
    var profileEmail;
    if(profile.emails.length > 0)
        profileEmail = profile.emails[0].value;
    else
        profileEmail = '';

    //check if email alreday used
    models.User.findOne({email: profileEmail.toLowerCase()}, function(err, user){
        if(err) {console.log(err); return callback(err)}
        if(user) return callback("email already used");

        newUser[strategy].id = profile.id;
        newUser[strategy].token = accessToken;

        if(profile.displayName){
            var slugDdisplayName = slug(profile.displayName, '-');
            newUser.unsafeUsername = (forbiddenUsernames.indexOf(slugDdisplayName.toLowerCase()) > -1 ) ? 'forbidden-name' : slugDdisplayName;
        }else{
            newUser.unsafeUsername = 'anonyme';
        }
        newUser.name = (profile.displayName || 'anonyme');
        newUser.roles = ['ROLE_USER'];
        newUser.language = (sess.language || 'en');

        createAvatar(newUser, profile, function(image){
            var avatar = image;
            newUser._avatar = avatar._id;

            newUser.save(function(err){
                if (err) { return callback(err); }

                //if no email
                if(profileEmail != ''){
                    updateEmail.update(newUser, profileEmail, function(err, newUser){
                        if (err) { return callback(err); }
                        avatar.save(function(err){
                            if (err) { return callback(err); }
                            newUser._avatar = avatar;
                            createMyCollectionSort(newUser, function(err){
                                if (err) { return callback(err); }
                                callback(null, newUser);
                            })
                        });
                    });
                }else{
                    avatar.save(function(err){
                        if (err) { return callback(err); }
                        newUser._avatar = avatar;
                        createMyCollectionSort(newUser, function(err){
                            if (err) { return callback(err); }
                            callback(null, newUser);
                        })
                    });
                }

            })
        });

    })
}

function createMyCollectionSort(newUser, callback){
    var myCollectionSort = new models.CustomSort();
    myCollectionSort.type = sortTypes.MY_COLLECTIONS.id;
    myCollectionSort._user = newUser._id;
    myCollectionSort.save(function(err){
        callback(err)
    });
}

function createAvatar(newUser, profile, callback){
    var image = new models.Image();
    image.type = imagesTypes.AVATAR.name;
    image.mime = 'jpg';
    image._user = newUser._id;
    if(profile.photos[0]){
        imageUpdloader.getSocialNetworkAvatar(image, profile.photos[0].value,function(err){
            callback(image);
        });
    }else{
        callback(image);
    }
}

module.exports = {
  createUser: createUser,
};
<|endoftext|>


<commit_before>var Client = require("./client");
var fs = require("fs");
var superagent = require("superagent");
var errors = require("./errors");
var MEDIA_PATH = "media";

function sendFile(request, file, mediaType, callback) {
	var stream = null;
	request.buffer().type(mediaType || "application/octet-stream");
	if (typeof file === "string") {
		stream = fs.createReadStream(file);
	}
	else if (Buffer.isBuffer(file)) {
		request.set("Content-Length", file.length);
		request.write(file);
		request.end(callback);
		return;
	}
	else if (typeof file.pipe === "function" && typeof file.read === "function" && typeof file.on === "function") {
		stream = file;
	}
	if (stream) {
		//  request.on("response") sometimes could not be called
		request.req.on("response", function (res) {
			request.res = res;
			var response = new superagent.Response(request);
			callback(response);
		});
		stream.pipe(request);
		return;
	}

	callback({ statusCode : 400, text : "Invalid data to send", body : { message : "Invalid data to send" } });
}

module.exports = {
	/**
	 * Get a list of your media files
	 * @param client Client instance
	 * @param query query parameters
	 * @param callback callback function
	 * @example
	 * bandwidth.Media.list(client, function(err, list){});
	 */
	list : function (client, query, callback) {
		if (arguments.length === 1) {
			callback = client;
			client = new Client();
		}
		else if (arguments.length === 2) {
			callback = query;
			if (client instanceof Client) {
				query = {};
			}
			else {
				query = client;
				client = new Client();
			}
		}

		client.makeRequest("get", client.concatUserPath(MEDIA_PATH), query, callback);
	},

	/**
	 * Uploads a media file (or stream, or buffer) to the name you choose
	 * @param client Client instance
	 * @param name file name
	 * @param mediaTypr media type of file
	 * @param callback callback function
	 * @example
	 * bandwidth.Media.upload(client, "file.pdf", stream, "application/pdf", function(err){});
	 */
	upload : function (client, name, data, mediaType, callback) {
		if (arguments.length === 3) {
			callback = data;
			data = name;
			name = client;
			client = new Client();
			mediaType = null;
		}
		else if (arguments.length === 4) {
			callback = mediaType;
			if (client instanceof Client) {
				mediaType = null;
			}
			else {
				mediaType = data;
				data = name;
				name = client;
				client = new Client();
			}
		}

		var request = client.createRequest("put", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));
		sendFile(request, data, mediaType, function (res) {
			client.checkResponse(res, callback);
		});
	},

	/**
	 * Downloads a media file you uploaded to given destination(file or stream)
	 * @param client Client instance
	 * @param name file name
	 * @param destination file name or stream to write downloaded file
	 * @returns request object
	 * @example
	 * bandwidth.Media.download(client, "file1.pdf", "/tmp/file1.pdf").end(function(err, res){});
	 */
	download : function (client, name, destination) {
		if (arguments.length <= 2) {
			if (client instanceof Client) {
				destination = null;
			}
			else {
				destination = name;
				name = client;
				client = new Client();
			}
		}

		var request = client.createRequest("get", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));
		if (destination) {
			var stream = null;
			if (typeof destination === "string") {
				stream = fs.createWriteStream(destination);
			}
			else if (typeof destination.write === "function") {
				stream = destination;
			}

			if (stream) {
				return request.pipe(stream);
			}
		}

		return request;
	},

	/**
	 * Permanently deletes a media file you uploaded
	 * @param client Client instance
	 * @param name file name
	 * @param callback callback function
	 * @example
	 * bandwidth.delete(client, "file1.pdf", function(err){});
	 */
	delete : function (client, name, callback) {
		if (arguments.length === 2) {
			callback = name;
			name = client;
			client = new Client();
		}

		client.makeRequest("del", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name), callback);
	},

	/**
	 * Get information about a media file
	 * @param client Client instance
	 * @param name file name
	 * @param callback
	 * @example
	 * bandwidth.Media.getInfo(client, "file1.wav", function(err, res){});
	 */
	getInfo : function (client, name, callback) {
		if (arguments.length === 2) {
			callback = name;
			name = client;
			client = new Client();
		}

		var request = client.createRequest("head", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));
		request.end(function (err, res) {
			if (res.ok) {
				return callback(null,
					{
						contentType : res.type,
						contentLength : res.header["content-length"]
					});
			}

			return callback(new errors.BandwidthError("Http code " + res.status, res.status));
		});
	},

	/**
	 * Get a media file binary contents
	 * @param client Client instance
	 * @param name file name
	 * @param callback
	 * @example
	 * bandwidth.Media.getContents(client, "file1.wav", function(err, res){});
	 */
	getContents : function (client, name, callback) {
		if (arguments.length === 2) {
			callback = name;
			name = client;
			client = new Client();
		}
		var path = client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name);
		client.rawGetRequest(path)
			.on("error", function (err) {
				callback(err, null);
			})
			.on("response", function (res) {
				var buf = [];
				res.on("data", function (chunk) {
					buf.push(chunk);
				});
				res.on("end", function () {
					var data = Buffer.concat(buf);
					callback(null, {
						contentType :   res.headers["content-type"].split(";")[0],
						contentLength : data.length,
						contentBody :   data
					});
				});
			});
	}
};
<commit_msg>Fixes in code alignment<commit_after>var Client = require("./client");
var fs = require("fs");
var superagent = require("superagent");
var errors = require("./errors");
var MEDIA_PATH = "media";

function sendFile(request, file, mediaType, callback) {
	var stream = null;
	request.buffer().type(mediaType || "application/octet-stream");
	if (typeof file === "string") {
		stream = fs.createReadStream(file);
	}
	else if (Buffer.isBuffer(file)) {
		request.set("Content-Length", file.length);
		request.write(file);
		request.end(callback);
		return;
	}
	else if (typeof file.pipe === "function" && typeof file.read === "function" && typeof file.on === "function") {
		stream = file;
	}
	if (stream) {
		//  request.on("response") sometimes could not be called
		request.req.on("response", function (res) {
			request.res = res;
			var response = new superagent.Response(request);
			callback(response);
		});
		stream.pipe(request);
		return;
	}

	callback({ statusCode : 400, text : "Invalid data to send", body : { message : "Invalid data to send" } });
}

module.exports = {
	/**
	 * Get a list of your media files
	 * @param client Client instance
	 * @param query query parameters
	 * @param callback callback function
	 * @example
	 * bandwidth.Media.list(client, function(err, list){});
	 */
	list : function (client, query, callback) {
		if (arguments.length === 1) {
			callback = client;
			client = new Client();
		}
		else if (arguments.length === 2) {
			callback = query;
			if (client instanceof Client) {
				query = {};
			}
			else {
				query = client;
				client = new Client();
			}
		}

		client.makeRequest("get", client.concatUserPath(MEDIA_PATH), query, callback);
	},

	/**
	 * Uploads a media file (or stream, or buffer) to the name you choose
	 * @param client Client instance
	 * @param name file name
	 * @param mediaTypr media type of file
	 * @param callback callback function
	 * @example
	 * bandwidth.Media.upload(client, "file.pdf", stream, "application/pdf", function(err){});
	 */
	upload : function (client, name, data, mediaType, callback) {
		if (arguments.length === 3) {
			callback = data;
			data = name;
			name = client;
			client = new Client();
			mediaType = null;
		}
		else if (arguments.length === 4) {
			callback = mediaType;
			if (client instanceof Client) {
				mediaType = null;
			}
			else {
				mediaType = data;
				data = name;
				name = client;
				client = new Client();
			}
		}

		var request = client.createRequest("put", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));
		sendFile(request, data, mediaType, function (res) {
			client.checkResponse(res, callback);
		});
	},

	/**
	 * Downloads a media file you uploaded to given destination(file or stream)
	 * @param client Client instance
	 * @param name file name
	 * @param destination file name or stream to write downloaded file
	 * @returns request object
	 * @example
	 * bandwidth.Media.download(client, "file1.pdf", "/tmp/file1.pdf").end(function(err, res){});
	 */
	download : function (client, name, destination) {
		if (arguments.length <= 2) {
			if (client instanceof Client) {
				destination = null;
			}
			else {
				destination = name;
				name = client;
				client = new Client();
			}
		}

		var request = client.createRequest("get", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));
		if (destination) {
			var stream = null;
			if (typeof destination === "string") {
				stream = fs.createWriteStream(destination);
			}
			else if (typeof destination.write === "function") {
				stream = destination;
			}

			if (stream) {
				return request.pipe(stream);
			}
		}

		return request;
	},

	/**
	 * Permanently deletes a media file you uploaded
	 * @param client Client instance
	 * @param name file name
	 * @param callback callback function
	 * @example
	 * bandwidth.delete(client, "file1.pdf", function(err){});
	 */
	delete : function (client, name, callback) {
		if (arguments.length === 2) {
			callback = name;
			name = client;
			client = new Client();
		}

		client.makeRequest("del", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name), callback);
	},

	/**
	 * Get information about a media file
	 * @param client Client instance
	 * @param name file name
	 * @param callback
	 * @example
	 * bandwidth.Media.getInfo(client, "file1.wav", function(err, res){});
	 */
	getInfo : function (client, name, callback) {
		if (arguments.length === 2) {
			callback = name;
			name = client;
			client = new Client();
		}

		var request = client.createRequest("head", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));
		request.end(function (err, res) {
			if (res.ok) {
				return callback(null,
					{
						contentType   : res.type,
						contentLength : res.header["content-length"]
					});
			}

			return callback(new errors.BandwidthError("Http code " + res.status, res.status));
		});
	},

	/**
	 * Get a media file binary contents
	 * @param client Client instance
	 * @param name file name
	 * @param callback
	 * @example
	 * bandwidth.Media.getContents(client, "file1.wav", function(err, res){});
	 */
	getContents : function (client, name, callback) {
		if (arguments.length === 2) {
			callback = name;
			name = client;
			client = new Client();
		}
		var path = client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name);
		client.rawGetRequest(path)
			.on("error", function (err) {
				callback(err, null);
			})
			.on("response", function (res) {
				var buf = [];
				res.on("data", function (chunk) {
					buf.push(chunk);
				});
				res.on("end", function () {
					var data = Buffer.concat(buf);
					callback(null, {
						contentType   : res.headers["content-type"].split(";")[0],
						contentLength : data.length,
						contentBody   : data
					});
				});
			});
	}
};
<|endoftext|>


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

    /*
    * Module dependencies.
    */
    var validator           = require('validator');
    var moment              = require('moment');
    var is                  = require('is');
    var extend              = require('extend');
    var Entity              = require('./entity');
    var datastoreSerializer = require('./serializer').Datastore;
    var utils               = require('./utils');
    var queryHelpers        = require('./helper').QueryHelpers;

    class Model extends Entity{
        constructor (data, id, ancestors, namespace) {
            super(data, id, ancestors, namespace);
        }

        static compile(name, schema, ds, base) {
            var ModelInstance = class extends Model {
                constructor (data, id, ancestors, namespace) {
                    super(data, id, ancestors, namespace);
                }
                static init() {
                }
            }

            ModelInstance.schema = schema;
            applyMethods(ModelInstance.prototype, schema);

            ModelInstance.prototype.entityName = ModelInstance.entityName = name;
            ModelInstance.prototype.ds         = ModelInstance.ds = ds;
            ModelInstance.hooks                = schema.s.hooks.clone();
            ModelInstance.base                 = base;

            return ModelInstance;
        }

        static get(id, ancestors, cb) {
            let _this = this;
            let args  = arrayArguments(arguments);

            cb        = args.pop();
            id        = isNaN(parseInt(id)) ? id : parseInt(id);
            ancestors = args.length > 1 ? args[1] : undefined;

            let key = this.createKey(id, ancestors);

            this.ds.get(key, (err, entity) => {
                if (err) {
                    return cb(err);
                }

                if (!entity) {
                    return cb({
                        code   : 404,
                        message: _this.entityName + ' {' + id.toString() + '} not found'
                    });
                }

                entity.simplify = () => {
                    return datastoreSerializer.fromDatastore(entity);
                };
                cb(null, entity);
            });
        }

        static update(id, data, ancestors, cb) {
            var _this = this;

            let args = arrayArguments(arguments);

            cb        = args.pop();
            id        = isNaN(parseInt(id)) ? id : parseInt(id);
            ancestors = args.length > 2 ? args[2] : undefined;

            let key = this.createKey(id, ancestors);
            let M   = this.compile(this.entityName, this.schema, this.ds);

            this.ds.get(key, (err, entity) => {
                if (err) {
                    return cb(err);
                }

                if (!entity) {
                    return cb({
                        code   : 404,
                        message: 'Entity {' + id.toString() + '} to update not found'
                    });
                }

                extend(true, entity.data, data);

                let model  = new M(entity.data, id, ancestors);

                model.save({op:'update'}, (err, entity, info) => {
                    if (err) {
                        return cb(err);
                    }

                    cb(null, entity, info);
                });
            });
        }

        static query(namespace) {
            var _this = this;

            let createQueryArgs = [this.entityName];

            if (namespace) {
                createQueryArgs.unshift(namespace);
            }

            let query = this.ds.createQuery.apply(this.ds, createQueryArgs);

            query.run = function(options, cb) {
                let args = [];
                for (let i = 0; i < arguments.length; i++) {
                    args.push(arguments[i]);
                }
                cb = args.pop();

                options = args.length > 0 ? args[0] : {};
                options = utils.options(_this.schema.options.entities, options);

                _this.ds.runQuery(query, (err, entities) => {
                    if (err) {
                        return cb(err);
                    }
                    if (options.simplifyResult) {
                        entities = entities.map(datastoreSerializer.fromDatastore);
                    }
                    cb(null, entities);
                });
            };

            return query;
        }

        static list(options, cb) {
            let _this = this;
            let args  = arrayArguments(arguments);

            cb      = args.pop();
            options = args.length > 0 ? args[0] : {};

            if(this.schema.shortcutQueries.hasOwnProperty('list')) {
                options = utils.options(this.schema.shortcutQueries.list, options);
            }

            let createQueryArgs = [this.entityName];
            if (options.namespace) {
                createQueryArgs.unshift(options.namespace);
            }

            let query = this.ds.createQuery.apply(this.ds, createQueryArgs);

            // update query with options settings
            query = queryHelpers.buildFromOptions(query, options, this.ds);

            // merge entities option
            options = utils.options(_this.schema.options.entities, options);

            this.ds.runQuery(query, (err, entities) => {
                if (err) {
                    return cb(err);
                }
                if (options.simplifyResult) {
                    entities = entities.map(datastoreSerializer.fromDatastore);
                }
                cb(null, entities);
            });
        }

        static delete(id, ancestors, cb) {
            let args = arrayArguments(arguments);

            cb = args.pop();
            id = isNaN(parseInt(id)) ? id : parseInt(id);

            let path = [this.entityName, id];
            path     = ancestors && is.array(ancestors) ? ancestors.concat(path) : path;

            let key = this.ds.key(path);
            this.ds.delete(key, (err, apiRes) => {
                if (err) {
                    return cb(err);
                }
                let success = apiRes.indexUpdates > 0;
                cb(null, success, apiRes);
            });
        }

        static findOne(query, cb) {
            var _this = this;

            this.hooks.execPre('findOne', _this, () => {
                // Pre methods done
                // [process here...]

                _this.hooks.execPost('findOne', null, [], () => {
                    // all post hooks are done
                });
            });
        }

        static createKey(id, ancestors) {
            var key;
            if (ancestors && is.array(ancestors)) {
                key = this.ds.key(ancestors.concat([this.entityName, id]));
            } else {
                key = this.ds.key([this.entityName, id]);
            }
            return key;
        }

        save (options, cb) {
            let _this = this;
            let args  = arrayArguments(arguments);
            let saveOptions = {
                op:'save',
                transaction:false
            }

            cb      = args.pop();
            options = args.length > 0 && args[0] !== null ? args[0] : {};

            extend(saveOptions, options);

            let entity = {
                key : this.entityKey,
                data : datastoreSerializer.toDatastore(this.entityData, this.excludedFromIndexes)
            };

            if (!saveOptions.transaction) {
                this.ds.save(entity, (err) => {
                    if (err) {
                        return cb(err);
                    }

                    let entitySaved = {
                        key:_this.entityKey,
                        data:_this.entityData
                    };

                    let info = {
                        op : saveOptions.op
                    };

                    entitySaved.simplify = () => {
                        return datastoreSerializer.fromDatastore(entitySaved);
                    };

                    _this.emit(saveOptions.op);

                    cb(null, entitySaved, info);
                });
            } else {
                // TODO save to transaction
                /**
                 * transaction.save(.....)
                 */
            }
        }

        validate(cb) {
            // console.log('validating....', this.entityData, this.schema);
            let error;
            let skip = false;
            var self   = this;
            var schema = this.schema;

            Object.keys(this.entityData).forEach((k) => {
                // Properties dict
                if (!schema.paths.hasOwnProperty(k) && schema.options.unknownProperties === true) {
                    // No more validation, key does not exist but it is allowed
                    skip = true;
                }

                if (!skip && !schema.paths.hasOwnProperty(k)) {
                    error = {
                        success : false,
                        code:400,
                        message:'Property not allowed ' + k
                    };
                }

                // Properties type
                if (!skip && !error && self.entityData[k] !== null && schema.paths[k].hasOwnProperty('type')) {
                    if (schema.paths[k].type === 'datetime') {
                        if (self.entityData.birthday.constructor.name !== 'Date' &&
                            (typeof self.entityData[k] !== 'string' ||
                                !self.entityData[k].match(/\d{4}-\d{2}-\d{2}([ ,T])?(\d{2}:\d{2}:\d{2})?(\.\d{1,3})?/) ||
                                !moment(self.entityData[k]).isValid())) {
                            error = {
                                success: false,
                                code   : 400,
                                message: 'Wrong date format for ' + k
                            };
                        }
                    } else if (schema.paths[k].type === 'array') {
                        if (typeof self.entityData[k] !== 'object' || !is.array(self.entityData[k])) {
                            error = {
                                success: false,
                                code   : 400,
                                message: 'Data type error for ' + k
                            };
                        }
                    } else {
                        if (typeof self.entityData[k] !== schema.paths[k].type) {
                            error = {
                                success: false,
                                code   : 400,
                                message: 'Data type error for ' + k
                            };
                        }
                    }
                }

                // Value Validation
                if (!skip && !error && schema.paths[k].hasOwnProperty('validate') && self.entityData[k] && self.entityData[k] !== '') {
                    if (!validator[schema.paths[k].validate](self.entityData[k])) {
                        error = {
                            success: false,
                            code   : 401,
                            message: 'Wrong format for property {' + k + '}'
                        };
                    }
                }

                // Preset values
                if (!skip && !error && schema.paths[k].hasOwnProperty('values') && self.entityData[k] !== '') {
                    if (schema.paths[k].values.indexOf(self.entityData[k]) < 0) {
                        error = {
                            success: false,
                            code   : 400,
                            message: 'Value not allowed for ' + k
                        };
                    }
                }
            });

            if (cb) {
                var payload =  error ? error : {success:true};
                cb(payload);
            } else {
                return error ? error : {success:true};
            }
        }
    }

    /**
     *
     * @param self {Model}
     * @param schema {Schema}
     * @returns {Model}
     */
    function applyMethods (self, schema) {
        Object.keys(schema.methods).forEach((method) => {
            self[method] = schema.methods[method];
        });
        return self;
    }

    function arrayArguments(args) {
        let a = [];
        for (let i = 0, l = args.length; i < l; i++) {
            a.push(args[i]);
        }
        return a;
    }

    module.exports = exports = Model;
})();
<commit_msg>fix bug validate<commit_after>(function() {
    'use strict';

    /*
    * Module dependencies.
    */
    var validator           = require('validator');
    var moment              = require('moment');
    var is                  = require('is');
    var extend              = require('extend');
    var Entity              = require('./entity');
    var datastoreSerializer = require('./serializer').Datastore;
    var utils               = require('./utils');
    var queryHelpers        = require('./helper').QueryHelpers;

    class Model extends Entity{
        constructor (data, id, ancestors, namespace) {
            super(data, id, ancestors, namespace);
        }

        static compile(name, schema, ds, base) {
            var ModelInstance = class extends Model {
                constructor (data, id, ancestors, namespace) {
                    super(data, id, ancestors, namespace);
                }
                static init() {
                }
            }

            ModelInstance.schema = schema;
            applyMethods(ModelInstance.prototype, schema);

            ModelInstance.prototype.entityName = ModelInstance.entityName = name;
            ModelInstance.prototype.ds         = ModelInstance.ds = ds;
            ModelInstance.hooks                = schema.s.hooks.clone();
            ModelInstance.base                 = base;

            return ModelInstance;
        }

        static get(id, ancestors, cb) {
            let _this = this;
            let args  = arrayArguments(arguments);

            cb        = args.pop();
            id        = isNaN(parseInt(id)) ? id : parseInt(id);
            ancestors = args.length > 1 ? args[1] : undefined;

            let key = this.createKey(id, ancestors);

            this.ds.get(key, (err, entity) => {
                if (err) {
                    return cb(err);
                }

                if (!entity) {
                    return cb({
                        code   : 404,
                        message: _this.entityName + ' {' + id.toString() + '} not found'
                    });
                }

                entity.simplify = () => {
                    return datastoreSerializer.fromDatastore(entity);
                };
                cb(null, entity);
            });
        }

        static update(id, data, ancestors, cb) {
            var _this = this;

            let args = arrayArguments(arguments);

            cb        = args.pop();
            id        = isNaN(parseInt(id)) ? id : parseInt(id);
            ancestors = args.length > 2 ? args[2] : undefined;

            let key = this.createKey(id, ancestors);
            let M   = this.compile(this.entityName, this.schema, this.ds);

            this.ds.get(key, (err, entity) => {
                if (err) {
                    return cb(err);
                }

                if (!entity) {
                    return cb({
                        code   : 404,
                        message: 'Entity {' + id.toString() + '} to update not found'
                    });
                }

                extend(true, entity.data, data);

                let model  = new M(entity.data, id, ancestors);

                model.save({op:'update'}, (err, entity, info) => {
                    if (err) {
                        return cb(err);
                    }

                    cb(null, entity, info);
                });
            });
        }

        static query(namespace) {
            var _this = this;

            let createQueryArgs = [this.entityName];

            if (namespace) {
                createQueryArgs.unshift(namespace);
            }

            let query = this.ds.createQuery.apply(this.ds, createQueryArgs);

            query.run = function(options, cb) {
                let args = [];
                for (let i = 0; i < arguments.length; i++) {
                    args.push(arguments[i]);
                }
                cb = args.pop();

                options = args.length > 0 ? args[0] : {};
                options = utils.options(_this.schema.options.entities, options);

                _this.ds.runQuery(query, (err, entities) => {
                    if (err) {
                        return cb(err);
                    }
                    if (options.simplifyResult) {
                        entities = entities.map(datastoreSerializer.fromDatastore);
                    }
                    cb(null, entities);
                });
            };

            return query;
        }

        static list(options, cb) {
            let _this = this;
            let args  = arrayArguments(arguments);

            cb      = args.pop();
            options = args.length > 0 ? args[0] : {};

            if(this.schema.shortcutQueries.hasOwnProperty('list')) {
                options = utils.options(this.schema.shortcutQueries.list, options);
            }

            let createQueryArgs = [this.entityName];
            if (options.namespace) {
                createQueryArgs.unshift(options.namespace);
            }

            let query = this.ds.createQuery.apply(this.ds, createQueryArgs);

            // update query with options settings
            query = queryHelpers.buildFromOptions(query, options, this.ds);

            // merge entities option
            options = utils.options(_this.schema.options.entities, options);

            this.ds.runQuery(query, (err, entities) => {
                if (err) {
                    return cb(err);
                }
                if (options.simplifyResult) {
                    entities = entities.map(datastoreSerializer.fromDatastore);
                }
                cb(null, entities);
            });
        }

        static delete(id, ancestors, cb) {
            let args = arrayArguments(arguments);

            cb = args.pop();
            id = isNaN(parseInt(id)) ? id : parseInt(id);

            let path = [this.entityName, id];
            path     = ancestors && is.array(ancestors) ? ancestors.concat(path) : path;

            let key = this.ds.key(path);
            this.ds.delete(key, (err, apiRes) => {
                if (err) {
                    return cb(err);
                }
                let success = apiRes.indexUpdates > 0;
                cb(null, success, apiRes);
            });
        }

        static findOne(query, cb) {
            var _this = this;

            this.hooks.execPre('findOne', _this, () => {
                // Pre methods done
                // [process here...]

                _this.hooks.execPost('findOne', null, [], () => {
                    // all post hooks are done
                });
            });
        }

        static createKey(id, ancestors) {
            var key;
            if (ancestors && is.array(ancestors)) {
                key = this.ds.key(ancestors.concat([this.entityName, id]));
            } else {
                key = this.ds.key([this.entityName, id]);
            }
            return key;
        }

        save (options, cb) {
            let _this = this;
            let args  = arrayArguments(arguments);
            let saveOptions = {
                op:'save',
                transaction:false
            }
            cb      = args.pop();
            options = args.length > 0 && args[0] !== null ? args[0] : {};

            extend(saveOptions, options);

            let entity = {
                key : this.entityKey,
                data : datastoreSerializer.toDatastore(this.entityData, this.excludedFromIndexes)
            };

            if (!saveOptions.transaction) {
                this.ds.save(entity, (err) => {
                    if (err) {
                        return cb(err);
                    }

                    let entitySaved = {
                        key:_this.entityKey,
                        data:_this.entityData
                    };

                    let info = {
                        op : saveOptions.op
                    };

                    entitySaved.simplify = () => {
                        return datastoreSerializer.fromDatastore(entitySaved);
                    };

                    _this.emit(saveOptions.op);

                    cb(null, entitySaved, info);
                });
            } else {
                // TODO save to transaction
                /**
                 * transaction.save(.....)
                 */
            }
        }

        validate(cb) {
            // console.log('validating....', this.entityData, this.schema);
            let error;
            var self   = this;
            var schema = this.schema;

            Object.keys(this.entityData).forEach((k) => {
                let skip = false;

                // Properties dict
                if (!schema.paths.hasOwnProperty(k) && schema.options.unknownProperties === true) {
                    // No more validation, key does not exist but it is allowed
                    skip = true;
                }

                if (!skip && !schema.paths.hasOwnProperty(k)) {
                    error = {
                        success : false,
                        code:400,
                        message:'Property not allowed ' + k
                    };
                }

                // Properties type
                if (!skip && !error && self.entityData[k] !== null && schema.paths[k].hasOwnProperty('type')) {
                    if (schema.paths[k].type === 'datetime') {
                        if (self.entityData[k].constructor.name !== 'Date' &&
                            (typeof self.entityData[k] !== 'string' ||
                                !self.entityData[k].match(/\d{4}-\d{2}-\d{2}([ ,T])?(\d{2}:\d{2}:\d{2})?(\.\d{1,3})?/) ||
                                !moment(self.entityData[k]).isValid())) {
                            error = {
                                success: false,
                                code   : 400,
                                message: 'Wrong date format for ' + k
                            };
                        }
                    } else if (schema.paths[k].type === 'array') {
                        if (typeof self.entityData[k] !== 'object' || !is.array(self.entityData[k])) {
                            error = {
                                success: false,
                                code   : 400,
                                message: 'Data type error for ' + k
                            };
                        }
                    } else {
                        if (typeof self.entityData[k] !== schema.paths[k].type) {
                            error = {
                                success: false,
                                code   : 400,
                                message: 'Data type error for ' + k
                            };
                        }
                    }
                }

                // Value Validation
                if (!skip && !error && schema.paths[k].hasOwnProperty('validate') && self.entityData[k] && self.entityData[k] !== '') {
                    if (!validator[schema.paths[k].validate](self.entityData[k])) {
                        error = {
                            success: false,
                            code   : 401,
                            message: 'Wrong format for property {' + k + '}'
                        };
                    }
                }

                // Preset values
                if (!skip && !error && schema.paths[k].hasOwnProperty('values') && self.entityData[k] !== '') {
                    if (schema.paths[k].values.indexOf(self.entityData[k]) < 0) {
                        error = {
                            success: false,
                            code   : 400,
                            message: 'Value not allowed for ' + k
                        };
                    }
                }
            });

            if (cb) {
                var payload =  error ? error : {success:true};
                cb(payload);
            } else {
                return error ? error : {success:true};
            }
        }
    }

    /**
     *
     * @param self {Model}
     * @param schema {Schema}
     * @returns {Model}
     */
    function applyMethods (self, schema) {
        Object.keys(schema.methods).forEach((method) => {
            self[method] = schema.methods[method];
        });
        return self;
    }

    function arrayArguments(args) {
        let a = [];
        for (let i = 0, l = args.length; i < l; i++) {
            a.push(args[i]);
        }
        return a;
    }

    module.exports = exports = Model;
})();
<|endoftext|>


<commit_before>import { isKnownView, getViewMeta, getViewClass } from '../element-registry'
import { makeMap, once } from 'shared/util'
import { VUE_VM_REF } from '../runtime'

export const isReservedTag = makeMap('template', true)

let _Vue

export function setVue(Vue) {
  _Vue = Vue
}

export const canBeLeftOpenTag = function(el) {
  return getViewMeta(el).canBeLeftOpenTag
}

export const isUnaryTag = function(el) {
  return getViewMeta(el).isUnaryTag
}

export function mustUseProp() {
  // console.log('mustUseProp')
}

export function getTagNamespace(el) {
  return getViewMeta(el).tagNamespace
}

export function isUnknownElement(el) {
  return !isKnownView(el)
}

export function isPage(el) {
  return el && el.tagName === 'nativepage'
}

/** @deprecated */
export function ensurePage(el, vm) {
  if (!isPage(el)) {
    const page = new (getViewClass('page'))()
    page.content = el.nativeView
    if (vm) {
      page[VUE_VM_REF] = vm
      page.disposeNativeView = after(page.disposeNativeView, page, () =>
        vm.$destroy()
      )
    }
    return page
  }

  if (vm) {
    el.nativeView[VUE_VM_REF] = vm
    el.disposeNativeView = after(el.disposeNativeView, el, () => vm.$destroy())
  }

  return el.nativeView
}

export function query(el, renderer, document) {
  // Todo
}

export const VUE_VERSION = process.env.VUE_VERSION
export const NS_VUE_VERSION = process.env.NS_VUE_VERSION

const infoTrace = once(() => {
  console.log(
    `NativeScript-Vue has "Vue.config.silent" set to true, to see output logs set it to false.`
  )
})

export function trace(message) {
  if (_Vue && _Vue.config.silent) {
    return infoTrace()
  }

  console.log(
    `{NSVue (Vue: ${VUE_VERSION} | NSVue: ${NS_VUE_VERSION})} -> ${message}`
  )
}

export function before(original, thisArg, wrap) {
  return function(...args) {
    wrap.call(null, ...args)
    original.call(thisArg, ...args)
  }
}

export function after(original, thisArg, wrap) {
  return function(...args) {
    wrap.call(null, ...args)
    original.call(thisArg, ...args)
  }
}

export function deepProxy(object, depth = 0) {
  return new Proxy(object, {
    get(target, key) {
      if (key === 'toString' || key === 'valueOf') {
        return () => ''
      }

      if (key === Symbol.toPrimitive) {
        return hint => hint
      }

      if (depth > 10) {
        throw new Error('deepProxy over 10 deep.')
      }
      return deepProxy({}, depth + 1)
    }
  })
}
<commit_msg>fix: fix function call order in `after` util<commit_after>import { isKnownView, getViewMeta, getViewClass } from '../element-registry'
import { makeMap, once } from 'shared/util'
import { VUE_VM_REF } from '../runtime'

export const isReservedTag = makeMap('template', true)

let _Vue

export function setVue(Vue) {
  _Vue = Vue
}

export const canBeLeftOpenTag = function(el) {
  return getViewMeta(el).canBeLeftOpenTag
}

export const isUnaryTag = function(el) {
  return getViewMeta(el).isUnaryTag
}

export function mustUseProp() {
  // console.log('mustUseProp')
}

export function getTagNamespace(el) {
  return getViewMeta(el).tagNamespace
}

export function isUnknownElement(el) {
  return !isKnownView(el)
}

export function isPage(el) {
  return el && el.tagName === 'nativepage'
}

/** @deprecated */
export function ensurePage(el, vm) {
  if (!isPage(el)) {
    const page = new (getViewClass('page'))()
    page.content = el.nativeView
    if (vm) {
      page[VUE_VM_REF] = vm
      page.disposeNativeView = after(page.disposeNativeView, page, () =>
        vm.$destroy()
      )
    }
    return page
  }

  if (vm) {
    el.nativeView[VUE_VM_REF] = vm
    el.disposeNativeView = after(el.disposeNativeView, el, () => vm.$destroy())
  }

  return el.nativeView
}

export function query(el, renderer, document) {
  // Todo
}

export const VUE_VERSION = process.env.VUE_VERSION
export const NS_VUE_VERSION = process.env.NS_VUE_VERSION

const infoTrace = once(() => {
  console.log(
    `NativeScript-Vue has "Vue.config.silent" set to true, to see output logs set it to false.`
  )
})

export function trace(message) {
  if (_Vue && _Vue.config.silent) {
    return infoTrace()
  }

  console.log(
    `{NSVue (Vue: ${VUE_VERSION} | NSVue: ${NS_VUE_VERSION})} -> ${message}`
  )
}

export function before(original, thisArg, wrap) {
  return function(...args) {
    wrap.call(null, ...args)
    original.call(thisArg, ...args)
  }
}

export function after(original, thisArg, wrap) {
  return function(...args) {
    original.call(thisArg, ...args)
    wrap.call(null, ...args)
  }
}

export function deepProxy(object, depth = 0) {
  return new Proxy(object, {
    get(target, key) {
      if (key === 'toString' || key === 'valueOf') {
        return () => ''
      }

      if (key === Symbol.toPrimitive) {
        return hint => hint
      }

      if (depth > 10) {
        throw new Error('deepProxy over 10 deep.')
      }
      return deepProxy({}, depth + 1)
    }
  })
}
<|endoftext|>


<commit_before>/* SHA512 for JavaScript
 *
 * The MIT License (MIT)
 * Copyright (c) 2016 Leonardone @ NEETSDKASU
 */

function SHA512JS() {

	var Int64 = new function() {

		var SIZE = 5;
		var LEN = 4;
		var BITLEN = 16;
		var MASK = 0xFFFF;

		this.valueOf = function(n) {
			// n: Number(Integer)
			var i, v = new Array(SIZE);
			for (i = 0; i < SIZE; i++) {
				v[i] = n & MASK;
				n >>= BITLEN;
			}
			return v;
		};

		this.parse = function(s) {
			// s: Hex String
			var i, v = new Array(SIZE), j;
			i = 0;
			for (j = s.length - 4; j >= 0 && i < LEN; j -= 4) {
				v[i] = parseInt('0x' + s.substring(j, j + 4));
				i++;
			}
			if (j > -4 && i < LEN) {
				v[i] = parseInt('0x' + s.substring(0, j + 4));
				i++;
			}
			for (; i < SIZE; i++) {
				v[i] = 0;
			}
			return v;
		};

		this.add = function(v1, v2) {
			var i, v = new Array(SIZE), t = 0;
			for (i = 0; i < LEN; i++) {
				t += v1[i] + v2[i];
				v[i] = t & MASK;
				t >>= BITLEN;
			}
			v[LEN] = 0;
			return v;
		};

		this.bwXor = function(v1, v2) {
			var i, v = new Array(SIZE);
			for (i = 0; i < LEN; i++) {
				v[i] = v1[i] ^ v2[i];
			}
			v[LEN] = 0;
			return v;
		};

		this.bwAnd = function(v1, v2) {
			var i, v = new Array(SIZE);
			for (i = 0; i < LEN; i++) {
				v[i] = v1[i] & v2[i];
			}
			v[LEN] = 0;
			return v;
		};

		this.bwOr  = function(v1, v2) {
			var i, v = new Array(SIZE);
			for (i = 0; i < LEN; i++) {
				v[i] = v1[i] | v2[i];
			}
			v[LEN] = 0;
			return v;
		};

		this.bwNot = function(v1) {
			var i, v = new Array(SIZE);
			for (i = 0; i < LEN; i++) {
				v[i] = v1[i] ^ MASK;
			}
			v[LEN] = 0;
			return v;
		};

		this.shiftR = function(v1, s) {
			var i, v = new Array(SIZE), k, m, p;
			k = (s & 63) >> 4; // div BITLEN(16)
			for (i = 0; i + k < LEN; i++) {
				v[i] = v1[i + k];
			}
			s &= MASK;
			m = (1 << s) - 1; // mask
			p = BITLEN - s;   // shiftL
			for (i = 0; i < LEN; i++) {
				v[i] >>= s;
				v[i] |= (v[i + 1] & m) << p;
			}
			return v;
		};

		this.rotateR = function(v1, r) {
			var i, v = new Array(SIZE), k, m, p;
			k = (r & 63) >> 4; // div BITLEN(16)
			for (i = 0; i < LEN; i++) {
				v[i] = v1[(i + k) & 3]; // % LEN(4)
			}
			r &= MASK;
			m = (1 << r) - 1;  // mask
			p = BITLEN - r;    // shiftL
			v[LEN] = v[0] & m; // lowest bits
			for (i = 0; i < LEN; i++) {
				v[i] >>= r;
				v[i] |= (v[i + 1] & m) << p;
			}
			v[LEN] = 0;
			return v;
		};

		this.toHex = function(v) {
			var i, c, s = '';
			for (i = LEN - 1; i >= 0; i--) {
				c = v[i].toString(16);
				while (c.length < 4) { c = '0' + c; } // 4 hex-characters at BITLEN(16)
				s += c;
			}
			return s;
		};

		this.copyBytes = function(v, dest, offset) {
			var i, j = offset;
			for (i = LEN - 1; i >= 0; i--) {
				dest[j]     = v[i] >> 8; // BITLEN(16)
				dest[j + 1] = v[i] &  0xFF;
				j += 2;
			}
		};
	};

	this.getInt64 = function() { return Int64; };

	var _init_hash_value = [
		Int64.parse('6a09e667f3bcc908'),
		Int64.parse('bb67ae8584caa73b'),
		Int64.parse('3c6ef372fe94f82b'),
		Int64.parse('a54ff53a5f1d36f1'),
		Int64.parse('510e527fade682d1'),
		Int64.parse('9b05688c2b3e6c1f'),
		Int64.parse('1f83d9abfb41bd6b'),
		Int64.parse('5be0cd19137e2179')
	];

	var __init_hash = function(x) {
		var i, hash = x.hash;
		for (i = 0; i < 8; i++) {
			hash[i] = _init_hash_value[i]
		}
		x.a = hash[0];
		x.b = hash[1];
		x.c = hash[2];
		x.d = hash[3];
		x.e = hash[4];
		x.f = hash[5];
		x.g = hash[6];
		x.h = hash[7];
	};

	var __Ch = function(x, y, z) {
		return Int64.bwXor(
			Int64.bwAnd(x, y),
			Int64.bwAnd(Int64.bwNot(x), z)
			);
	};

	var __Maj = function(x, y, z) {
		return Int64.bwXor(
			Int64.bwAnd(x, y),
			Int64.bwXor(
				Int64.bwAnd(x, z),
				Int64.bwAnd(y, z)
			));
	};

	var __ucSigma0 = function(x) {
		return Int64.bwXor(
			Int64.shiftR(x, 28),
			Int64.bwXor(
				Int64.shiftR(x, 34),
				Int64.shiftR(x, 39)
			));
	};

	var __ucSigma1 = function(x) {
		return Int64.bwXor(
			Int64.shiftR(x, 14),
			Int64.bwXor(
				Int64.shiftR(x, 18),
				Int64.shiftR(x, 41)
			));
	};

	var __lcSigma0 = function(x) {
		return Int64.bwXor(
			Int64.shiftR(x, 1),
			Int64.bwXor(
				Int64.shiftR(x, 8),
				Int64.rotateR(x, 7)
			));
	};

	var __lcSigma1 = function(x) {
		return Int64.bwXor(
			Int64.shiftR(x, 19),
			Int64.bwXor(
				Int64.shiftR(x, 61),
				Int64.rotateR(x, 6)
			));
	};

	this.create = function() {
		var x = {
			"hash": new Array(8),
			"w": new Array(80)
		};
		__init_hash(x);
		return x;
	};

	this.init = __init_hash;

	var __update = function(x, data, offset) {
		var j;

		// calc Wj
		var w = x.w;
		for (j = 0; j < 16; j++) {
			w[j] = data[offset + j];
		}
		for (j = 16; j < 80; j++) {
			w[j] = Int64.add(
				__lcSigma1(w[j - 2]),
				Int64.add(
					w[j - 7],
					Int64.add(
						__lcSigma0(w[j - 15]),
						w[j - 16]
				)));
		}

	};

	this.update = __update;

	this.getHash = function(x, dest, offset) {
		// ByteArray
		var i;
		for (i = 0; i < 8; i++) {
			Int64.copyBytes(x.hash[i], dest, offset + i * 8);
		}
	};
}
<commit_msg>Calc Wj の関数追い出し<commit_after>/* SHA512 for JavaScript
 *
 * The MIT License (MIT)
 * Copyright (c) 2016 Leonardone @ NEETSDKASU
 */

function SHA512JS() {

	var Int64 = new function() {

		var SIZE = 5;
		var LEN = 4;
		var BITLEN = 16;
		var MASK = 0xFFFF;

		this.valueOf = function(n) {
			// n: Number(Integer)
			var i, v = new Array(SIZE);
			for (i = 0; i < SIZE; i++) {
				v[i] = n & MASK;
				n >>= BITLEN;
			}
			return v;
		};

		this.parse = function(s) {
			// s: Hex String
			var i, v = new Array(SIZE), j;
			i = 0;
			for (j = s.length - 4; j >= 0 && i < LEN; j -= 4) {
				v[i] = parseInt('0x' + s.substring(j, j + 4));
				i++;
			}
			if (j > -4 && i < LEN) {
				v[i] = parseInt('0x' + s.substring(0, j + 4));
				i++;
			}
			for (; i < SIZE; i++) {
				v[i] = 0;
			}
			return v;
		};

		this.add = function(v1, v2) {
			var i, v = new Array(SIZE), t = 0;
			for (i = 0; i < LEN; i++) {
				t += v1[i] + v2[i];
				v[i] = t & MASK;
				t >>= BITLEN;
			}
			v[LEN] = 0;
			return v;
		};

		this.bwXor = function(v1, v2) {
			var i, v = new Array(SIZE);
			for (i = 0; i < LEN; i++) {
				v[i] = v1[i] ^ v2[i];
			}
			v[LEN] = 0;
			return v;
		};

		this.bwAnd = function(v1, v2) {
			var i, v = new Array(SIZE);
			for (i = 0; i < LEN; i++) {
				v[i] = v1[i] & v2[i];
			}
			v[LEN] = 0;
			return v;
		};

		this.bwOr  = function(v1, v2) {
			var i, v = new Array(SIZE);
			for (i = 0; i < LEN; i++) {
				v[i] = v1[i] | v2[i];
			}
			v[LEN] = 0;
			return v;
		};

		this.bwNot = function(v1) {
			var i, v = new Array(SIZE);
			for (i = 0; i < LEN; i++) {
				v[i] = v1[i] ^ MASK;
			}
			v[LEN] = 0;
			return v;
		};

		this.shiftR = function(v1, s) {
			var i, v = new Array(SIZE), k, m, p;
			k = (s & 63) >> 4; // div BITLEN(16)
			for (i = 0; i + k < LEN; i++) {
				v[i] = v1[i + k];
			}
			s &= MASK;
			m = (1 << s) - 1; // mask
			p = BITLEN - s;   // shiftL
			for (i = 0; i < LEN; i++) {
				v[i] >>= s;
				v[i] |= (v[i + 1] & m) << p;
			}
			return v;
		};

		this.rotateR = function(v1, r) {
			var i, v = new Array(SIZE), k, m, p;
			k = (r & 63) >> 4; // div BITLEN(16)
			for (i = 0; i < LEN; i++) {
				v[i] = v1[(i + k) & 3]; // % LEN(4)
			}
			r &= MASK;
			m = (1 << r) - 1;  // mask
			p = BITLEN - r;    // shiftL
			v[LEN] = v[0] & m; // lowest bits
			for (i = 0; i < LEN; i++) {
				v[i] >>= r;
				v[i] |= (v[i + 1] & m) << p;
			}
			v[LEN] = 0;
			return v;
		};

		this.toHex = function(v) {
			var i, c, s = '';
			for (i = LEN - 1; i >= 0; i--) {
				c = v[i].toString(16);
				while (c.length < 4) { c = '0' + c; } // 4 hex-characters at BITLEN(16)
				s += c;
			}
			return s;
		};

		this.copyBytes = function(v, dest, offset) {
			var i, j = offset;
			for (i = LEN - 1; i >= 0; i--) {
				dest[j]     = v[i] >> 8; // BITLEN(16)
				dest[j + 1] = v[i] &  0xFF;
				j += 2;
			}
		};
	};

	this.getInt64 = function() { return Int64; };

	var _init_hash_value = [
		Int64.parse('6a09e667f3bcc908'),
		Int64.parse('bb67ae8584caa73b'),
		Int64.parse('3c6ef372fe94f82b'),
		Int64.parse('a54ff53a5f1d36f1'),
		Int64.parse('510e527fade682d1'),
		Int64.parse('9b05688c2b3e6c1f'),
		Int64.parse('1f83d9abfb41bd6b'),
		Int64.parse('5be0cd19137e2179')
	];

	var __init_hash = function(x) {
		var i, hash = x.hash;
		for (i = 0; i < 8; i++) {
			hash[i] = _init_hash_value[i]
		}
		x.a = hash[0];
		x.b = hash[1];
		x.c = hash[2];
		x.d = hash[3];
		x.e = hash[4];
		x.f = hash[5];
		x.g = hash[6];
		x.h = hash[7];
	};

	var __Ch = function(x, y, z) {
		return Int64.bwXor(
			Int64.bwAnd(x, y),
			Int64.bwAnd(Int64.bwNot(x), z)
			);
	};

	var __Maj = function(x, y, z) {
		return Int64.bwXor(
			Int64.bwAnd(x, y),
			Int64.bwXor(
				Int64.bwAnd(x, z),
				Int64.bwAnd(y, z)
			));
	};

	var __ucSigma0 = function(x) {
		return Int64.bwXor(
			Int64.shiftR(x, 28),
			Int64.bwXor(
				Int64.shiftR(x, 34),
				Int64.shiftR(x, 39)
			));
	};

	var __ucSigma1 = function(x) {
		return Int64.bwXor(
			Int64.shiftR(x, 14),
			Int64.bwXor(
				Int64.shiftR(x, 18),
				Int64.shiftR(x, 41)
			));
	};

	var __lcSigma0 = function(x) {
		return Int64.bwXor(
			Int64.shiftR(x, 1),
			Int64.bwXor(
				Int64.shiftR(x, 8),
				Int64.rotateR(x, 7)
			));
	};

	var __lcSigma1 = function(x) {
		return Int64.bwXor(
			Int64.shiftR(x, 19),
			Int64.bwXor(
				Int64.shiftR(x, 61),
				Int64.rotateR(x, 6)
			));
	};

	this.create = function() {
		var x = {
			"hash": new Array(8),
			"w": new Array(80)
		};
		__init_hash(x);
		return x;
	};

	this.init = __init_hash;

	var __calcWj = function(x, data, offset) {
		var j, w = x.w;
		for (j = 0; j < 16; j++) {
			w[j] = data[offset + j];
		}
		for (j = 16; j < 80; j++) {
			w[j] = Int64.add(
				__lcSigma1(w[j - 2]),
				Int64.add(
					w[j - 7],
					Int64.add(
						__lcSigma0(w[j - 15]),
						w[j - 16]
				)));
		}
	};

	var __update = function(x, data, offset) {

		__calcWj(x, data, offset);
	};

	this.update = __update;

	this.getHash = function(x, dest, offset) {
		// ByteArray
		var i;
		for (i = 0; i < 8; i++) {
			Int64.copyBytes(x.hash[i], dest, offset + i * 8);
		}
	};
}
<|endoftext|>


<commit_before>var Model = {};

Model.Note = function(time, instrument_number, duration, amplitude, frequency, score) {
  this.instrument_number = instrument_number;
  this.start = time;
  this.end = this.start + duration;
  this.amplitude = amplitude / score.maxAmplitude;
  this.frequency = frequency / (score.blockSize / score.rate);
};

Model.Score = function(parameters) {
  var parameters = typeof parameters !== 'undefined' ? parameters : {};

  this.notes = [];
  this.instruments = {};
  this.maxAmplitude = parameters.maxAmplitude || 1;
  this.blockSize = parameters.blockSize || 1;
  this.rate = parameters.rate || 1;
};

Model.Instrument = function() {
  this.unit_generators = [];
};

Model.Oscillator = function() {
};

Model.Output = function() {
};

Model.Instrument.prototype.to_data = function(note, sampleRate) {
  var size = (note.end - note.start) * sampleRate;
  var note_data = new Float32Array(Math.round(size));

  var amplitude = note.amplitude;
  var frequency = note.frequency;
  var angular_frequency = 2*Math.PI*frequency;

  for (var i = 0; i < note_data.length; i++) {
    var t = i / sampleRate;
    note_data[i] = Math.sin(t*angular_frequency) * amplitude;
  }

  return note_data;
};

Model.Score.prototype.getInstrument = function(instrument_number) {
  return this.instruments[instrument_number];
};

Model.Score.prototype.to_data = function(sampleRate) {
  var data = new Float32Array(this.duration * sampleRate);

  this.notes.forEach(function(note) {
    var instrument = this.getInstrument(note.instrument_number);
    var note_data = instrument.to_data(note, sampleRate);

    var start = note.start * sampleRate;

    for (var i = 0; i < note_data.length; i++) {
      data[start+i] += note_data[i];
    };
  }, this);

  return data;
};

module.exports = Model;
<commit_msg>Move calculation of data into unit generators<commit_after>var Model = {};

Model.Note = function(time, instrument_number, duration, amplitude, frequency, score) {
  this.instrument_number = instrument_number;
  this.start = time;
  this.end = this.start + duration;
  this.amplitude = amplitude / score.maxAmplitude;
  this.frequency = frequency / (score.blockSize / score.rate);
};

Model.Score = function(parameters) {
  var parameters = typeof parameters !== 'undefined' ? parameters : {};

  this.notes = [];
  this.instruments = {};
  this.maxAmplitude = parameters.maxAmplitude || 1;
  this.blockSize = parameters.blockSize || 1;
  this.rate = parameters.rate || 1;
};

Model.Instrument = function() {
  this.unit_generators = [];
  this.output = 0;
};

Model.Oscillator = function() {
};

Model.Oscillator.prototype.to_data = function(index, note, instrument, sampleRate) {
  var amplitude = note.amplitude;
  var frequency = note.frequency;
  var angular_frequency = 2*Math.PI*frequency;
  var t = index / sampleRate;

  instrument.output = Math.sin(t*angular_frequency) * amplitude;
};

Model.Output = function() {
};

Model.Output.prototype.to_data = function(index, note, instrument, sampleRate) {
};

Model.Instrument.prototype.to_data = function(note, sampleRate) {
  var size = (note.end - note.start) * sampleRate;
  var note_data = new Float32Array(Math.round(size));

  for (var i = 0; i < note_data.length; i++) {
    this.unit_generators.forEach(function(unit_generator) {
      unit_generator.to_data(i, note, this, sampleRate);
    }, this);

    note_data[i] = this.output;
  }

  return note_data;
};

Model.Score.prototype.getInstrument = function(instrument_number) {
  return this.instruments[instrument_number];
};

Model.Score.prototype.to_data = function(sampleRate) {
  var data = new Float32Array(this.duration * sampleRate);

  this.notes.forEach(function(note) {
    var instrument = this.getInstrument(note.instrument_number);
    var note_data = instrument.to_data(note, sampleRate);

    var start = note.start * sampleRate;

    for (var i = 0; i < note_data.length; i++) {
      data[start+i] += note_data[i];
    };
  }, this);

  return data;
};

module.exports = Model;
<|endoftext|>


<commit_before>/*
 * sharer.js
 *
 * Tiny js lib to create a simple share component. No deps.
 * Version: 0.1.0
 * Author: Ellison Leão
 *
 */

;(function (window, document) {
    "use strict";
    var Sharer = function(elem) {
        this.elem = elem;
    };

    Sharer.prototype = {
        share: function() {
            var sharer = this.elem.getAttribute('data-sharer');
            switch (sharer) {
                case 'facebook':
                    this.fb();
                    break;
                case 'twitter':
                    this.tw();
                    break;
                case 'email':
                    this.email();
                    break;
                case 'googleplus':
                    this.gplus();
                    break;
                default:
                    break;
            }
        },

        fb: function() {
            var url = encodeURIComponent(this.elem.getAttribute('data-url')),
                fbSharer = 'http://www.facebook.com/sharer/sharer.php?u=' + url;
            window.open(fbSharer, '', 'height=400,width=400,scrollbars=no');
        },

       tw: function() {
            var text = this.elem.getAttribute('data-title'),
                params = '?text='+encodeURIComponent(text)+'&url='+encodeURIComponent(this.elem.getAttribute('data-url')),
                url = 'https://twitter.com/intent/tweet/' + params;
            window.open(url, '', 'height=400,width=400,scrollbars=no');
        },

        gplus: function() {
            var url = 'https://plus.google.com/share',
                params = '?url='+encodeURIComponent(this.elem.getAttribute('data-url'));
            window.open(url + params, '', 'width=400,height=400,scrollbars=no');
        },

        email: function() {
            var to = this.elem.getAttribute('data-to'),
                subject = this.elem.getAttribute('data-subject'),
                body = subject + '\n'+ this.elem.getAttribute('data-title') + '\n' + this.elem.getAttribute('data-url'),
                params = to + '?subject='+encodeURIComponent(subject)+'&body='+encodeURIComponent(body);
            window.location.href = "mailto:" + params;
        }
    }

    var elems = document.querySelectorAll('.sharer'),
        i,
        l = elems.length;

    for (i = 0; i < l ; i++) {
        elems[i].addEventListener('click', function(){
            var sharer = new Sharer(this);
            sharer.share();
        });
    }
})(window, document);
<commit_msg>wrapping adding event only when page loads<commit_after>/*
 * sharer.js
 *
 * Tiny js lib to create a simple share component. No deps.
 * Version: 0.1.0
 * Author: Ellison Leao
 *
 */

;(function (window, document) {
    "use strict";
    var Sharer = function(elem) {
        this.elem = elem;
    };

    Sharer.prototype = {
        share: function() {
            var sharer = this.elem.getAttribute('data-sharer');
            switch (sharer) {
                case 'facebook':
                    this.fb();
                    break;
                case 'twitter':
                    this.tw();
                    break;
                case 'email':
                    this.email();
                    break;
                case 'googleplus':
                    this.gplus();
                    break;
                default:
                    break;
            }
        },

        fb: function() {
            var url = encodeURIComponent(this.elem.getAttribute('data-url')),
                fbSharer = 'http://www.facebook.com/sharer/sharer.php?u=' + url;
            window.open(fbSharer, '', 'height=400,width=400,scrollbars=no');
        },

       tw: function() {
            var text = this.elem.getAttribute('data-title'),
                params = '?text='+encodeURIComponent(text)+'&url='+encodeURIComponent(this.elem.getAttribute('data-url')),
                url = 'https://twitter.com/intent/tweet/' + params;
            window.open(url, '', 'height=400,width=400,scrollbars=no');
        },

        gplus: function() {
            var url = 'https://plus.google.com/share',
                params = '?url='+encodeURIComponent(this.elem.getAttribute('data-url'));
            window.open(url + params, '', 'width=400,height=400,scrollbars=no');
        },

        email: function() {
            var to = this.elem.getAttribute('data-to'),
                subject = this.elem.getAttribute('data-subject'),
                body = subject + '\n'+ this.elem.getAttribute('data-title') + '\n' + this.elem.getAttribute('data-url'),
                params = to + '?subject='+encodeURIComponent(subject)+'&body='+encodeURIComponent(body);
            window.location.href = "mailto:" + params;
        }
    }

    window.addEventListener('load', function() {
        var elems = document.querySelectorAll('.sharer'),
            i,
            l = elems.length;

        for (i = 0; i < l ; i++) {
            elems[i].addEventListener('click', function(){
                console.log('adding event on click');
                var sharer = new Sharer(this);
                sharer.share();
            }, false);
        }
    });
})(window, document);
<|endoftext|>


<commit_before>HospitalCheckup.module("Common.Chart", function(Chart, HospitalCheckup, Backbone, Marionette, $, _){

  //all the common elements that all list charts in hospital app will share
  Chart.BarBase = ChartBaseView.extend({
    constructor: function(options) {
      ChartBaseView.apply(this, arguments);
      this.options.bar_padding = options.bar_padding || 4;
      this.options.section = options.section || "infections";
      this.options.stat = options.stat || "ratio";
      this.duration = 500;
      this.easing = "sin-in-out"; // https://github.com/mbostock/d3/wiki/Transitions#wiki-d3_ease
      this.bar_height = (this.dimensions.height / this.collection.length) - this.options.bar_padding;
      this.$chart_container.attr('id', this.el.id+"-container");
      return this;
    },
    draw: function() {
      var data = this.filter_data(this.data);
      this.get_scales(data);
      this.create_axis("x", "bottom"); //super
      this.create_axis("y", "left"); //super
      this.create_svg(); //super
      this.create_svg_containers();
      this.draw_base_bars(data);
      this.draw_data(data);
      this.draw_axes(data);//needs to be on top of bars
    },

    //remove items with no data and sort by stat
    filter_data: function(){
      var chart = this,
      section = chart.options.section,
      stat = chart.options.stat;

      var filtered = chart.data.filter(function(d){
        return d[section][chart.options.measure].na != 1;
      });
      filtered.sort(function(a,b){
        return d3.ascending(a[section][chart.options.measure][stat], b[section][chart.options.measure][stat]);
      });
      return filtered;
    },

    get_xMax: function(data){
      var chart = this;
      return d3.max(data, function(d) { return d[chart.options.section][chart.options.measure].upper });
    },

    get_currentHeight: function(data){
      return (this.options.bar_padding + this.bar_height) * data.length;
    },

    get_scales: function(data) {
      var chart = this;
      chart.yScale = d3.scale.ordinal()
        .rangeBands([0, chart.get_currentHeight(data)])
        .domain(_.map(data, function(d) { return d.display_name; }));

      chart.xScale = d3.scale.linear()
        .rangeRound([0, chart.dimensions.width])
        .domain([0, chart.get_xMax(data)])
        .nice(); //extend bounds to nearest round value
    },

    create_svg_containers: function(){
      //extend this
      return this;
    },

    draw_base_bars: function(data) {
      var chart = this;
      var bars = chart.svg.select("#baseBars").selectAll(".base.bar")
        .data(data);
        //.data(data, function(d){ return d.id });

      bars.exit().transition().duration(chart.duration)
        .ease(chart.easing)
        .style("opacity", 0).remove();

      bars.enter().append("rect")
        .attr("class", "base bar")
        .style("opacity", 0)
        .attr("y", function(d) {
          return chart.yScale(d.display_name);
        })
        .attr("width", chart.dimensions.width)
        .attr("height", chart.bar_height);

      bars.transition().duration(chart.duration)
        .ease(chart.easing)
        .style("opacity", 1)
        //.attr("y", function(d){ return chart.yScale(d.display_name); })
    },

    draw_axes: function(data) {
      var chart = this;
      //create and set x axis position
      chart.svg.select("#axes").append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + chart.get_currentHeight(data) + ")")
        //.attr("text-anchor", "middle")
        .call(chart.xAxis);

      //create and set y axis positions
      var gy = chart.svg.select("#axes").append("g")
        .attr("class", "y axis")
        .attr("y", 6)
        .call(chart.yAxis);
    },

    draw_data: function(data){
      return this;
    },

    onUpdateChart: function(filtered, height){
      var chart = this;

      //update scales and axes
      chart.xScale.domain([0, chart.get_xMax(filtered)]).nice();
      chart.xAxis.scale(chart.xScale);

      chart.svg.select("#axes").selectAll(".x.axis")
        .transition().duration(chart.duration)
        .ease(chart.easing)  // https://github.com/mbostock/d3/wiki/Transitions#wiki-d3_ease
        .attr("transform", "translate(0," + height + ")")
        .call(chart.xAxis);

      chart.yScale.rangeBands([0, height]).domain(_.map(filtered, function(d) { return d.display_name; }));

      chart.svg.select("#axes").selectAll(".y.axis")
        .transition().duration(chart.duration)
        .ease(chart.easing)
        .call(chart.yAxis);

      chart.draw_base_bars(filtered);
      chart.onSelectHospital(chart.selected);
    },

    onSelectHospital: function(label){
      d3.selectAll(".y.axis text").classed("active", function(d){
        return d === label
      });
      this.selected = label; //store it so we can check for it when new labels enter
    },

    set_tooltip: function(chart, obj, measure){
      obj.on("mouseover", function(d) {
        chart.attach_tooltip(d, measure);
      })
      .on("mouseout", function() {
        $("#ttip").remove();
      });
    },

    attach_tooltip: function(data, measure) {
      data.measure = measure; //template needs access

      var tmpl = _.template($("#"+this.options.section+"-tooltip-template").html());
      var tt = $(tmpl(data));
      tt.css("top", (parseFloat(d3.event.layerY - 15)) + "px");
      tt.css("left", (parseFloat(d3.event.layerX + 25)) + "px");
      this.$el.append(tt);
    }
  });

  Chart.BarRangeDot = Chart.BarBase.extend({
    constructor: function(options) {
      Chart.BarBase.apply(this, arguments);
      return this;
    },

    //create containers so that entering items stay layered at the correct depth
    create_svg_containers: function(){
      var chart = this,
      ids = ["baseBars", "rangeBars", "axes", "contextLines", "statCircles"];

      for(var i=0; i<ids.length; i++){
        chart.svg.append("g").attr("id", ids[i]);
      }
    },

    draw_data: function(data){
      this.draw_range_bars(data);
      this.draw_context_lines(data);
      this.draw_stat_circles(data);
    },

    draw_range_bars: function(data){
      var chart = this,
      measure = chart.options.measure,
      section = chart.options.section;

      var rangeBars = chart.svg.select("#rangeBars").selectAll(".range.bar")
        .data(data, function(d){ return d.id });

      rangeBars.exit().transition().duration(chart.duration)
        .ease(chart.easing)
        .style("opacity", 0).remove();

      rangeBars.enter()
      .append("rect")
      .attr("class", "range bar")
        .style("opacity", 0)
      .attr("x", function(d) {
        return chart.xScale(d[section][measure].lower);
      })
      .attr("y", function(d) {
        return chart.yScale(d.display_name);
      })
      .attr("width", function(d){
        return chart.xScale(d[section][measure].upper - d[section][measure].lower)
      })
      .attr("height", chart.bar_height);
      chart.set_tooltip(chart, rangeBars, measure);

      //update
      rangeBars.transition().duration(chart.duration)
        .ease(chart.easing)
        .style("opacity", 1)
        .attr("x", function(d) {
          return chart.xScale(d[section][measure].lower);
        })
        .attr("y", function(d) {
          return chart.yScale(d.display_name);
        })
        .attr("width", function(d){
          return chart.xScale(d[section][measure].upper - d[section][measure].lower);
        })
        .each(function(d){
          var ratingClasses = {"normal": false, "good": false, "bad": false};
          ratingClasses[d[section][measure].ratingClass] = true;
          d3.select(this).classed(ratingClasses);
        });
    },

    draw_context_lines: function(data){
      var chart = this,
      height = chart.get_currentHeight(data),
      avg = HospitalCheckup.Entities.averages.get(chart.options.measure); //TODO this is only for infections, need the others soon

      var contextLines = chart.svg.select("#contextLines");

      contextLines.append("line")
        .attr("y1", 0)
        .attr("y2", height)
        .attr("x1", chart.xScale(avg))
        .attr("x2", chart.xScale(avg))
        .attr("id", "averageLine");

      contextLines.append("text")
        .text("State avg.")
        .attr("text-anchor", function(){
          if(avg < 1){
            return "end"
          } return "start"
        })
        .attr("class", "chart-label")
        .attr("id", "avgTxt")
        .transition().duration(chart.duration)
        .ease(chart.easing)
        .attr("x", chart.xScale(avg))
        .attr("y", -5);

      contextLines.append("line")
        .attr("y1", 0)
        .attr("y2", height)
        .attr("x1", chart.xScale(1)) //benchmark is always 1
        .attr("x2", chart.xScale(1))
        .attr("id", "benchmarkLine");

      contextLines.append("text")
        .text("Benchmark")
        .attr("text-anchor", function(){ //figure out which side the line is on
          if(avg < 1){
            return "start"
          } return "end"
        })
        .attr("class", "chart-label")
        .attr("id", "benchmarkTxt")
        .attr("x", chart.xScale(1))
        .attr("y", -5);
    },

    draw_stat_circles: function(data){
      var chart = this,
      measure = chart.options.measure,
      section = chart.options.section,
      stat = chart.options.stat;

      var circles = chart.svg.select("#statCircles").selectAll(".stat-circle")
        .data(data, function(d){ return d.id });

      circles.exit().transition().duration(chart.duration)
        .ease(chart.easing)
        .style("opacity", 0).remove();;

      circles.enter().append("circle")
        .style("opacity", 0)
        .attr("class", "stat-circle")
        .attr("cx", function(d) {
          return chart.xScale(d[section][measure][stat]);
        })
        .attr("cy", function(d) {
          return chart.yScale(d.display_name)+chart.bar_height/2;
        })
        .attr("r", 6);
        chart.set_tooltip(chart, circles, measure);

      //update
      circles.transition().duration(chart.duration)
        .ease(chart.easing)
        .style("opacity", 1)
        .attr("cx", function(d) {
          return chart.xScale(d[section][measure][stat]);
        })
        .attr("cy", function(d) {
          return chart.yScale(d.display_name)+chart.bar_height/2;
        });
    },

    onUpdateChart: function(criterion){
      this.options.measure = criterion;
      var chart = this,
      filtered = chart.filter_data(),
      height = chart.get_currentHeight(filtered),
      avg = HospitalCheckup.Entities.averages.get(criterion); //TODO need other sections soon

      Chart.BarBase.prototype.onUpdateChart.call(this, filtered, height); //am I doing this right?

      chart.draw_range_bars(filtered);
      chart.draw_stat_circles(filtered);

      //update context lines
      chart.svg.select("#averageLine")
        .transition().duration(chart.duration)
        .ease(chart.easing)
        .attr("y2", height)
        .attr("x1", chart.xScale(avg))
        .attr("x2", chart.xScale(avg));

      chart.svg.select("#avgTxt")
        .transition().duration(chart.duration)
        .ease(chart.easing)
        .attr("x", chart.xScale(avg))
        .attr("text-anchor", function(){
          if(avg < 1){
            return "end"
          } return "start"
        });

      chart.svg.select("#benchmarkLine")
        .transition().duration(chart.duration)
        .ease(chart.easing)
        .attr("y2", height)
        .attr("x1", chart.xScale(1)) //benchmark is always 1
        .attr("x2", chart.xScale(1));

      chart.svg.select("#benchmarkTxt")
        .transition().duration(chart.duration)
        .ease(chart.easing)
        .attr("x", chart.xScale(1))
        .attr("text-anchor", function(){
          if(avg < 1){
            return "start"
          } return "end"
        });
    }
  });

  Chart.HospitalDetail = ChartBaseView.extend({
    constructor: function(options) {
      ChartBaseView.apply(this, arguments);
      return this;
    },
    draw: function(){
      this.get_scales(this.data);
      this.create_axis("x", "bottom"); //super
      this.create_svg(); //super
      this.draw_axes(this.data);
      this.draw_data();

    },

    get_scales: function(data) {
      this.xScale = d3.scale.linear()
        .rangeRound([0, this.dimensions.width])
      .domain([0, d3.max([data.predicted, data.observed])])
        .nice(); //extend bounds to nearest round value
    },

    draw_axes: function(data) {
      //create and set x axis position
      this.svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + this.dimensions.height + ")")
        .call(this.xAxis);
    },

    draw_data: function(){
      this.draw_lines("predicted");
      this.draw_lines("observed");
    },

    draw_lines: function(str){
      var num = this.data[str],
      chart = this;

      this.svg.append("line")
        .attr("class", str)
        .attr("y1", 0)
        .attr("y2", this.dimensions.height)
        .attr("x1", this.xScale(num))
        .attr("x2", this.xScale(num))

      this.svg.append("text").text(d3.round(num, rounder(num)))
      .attr("class", str+" chart-label txt")
      .attr("text-anchor", "middle")
      .attr("x", this.xScale(num))
      .attr("y", function(){
        //if the lables might overlap, bump up the predicted one
        if(str==="observed" | Math.abs(chart.xScale(num) - chart.xScale(chart.data.observed)) >= 21){
          return -5
        }
        return -18
      })

      //round display text relative to its value
      function rounder(num){
        if (num > .1){
          return 1
        } else if (num > .01){
          return 2
        } else {
          return 3
        }
      }
    }
  });
});<commit_msg>Only show benchmark line on infections section<commit_after>HospitalCheckup.module("Common.Chart", function(Chart, HospitalCheckup, Backbone, Marionette, $, _){

  //all the common elements that all list charts in hospital app will share
  Chart.BarBase = ChartBaseView.extend({
    constructor: function(options) {
      ChartBaseView.apply(this, arguments);
      this.options.bar_padding = options.bar_padding || 4;
      this.options.section = options.section || "infections";
      this.options.stat = options.stat || "ratio";
      this.duration = 500;
      this.easing = "sin-in-out"; // https://github.com/mbostock/d3/wiki/Transitions#wiki-d3_ease
      this.bar_height = (this.dimensions.height / this.collection.length) - this.options.bar_padding;
      this.$chart_container.attr('id', this.el.id+"-container");
      return this;
    },
    draw: function() {
      var data = this.filter_data(this.data);
      this.get_scales(data);
      this.create_axis("x", "bottom"); //super
      this.create_axis("y", "left"); //super
      this.create_svg(); //super
      this.create_svg_containers();
      this.draw_base_bars(data);
      this.draw_data(data);
      this.draw_axes(data);//needs to be on top of bars
    },

    //remove items with no data and sort by stat
    filter_data: function(){
      var chart = this,
      section = chart.options.section,
      stat = chart.options.stat;

      var filtered = chart.data.filter(function(d){
        return d[section][chart.options.measure].na != 1;
      });
      filtered.sort(function(a,b){
        return d3.ascending(a[section][chart.options.measure][stat], b[section][chart.options.measure][stat]);
      });
      return filtered;
    },

    get_xMax: function(data){
      var chart = this;
      return d3.max(data, function(d) { return d[chart.options.section][chart.options.measure].upper });
    },

    get_currentHeight: function(data){
      return (this.options.bar_padding + this.bar_height) * data.length;
    },

    get_scales: function(data) {
      var chart = this;
      chart.yScale = d3.scale.ordinal()
        .rangeBands([0, chart.get_currentHeight(data)])
        .domain(_.map(data, function(d) { return d.display_name; }));

      chart.xScale = d3.scale.linear()
        .rangeRound([0, chart.dimensions.width])
        .domain([0, chart.get_xMax(data)])
        .nice(); //extend bounds to nearest round value
    },

    create_svg_containers: function(){
      //extend this
      return this;
    },

    draw_base_bars: function(data) {
      var chart = this;
      var bars = chart.svg.select("#baseBars").selectAll(".base.bar")
        .data(data);
        //.data(data, function(d){ return d.id });

      bars.exit().transition().duration(chart.duration)
        .ease(chart.easing)
        .style("opacity", 0).remove();

      bars.enter().append("rect")
        .attr("class", "base bar")
        .style("opacity", 0)
        .attr("y", function(d) {
          return chart.yScale(d.display_name);
        })
        .attr("width", chart.dimensions.width)
        .attr("height", chart.bar_height);

      bars.transition().duration(chart.duration)
        .ease(chart.easing)
        .style("opacity", 1)
        //.attr("y", function(d){ return chart.yScale(d.display_name); })
    },

    draw_axes: function(data) {
      var chart = this;
      //create and set x axis position
      chart.svg.select("#axes").append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + chart.get_currentHeight(data) + ")")
        //.attr("text-anchor", "middle")
        .call(chart.xAxis);

      //create and set y axis positions
      var gy = chart.svg.select("#axes").append("g")
        .attr("class", "y axis")
        .attr("y", 6)
        .call(chart.yAxis);
    },

    draw_data: function(data){
      return this;
    },

    onUpdateChart: function(filtered, height){
      var chart = this;

      //update scales and axes
      chart.xScale.domain([0, chart.get_xMax(filtered)]).nice();
      chart.xAxis.scale(chart.xScale);

      chart.svg.select("#axes").selectAll(".x.axis")
        .transition().duration(chart.duration)
        .ease(chart.easing)  // https://github.com/mbostock/d3/wiki/Transitions#wiki-d3_ease
        .attr("transform", "translate(0," + height + ")")
        .call(chart.xAxis);

      chart.yScale.rangeBands([0, height]).domain(_.map(filtered, function(d) { return d.display_name; }));

      chart.svg.select("#axes").selectAll(".y.axis")
        .transition().duration(chart.duration)
        .ease(chart.easing)
        .call(chart.yAxis);

      chart.draw_base_bars(filtered);
      chart.onSelectHospital(chart.selected);
    },

    onSelectHospital: function(label){
      d3.selectAll(".y.axis text").classed("active", function(d){
        return d === label
      });
      this.selected = label; //store it so we can check for it when new labels enter
    },

    set_tooltip: function(chart, obj, measure){
      obj.on("mouseover", function(d) {
        chart.attach_tooltip(d, measure);
      })
      .on("mouseout", function() {
        $("#ttip").remove();
      });
    },

    attach_tooltip: function(data, measure) {
      data.measure = measure; //template needs access

      var tmpl = _.template($("#"+this.options.section+"-tooltip-template").html());
      var tt = $(tmpl(data));
      tt.css("top", (parseFloat(d3.event.layerY - 15)) + "px");
      tt.css("left", (parseFloat(d3.event.layerX + 25)) + "px");
      this.$el.append(tt);
    }
  });

  Chart.BarRangeDot = Chart.BarBase.extend({
    constructor: function(options) {
      Chart.BarBase.apply(this, arguments);
      return this;
    },

    //create containers so that entering items stay layered at the correct depth
    create_svg_containers: function(){
      var chart = this,
      ids = ["baseBars", "rangeBars", "axes", "contextLines", "statCircles"];

      for(var i=0; i<ids.length; i++){
        chart.svg.append("g").attr("id", ids[i]);
      }
    },

    draw_data: function(data){
      this.draw_range_bars(data);
      this.draw_context_lines(data);
      this.draw_stat_circles(data);
    },

    draw_range_bars: function(data){
      var chart = this,
      measure = chart.options.measure,
      section = chart.options.section;

      var rangeBars = chart.svg.select("#rangeBars").selectAll(".range.bar")
        .data(data, function(d){ return d.id });

      rangeBars.exit().transition().duration(chart.duration)
        .ease(chart.easing)
        .style("opacity", 0).remove();

      rangeBars.enter()
      .append("rect")
      .attr("class", "range bar")
        .style("opacity", 0)
      .attr("x", function(d) {
        return chart.xScale(d[section][measure].lower);
      })
      .attr("y", function(d) {
        return chart.yScale(d.display_name);
      })
      .attr("width", function(d){
        return chart.xScale(d[section][measure].upper - d[section][measure].lower)
      })
      .attr("height", chart.bar_height);
      chart.set_tooltip(chart, rangeBars, measure);

      //update
      rangeBars.transition().duration(chart.duration)
        .ease(chart.easing)
        .style("opacity", 1)
        .attr("x", function(d) {
          return chart.xScale(d[section][measure].lower);
        })
        .attr("y", function(d) {
          return chart.yScale(d.display_name);
        })
        .attr("width", function(d){
          return chart.xScale(d[section][measure].upper - d[section][measure].lower);
        })
        .each(function(d){
          var ratingClasses = {"normal": false, "good": false, "bad": false};
          ratingClasses[d[section][measure].ratingClass] = true;
          d3.select(this).classed(ratingClasses);
        });
    },

    draw_context_lines: function(data){
      var chart = this,
      height = chart.get_currentHeight(data),
      avg = HospitalCheckup.Entities.averages.get(chart.options.measure); //TODO this is only for infections, need the others soon

      var contextLines = chart.svg.select("#contextLines");

      contextLines.append("line")
        .attr("y1", 0)
        .attr("y2", height)
        .attr("x1", chart.xScale(avg))
        .attr("x2", chart.xScale(avg))
        .attr("id", "averageLine");

      contextLines.append("text")
        .text("State avg.")
        .attr("text-anchor", function(){
          if(avg < 1){
            return "end"
          } return "start"
        })
        .attr("class", "chart-label")
        .attr("id", "avgTxt")
        .transition().duration(chart.duration)
        .ease(chart.easing)
        .attr("x", chart.xScale(avg))
        .attr("y", -5);

      if(chart.options.section === "infections"){
        contextLines.append("line")
          .attr("y1", 0)
          .attr("y2", height)
          .attr("x1", chart.xScale(1)) //benchmark is always 1
          .attr("x2", chart.xScale(1))
          .attr("id", "benchmarkLine");

        contextLines.append("text")
          .text("Benchmark")
          .attr("text-anchor", function(){ //figure out which side the line is on
            if(avg < 1){
              return "start"
            } return "end"
          })
          .attr("class", "chart-label")
          .attr("id", "benchmarkTxt")
          .attr("x", chart.xScale(1))
          .attr("y", -5);
      }
    },

    draw_stat_circles: function(data){
      var chart = this,
      measure = chart.options.measure,
      section = chart.options.section,
      stat = chart.options.stat;

      var circles = chart.svg.select("#statCircles").selectAll(".stat-circle")
        .data(data, function(d){ return d.id });

      circles.exit().transition().duration(chart.duration)
        .ease(chart.easing)
        .style("opacity", 0).remove();;

      circles.enter().append("circle")
        .style("opacity", 0)
        .attr("class", "stat-circle")
        .attr("cx", function(d) {
          return chart.xScale(d[section][measure][stat]);
        })
        .attr("cy", function(d) {
          return chart.yScale(d.display_name)+chart.bar_height/2;
        })
        .attr("r", 6);
        chart.set_tooltip(chart, circles, measure);

      //update
      circles.transition().duration(chart.duration)
        .ease(chart.easing)
        .style("opacity", 1)
        .attr("cx", function(d) {
          return chart.xScale(d[section][measure][stat]);
        })
        .attr("cy", function(d) {
          return chart.yScale(d.display_name)+chart.bar_height/2;
        });
    },

    onUpdateChart: function(criterion){
      this.options.measure = criterion;
      var chart = this,
      filtered = chart.filter_data(),
      height = chart.get_currentHeight(filtered),
      avg = HospitalCheckup.Entities.averages.get(criterion); //TODO need other sections soon

      Chart.BarBase.prototype.onUpdateChart.call(this, filtered, height); //am I doing this right?

      chart.draw_range_bars(filtered);
      chart.draw_stat_circles(filtered);

      //update context lines
      chart.svg.select("#averageLine")
        .transition().duration(chart.duration)
        .ease(chart.easing)
        .attr("y2", height)
        .attr("x1", chart.xScale(avg))
        .attr("x2", chart.xScale(avg));

      chart.svg.select("#avgTxt")
        .transition().duration(chart.duration)
        .ease(chart.easing)
        .attr("x", chart.xScale(avg))
        .attr("text-anchor", function(){
          if(avg < 1){
            return "end"
          } return "start"
        });

      if(chart.options.section === "infections"){
        chart.svg.select("#benchmarkLine")
          .transition().duration(chart.duration)
          .ease(chart.easing)
          .attr("y2", height)
          .attr("x1", chart.xScale(1)) //benchmark is always 1
          .attr("x2", chart.xScale(1));

        chart.svg.select("#benchmarkTxt")
          .transition().duration(chart.duration)
          .ease(chart.easing)
          .attr("x", chart.xScale(1))
          .attr("text-anchor", function(){
            if(avg < 1){
              return "start"
            } return "end"
          });
      }
    }
  });

  Chart.HospitalDetail = ChartBaseView.extend({
    constructor: function(options) {
      ChartBaseView.apply(this, arguments);
      return this;
    },
    draw: function(){
      this.get_scales(this.data);
      this.create_axis("x", "bottom"); //super
      this.create_svg(); //super
      this.draw_axes(this.data);
      this.draw_data();

    },

    get_scales: function(data) {
      this.xScale = d3.scale.linear()
        .rangeRound([0, this.dimensions.width])
      .domain([0, d3.max([data.predicted, data.observed])])
        .nice(); //extend bounds to nearest round value
    },

    draw_axes: function(data) {
      //create and set x axis position
      this.svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + this.dimensions.height + ")")
        .call(this.xAxis);
    },

    draw_data: function(){
      this.draw_lines("predicted");
      this.draw_lines("observed");
    },

    draw_lines: function(str){
      var num = this.data[str],
      chart = this;

      this.svg.append("line")
        .attr("class", str)
        .attr("y1", 0)
        .attr("y2", this.dimensions.height)
        .attr("x1", this.xScale(num))
        .attr("x2", this.xScale(num))

      this.svg.append("text").text(d3.round(num, rounder(num)))
      .attr("class", str+" chart-label txt")
      .attr("text-anchor", "middle")
      .attr("x", this.xScale(num))
      .attr("y", function(){
        //if the lables might overlap, bump up the predicted one
        if(str==="observed" | Math.abs(chart.xScale(num) - chart.xScale(chart.data.observed)) >= 21){
          return -5
        }
        return -18
      })

      //round display text relative to its value
      function rounder(num){
        if (num > .1){
          return 1
        } else if (num > .01){
          return 2
        } else {
          return 3
        }
      }
    }
  });
});<|endoftext|>