<commit_before>var utilities = require('./utilities')
  , mongoose = require('mongoose');

app.get('/votes/export', utilities.checkAdmin, function(req, res){
	// Export all game data as a CSV
	var Game = mongoose.model('Game')
	  , Round = mongoose.model('Round')
	  , Vote = mongoose.model('Vote');
	Game.find().populate('opponents').asc('startTime').run(function(err, games){
		var game = null
		  , round = null
		  , numVotes = 0
		  , csv = 'player ID, player email, player type, game ID, round #, vote date, player\'s vote, info type this round, player\'s info this round, opponent\'s info this round\n'
		  , handleVote = function(game, round){
				return function(err, vote){
					// Handle the vote
					var addToCSV = vote.player._id + ', ' + vote.player.email + ', ' + (vote.player.defending ? 'defending' : 'accumulating') + ', ' + game._id + ', ' + round.number + ', ' + vote.date + ', ' + vote.value + ', ' + vote.player.getProfileSlug(game.startTime) + ', ' + vote.player.getProfileForCSV(game.startTime) + ', ';

					// Determine which of the players was this one in the round
					var player = null;
					if(game.opponents[0]._id == vote.player._id){
						addToCSV += game.opponents[0].getOpponentProfileForCSV(game.startTime);
					}else{
						addToCSV += game.opponents[1].getOpponentProfileForCSV(game.startTime);
					}
					addToCSV += '\n';
					csv += addToCSV;
					
					if(--numVotes == 0){
						res.attachment('export.csv');
						res.contentType('csv');
						res.send(csv);
						return;
					}
				}
			}
		  , handleRound = function(game){
				return function(err, round){
					// Handle the round!
					for(var i=0; i<round.votes.length; i++){
						var vote = round.votes[i];
						numVotes++;
						Vote.findById(vote).populate('player').run(handleVote(game, round));
					}
				};
			};
		for(var i=0; i<games.length; i++){
			game = games[i];
			for(var j=0; j<game.rounds.length; j++){
				round = game.rounds[j];
				Round.findById(round).run(handleRound(game));
			}
		}
	});
	return;
});<commit_msg>Changing vote export to handle request timeouts in a MUCH better way for #39.<commit_after>var utilities = require('./utilities')
  , mongoose = require('mongoose');

app.get('/votes/export', utilities.checkAdmin, function(req, res, next){
	// Export all game data as a CSV
	var Game = mongoose.model('Game')
	  , Round = mongoose.model('Round')
	  , Vote = mongoose.model('Vote');

/* 	res.contentType('.csv'); */

	var csv = 'player ID, player email, player type, game ID, round #, vote date, player\'s vote, info type this round, player\'s info this round, opponent\'s info this round\n';
	
	res.writeHead(200, {
		'Content-Type': 'text/csv',
		'Content-Disposition': 'attachment;filename=export.csv'
	});

	Game.find({}, ['_id', 'rounds', 'startTime', 'opponents', 'rounds']).populate('opponents').populate('rounds', ['number', 'votes'])/*.asc('startTime')*/.run(function(err, games){
		var game = null
		  , round = null
		  , numVotes = 0
		  , start = Date.now()
		  , handleVote = function(game, round){
				return function(err, vote){
					// Handle the vote
					var addToCSV = vote.player._id + ', ' + vote.player.email + ', ' + (vote.player.defending ? 'defending' : 'accumulating') + ', ' + game._id + ', ' + round.number + ', ' + vote.date + ', ' + vote.value + ', ' + vote.player.getProfileSlug(game.startTime) + ', ' + vote.player.getProfileForCSV(game.startTime) + ', ';

					// Determine which of the players was this one in the round
					var player = null;
					if(game.opponents[0]._id == vote.player._id){
						addToCSV += game.opponents[0].getOpponentProfileForCSV(game.startTime);
					}else{
						addToCSV += game.opponents[1].getOpponentProfileForCSV(game.startTime);
					}
					addToCSV += '\n';
					res.write(addToCSV);
					
					if(--numVotes == 0){
						util.log('done! '+Date.now());
						util.log('total time: '+((Date.now()-start)/1000)+'s');
						res.end();
					}
				}
			};
		util.log('starting: '+Date.now());
		res.write(csv);
		
		for(var i=0; i<games.length; i++){
			game = games[i];
			for(var j=0; j<game.rounds.length; j++){
				round = game.rounds[j];
				numVotes += round.votes;
				for(var k=0; k<round.votes.length; k++){
					var vote = round.votes[k];
					Vote.findById(vote).populate('player').run(handleVote(game, round));
				}
			}
		}
	});
	return;
});
{'fraction_non_alphanumeric': 0.18450607380242953, 'fraction_numerical': 0.005730002292000917, 'mean_word_length': 3.200192492781521, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '322111', 'n_tokens_mistral': 1818, 'n_tokens_neox': 1496, 'n_words': 312}