<commit_before>var PouchDB = require('pouchdb');
var fs = require('fs');
var md5 = require('md5-jkmyers');
var xlsx = require('xlsx');
var PouchDB = require('pouchdb');
var rootDir = './import-data';
GLOBAL.termCounter = [];
var resendLimit = 9;

var glyphs = ["","","","","","","","","","","","","ʾ","ʿ",""];
var accents =["_Kh","_Gh","_Sh","_Ch","_Th","_th","_ch","_kh","_dh","_zh","_sh","_gh","’","‘","_Dh"];

var conversionHolder ='';
var mainRowCounter = 0;
var subRowCounter = 0;
var worksheetNo = 0;
var filename = '';

module.exports.startProcess = function(req,res){
	if(res!=null)
	{
		res.send("starting Export Process ...");
	}
	console.log("starting Export Process ...");
	//
	//scan for files in rootDir
	// push verified files to ListOfFiles
	var ListOfFiles = [];
	scanDir(rootDir,ListOfFiles);
	checkHash(ListOfFiles);
	// traverse ListOfFiles and process each file
	console.log("waiting for another request ...");
}
// returns Array of directories
function scanDir(sourceDir, ListOfFiles)
{
	var returnedList = [];
	returnedList = fs.readdirSync(sourceDir);
	returnedList.forEach(function(file){
		if(fs.existsSync(rootDir+'/'+file))
		{
			//filename = file;
			ListOfFiles.push(rootDir+'/'+file);
		}
	});
}
function checkHash(ListOfFiles)
{
	ListOfFiles.forEach(function(file){
		GLOBAL.termCounter = [];
		processFiles(file);
		GLOBAL.termCounter = [];
	});
}
function processFiles(file)
{
	console.log("Processing "+file);
	var LastAColumnValue = '';
	var LastBColumnValue = '';
  	var workbook = xlsx.readFile(file);
  	//debugger;
  	var sheet_name_list = workbook.SheetNames;
  	GLOBAL.count_limit = 0;
  	worksheetNo=0;
	sheet_name_list.forEach(function(y) {
		var worksheet = workbook.Sheets[y];
		var columnARegex = /^A.+/gmi;
		var columnBRegex = /^B.+/gmi;
		var columnERegex = /^F.+/gmi;
		mainRowCounter = 0;
		subRowCounter = 0;
		worksheetNo ++;
		conversionHolder='';
		for (z in worksheet) {
			if(z[0] === '!') continue;
			if(columnARegex.test(z) && z[1]>1)//orignal word
			{
				LastAColumnValue = JSON.stringify(worksheet[z].v);
			}
			if(columnBRegex.test(z) && z[1]>1)//accent word
			{
				LastBColumnValue = JSON.stringify(worksheet[z].v);
			}
			if(columnERegex.test(z) && z[1]>1)//description
			{
				mainRowCounter ++;
				saveRecord(file,LastAColumnValue,LastBColumnValue,JSON.stringify(worksheet[z].v));
			}
		}
	});
}
function convertGlyph(Astring,Bstring,Cstring,file)
{
	// subRowCounter ++;
	var oldString = Bstring;

	glyphs.forEach(function(glyph){
		if(Bstring.indexOf(glyph)!=-1)
		{
			var glyphRegex = new RegExp(glyph,"g");
			var myindex = glyphs.indexOf(glyph);
			Bstring = Bstring.replace(glyphRegex, accents[myindex]);
		}
	});
	// console.log(oldString+" -> "+Bstring);
	// conversionHolder=conversionHolder+oldString+" -> "+Bstring+"\n";
	// if(subRowCounter == mainRowCounter)
	// {
	// 	//save data into UTF8 format file
	// 	var filenames = file.split('/');
	// 	filename = filenames[(filenames.length)-1];
	// 	var options = {
	// 		encoding:'utf8'
	// 	};
	// 	//form the data here but we need to also save the definition
	// 	fs.writeFileSync(filename+worksheetNo+".txt", conversionHolder, options);
	// }
	return Bstring;
}
function saveRecord(file,Astring,Bstring,Cstring)
{
	//Structure:
	// {
	// 	id:genUUID('xxxxxxxxxx'),
	// 	source: 'marciel',
	// 	term:{
	// 		word1,
	// 		word2
	// 	},
	// 	original:"string",
	// 	definition:"string"
	// }
	//find existing record with source == 'marciel' and term == Bstring
	var ConvertedBString = convertGlyph(Astring,Bstring,Cstring,file);
	var splitBstring = Bstring.split(" ");
	var splitConvertedBString = ConvertedBString.split(" ");
	var mapFunction = 'function(doc){ if(doc.source == "marciel" ';
	var emitPortion = "emit(doc.original,doc.term);";
	for(var x=0;x<splitConvertedBString.length;x++)
	{
		var temp = '';
		var temp2 = '';
		try{
			temp = eval("("+splitConvertedBString[x]+")");
			temp = splitConvertedBString[x];
		}catch(error){
			if(splitConvertedBString[x].indexOf('"')>0)
			{
				temp = '"'+splitConvertedBString[x];
			}else{
				temp = splitConvertedBString[x]+'"';
			}
			try{
				temp2 = eval("("+temp+")");
			}catch(error){
				temp2 = temp;
				if(temp2.indexOf('"')>0)
				{
					temp = '"'+temp2;
				}else{
					temp = temp2+'"';
				}
			}
		}
		mapFunction = mapFunction+"&& doc.term["+x+"] == "+temp+" ";
	}
	mapFunction = mapFunction+"){"+emitPortion+"}}";
	//console.log(mapFunction);

	queryME(mapFunction,Astring,splitBstring,Cstring,splitConvertedBString);
}

function queryME(mapFunction,Astring,splitBstring,Cstring,splitConvertedBString)
{
	GLOBAL.db.query({"map": mapFunction}, function(err, response){
		//console.log("responding to db.query");
		//GLOBAL.db.viewCleanup();
		if(err==null)
		{
			subRowCounter ++;
			if(response.rows.length>0)
			{
				//then this means that the data is there and we should do nothing
				console.log("DB already has the term "+Astring);
			}else{
				console.log("Processing "+Astring);
				saveME(Astring,splitBstring,Cstring,splitConvertedBString);
			}
		}else{
			if(err.status==404)
			{
				//no data found then we will save the record
				subRowCounter ++;
				console.log(Astring+" term is not found - Saving Term");
				saveME(Astring,splitBstring,Cstring,splitConvertedBString);
			}else{
				if(err.message == undefined)
				{
					console.log("Undefined reached - resending query for "+Astring);
					//GLOBAL.db = new PouchDB(GLOBAL.db_name);
					setImmediate(queryME,mapFunction,Astring,splitBstring,Cstring,splitConvertedBString);
				}else{
					console.log("Error with map query");
					console.log(mapFunction);
					console.log(err);
				}
			}
		}
	});
}
function saveME(Astring,splitBstring,Cstring,splitConvertedBString)
{
	//Structure:
	// {
	// 	id:genUUID('xxxxxxxxxx'),
	// 	source: 'marciel',
	// 	term:[
	// 		word1,
	// 		word2
	// 	],
	// 	original:"string",
	// 	definition:"string"
	// }
	var mystruct = {
		term:[],
		termNonConvert:[]
	};
	mystruct["id"]=genUUID('xxxxxxxxxx');
	mystruct["source"]="marciel";
	splitBstring.forEach(function(word){
		var temp = word;
		temp = temp.replace('"', '');
		temp = temp.replace('"', '');
		mystruct.term.push(temp);
	});
	splitConvertedBString.forEach(function(word){
		var temp = word;
		temp = temp.replace('"', '');
		temp = temp.replace('"', '');
		mystruct.termNonConvert.push(temp);
	});
	mystruct["original"]=eval("("+Astring+")");
	mystruct["definition"]=eval("("+Cstring+")");
	mystruct["type"]="term";
	mystruct["user"]="chad";
	var uid = genUUID();
	saveMEDATA(mystruct,uid,splitBstring);

}
function saveMEDATA(mystruct,uid,Bstring)
{
	//if(process.env.NODE_ENV=='development'){
		//var db = new PouchDB(GLOBAL.db_temp,GLOBAL.PouchDB_opts);
	// }else{
	// 	var db = new PouchDB(remoteLocation+GLOBAL.db_temp,GLOBAL.PouchDB_opts);
	// }

	GLOBAL.db_temp.put(mystruct,uid,function(err,res){
		if(err==null)
		{
			console.log("Saved accent");
			console.log(Bstring);
		}else{
			if(err.message!="undefined")
			{
				if(GLOBAL.termCounter[Bstring] == NaN || GLOBAL.termCounter[Bstring] == undefined)
				{
					GLOBAL.termCounter[Bstring]=1;
				}else{
					GLOBAL.termCounter[Bstring]=GLOBAL.termCounter[Bstring]+1;
				}
				if(GLOBAL.termCounter[Bstring]>resendLimit)
				{
					console.log("Undefined reached");
					console.log("Term "+Bstring+" has reached resend Limit - Terminating resend");
				}else{
					console.log("Undefined reached - resending save for "+Bstring);
					console.log("Current Resend Count : "+GLOBAL.termCounter[Bstring]);
					setImmediate(saveMEDATA,mystruct,uid,Bstring);
				}
			}else{
				console.log("Error Saving Data");
				console.log(err);
			}
		}
	});
}
function genUUID(pattern)
{
	pattern = pattern || 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
	var uuid = pattern.replace(/[xy]/g, function(c) {
		var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
		return v.toString(16);
	});
	return uuid;
};<commit_msg>added secondary check to the access_temp collection if data also exists there<commit_after>var PouchDB = require('pouchdb');
var fs = require('fs');
var md5 = require('md5-jkmyers');
var xlsx = require('xlsx');
var PouchDB = require('pouchdb');
var rootDir = './import-data';
GLOBAL.termCounter = [];
var resendLimit = 9;

var glyphs = ["","","","","","","","","","","","","ʾ","ʿ",""];
var accents =["_Kh","_Gh","_Sh","_Ch","_Th","_th","_ch","_kh","_dh","_zh","_sh","_gh","’","‘","_Dh"];

var conversionHolder ='';
var mainRowCounter = 0;
var subRowCounter = 0;
var worksheetNo = 0;
var filename = '';

module.exports.startProcess = function(req,res){
	if(res!=null)
	{
		res.send("starting Export Process ...");
	}
	console.log("starting Export Process ...");
	//
	//scan for files in rootDir
	// push verified files to ListOfFiles
	var ListOfFiles = [];
	scanDir(rootDir,ListOfFiles);
	checkHash(ListOfFiles);
	// traverse ListOfFiles and process each file
	console.log("waiting for another request ...");
}
// returns Array of directories
function scanDir(sourceDir, ListOfFiles)
{
	var returnedList = [];
	returnedList = fs.readdirSync(sourceDir);
	returnedList.forEach(function(file){
		if(fs.existsSync(rootDir+'/'+file))
		{
			//filename = file;
			ListOfFiles.push(rootDir+'/'+file);
		}
	});
}
function checkHash(ListOfFiles)
{
	ListOfFiles.forEach(function(file){
		GLOBAL.termCounter = [];
		processFiles(file);
		GLOBAL.termCounter = [];
	});
}
function processFiles(file)
{
	console.log("Processing "+file);
	var LastAColumnValue = '';
	var LastBColumnValue = '';
  	var workbook = xlsx.readFile(file);
  	//debugger;
  	var sheet_name_list = workbook.SheetNames;
  	GLOBAL.count_limit = 0;
  	worksheetNo=0;
	sheet_name_list.forEach(function(y) {
		var worksheet = workbook.Sheets[y];
		var columnARegex = /^A.+/gmi;
		var columnBRegex = /^B.+/gmi;
		var columnERegex = /^F.+/gmi;
		mainRowCounter = 0;
		subRowCounter = 0;
		worksheetNo ++;
		conversionHolder='';
		for (z in worksheet) {
			if(z[0] === '!') continue;
			if(columnARegex.test(z) && z[1]>1)//orignal word
			{
				LastAColumnValue = JSON.stringify(worksheet[z].v);
			}
			if(columnBRegex.test(z) && z[1]>1)//accent word
			{
				LastBColumnValue = JSON.stringify(worksheet[z].v);
			}
			if(columnERegex.test(z) && z[1]>1)//description
			{
				mainRowCounter ++;
				saveRecord(file,LastAColumnValue,LastBColumnValue,JSON.stringify(worksheet[z].v));
			}
		}
	});
}
function convertGlyph(Astring,Bstring,Cstring,file)
{
	// subRowCounter ++;
	var oldString = Bstring;

	glyphs.forEach(function(glyph){
		if(Bstring.indexOf(glyph)!=-1)
		{
			var glyphRegex = new RegExp(glyph,"g");
			var myindex = glyphs.indexOf(glyph);
			Bstring = Bstring.replace(glyphRegex, accents[myindex]);
		}
	});
	// console.log(oldString+" -> "+Bstring);
	// conversionHolder=conversionHolder+oldString+" -> "+Bstring+"\n";
	// if(subRowCounter == mainRowCounter)
	// {
	// 	//save data into UTF8 format file
	// 	var filenames = file.split('/');
	// 	filename = filenames[(filenames.length)-1];
	// 	var options = {
	// 		encoding:'utf8'
	// 	};
	// 	//form the data here but we need to also save the definition
	// 	fs.writeFileSync(filename+worksheetNo+".txt", conversionHolder, options);
	// }
	return Bstring;
}
function saveRecord(file,Astring,Bstring,Cstring)
{
	//Structure:
	// {
	// 	id:genUUID('xxxxxxxxxx'),
	// 	source: 'marciel',
	// 	term:{
	// 		word1,
	// 		word2
	// 	},
	// 	original:"string",
	// 	definition:"string"
	// }
	//find existing record with source == 'marciel' and term == Bstring
	var ConvertedBString = convertGlyph(Astring,Bstring,Cstring,file);
	var splitBstring = Bstring.split(" ");
	var splitConvertedBString = ConvertedBString.split(" ");
	var mapFunction = 'function(doc){ if(doc.source == "marciel" ';
	var emitPortion = "emit(doc.original,doc.term);";
	for(var x=0;x<splitConvertedBString.length;x++)
	{
		var temp = '';
		var temp2 = '';
		try{
			temp = eval("("+splitConvertedBString[x]+")");
			temp = splitConvertedBString[x];
		}catch(error){
			if(splitConvertedBString[x].indexOf('"')>0)
			{
				temp = '"'+splitConvertedBString[x];
			}else{
				temp = splitConvertedBString[x]+'"';
			}
			try{
				temp2 = eval("("+temp+")");
			}catch(error){
				temp2 = temp;
				if(temp2.indexOf('"')>0)
				{
					temp = '"'+temp2;
				}else{
					temp = temp2+'"';
				}
			}
		}
		mapFunction = mapFunction+"&& doc.term["+x+"] == "+temp+" ";
	}
	mapFunction = mapFunction+"){"+emitPortion+"}}";
	//console.log(mapFunction);

	queryME(mapFunction,Astring,splitBstring,Cstring,splitConvertedBString);
}

function queryME(mapFunction,Astring,splitBstring,Cstring,splitConvertedBString)
{
	GLOBAL.db.query({"map": mapFunction}, function(err, response){
		//console.log("responding to db.query");
		//GLOBAL.db.viewCleanup();
		if(err==null)
		{
			subRowCounter ++;
			if(response.rows.length>0)
			{
				//then this means that the data is there and we should do nothing
				console.log("DB already has the term "+Astring);
			}else{
				console.log("Processing "+Astring);
				//saveME(Astring,splitBstring,Cstring,splitConvertedBString);
				queryMEtemp(mapFunction,Astring,splitBstring,Cstring,splitConvertedBString);
			}
		}else{
			if(err.status==404)
			{
				//no data found then we will save the record
				subRowCounter ++;
				console.log(Astring+" term is not found - Saving Term");
				//saveME(Astring,splitBstring,Cstring,splitConvertedBString);
				queryMEtemp(mapFunction,Astring,splitBstring,Cstring,splitConvertedBString);
			}else{
				if(err.message == undefined)
				{
					console.log("Undefined reached - resending query for "+Astring);
					//GLOBAL.db = new PouchDB(GLOBAL.db_name);
					setImmediate(queryME,mapFunction,Astring,splitBstring,Cstring,splitConvertedBString);
				}else{
					console.log("Error with map query");
					console.log(mapFunction);
					console.log(err);
				}
			}
		}
	});
}
function queryMEtemp(mapFunction,Astring,splitBstring,Cstring,splitConvertedBString)
{
	GLOBAL.db_temp.query({"map": mapFunction}, function(err, response){
		//console.log("responding to db.query");
		//GLOBAL.db.viewCleanup();
		if(err==null)
		{
			subRowCounter ++;
			if(response.rows.length>0)
			{
				//then this means that the data is there and we should do nothing
				console.log("DB already has the term "+Astring);
			}else{
				console.log("Processing "+Astring);
				saveME(Astring,splitBstring,Cstring,splitConvertedBString);
			}
		}else{
			if(err.status==404)
			{
				//no data found then we will save the record
				subRowCounter ++;
				console.log(Astring+" term is not found - Saving Term");
				saveME(Astring,splitBstring,Cstring,splitConvertedBString);
			}else{
				if(err.message == undefined)
				{
					console.log("Undefined reached - resending query for "+Astring);
					//GLOBAL.db = new PouchDB(GLOBAL.db_name);
					setImmediate(queryMEtemp,mapFunction,Astring,splitBstring,Cstring,splitConvertedBString);
				}else{
					console.log("Error with map query");
					console.log(mapFunction);
					console.log(err);
				}
			}
		}
	});
}
function saveME(Astring,splitBstring,Cstring,splitConvertedBString)
{
	//Structure:
	// {
	// 	id:genUUID('xxxxxxxxxx'),
	// 	source: 'marciel',
	// 	term:[
	// 		word1,
	// 		word2
	// 	],
	// 	original:"string",
	// 	definition:"string"
	// }
	var mystruct = {
		term:[],
		termNonConvert:[]
	};
	mystruct["id"]=genUUID('xxxxxxxxxx');
	mystruct["source"]="marciel";
	splitBstring.forEach(function(word){
		var temp = word;
		temp = temp.replace('"', '');
		temp = temp.replace('"', '');
		mystruct.term.push(temp);
	});
	splitConvertedBString.forEach(function(word){
		var temp = word;
		temp = temp.replace('"', '');
		temp = temp.replace('"', '');
		mystruct.termNonConvert.push(temp);
	});
	mystruct["original"]=eval("("+Astring+")");
	mystruct["definition"]=eval("("+Cstring+")");
	mystruct["type"]="term";
	mystruct["user"]="chad";
	var uid = genUUID();
	saveMEDATA(mystruct,uid,splitBstring);

}
function saveMEDATA(mystruct,uid,Bstring)
{
	//if(process.env.NODE_ENV=='development'){
		//var db = new PouchDB(GLOBAL.db_temp,GLOBAL.PouchDB_opts);
	// }else{
	// 	var db = new PouchDB(remoteLocation+GLOBAL.db_temp,GLOBAL.PouchDB_opts);
	// }

	GLOBAL.db_temp.put(mystruct,uid,function(err,res){
		if(err==null)
		{
			console.log("Saved accent");
			console.log(Bstring);
		}else{
			if(err.message!="undefined")
			{
				if(GLOBAL.termCounter[Bstring] == NaN || GLOBAL.termCounter[Bstring] == undefined)
				{
					GLOBAL.termCounter[Bstring]=1;
				}else{
					GLOBAL.termCounter[Bstring]=GLOBAL.termCounter[Bstring]+1;
				}
				if(GLOBAL.termCounter[Bstring]>resendLimit)
				{
					console.log("Undefined reached");
					console.log("Term "+Bstring+" has reached resend Limit - Terminating resend");
				}else{
					console.log("Undefined reached - resending save for "+Bstring);
					console.log("Current Resend Count : "+GLOBAL.termCounter[Bstring]);
					setImmediate(saveMEDATA,mystruct,uid,Bstring);
				}
			}else{
				console.log("Error Saving Data");
				console.log(err);
			}
		}
	});
}
function genUUID(pattern)
{
	pattern = pattern || 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
	var uuid = pattern.replace(/[xy]/g, function(c) {
		var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
		return v.toString(16);
	});
	return uuid;
};<|endoftext|>


<commit_before>Reveal.addEventListener( 'slidechanged', function( event ) {

    $(function () {
    $('#container2').highcharts({
        chart: {
            type: 'line'
        },
        title: {
            text: 'Camera Promo'
        },
        subtitle: {
            text: 'August 3, 2014 - August 14 2014'
        },
        xAxis: {
            categories:['9/3','9/4','9/5','9/6','9/7','9/8','9/9','9/10','9/11','9/12','9/13','9/14']

        },
        yAxis: {
            title: {
                text: 'Total Response Rate (%)'
            },labels: {
                valueSuffix:"%"
            },
        },
        plotOptions: {
            line: {
                dataLabels: {
                    enabled: true,
                    valueSuffix:"%"
                },
                enableMouseTracking: false
            }
        },
        series: [{
            name: 'Camera Promo',
            data: [4.80,4.56,5.09,3.69,3.68,5.14,4.83,5.14,4.69,4.82,4.71,4.46], color:'#7030a0',lineWidth:'4px'

        }, {
            name: 'Control Dates',
            data: [4.05,3.83,3.83,3.32,3.21,4.39,4.10,4.05,3.83,3.83,3.32,3.21],
                   dashStyle: 'shortdash', color:'#F6DC85',

        }]
    });
});

})<commit_msg>asdfasdfa<commit_after>Reveal.addEventListener( 'slidechanged', function( event ) {

    $(function () {
    $('#container2').highcharts({
        chart: {
            type: 'line'
        },
        title: {
            text: 'Camera Promo'
        },
        subtitle: {
            text: 'August 3, 2014 - August 14 2014'
        },
        xAxis: {
            categories:['9/3','9/4','9/5','9/6','9/7','9/8','9/9','9/10','9/11','9/12','9/13','9/14']

        },
        yAxis: {
            title: {
                text: 'Total Response Rate (%)'
            },labels: {
                valueSuffix:"%"
            },
        }
        plotOptions: {
            line: {
                dataLabels: {
                    enabled: true,
                    valueSuffix:"%"
                },
                enableMouseTracking: false
            }
        },
        series: [{
            name: 'Camera Promo',
            data: [4.80,4.56,5.09,3.69,3.68,5.14,4.83,5.14,4.69,4.82,4.71,4.46], color:'#7030a0',lineWidth:'4px'

        }, {
            name: 'Control Dates',
            data: [4.05,3.83,3.83,3.32,3.21,4.39,4.10,4.05,3.83,3.83,3.32,3.21],
                   dashStyle: 'shortdash', color:'#F6DC85'

        }]
    });
});
<|endoftext|>


<commit_before>var collect = require('collect-stream')
var xtend = require('xtend')
var mapStream = require('through2-map')

var errors = require('../lib/errors')
var toOsmObj = require('../transforms/osm_p2p_to_obj.js')

module.exports = function (osm) {
  return function getHistory (id, cb) {
    var r = osm.kv.createHistoryStream(id).on('error', function (err) {
      if (/^notfound/i.test(err) || err.notFound) {
        err = new errors.NotFound('element id: ' + id)
      }
      if (cb) return cb(err)
      if (stream) return stream.emit('error', err)
    })
    if (cb) {
      collect(r, function (err, rows) {
        if (err) return cb(err)
        cb(null, rows.map(rowMap))
      })
    } else {
      var stream = r.pipe(mapStream.obj(rowMap))
      return stream
    }
  }
}

function rowMap (row) {
  return xtend(toOsmObj.fn(row.value), {
    id: row.key,
    version: row.link
  })
}

function notFound (err) {
  return err && (/^notfound/i.test(err) || err.notFound)
}
<commit_msg>Remove unused fn<commit_after>var collect = require('collect-stream')
var xtend = require('xtend')
var mapStream = require('through2-map')

var errors = require('../lib/errors')
var toOsmObj = require('../transforms/osm_p2p_to_obj.js')

module.exports = function (osm) {
  return function getHistory (id, cb) {
    var r = osm.kv.createHistoryStream(id).on('error', function (err) {
      if (/^notfound/i.test(err) || err.notFound) {
        err = new errors.NotFound('element id: ' + id)
      }
      if (cb) return cb(err)
      if (stream) return stream.emit('error', err)
    })
    if (cb) {
      collect(r, function (err, rows) {
        if (err) return cb(err)
        cb(null, rows.map(rowMap))
      })
    } else {
      var stream = r.pipe(mapStream.obj(rowMap))
      return stream
    }
  }
}

function rowMap (row) {
  return xtend(toOsmObj.fn(row.value), {
    id: row.key,
    version: row.link
  })
}
<|endoftext|>


<commit_before>
(function(){
	var root = this,
		Backbone = root.Backbone,
		sharejs = root.sharejs,
		_ = root._;
	//TODO: Ensure the above imports are resolved and work in node.js

	var diff = (function() {
		//The following two methods were lifted from http://code.google.com/p/google-diff-match-patch/
		var diff_commonPrefix = function(text1, text2) {
			// Quick check for common null cases.
			if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) {
				return 0;
			}
			// Binary search.
			// Performance analysis: http://neil.fraser.name/news/2007/10/09/
			var pointermin = 0;
			var pointermax = Math.min(text1.length, text2.length);
			var pointermid = pointermax;
			var pointerstart = 0;
			while (pointermin < pointermid) {
				if (text1.substring(pointerstart, pointermid) ==
						text2.substring(pointerstart, pointermid)) {
					pointermin = pointermid;
					pointerstart = pointermin;
				} else {
					pointermax = pointermid;
				}
				pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
			}
			return pointermid;
		};

		var diff_commonSuffix = function(text1, text2) {
			// Quick check for common null cases.
			if (!text1 || !text2 ||
					text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) {
				return 0;
			}
			// Binary search.
			// Performance analysis: http://neil.fraser.name/news/2007/10/09/
			var pointermin = 0;
			var pointermax = Math.min(text1.length, text2.length);
			var pointermid = pointermax;
			var pointerend = 0;
			while (pointermin < pointermid) {
				if (text1.substring(text1.length - pointermid, text1.length - pointerend) ==
						text2.substring(text2.length - pointermid, text2.length - pointerend)) {
					pointermin = pointermid;
					pointerend = pointermin;
				} else {
					pointermax = pointermid;
				}
				pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
			}
			return pointermid;
		};

		return function(str1, str2) {
			var prefix = diff_commonPrefix(str1, str2),
				suffix = diff_commonSuffix(str1, str2);

			return {
				d: str1.substring(prefix, str1.length - suffix),
				i: str2.substring(prefix, str2.length - suffix),
				p: prefix
			};
		};

	}).call(this);

	//Lifted from jQuery
	var type = (function() {
		var class2type = {};

		_.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(name) {
			class2type[ "[object " + name + "]" ] = name.toLowerCase();
		});

		return function( obj ) {
			return obj == null ?
				String(obj ):
				class2type[Object.prototype.toString.call(obj)] || "object";
		}
	}).call(this);

	var S4 = function() {
		return (((1 + Math.random()) * 65536) | 0).toString(16).substring(1);
	};

	var generateGUID = function() {
		return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4();
	};

	var isShareModel = function(obj) {
		return obj instanceof Backbone.SharedModel || obj instanceof Backbone.SharedCollection;
	};

	Backbone.SharedModel = Backbone.Model.extend({
		constructor: function(attr, options) {
			Backbone.Model.prototype.constructor.apply(this, arguments);

			var self = this;

			attr = attr || {};
			options = options || {};

			this.set('id', attr.id || generateGUID());

			this.defaults = this.defaults || {};
			this.documentPath = options.documentPath || this.generateDocumentPath();
			this.pendingOperations = [];

			if (!this.subDocTypes) {
				this._inferSubDocTypes();
			}

			if (!Array.isArray(this.documentPath)) {
				throw new Error('Document path must be an array');
			}

			if (options.parent) {
				this.setParent(options.parent);
			} else if (!options.defer) {
				this.isRoot = true;
				this.documentName = options.documentName || this.generateDocumentName();
				sharejs.open(this.documentName, 'json', function(err, doc) {
					if (err) throw err;

					console.log('Opened document "' + self.documentName + '"');
					self.initShareDoc(doc);
				});
			}

			this.on("change", function(model, options) {
				if (!options || !options.local) {
					return self._sendModelChange(options);
				}
			});
		},

		setParent: function(parent) {
			var self = this;

			this.parent = parent;

			if (this.parent.shareDoc) {
				this.isRoot = false;
				this.initShareDoc(this.parent.shareDoc);
			} else {
				this.parent.on('share:connected', function(shareDoc) {
					self.isRoot = false;
					self.initShareDoc(shareDoc);
				});
			}
		},

		generateDocumentPath: function() {
			return [];
		},

		generateDocumentName: function() {
			return this.get('id');
		},

		initShareDoc: function(shareDoc) {
			var self = this, attributes;

			if (shareDoc.type.name !== 'json') {
				throw new Error('ShareJS document must be of type "json"');
			}

			this.shareDoc = shareDoc;

			if (shareDoc.created) {
				shareDoc.submitOp([{p: this.documentPath, od: null, oi: this.toJSON()}]);
				shareDoc.created = false;
			}

			shareDoc.on('remoteop', function(ops) {
				_.each(ops, function(op, i) {
					if (_.isEqual(op.p, self.documentPath)) {
						this._handleOperation(op);
					}
				});
			});

			if (this.pendingOperations.length) {
				shareDoc.submitOp(this.pendingOperations, function(error) {
					if (!error) self.pendingOperations.length = 0;
					this.trigger('share:connected', this.shareDoc);
				});
			} else {
				this.trigger('share:connected', this.shareDoc);
			}
		},

		_inferSubDocTypes: function() {
			this.subDocTypes = {};
			_.each(_.pairs(this.attributes), function(pair) {
				var k = pair[0], v = pair[1];

				if (isShareModel(v)) {
					subDocTypes[k] = Object.getPrototypeOf(v).constructor;
				}
			});
		},

		_sendModelChange: function() {
			var self = this;

			var ops = [];
			_.each(_.pairs(this.changedAttributes()), function(pair) {
				var k = pair[0], v = pair[1], t = type(v), prev = self.previous(k);
				var result, textDiff;
				result = {p: self.documentPath.concat([k])};
				switch(t) {
					case 'string':
						textDiff = diff(prev, v);
						result.p.push(textDiff.p);

						if (!!textDiff.d) {
							result.sd = textDiff.d;
						}
						if (!!textDiff.i) {
							if (result.sd) {
								ops.push(result);
								result = _.clone(result);
								delete result.sd;
							}
							result.si = textDiff.i;
						}
						break;
					case 'number':
						result.na = v - prev;
						break;
					case 'boolean':
						result.oi = v;
						result.od = !v;
						break;
					case 'object':
					case 'array':
						if (isShareModel(v)) {
							result.oi = v.toJSON();
						} else {
							result.oi = v;
						}

						if (prev) {
							if (isShareModel(prev)) {
								result.od = prev.toJSON();
							} else {
								result.od = prev;
							}
						}
						break;
					case 'null':
					case 'undefined':
						if (isShareModel(prev)) {
							result.od = prev.toJSON();
						} else {
							result.od = prev;
						}
						break;
					default:
						console.log('Ignoring attempt to send change on type ' + t);
						break;
				}

				return ops.push(result);
			});

			if (this.shareDoc) {
				console.log('Sending:', ops);
				this.shareDoc.submitOp(ops, function(error, ops) {
					//self.shareDoc.submitOp(self.shareDoc.type.invert(ops), function() {
						console.log(arguments);
					//});
				});
			} else {
				Array.prototype.push(pendingOperations, ops);
			}
		},

		_handleOperation: function (op) {
		},

		_handleStringOperation: function(op) {
			var pathProp = op.p[op.p.length - 2],
				pathIndex = op.p[op.p.length - 1],
				original = this.get(pathProp),
				modified, deleted;

			if (op.si) {
				this.set(
					pathProp,
					original.slice(0, pathIndex) + op.si + original.slice(pathIndex),
					{local: true}
				);
			}

			if (op.sd) {
				deleted = original.slice(pathIndex, pathIndex + op.sd.length);
				if (op.sd !== deleted) {
					throw new Error('Delete component ' + op.sd + ' does not match deleted text ' + deleted);
				}
				modified = original.slice(0, pathIndex) + original.slice(pathIndex + op.sd.length);

				this.set(pathProp, modified, {local: true});
			}
		},

		_handleObjectOperation: function(op) {
			if (!_.isEqual(op.p.slice(0, op.p.length - 1), this.documentPath)) return;

			var pathProp = op.p[op.p.length - 1],
				obj = this.get(pathProp),
				subDocType = this.subDocTypes[pathProp];

			if (op.oi || op.oi === false) {
				if (subDocType) {
					this.set(pathProp, new subDocType(op.oi), {local: true});
				} else {
					this.set(pathProp, op.oi, {local: true});
				}
			} else {
				this.unset(pathProp, {local: true});
			}
		},

		_handleNumberOperation: function(op) {
			var pathProp = op.p[op.p.length - 1],
				currentValue = this.get(pathProp);

			this.set(pathProp, currentValue + op.na, {local: true});
		}
	});

	// Collection path should be a simple name?
	// Need to deal with non-roots
	// Need to deal with hooking up parents to children
	// Need to come up with undo-redo
	// Check paths on receiving ops
	// Need to validate models
	// Error handling on submitOp
	// Verify re-opening works

	Backbone.SharedCollection = Backbone.Collection.extend({
		constructor: function(models, options) {
			Backbone.Collection.prototype.constructor.apply(this, arguments);

			var self = this;

			options = options || {};

			this.documentPath = options.documentPath || this.generateDocumentPath();

			if (!Array.isArray(this.documentPath)) {
				throw new Error('Document path must be an array');
			}

			if (options.shareDoc) {
				this.isRoot = false;
				this.initShareDoc(options.shareDoc);
			} else {
				this.isRoot = true;
				this.documentName = options.documentName || this.generateDocumentName();
				sharejs.open(this.documentName, 'json', function(err, doc) {
					if (err) throw err;

					console.log('Opened document "' + self.documentName + '"');
					self.initShareDoc(doc);
				});
			}
		},

		generateDocumentPath: function() {
			return [];
		},

		generateDocumentName: function() {
			return generateGUID();
		},

		initShareDoc: function(shareDoc) {
			var self = this;

			if (shareDoc.type.name !== 'json') {
				throw new Error('ShareJS document must be of type "json"');
			}

			this.shareDoc = shareDoc;

			if (shareDoc.created) {
				shareDoc.submitOp([{p: [], oi: this.toJSON()}]);
			}

			shareDoc.on('remoteop', function(ops) {
				_.each(ops, function(op, i) {
					if (_.isEqual(op.p, self.documentPath)) {
						this._handleListOperation(op);
					}
				});
			});

			this.on("add", function(model, options) {
				if (!options || !options.local) {
					return self._sendModelAdd(options);
				}
			});

			this.on("remove", function(model, options) {
				if (!options || !options.local) {
					return self._sendModelRemove(options);
				}
			});
		},

		_sendModelAdd: function(model, options) {
			var ops = [{
				p: this.documentPath.concat(
					[options && options.at ? options.at : this.length - 1]),
				li: model.toJSON()
			}];

			this.shareDoc.submitOp(ops, function(error, ops) {
				//self.shareDoc.submitOp(self.shareDoc.type.invert(ops), function() {
					console.log(arguments);
				//});
			});
		},

		_sendModelRemove: function(model, options) {
			var ops = [{
				p: this.documentPath.concat(
					[options && options.index ? options.index : this.length - 1]),
				ld: model.toJSON()
			}];

			this.shareDoc.submitOp(ops, function(error, ops) {
				//self.shareDoc.submitOp(self.shareDoc.type.invert(ops), function() {
					console.log(arguments);
				//});
			});
		},

		_handleListOperation: function(op) {
			if (op.li) {
				this.create(op.li, {local: true});
			}

			if (op.ld) {
				this.remove(op.ld, {local: true});
			}
		}
	});

}).call(this);<commit_msg>Moved path comparison responsibility down<commit_after>
(function(){
	var root = this,
		Backbone = root.Backbone,
		sharejs = root.sharejs,
		_ = root._;
	//TODO: Ensure the above imports are resolved and work in node.js

	var diff = (function() {
		//The following two methods were lifted from http://code.google.com/p/google-diff-match-patch/
		var diff_commonPrefix = function(text1, text2) {
			// Quick check for common null cases.
			if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) {
				return 0;
			}
			// Binary search.
			// Performance analysis: http://neil.fraser.name/news/2007/10/09/
			var pointermin = 0;
			var pointermax = Math.min(text1.length, text2.length);
			var pointermid = pointermax;
			var pointerstart = 0;
			while (pointermin < pointermid) {
				if (text1.substring(pointerstart, pointermid) ==
						text2.substring(pointerstart, pointermid)) {
					pointermin = pointermid;
					pointerstart = pointermin;
				} else {
					pointermax = pointermid;
				}
				pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
			}
			return pointermid;
		};

		var diff_commonSuffix = function(text1, text2) {
			// Quick check for common null cases.
			if (!text1 || !text2 ||
					text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) {
				return 0;
			}
			// Binary search.
			// Performance analysis: http://neil.fraser.name/news/2007/10/09/
			var pointermin = 0;
			var pointermax = Math.min(text1.length, text2.length);
			var pointermid = pointermax;
			var pointerend = 0;
			while (pointermin < pointermid) {
				if (text1.substring(text1.length - pointermid, text1.length - pointerend) ==
						text2.substring(text2.length - pointermid, text2.length - pointerend)) {
					pointermin = pointermid;
					pointerend = pointermin;
				} else {
					pointermax = pointermid;
				}
				pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
			}
			return pointermid;
		};

		return function(str1, str2) {
			var prefix = diff_commonPrefix(str1, str2),
				suffix = diff_commonSuffix(str1, str2);

			return {
				d: str1.substring(prefix, str1.length - suffix),
				i: str2.substring(prefix, str2.length - suffix),
				p: prefix
			};
		};

	}).call(this);

	//Lifted from jQuery
	var type = (function() {
		var class2type = {};

		_.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(name) {
			class2type[ "[object " + name + "]" ] = name.toLowerCase();
		});

		return function( obj ) {
			return obj == null ?
				String(obj ):
				class2type[Object.prototype.toString.call(obj)] || "object";
		}
	}).call(this);

	var S4 = function() {
		return (((1 + Math.random()) * 65536) | 0).toString(16).substring(1);
	};

	var generateGUID = function() {
		return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4();
	};

	var isShareModel = function(obj) {
		return obj instanceof Backbone.SharedModel || obj instanceof Backbone.SharedCollection;
	};

	Backbone.SharedModel = Backbone.Model.extend({
		constructor: function(attr, options) {
			Backbone.Model.prototype.constructor.apply(this, arguments);

			var self = this;

			attr = attr || {};
			options = options || {};

			this.set('id', attr.id || generateGUID());

			this.defaults = this.defaults || {};
			this.documentPath = options.documentPath || this.generateDocumentPath();
			this.pendingOperations = [];

			if (!this.subDocTypes) {
				this._inferSubDocTypes();
			}

			if (!Array.isArray(this.documentPath)) {
				throw new Error('Document path must be an array');
			}

			if (options.parent) {
				this.setParent(options.parent);
			} else if (!options.defer) {
				this.isRoot = true;
				this.documentName = options.documentName || this.generateDocumentName();
				sharejs.open(this.documentName, 'json', function(err, doc) {
					if (err) throw err;

					console.log('Opened document "' + self.documentName + '"');
					self.initShareDoc(doc);
				});
			}

			this.on("change", function(model, options) {
				if (!options || !options.local) {
					return self._sendModelChange(options);
				}
			});
		},

		setParent: function(parent) {
			var self = this;

			this.parent = parent;

			if (this.parent.shareDoc) {
				this.isRoot = false;
				this.initShareDoc(this.parent.shareDoc);
			} else {
				this.parent.on('share:connected', function(shareDoc) {
					self.isRoot = false;
					self.initShareDoc(shareDoc);
				});
			}
		},

		generateDocumentPath: function() {
			return [];
		},

		generateDocumentName: function() {
			return this.get('id');
		},

		initShareDoc: function(shareDoc) {
			var self = this, attributes;

			if (shareDoc.type.name !== 'json') {
				throw new Error('ShareJS document must be of type "json"');
			}

			this.shareDoc = shareDoc;

			if (shareDoc.created) {
				shareDoc.submitOp([{p: this.documentPath, od: null, oi: this.toJSON()}]);
				shareDoc.created = false;
			}

			shareDoc.on('remoteop', function(ops) {
				_.each(ops, function(op, i) {
					if (_.isEqual(op.p, self.documentPath)) {
						this._handleOperation(op);
					}
				});
			});

			if (this.pendingOperations.length) {
				shareDoc.submitOp(this.pendingOperations, function(error) {
					if (!error) self.pendingOperations.length = 0;
					this.trigger('share:connected', this.shareDoc);
				});
			} else {
				this.trigger('share:connected', this.shareDoc);
			}
		},

		_inferSubDocTypes: function() {
			this.subDocTypes = {};
			_.each(_.pairs(this.attributes), function(pair) {
				var k = pair[0], v = pair[1];

				if (isShareModel(v)) {
					subDocTypes[k] = Object.getPrototypeOf(v).constructor;
				}
			});
		},

		_sendModelChange: function() {
			var self = this;

			var ops = [];
			_.each(_.pairs(this.changedAttributes()), function(pair) {
				var k = pair[0], v = pair[1], t = type(v), prev = self.previous(k);
				var result, textDiff;
				result = {p: self.documentPath.concat([k])};
				switch(t) {
					case 'string':
						textDiff = diff(prev, v);
						result.p.push(textDiff.p);

						if (!!textDiff.d) {
							result.sd = textDiff.d;
						}
						if (!!textDiff.i) {
							if (result.sd) {
								ops.push(result);
								result = _.clone(result);
								delete result.sd;
							}
							result.si = textDiff.i;
						}
						break;
					case 'number':
						result.na = v - prev;
						break;
					case 'boolean':
						result.oi = v;
						result.od = !v;
						break;
					case 'object':
					case 'array':
						if (isShareModel(v)) {
							result.oi = v.toJSON();
						} else {
							result.oi = v;
						}

						if (prev) {
							if (isShareModel(prev)) {
								result.od = prev.toJSON();
							} else {
								result.od = prev;
							}
						}
						break;
					case 'null':
					case 'undefined':
						if (isShareModel(prev)) {
							result.od = prev.toJSON();
						} else {
							result.od = prev;
						}
						break;
					default:
						console.log('Ignoring attempt to send change on type ' + t);
						break;
				}

				return ops.push(result);
			});

			if (this.shareDoc) {
				console.log('Sending:', ops);
				this.shareDoc.submitOp(ops, function(error, ops) {
					//self.shareDoc.submitOp(self.shareDoc.type.invert(ops), function() {
						console.log(arguments);
					//});
				});
			} else {
				Array.prototype.push(pendingOperations, ops);
			}
		},

		_handleOperation: function (op) {
			if (op.si || op.sd) this._handleStringOperation(op);
			if (op.oi || op.od) this._handleObjectOperation(op);
			if (op.na) this._handleNumberOperation(op);
		},

		_handleStringOperation: function(op) {
			if (!_.isEqual(op.p.slice(0, op.p.length - 2), this.documentPath)) return;

			var pathProp = op.p[op.p.length - 2],
				pathIndex = op.p[op.p.length - 1],
				original = this.get(pathProp),
				modified, deleted;

			if (op.si) {
				this.set(
					pathProp,
					original.slice(0, pathIndex) + op.si + original.slice(pathIndex),
					{local: true}
				);
			}

			if (op.sd) {
				deleted = original.slice(pathIndex, pathIndex + op.sd.length);
				if (op.sd !== deleted) {
					throw new Error('Delete component ' + op.sd + ' does not match deleted text ' + deleted);
				}
				modified = original.slice(0, pathIndex) + original.slice(pathIndex + op.sd.length);

				this.set(pathProp, modified, {local: true});
			}
		},

		_handleObjectOperation: function(op) {
			if (!_.isEqual(op.p.slice(0, op.p.length - 1), this.documentPath)) return;

			var pathProp = op.p[op.p.length - 1],
				obj = this.get(pathProp),
				subDocType = this.subDocTypes[pathProp];

			if (op.oi || op.oi === false) {
				if (subDocType) {
					this.set(pathProp, new subDocType(op.oi), {local: true});
				} else {
					this.set(pathProp, op.oi, {local: true});
				}
			} else {
				this.unset(pathProp, {local: true});
			}
		},

		_handleNumberOperation: function(op) {
			if (!_.isEqual(op.p.slice(0, op.p.length - 1), this.documentPath)) return;

			var pathProp = op.p[op.p.length - 1],
				currentValue = this.get(pathProp);

			this.set(pathProp, currentValue + op.na, {local: true});
		}
	});

	// Collection path should be a simple name?
	// Need to deal with non-roots
	// Need to deal with hooking up parents to children
	// Need to come up with undo-redo
	// Check paths on receiving ops
	// Need to validate models
	// Error handling on submitOp
	// Verify re-opening works

	Backbone.SharedCollection = Backbone.Collection.extend({
		constructor: function(models, options) {
			Backbone.Collection.prototype.constructor.apply(this, arguments);

			var self = this;

			options = options || {};

			this.documentPath = options.documentPath || this.generateDocumentPath();

			if (!Array.isArray(this.documentPath)) {
				throw new Error('Document path must be an array');
			}

			if (options.shareDoc) {
				this.isRoot = false;
				this.initShareDoc(options.shareDoc);
			} else {
				this.isRoot = true;
				this.documentName = options.documentName || this.generateDocumentName();
				sharejs.open(this.documentName, 'json', function(err, doc) {
					if (err) throw err;

					console.log('Opened document "' + self.documentName + '"');
					self.initShareDoc(doc);
				});
			}
		},

		generateDocumentPath: function() {
			return [];
		},

		generateDocumentName: function() {
			return generateGUID();
		},

		initShareDoc: function(shareDoc) {
			var self = this;

			if (shareDoc.type.name !== 'json') {
				throw new Error('ShareJS document must be of type "json"');
			}

			this.shareDoc = shareDoc;

			if (shareDoc.created) {
				shareDoc.submitOp([{p: [], oi: this.toJSON()}]);
			}

			shareDoc.on('remoteop', function(ops) {
				_.each(ops, function(op, i) {
					if (_.isEqual(op.p, self.documentPath)) {
						this._handleListOperation(op);
					}
				});
			});

			this.on("add", function(model, options) {
				if (!options || !options.local) {
					return self._sendModelAdd(options);
				}
			});

			this.on("remove", function(model, options) {
				if (!options || !options.local) {
					return self._sendModelRemove(options);
				}
			});
		},

		_sendModelAdd: function(model, options) {
			var ops = [{
				p: this.documentPath.concat(
					[options && options.at ? options.at : this.length - 1]),
				li: model.toJSON()
			}];

			this.shareDoc.submitOp(ops, function(error, ops) {
				//self.shareDoc.submitOp(self.shareDoc.type.invert(ops), function() {
					console.log(arguments);
				//});
			});
		},

		_sendModelRemove: function(model, options) {
			var ops = [{
				p: this.documentPath.concat(
					[options && options.index ? options.index : this.length - 1]),
				ld: model.toJSON()
			}];

			this.shareDoc.submitOp(ops, function(error, ops) {
				//self.shareDoc.submitOp(self.shareDoc.type.invert(ops), function() {
					console.log(arguments);
				//});
			});
		},

		_handleListOperation: function(op) {
			if (op.li) {
				this.create(op.li, {local: true});
			}

			if (op.ld) {
				this.remove(op.ld, {local: true});
			}
		}
	});

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


<commit_before>var async = require('async');
var _mapValues = require('lodash/mapValues');
var _zipObject = require('lodash/zipObject');
var _filter = require('lodash/filter');

var DEFAULT_PAGESIZE = 50;

/**
 * This is a collection of methods that allow you to create, update and delete social items.
 *
 * These methods all exclude the 'loggedinuser' parameter as they are all carried out only by
 * the currently logged in user and / or system level calls (e.g. adding a user via integration
 * with an SSO flow).
 *
 */
module.exports = function (api) {
  var client = api.client;
  var messaging = api.messaging;
  var q = client.queries;

  function joinGroup (keyspace, group, user, timestamp, cb) {
    var memberValues = [group, user, timestamp];
    client.execute(q(keyspace, 'upsertMember'), memberValues, function (err) {
      if (err) return cb(err);
      getGroup(keyspace, group, function (err, result) {
        if (err) return cb(err);
        var joinGroupContent = {
          category: 'social-group',
          type: 'new-member',
          data: {
            group: {
              id: group,
              name: result.groupname
            }
          }
        };
        api.post.addPost(keyspace, user, joinGroupContent, 'application/json', timestamp, 'public', function (err, result) {
          if (err) return cb(err);
          cb(null, _zipObject(['group', 'user', 'timestamp'], memberValues));
        });
      });
    });
  }

  function addGroup (keyspace, groupName, supergroupId, user, timestamp, options, next) {
    if (!next) {
      next = options;
      options = {};
    }

    var groupData = options.groupData || {};
    var group = client.isValidId(options.group) ? options.group : client.generateId();

    groupData = _mapValues(groupData, function (value) {
      return value.toString();
    }); // Always ensure our groupdata is <text,text>

    // Check group doesn't already exist with this name in this supergroup
    getGroupByNameWithinSupergroup(keyspace, groupName, supergroupId, function (err, existingGroup) {
      if (err && err.statusCode !== 404) { return next(err); }
      if (existingGroup) {
        return next({
          statusCode: 409,
          message: 'Group with groupname ' + groupName + ' already exists for supergroupId ' + supergroupId
        });
      }

      var groupValues = [group, groupData, groupName, supergroupId];

      client.execute(q(keyspace, 'upsertGroup'), groupValues, {}, function (err, result) {
        if (err) { return next(err); }
        joinGroup(keyspace, group, user, timestamp, function (err, result) {
          if (err) { return next(err); }
          next(null, _zipObject(['group', 'groupData', 'groupName', 'supergroupId'], groupValues));
        });
      });
    });
  }

  function getGroupByNameWithinSupergroup (keyspace, groupName, supergroupId, next) {
    client.get(q(keyspace, 'selectGroupByNameAndSupergroup'), [groupName, supergroupId], {}, function (err, result) {
      if (err) { return next(err); }
      if (!result) { return next(api.common.error(404, 'Unable to find group by groupName: ' + groupName + ' and supergroupId ' + supergroupId)); }
      next(null, result);
    });
  }

  function getGroup (keyspace, group, next) {
    client.get(q(keyspace, 'selectGroupById'), [group], {}, function (err, result) {
      if (err) { return next(err); }
      if (!result) { return next(api.common.error(404, 'Unable to find group by id: ' + group)); }
      next(null, result);
    });
  }

  function getGroups (keyspace, groups, next) {
    async.map(groups, function (group, cb) {
      getGroup(keyspace, group, function (err, result) {
        if (err) return cb();
        cb(null, result);
      });
    }, next);
  }

  function updateGroup (keyspace, userAltid, group, groupName, supergroupId, groupData, next) {
    getGroup(keyspace, group, function (err, result) {
      if (err) { return next(err); }

      if (userAltid.toString() !== result.groupdata.admin) {
        return next(new Error('Unable to update the group, only admin can update it.'));
      }

      groupData = _mapValues(groupData, function (value) {
        return value.toString();
      }); // Always ensure our groupData is <text,text>

      var groupValues = [groupName, supergroupId, groupData, group];
      client.execute(q(keyspace, 'updateGroup'), groupValues, {}, function (err, value) {
        if (err) { return next(err); }
        next(null, _zipObject(['groupName', 'supergroupId', 'groupData', 'group'], groupValues));
      });
    });
  }

  function removeMembers (jobData, cb) {
    client.execute(q(jobData.keyspace, 'removeMembers'), [jobData.group], function (err) {
      if (err) return cb(err);
      cb(null, { status: 'removed' });
    });
  }

  function removeMembersByUser (keyspace, user, next) {
    client.execute(q(keyspace, 'selectGroupsForUser'), [user], function (err, results) {
      if (err) return next(err);
      async.each(results, function (member, cb) {
        client.execute(q(keyspace, 'removeMember'), [member.group, user], cb);
      }, next);
    });
  }

  function removeGroup (keyspace, userAltid, user, group, next) {
    getGroup(keyspace, group, function (err, result) {
      if (err) { return next(err); }
      if (userAltid.toString() !== result.groupdata.admin) {
        return next(new Error('Unable to remove the group, only admin can remove it.'));
      }
      var jobData = {
        keyspace: keyspace,
        user: user,
        group: group
      };

      var _removeMembers = function (cb) {
        if (messaging.enabled) {
          messaging.submit('seguir-remove-members', jobData, cb);
        } else {
          removeMembers(jobData, cb);
        }
      };
      var _removeGroup = function (cb) {
        client.execute(q(keyspace, 'removeGroup'), [group], function (err) {
          if (err) return cb(err);
          cb(null, { status: 'removed' });
        });
      };
      async.series([
        _removeMembers,
        _removeGroup
      ], next);
    });
  }

  function getGroupsByUser (keyspace, user, next) {
    client.execute(q(keyspace, 'selectGroupsForUser'), [user], function (err, results) {
      if (err) return next(err);

      if (results && results.length > 0) {
        async.map(results, function (group, cb) {
          getGroup(keyspace, group.group, function (err, result) {
            if (err) {
              return cb(null, null);
            }
            cb(null, result);
          });
        }, function (err, groups) {
          if (err) { return next(err); }
          var existingGroups = _filter(groups, function (group) {
            return group !== null;
          });
          next(null, existingGroups);
        });
      } else {
        next(null, []);
      }
    });
  }

  function getGroupsBySupergroupId (keyspace, supergroupId, liu, options, next) {
    if (!next) {
      next = options;
      options = {};
    }
    var pageState = options.pageState;
    var pageSize = options.pageSize || DEFAULT_PAGESIZE;

    client.execute(q(keyspace, 'selectGroupsBySupergroupId'), [supergroupId], {pageState: pageState, pageSize: pageSize}, function (err, data, nextPageState) {
      if (err) { return next(err); }

      if (data && data.length > 0) {
        async.map(data, function (item, cb) {
          api.common.isUserGroupMember(keyspace, liu, item.group, function (err) {
            if (!err) {
              item.isMember = true;
            }
            cb();
          });
        }, function () {
          next(null, data, nextPageState);
        });
      } else {
        next(null, []);
      }
    });
  }

  function getGroupMembers (keyspace, group, next) {
    client.execute(q(keyspace, 'selectGroupMembers'), [group], {}, function (err, groupMembers) {
      if (err) { return next(err); }

      async.mapSeries(groupMembers, function (member, cb) {
        api.user.mapUserIdToUser(keyspace, member, ['user'], cb);
      }, next);
    });
  }

  function leaveGroup (keyspace, group, user, cb) {
    var memberValues = [group, user];
    client.execute(q(keyspace, 'removeMember'), memberValues, function (err) {
      if (err) return cb(err);
      cb(null, { status: 'removed' });
    });
  }

  return {
    addGroup: addGroup,
    getGroup: getGroup,
    getGroups: getGroups,
    joinGroup: joinGroup,
    leaveGroup: leaveGroup,
    updateGroup: updateGroup,
    removeGroup: removeGroup,
    removeMembers: removeMembers,
    getGroupsByUser: getGroupsByUser,
    getGroupsBySupergroupId: getGroupsBySupergroupId,
    getGroupMembers: getGroupMembers,
    removeMembersByUser: removeMembersByUser
  };
};
<commit_msg>migrate to es6-group<commit_after>const async = require('async');
const _mapValues = require('lodash/mapValues');
const _zipObject = require('lodash/zipObject');
const _filter = require('lodash/filter');

const DEFAULT_PAGESIZE = 50;

/**
 * This is a collection of methods that allow you to create, update and delete social items.
 *
 * These methods all exclude the 'loggedinuser' parameter as they are all carried out only by
 * the currently logged in user and / or system level calls (e.g. adding a user via integration
 * with an SSO flow).
 *
 */
module.exports = (api) => {
  const client = api.client;
  const messaging = api.messaging;
  const q = client.queries;

  const joinGroup = (keyspace, group, user, timestamp, cb) => {
    const memberValues = [group, user, timestamp];
    client.execute(q(keyspace, 'upsertMember'), memberValues, (err) => {
      if (err) return cb(err);
      getGroup(keyspace, group, (err, result) => {
        if (err) return cb(err);
        const joinGroupContent = {
          category: 'social-group',
          type: 'new-member',
          data: {
            group: {
              id: group,
              name: result.groupname
            }
          }
        };
        api.post.addPost(keyspace, user, joinGroupContent, 'application/json', timestamp, 'public', function (err, result) {
          if (err) return cb(err);
          cb(null, _zipObject(['group', 'user', 'timestamp'], memberValues));
        });
      });
    });
  };

  const addGroup = (keyspace, groupName, supergroupId, user, timestamp, options, next) => {
    if (!next) {
      next = options;
      options = {};
    }

    let groupData = options.groupData || {};
    const group = client.isValidId(options.group) ? options.group : client.generateId();

    groupData = _mapValues(groupData, (value) => {
      return value.toString();
    }); // Always ensure our groupdata is <text,text>

    // Check group doesn't already exist with this name in this supergroup
    getGroupByNameWithinSupergroup(keyspace, groupName, supergroupId, (err, existingGroup) => {
      if (err && err.statusCode !== 404) { return next(err); }
      if (existingGroup) {
        return next({
          statusCode: 409,
          message: 'Group with groupname ' + groupName + ' already exists for supergroupId ' + supergroupId
        });
      }

      const groupValues = [group, groupData, groupName, supergroupId];

      client.execute(q(keyspace, 'upsertGroup'), groupValues, {}, (err, result) => {
        if (err) { return next(err); }
        joinGroup(keyspace, group, user, timestamp, (err, result) => {
          if (err) { return next(err); }
          next(null, _zipObject(['group', 'groupData', 'groupName', 'supergroupId'], groupValues));
        });
      });
    });
  };

  const getGroupByNameWithinSupergroup = (keyspace, groupName, supergroupId, next) => {
    client.get(q(keyspace, 'selectGroupByNameAndSupergroup'), [groupName, supergroupId], {}, (err, result) => {
      if (err) { return next(err); }
      if (!result) { return next(api.common.error(404, 'Unable to find group by groupName: ' + groupName + ' and supergroupId ' + supergroupId)); }
      next(null, result);
    });
  };

  const getGroup = (keyspace, group, next) => {
    client.get(q(keyspace, 'selectGroupById'), [group], {}, (err, result) => {
      if (err) { return next(err); }
      if (!result) { return next(api.common.error(404, 'Unable to find group by id: ' + group)); }
      next(null, result);
    });
  };

  const getGroups = (keyspace, groups, next) => {
    async.map(groups, (group, cb) => {
      getGroup(keyspace, group, (err, result) => {
        if (err) return cb();
        cb(null, result);
      });
    }, next);
  };

  const updateGroup = (keyspace, userAltid, group, groupName, supergroupId, groupData, next) => {
    getGroup(keyspace, group, (err, result) => {
      if (err) { return next(err); }

      if (userAltid.toString() !== result.groupdata.admin) {
        return next(new Error('Unable to update the group, only admin can update it.'));
      }

      groupData = _mapValues(groupData, (value) => {
        return value.toString();
      }); // Always ensure our groupData is <text,text>

      const groupValues = [groupName, supergroupId, groupData, group];
      client.execute(q(keyspace, 'updateGroup'), groupValues, {}, (err, value) => {
        if (err) { return next(err); }
        next(null, _zipObject(['groupName', 'supergroupId', 'groupData', 'group'], groupValues));
      });
    });
  };

  const removeMembers = (jobData, cb) => {
    client.execute(q(jobData.keyspace, 'removeMembers'), [jobData.group], (err) => {
      if (err) return cb(err);
      cb(null, { status: 'removed' });
    });
  };

  const removeMembersByUser = (keyspace, user, next) => {
    client.execute(q(keyspace, 'selectGroupsForUser'), [user], (err, results) => {
      if (err) return next(err);
      async.each(results, (member, cb) => {
        client.execute(q(keyspace, 'removeMember'), [member.group, user], cb);
      }, next);
    });
  };

  const removeGroup = (keyspace, userAltid, user, group, next) => {
    getGroup(keyspace, group, (err, result) => {
      if (err) { return next(err); }
      if (userAltid.toString() !== result.groupdata.admin) {
        return next(new Error('Unable to remove the group, only admin can remove it.'));
      }
      const jobData = {
        keyspace: keyspace,
        user: user,
        group: group
      };

      const _removeMembers = (cb) => {
        if (messaging.enabled) {
          messaging.submit('seguir-remove-members', jobData, cb);
        } else {
          removeMembers(jobData, cb);
        }
      };
      const _removeGroup = (cb) => {
        client.execute(q(keyspace, 'removeGroup'), [group], (err) => {
          if (err) return cb(err);
          cb(null, { status: 'removed' });
        });
      };
      async.series([
        _removeMembers,
        _removeGroup
      ], next);
    });
  };

  const getGroupsByUser = (keyspace, user, next) => {
    client.execute(q(keyspace, 'selectGroupsForUser'), [user], (err, results) => {
      if (err) return next(err);

      if (results && results.length > 0) {
        async.map(results, (group, cb) => {
          getGroup(keyspace, group.group, (err, result) => {
            if (err) {
              return cb(null, null);
            }
            cb(null, result);
          });
        }, (err, groups) => {
          if (err) { return next(err); }
          const existingGroups = _filter(groups, (group) => {
            return group !== null;
          });
          next(null, existingGroups);
        });
      } else {
        next(null, []);
      }
    });
  };

  const getGroupsBySupergroupId = (keyspace, supergroupId, liu, options, next) => {
    if (!next) {
      next = options;
      options = {};
    }
    const pageState = options.pageState;
    const pageSize = options.pageSize || DEFAULT_PAGESIZE;

    client.execute(q(keyspace, 'selectGroupsBySupergroupId'), [supergroupId], {pageState: pageState, pageSize: pageSize}, (err, data, nextPageState) => {
      if (err) { return next(err); }

      if (data && data.length > 0) {
        async.map(data, (item, cb) => {
          api.common.isUserGroupMember(keyspace, liu, item.group, (err) => {
            if (!err) {
              item.isMember = true;
            }
            cb();
          });
        }, () => {
          next(null, data, nextPageState);
        });
      } else {
        next(null, []);
      }
    });
  };

  const getGroupMembers = (keyspace, group, next) => {
    client.execute(q(keyspace, 'selectGroupMembers'), [group], {}, (err, groupMembers) => {
      if (err) { return next(err); }

      async.mapSeries(groupMembers, (member, cb) => {
        api.user.mapUserIdToUser(keyspace, member, ['user'], cb);
      }, next);
    });
  };

  const leaveGroup = (keyspace, group, user, cb) => {
    const memberValues = [group, user];
    client.execute(q(keyspace, 'removeMember'), memberValues, (err) => {
      if (err) return cb(err);
      cb(null, { status: 'removed' });
    });
  };

  return {
    addGroup: addGroup,
    getGroup: getGroup,
    getGroups: getGroups,
    joinGroup: joinGroup,
    leaveGroup: leaveGroup,
    updateGroup: updateGroup,
    removeGroup: removeGroup,
    removeMembers: removeMembers,
    getGroupsByUser: getGroupsByUser,
    getGroupsBySupergroupId: getGroupsBySupergroupId,
    getGroupMembers: getGroupMembers,
    removeMembersByUser: removeMembersByUser
  };
};
<|endoftext|>


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

app.LibraryView = Backbone.View.extend({

	initialize: function (options){
		this.collection.on('add reset remove',function(){
			this.render(this.collection);
			}, this
			);

		this.itemView = options.itemView;
		this.filter = options.filter || false;
		if (this.filter){
			this.search(this.filter)
		} else {
			this.render();
		}
	},

	render: function (collection, isFiltered) {
		var numActiveItems = 0,
		totalItems = 0,
		numItemsDisplayed = 0;
		collection = collection || this.collection;
		this.$el.html('');

		if (!isFiltered){
			if (collection.length > 0){
				collection.each(function(item){
					this.renderItem(item);
				}, this);
			} else {
				this.$el.html($('#noItemsTemplate').html());
			}
		} else {
			//get the total number of active items
			numActiveItems = this.collection.where({active: true}).length;
			totalItems = numActiveItems;
			numItemsDisplayed = collection.toArray().length;
			if(numItemsDisplayed < totalItems){
				this.$el.html('Displaying ' + numItemsDisplayed + ' out of ' + totalItems);
			}
			collection.each(function(item){
				this.renderItem(item);
			}, this);
		}

		return this;
			},

	renderItem: function(item){
		var itemView = new this.itemView({
			model: item
		});
		this.$el.append(itemView.render().el);
	},

	search: function(options){
		var collection = (options && options.collection ? options.collection : this.collection);

		if (!options){
			this.render();
		}else {
			this.render(collection.search(options), true);
		}
	}
});<commit_msg>render optimization for library views<commit_after>var app = app || {};

app.LibraryView = Backbone.View.extend({

	initialize: function (options){
		this.collection.on('add reset remove',function(){
			this.render(this.collection);
			}, this
			);

		this.itemView = options.itemView;
		this.filter = options.filter || false;
		if (this.filter){
			this.search(this.filter)
		} else {
			this.render();
		}
	},

	render: function (collection, isFiltered) {
		var numActiveItems = 0,
		totalItems = 0,
		numItemsDisplayed = 0;
		collection = collection || this.collection;
		if(collection.length == this.collection.length){
			return;
		}
		this.$el.html('');

		if (!isFiltered){
			if (collection.length > 0){
				collection.each(function(item){
					this.renderItem(item);
				}, this);
			} else {
				this.$el.html($('#noItemsTemplate').html());
			}
		} else {
			//get the total number of active items
			numActiveItems = this.collection.where({active: true}).length;
			totalItems = numActiveItems;
			numItemsDisplayed = collection.toArray().length;
			if(numItemsDisplayed < totalItems){
				this.$el.html('Displaying ' + numItemsDisplayed + ' out of ' + totalItems);
			}
			collection.each(function(item){
				this.renderItem(item);
			}, this);
		}

		return this;
			},

	renderItem: function(item){
		var itemView = new this.itemView({
			model: item
		});
		this.$el.append(itemView.render().el);
	},

	search: function(options){
		var collection = (options && options.collection ? options.collection : this.collection);

		if (!options){
			this.render();
		}else {
			this.render(collection.search(options), true);
		}
	}
});<|endoftext|>


<commit_before>var util = require("core-util-is");
var config = require("./config");
var shallowCopy = require("./shallow-copy");

var SET_NOTHING = { headers: [] };

var handlers = {};

handlers.default = function() {
  return { headers: config.allHeaders };
};

handlers.IE = function(browser, directives) {
  if ((parseFloat(browser.version) >= 10) && directives.sandbox) {
    return {
      headers: ["X-Content-Security-Policy"],
      directives: { sandbox: directives.sandbox }
    };
  } else {
    return SET_NOTHING;
  }
};

handlers.Firefox = function(browser, directives) {

  var version = parseFloat(browser.version);

  if (version >= 23) {
    return { headers: ["Content-Security-Policy"] };
  } else if ((version >= 4) && (version < 23)) {

    policy = shallowCopy(directives);

    policy["default-src"] = policy["default-src"] || ["*"];

    Object.keys(policy).forEach(function (key) {
      var value = policy[key];
      if (key === "connect-src") {
        policy["xhr-src"] = value;
      } else if (key === "default-src") {
        if (version < 5) {
          policy.allow = value;
        } else {
          policy["default-src"] = value;
        }
      } else if (key !== "sandbox") {
        policy[key] = value;
      }

      var index;
      if ((index = policy[key].indexOf("'unsafe-inline'")) !== -1) {
        if (key === "script-src") {
          policy[key][index] = "'inline-script'";
        } else {
          policy[key].splice(index, 1);
        }
      }
      if ((index = policy[key].indexOf("'unsafe-eval'")) !== -1) {
        if (key === "script-src") {
          policy[key][index] = "'eval-script'";
        } else {
          policy[key].splice(index, 1);
        }
      }
    });

    return {
      headers: ["X-Content-Security-Policy"],
      directives: policy
    };

  } else {

    return SET_NOTHING;

  }

};

handlers.Chrome = function(browser) {
  var version = parseFloat(browser.version);
  if ((version >= 14) && (version < 25)) {
    return { headers: ["X-WebKit-CSP"] };
  } else if (version >= 25) {
    return { headers: ["Content-Security-Policy"] };
  } else {
    return SET_NOTHING;
  }
};

handlers.Safari = function(browser, directives, options) {
  var version = parseFloat(browser.version);
  if (version >= 7) {
    return { headers: ["Content-Security-Policy"] };
  } else if ((version >= 6) || ((version >= 5.1) && options.safari5)) {
    return { headers: ["X-WebKit-CSP"] };
  } else {
    return SET_NOTHING;
  }
};

handlers.Opera = function(browser) {
  if (parseFloat(browser.version) >= 15) {
    return { headers: ["Content-Security-Policy"] };
  } else {
    return SET_NOTHING;
  }
};

handlers["Android Browser"] = function(browser, directives, options) {
  if ((parseFloat(browser.os.version) < 4.4) || options.disableAndroid) {
    return SET_NOTHING;
  } else {
    return { headers: ["Content-Security-Policy"] };
  }
};

handlers["Chrome Mobile"] = function(browser, directives) {
  if (browser.os.family === "iOS") {
    var result = { headers: ["Content-Security-Policy"] };
    var connect = directives["connect-src"];
    if (!connect) {
      result.directives = shallowCopy(directives);
      result.directives["connect-src"] = ["'self'"];
    } else if (connect.indexOf("'self'") === -1) {
      result.directives = shallowCopy(directives);
      result.directives["connect-src"].push("'self'");
    }
    return result;
  } else {
    return handlers["Android Browser"].apply(this, arguments);
  }
};

module.exports = handlers;
<commit_msg>Fix accidental globalization of variable<commit_after>var util = require("core-util-is");
var config = require("./config");
var shallowCopy = require("./shallow-copy");

var SET_NOTHING = { headers: [] };

var handlers = {};

handlers.default = function() {
  return { headers: config.allHeaders };
};

handlers.IE = function(browser, directives) {
  if ((parseFloat(browser.version) >= 10) && directives.sandbox) {
    return {
      headers: ["X-Content-Security-Policy"],
      directives: { sandbox: directives.sandbox }
    };
  } else {
    return SET_NOTHING;
  }
};

handlers.Firefox = function(browser, directives) {

  var version = parseFloat(browser.version);

  if (version >= 23) {
    return { headers: ["Content-Security-Policy"] };
  } else if ((version >= 4) && (version < 23)) {

    var policy = shallowCopy(directives);

    policy["default-src"] = policy["default-src"] || ["*"];

    Object.keys(policy).forEach(function (key) {
      var value = policy[key];
      if (key === "connect-src") {
        policy["xhr-src"] = value;
      } else if (key === "default-src") {
        if (version < 5) {
          policy.allow = value;
        } else {
          policy["default-src"] = value;
        }
      } else if (key !== "sandbox") {
        policy[key] = value;
      }

      var index;
      if ((index = policy[key].indexOf("'unsafe-inline'")) !== -1) {
        if (key === "script-src") {
          policy[key][index] = "'inline-script'";
        } else {
          policy[key].splice(index, 1);
        }
      }
      if ((index = policy[key].indexOf("'unsafe-eval'")) !== -1) {
        if (key === "script-src") {
          policy[key][index] = "'eval-script'";
        } else {
          policy[key].splice(index, 1);
        }
      }
    });

    return {
      headers: ["X-Content-Security-Policy"],
      directives: policy
    };

  } else {

    return SET_NOTHING;

  }

};

handlers.Chrome = function(browser) {
  var version = parseFloat(browser.version);
  if ((version >= 14) && (version < 25)) {
    return { headers: ["X-WebKit-CSP"] };
  } else if (version >= 25) {
    return { headers: ["Content-Security-Policy"] };
  } else {
    return SET_NOTHING;
  }
};

handlers.Safari = function(browser, directives, options) {
  var version = parseFloat(browser.version);
  if (version >= 7) {
    return { headers: ["Content-Security-Policy"] };
  } else if ((version >= 6) || ((version >= 5.1) && options.safari5)) {
    return { headers: ["X-WebKit-CSP"] };
  } else {
    return SET_NOTHING;
  }
};

handlers.Opera = function(browser) {
  if (parseFloat(browser.version) >= 15) {
    return { headers: ["Content-Security-Policy"] };
  } else {
    return SET_NOTHING;
  }
};

handlers["Android Browser"] = function(browser, directives, options) {
  if ((parseFloat(browser.os.version) < 4.4) || options.disableAndroid) {
    return SET_NOTHING;
  } else {
    return { headers: ["Content-Security-Policy"] };
  }
};

handlers["Chrome Mobile"] = function(browser, directives) {
  if (browser.os.family === "iOS") {
    var result = { headers: ["Content-Security-Policy"] };
    var connect = directives["connect-src"];
    if (!connect) {
      result.directives = shallowCopy(directives);
      result.directives["connect-src"] = ["'self'"];
    } else if (connect.indexOf("'self'") === -1) {
      result.directives = shallowCopy(directives);
      result.directives["connect-src"].push("'self'");
    }
    return result;
  } else {
    return handlers["Android Browser"].apply(this, arguments);
  }
};

module.exports = handlers;
<|endoftext|>


<commit_before>'use strict';

angular.module('app').controller('quizzController', function ($rootScope, $scope, $stateParams, $state, $interval, quizz, config, session, api) {

    var type        = $stateParams.type || 'single',
        blind       = 'CREATED';

    /*
     * If we are not logged -> redirect to home
     */
    if(session.getLogged() === false || ($stateParams.type == 'multi' && ($stateParams.user_1 == $stateParams.user_2))){
        $state.go('home');
    }

    /*
     * Change status blind when change route
     */
    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
        if(fromState.name == 'quizz'){
            if(blind === 'CREATED'){
                api.blindUpdate($scope.blindId, 'CANCEL');
            }
            else if(blind === 'FINISH'){
                api.blindUpdate($scope.blindId, blind);
            }
        }
    });

    /*
     * Load Current ID Blind
     */
    quizz.blindStart(type).then(function(id){
        $scope.blindId = id;
    });

    /*
     * Load questions Single/Multi
     */
    quizz.loadQuestions(type, $stateParams.category).then(function (result) {
        if($stateParams.type == 'single'){
            $scope.questions = result.questions;
        }
        else{
            $scope.questions = result;
            console.log(result);
        }
    });

    /*
     * Quizz Start at Question 0 !
     */
    $scope.currentQuestion = 0;

    /*
     * Get PATH for img Url
     */
    $scope.path = config.apiUrl;

    /*
     * Content all responses for all questions
     */
    $scope.responses = quizz.emptyResponses();

    /*
     * Timer
     */
    $scope.countDown = config.timeMusic;
    $scope.percentCountDown = ($scope.countDown * 100) / config.timeMusic;

    $scope.$watch('countDown', function(newVal){
        $scope.percentCountDown = (newVal * 100) / config.timeMusic;
    });

    var timer = $interval(function(){
        $scope.countDown--;
    }, 1000);

    $scope.$watch('countDown', function(newVal){
       if(newVal == 0){
           $interval.cancel(timer);
           $scope.newQuestion(1, 1);
           console.log('Done');
       }
    });

    /*
     * Next Questions
     * TODO Move to Service
     */
    $scope.newQuestion = function (index, endTimer) {

        $interval.cancel(timer);
        $scope.countDown = config.timeMusic;

        var endTimer = endTimer || null;
        var question = $scope.questions[$scope.currentQuestion];

        if(endTimer == 1){
            $scope.responses[$scope.currentQuestion].value = 0;
            quizz.addResponse($scope.blindId, question.question.id);
            console.log('[QUIZZ] : Bad answer');
        }
        else{
            /* Good Answer with current Question */
            if (question.anwsers[index].status == 1) {
                $scope.responses[$scope.currentQuestion].value = 1;
                console.log('[QUIZZ] : Good answer');
            }
            else{
                $scope.responses[$scope.currentQuestion].value = 0;
                console.log('[QUIZZ] : Bad answer');
            }
            quizz.addResponse($scope.blindId, question.question.id, question.anwsers[index].id);
        }
        /* Check if last question */
        if($scope.currentQuestion == 19){
            $interval.cancel(timer);
            blind = 'FINISH';
            api.blindUpdate($scope.blindId, blind);
            console.log('[QUIZZ] : Challenge '+type+' done');
            if(type === 'single'){
                api.profilUser(session.getUser().facebook_id, session.getSexe()).then(function(result){
                    var newCategory = result.user.profil;
                    api.userCategory(session.getUser().facebook_id, newCategory).then(function(){
                        session.setCategory(newCategory);
                        $state.go('profil');
                    })
                });
            }
            else{
                /*
                 * Save response in API WAY
                 * Seed Notification to the second player.
                 */
            }
        }
        else{
            timer = $interval(function(){
                $scope.countDown--;
            }, 1000);
            $scope.currentQuestion++;
            console.log('[QUIZZ] : Next question : '+$scope.currentQuestion);
        }
    };

});<commit_msg>Redirect to home when we haven't type on quizz<commit_after>'use strict';

angular.module('app').controller('quizzController', function ($rootScope, $scope, $stateParams, $state, $interval, quizz, config, session, api) {

    var type        = $stateParams.type || null,
        blind       = 'CREATED';

    /*
     * If we are not logged -> redirect to home
     */
    if(session.getLogged() === false || ($stateParams.type == 'multi' && ($stateParams.user_1 == $stateParams.user_2)) || type == null){
        $state.go('home');
    }

    /*
     * Change status blind when change route
     */
    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
        if(fromState.name == 'quizz'){
            if(blind === 'CREATED'){
                api.blindUpdate($scope.blindId, 'CANCEL');
            }
            else if(blind === 'FINISH'){
                api.blindUpdate($scope.blindId, blind);
            }
        }
    });

    /*
     * Load Current ID Blind
     */
    quizz.blindStart(type).then(function(id){
        $scope.blindId = id;
    });

    /*
     * Load questions Single/Multi
     */
    quizz.loadQuestions(type, $stateParams.category).then(function (result) {
        if($stateParams.type == 'single'){
            $scope.questions = result.questions;
        }
        else{
            $scope.questions = result;
            console.log(result);
        }
    });

    /*
     * Quizz Start at Question 0 !
     */
    $scope.currentQuestion = 0;

    /*
     * Get PATH for img Url
     */
    $scope.path = config.apiUrl;

    /*
     * Content all responses for all questions
     */
    $scope.responses = quizz.emptyResponses();

    /*
     * Timer
     */
    $scope.countDown = config.timeMusic;
    $scope.percentCountDown = ($scope.countDown * 100) / config.timeMusic;

    $scope.$watch('countDown', function(newVal){
        $scope.percentCountDown = (newVal * 100) / config.timeMusic;
    });

    var timer = $interval(function(){
        $scope.countDown--;
    }, 1000);

    $scope.$watch('countDown', function(newVal){
       if(newVal == 0){
           $interval.cancel(timer);
           $scope.newQuestion(1, 1);
           console.log('Done');
       }
    });

    /*
     * Next Questions
     * TODO Move to Service
     */
    $scope.newQuestion = function (index, endTimer) {

        $interval.cancel(timer);
        $scope.countDown = config.timeMusic;

        var endTimer = endTimer || null;
        var question = $scope.questions[$scope.currentQuestion];

        if(endTimer == 1){
            $scope.responses[$scope.currentQuestion].value = 0;
            quizz.addResponse($scope.blindId, question.question.id);
            console.log('[QUIZZ] : Bad answer');
        }
        else{
            /* Good Answer with current Question */
            if (question.anwsers[index].status == 1) {
                $scope.responses[$scope.currentQuestion].value = 1;
                console.log('[QUIZZ] : Good answer');
            }
            else{
                $scope.responses[$scope.currentQuestion].value = 0;
                console.log('[QUIZZ] : Bad answer');
            }
            quizz.addResponse($scope.blindId, question.question.id, question.anwsers[index].id);
        }
        /* Check if last question */
        if($scope.currentQuestion == 19){
            $interval.cancel(timer);
            blind = 'FINISH';
            api.blindUpdate($scope.blindId, blind);
            console.log('[QUIZZ] : Challenge '+type+' done');
            if(type === 'single'){
                api.profilUser(session.getUser().facebook_id, session.getSexe()).then(function(result){
                    var newCategory = result.user.profil;
                    api.userCategory(session.getUser().facebook_id, newCategory).then(function(){
                        session.setCategory(newCategory);
                        $state.go('profil');
                    })
                });
            }
            else{
                /*
                 * Save response in API WAY
                 * Seed Notification to the second player.
                 */
            }
        }
        else{
            timer = $interval(function(){
                $scope.countDown--;
            }, 1000);
            $scope.currentQuestion++;
            console.log('[QUIZZ] : Next question : '+$scope.currentQuestion);
        }
    };

});<|endoftext|>


<commit_before> // Design Basic Game Solo Challenge

// This is a solo challenge

// Your mission description: You are a dog who is pulling off a spaghetti heist. You must escape with as much pasta as possible before the pasta police can arrest you.
// Overall mission: To gather up spaghetti as quickly as possible while avoiding the police.
// Goals: Get spaghetti.
// Characters: Player, Pasta Police,
// Objects: Spaghetti plate,
// Functions: Player move, police move, pickup pasta, display level to screen

// Pseudocode
//  Create a container for all the squares of a game level.
//  Fill the container with blank squares.
//  Create a player object and place it on a blank square.
//  Create a cop object and place it on a blank square.
//  Create a spaghetti object and place it on a blank square.
//  Iterate through the container for the level, displaying each value to the screen.
//  Move the player by adding or subtracting from the x or y value.
//  Then move the cop by checking the distance from the player and moving to close the gap.
//  If the player moves onto the spaghetti square, the player eats the spaghetti.
//  If the cop moves adjacent to the player, the player is arrested.

// Initial Code

// This function generates an empty level tabular array and then populates it with the player, a plate of spaghetti, and the cop.
function createLevel(){
  var levelWidth = 8;
  var levelHeight = 8;
  var level = [];
  for (var row = 0; row < levelHeight; row ++){
    var temp_row = [];
    for (var square = 0; square < levelWidth; square++) {
      temp_row.push(0);
    }
    level.push(temp_row);
  }
  level[player.yPos][player.xPos] = "@";
  level[cop1.yPos][cop1.xPos] = "C";
  level[spaghetti1.yPos][spaghetti1.xPos] = "S";
  return level;
}

var player = {
  xPos: 7,
  yPos: 7,
};

function Spaghetti(xPos, yPos, pasta){
  this.xPos = xPos;
  this.yPos = yPos;
  this.pasta = pasta;
}

function Cop(xPos, yPos, speed){
  this.xPos = xPos;
  this.yPos = yPos;
  this.speed = speed;
}

// Displays Level to Console
// Moves through the level array and concatenates a string to display to console.
function displayLevel(level){
  toDisplay = "";
  for (row= 0; row < level.length; row++){
    for (square = 0; square < level[row].length; square++){
      switch(level[row][square]) {
        case 0:
          toDisplay += ".";
          break;
        case "@":
          toDisplay += "@";
          break;
        case "C":
          toDisplay += "C";
          break;
        case "S":
          toDisplay += "S";
          break;
      }
    }
    toDisplay += "\n";
  }
  console.log(toDisplay);
}

// Cop Movement
// If the cop is further away on the x-axis the cop moves closer on that axis, otherwise moves closer on the y-axis.
function copMove(cop){
  if (Math.abs(cop.xPos - player.xPos) <= Math.abs(cop.yPos - player.yPos)){
      level[cop.yPos][cop.xPos] = 0;
      if (cop.xPos > player.xPos){
        cop.xPos -= 1;
      }
      else {
        cop.xPos += 1;
      }
      level[cop.yPos][cop.xPos] = "C";
      catchDog(cop);
  }
    else{
        level[cop.yPos][cop.xPos] = 0;
        if (cop.yPos > player.yPos){
          cop.yPos -= 1;
        }
        else {
          cop.yPos += 1;
        }
        level[cop.yPos][cop.xPos] = "C";
        catchDog(cop);
    }
}

// If the cop is ever adjacent to the player, the cop arrests the player and the game ends.
function catchDog(cop){
    console.log(Math.abs(player.xPos - cop.xPos));
    console.log(Math.abs(player.xPos - cop.xPos));
  if (Math.abs(player.xPos - cop.xPos) == 1 && Math.abs(player.yPos - cop.yPos) == 1){
    console.log("Ya Busted!");
  }
}

function eatSpaghetti(spaghetti){
  if (player.yPos == spaghetti.yPos && player.xPos == spaghetti.xPos){
    console.log("Yum, yum! I love that spaghetti!");
  }
}

// Player Movement Functions
function moveUp() {
  if (player.yPos - 1 >= 0){
    level[player.yPos][player.xPos] = 0;
    player.yPos -= 1;
    level[player.yPos][player.xPos] = "@";
  }
  eatSpaghetti(spaghetti1);
}

function moveDown() {
  if (player.yPos + 1 < level.length){
    level[player.yPos][player.xPos] = 0;
    player.yPos += 1;
    level[player.yPos][player.xPos] = "@";
  }
  eatSpaghetti(spaghetti1);
}

function moveRight() {
  if (player.xPos + 1 < level[0].length){
    level[player.yPos][player.xPos] = 0;
    player.xPos += 1;
    level[player.yPos][player.xPos] = "@";
  }
  eatSpaghetti(spaghetti1);
}

function moveLeft() {
  if (player.xPos - 1 >= 0){
    level[player.yPos][player.xPos] = 0;
    player.xPos -= 1;
    level[player.yPos][player.xPos] = "@";
  }
  eatSpaghetti(spaghetti1);
}

// console.log(displayLevel(level));
var cop1 = new Cop(4,4,1);
var spaghetti1 = new Spaghetti(1,1,1);
level = createLevel();
displayLevel(level);
moveUp();
copMove(cop1);
displayLevel(level);
moveLeft();
copMove(cop1);
displayLevel(level);
moveUp();
copMove(cop1);
displayLevel(level);
moveUp();
copMove(cop1);
displayLevel(level);
moveUp();
copMove(cop1);
displayLevel(level);
moveLeft();
copMove(cop1);
displayLevel(level);

// displayLevel(level);
// moveRight();
// displayLevel(level);
// copMove(cop1);
// displayLevel(level);

// Refactored Code

// Reflection
//What was the most difficult part of this challenge?
// What did you learn about creating objects and functions that interact with one another?
// Did you learn about any new built-in methods you could use in your refactored solution? If so, what were they and how do they work?
// How can you access and manipulate properties of objects?
//
//
//
//
//
//<commit_msg>Add refactoring.<commit_after> // Design Basic Game Solo Challenge

// This is a solo challenge

// Your mission description: You are a dog who is pulling off a spaghetti heist. You must escape with as much pasta as possible before the pasta police can arrest you.
// Overall mission: To gather up spaghetti as quickly as possible while avoiding the police.
// Goals: Get spaghetti.
// Characters: Player, Pasta Police,
// Objects: Spaghetti plate,
// Functions: Player move, police move, pickup pasta, display level to screen

// Pseudocode
//  Create a container for all the squares of a game level.
//  Fill the container with blank squares.
//  Create a player object and place it on a blank square.
//  Create a cop object and place it on a blank square.
//  Create a spaghetti object and place it on a blank square.
//  Iterate through the container for the level, displaying each value to the screen.
//  Move the player by adding or subtracting from the x or y value.
//  Then move the cop by checking the distance from the player and moving to close the gap.
//  If the player moves onto the spaghetti square, the player eats the spaghetti.
//  If the cop moves adjacent to the player, the player is arrested.

// // Initial Code

// // This function generates an empty level tabular array and then populates it with the player, a plate of spaghetti, and the cop.
// function createLevel(){
//   var levelWidth = 8;
//   var levelHeight = 8;
//   var level = [];
//   for (var row = 0; row < levelHeight; row ++){
//     var temp_row = [];
//     for (var square = 0; square < levelWidth; square++) {
//       temp_row.push(0);
//     }
//     level.push(temp_row);
//   }
//   level[player.yPos][player.xPos] = "@";
//   level[cop1.yPos][cop1.xPos] = "C";
//   level[spaghetti1.yPos][spaghetti1.xPos] = "S";
//   return level;
// }

// var player = {
//   xPos: 7,
//   yPos: 7,
// };

// function Spaghetti(xPos, yPos, pasta){
//   this.xPos = xPos;
//   this.yPos = yPos;
//   this.pasta = pasta;
// }

// function Cop(xPos, yPos, speed){
//   this.xPos = xPos;
//   this.yPos = yPos;
//   this.speed = speed;
// }

// // Displays Level to Console
// // Moves through the level array and concatenates a string to display to console.
// function displayLevel(level){
//   toDisplay = "";
//   for (row= 0; row < level.length; row++){
//     for (square = 0; square < level[row].length; square++){
//       switch(level[row][square]) {
//         case 0:
//           toDisplay += ".";
//           break;
//         case "@":
//           toDisplay += "@";
//           break;
//         case "C":
//           toDisplay += "C";
//           break;
//         case "S":
//           toDisplay += "S";
//           break;
//       }
//     }
//     toDisplay += "\n";
//   }
//   console.log(toDisplay);
// }

// // Cop Movement
// // If the cop is further away on the x-axis the cop moves closer on that axis, otherwise moves closer on the y-axis.
// function copMove(cop){
//   if (Math.abs(cop.xPos - player.xPos) <= Math.abs(cop.yPos - player.yPos)){
//       level[cop.yPos][cop.xPos] = 0;
//       if (cop.xPos > player.xPos){
//         cop.xPos -= 1;
//       }
//       else {
//         cop.xPos += 1;
//       }
//       level[cop.yPos][cop.xPos] = "C";
//       catchDog(cop);
//   }
//     else{
//         level[cop.yPos][cop.xPos] = 0;
//         if (cop.yPos > player.yPos){
//           cop.yPos -= 1;
//         }
//         else {
//           cop.yPos += 1;
//         }
//         level[cop.yPos][cop.xPos] = "C";
//         catchDog(cop);
//     }
// }

// // If the cop is ever adjacent to the player, the cop arrests the player and the game ends.
// function catchDog(cop){
//     console.log(Math.abs(player.xPos - cop.xPos));
//     console.log(Math.abs(player.xPos - cop.xPos));
//   if (Math.abs(player.xPos - cop.xPos) == 1 && Math.abs(player.yPos - cop.yPos) == 1){
//     console.log("Ya Busted!");
//   }
// }

// function eatSpaghetti(spaghetti){
//   if (player.yPos == spaghetti.yPos && player.xPos == spaghetti.xPos){
//     console.log("Yum, yum! I love that spaghetti!");
//   }
// }

// // Player Movement Functions
// function moveUp() {
//   if (player.yPos - 1 >= 0){
//     level[player.yPos][player.xPos] = 0;
//     player.yPos -= 1;
//     level[player.yPos][player.xPos] = "@";
//   }
//   eatSpaghetti(spaghetti1);
// }

// function moveDown() {
//   if (player.yPos + 1 < level.length){
//     level[player.yPos][player.xPos] = 0;
//     player.yPos += 1;
//     level[player.yPos][player.xPos] = "@";
//   }
//   eatSpaghetti(spaghetti1);
// }

// function moveRight() {
//   if (player.xPos + 1 < level[0].length){
//     level[player.yPos][player.xPos] = 0;
//     player.xPos += 1;
//     level[player.yPos][player.xPos] = "@";
//   }
//   eatSpaghetti(spaghetti1);
// }

// function moveLeft() {
//   if (player.xPos - 1 >= 0){
//     level[player.yPos][player.xPos] = 0;
//     player.xPos -= 1;
//     level[player.yPos][player.xPos] = "@";
//   }
//   eatSpaghetti(spaghetti1);
// }

// Refactored Code

// This function generates an empty level tabular array and then populates it with the player, a plate of spaghetti, and the cop.
function createLevel(){
  var levelWidth = 8;
  var levelHeight = 8;
  var level = [];
  for (var row = 0; row < levelHeight; row ++){
    var temp_row = [];
    for (var square = 0; square < levelWidth; square++) {
      temp_row.push(0);
    }
    level.push(temp_row);
  }
  level[player.yPos][player.xPos] = "@";
  level[cop1.yPos][cop1.xPos] = "C";
  level[spaghetti1.yPos][spaghetti1.xPos] = "S";
  return level;
}

var player = {
  xPos: 7,
  yPos: 7,
  pastaPoints: 0,
};

function Spaghetti(xPos, yPos, pasta){
  this.xPos = xPos;
  this.yPos = yPos;
  this.pasta = pasta;
}

function Cop(xPos, yPos, speed){
  this.xPos = xPos;
  this.yPos = yPos;
  this.speed = speed;
}

// Displays Level to Console
// Moves through the level array and concatenates a string to display to console.
function displayLevel(level){
  toDisplay = "";
  for (row= 0; row < level.length; row++){
    for (square = 0; square < level[row].length; square++){
      switch(level[row][square]) {
        case 0:
          toDisplay += ".";
          break;
        case "@":
          toDisplay += "@";
          break;
        case "C":
          toDisplay += "C";
          break;
        case "S":
          toDisplay += "S";
          break;
      }
    }
    toDisplay += "\n";
  }
  console.log(toDisplay);
}

// Cop Movement
// If the cop is further away on the x-axis the cop moves closer on that axis, otherwise moves closer on the y-axis.
function copMove(cop){
  if (Math.abs(cop.xPos - player.xPos) <= Math.abs(cop.yPos - player.yPos)){
      level[cop.yPos][cop.xPos] = 0;
      if (cop.xPos > player.xPos){
        cop.xPos -= 1;
      }
      else {
        cop.xPos += 1;
      }
      level[cop.yPos][cop.xPos] = "C";
      catchDog(cop);
  }
    else{
        level[cop.yPos][cop.xPos] = 0;
        if (cop.yPos > player.yPos){
          cop.yPos -= 1;
        }
        else {
          cop.yPos += 1;
        }
        level[cop.yPos][cop.xPos] = "C";
        catchDog(cop);
    }
}

// If the cop is ever adjacent to the player, the cop arrests the player and the game ends.
function catchDog(cop){
  if (Math.abs(player.xPos - cop.xPos) == 1 && Math.abs(player.yPos - cop.yPos) == 1){
    console.log("Ya Busted!");
  }
}

function eatSpaghetti(spaghetti){
  if (player.yPos == spaghetti.yPos && player.xPos == spaghetti.xPos){
    console.log("Yum, yum! I love that spaghetti!");
    player.pastaPoints += spaghetti.pasta;
  }
}

// Player Movement Functions
function moveUp() {
  if (player.yPos - 1 >= 0){
    playerMover(0,-1);
  }
}

function moveDown() {
  if (player.yPos + 1 < level.length){
    playerMover(0,1);
  }
}

function moveRight() {
  if (player.xPos + 1 < level[0].length){
    playerMover(1,0);
  }
}

function moveLeft() {
  if (player.xPos - 1 >= 0){
    playerMover(-1,0);
  }
}

function playerMover(deltaxPos, deltayPos){
    level[player.yPos][player.xPos] = 0;
    player.xPos += deltaxPos;
    player.yPos += deltayPos;
    level[player.yPos][player.xPos] = "@";
    eatSpaghetti(spaghetti1);
}

// console.log(displayLevel(level));
var cop1 = new Cop(4,4,1);
var spaghetti1 = new Spaghetti(1,1,1);
level = createLevel();
displayLevel(level);
moveUp();
copMove(cop1);
displayLevel(level);
moveLeft();
copMove(cop1);
displayLevel(level);
moveUp();
copMove(cop1);
displayLevel(level);
moveUp();
copMove(cop1);
displayLevel(level);
moveUp();
copMove(cop1);
displayLevel(level);
moveLeft();
copMove(cop1);
displayLevel(level);

// displayLevel(level);
// moveRight();
// displayLevel(level);
// copMove(cop1);
// displayLevel(level);

// Reflection
//What was the most difficult part of this challenge?
// What did you learn about creating objects and functions that interact with one another?
// Did you learn about any new built-in methods you could use in your refactored solution? If so, what were they and how do they work?
// How can you access and manipulate properties of objects?
//
//
//
//
//
//<|endoftext|>