<commit_before>/*
 * OPTIONS
 * Required
 * title - Title of the level
 * speed - Speed of the user
 * r - Radius of the user, can be a function
 * 
 * Personalities
 * name - Name
 * bio - Short biography
 * r - Radius, can be function
 * momentum - Momentum, can be function
 * color - Shape color
 * physics - Physics object for how shape behaves
 * 
 * Physics
 * a - Function to determine trajectory angle
 * dx - Function to determine change in x on tick
 * dy - Function to determine change in y on tick
 */
var physics = {
	follow: {
		a: function(d, c, w, h) { return Math.atan2(c.y - d.y, c.x - d.x); },
		dx: function(d, c, w, h) { return d.x + ($.isFunction(d.m) ? d.m(d, c, w, h) : d.m) * Math.cos(d.a) / (d.r * d.r); },
		dy: function(d, c, w, h) { return d.y + ($.isFunction(d.m) ? d.m(d, c, w, h) : d.m) * Math.sin(d.a) / (d.r * d.r); }
	}, followGhost: {
		a: function(d, c, w, h) { return Math.atan2(Math.abs(c.y - d.y) > Math.abs(h + c.y - d.y) ? h + c.y - d.y : c.y - d.y, Math.abs(c.x - d.x) > Math.abs(w + c.x - d.x) ? w + c.x - d.x : c.x - d.x) },
		dx: function(d, c, w, h) { return (d.x + ($.isFunction(d.m) ? d.m(d, c, w, h) : d.m) * Math.cos(d.a) / (d.r * d.r) + w) % w; },
		dy: function(d, c, w, h) { return (d.y + ($.isFunction(d.m) ? d.m(d, c, w, h) : d.m) * Math.sin(d.a) / (d.r * d.r) + h) % h; }
	}
}
physics.trajectory = {
	a: function(d, c, w, h) { return Math.atan2(c.y + 200 * movement.y - d.y, c.x + 100 * movement.x - d.x) },
	dx: physics.follow.dx,
	dy: physics.follow.dy
}
physics.gaurd = {
	a: function(d, c, w, h) { return dist(d.sx - c.x, d.sy - c.y) <= 200 ? Math.atan2(c.y - d.y, c.x - d.x) : Math.atan2(d.sy - d.y, d.sx - d.x) },
	dx: physics.follow.dx,
	dy: physics.follow.dy
}
var personalities = {
	basic: {
		name: 'Basic',
		bio: "Basic is your average Joe. He enjoys lounging around, weekends, and chasing you. He likes a relaxing chase, but likes to clear his mind while doing so. He'll go to where you are, but can easily be decieved if you run circles around him.",
		r: 20,
		momentum: 150,
		color: 'gray',
		physics: physics.follow
	},
	basicGhost: {
		name: 'Ghost',
		bio: "Ghost is a run-of-the mill ghost. She puts in about as much effor as Basic, but doesn't care for pesky walls. She'll chase you and it it's faster to go through the wall to get you she will.",
		r: 20,
		momentum: 150,
		color: '#EEE',
		physics: physics.followGhost
	},
	seeker: {
		name: 'Seeker',
		bio: "Seeker's gotten some intel about where you're going and moves to intercept you. Watch out: this guy's sneaky.",
		r: 20,
		momentum: 250,
		color: 'blue',
		physics: physics.trajectory
	},
	gaurd: {
		name: '<NAME>',
		bio: "Gaurd Dog won't bother you if you're far away, but if you get too close to him he'll chase after you. He's very protective of his space.",
		r: 20,
		momentum: 350,
		color: 'green',
		physics: physics.gaurd
	}
}, defaultStart = {
	x: function(w, h) { return w / 2; },
	y: function(w, h) { return h / 2; }
};
var levels = {1: {title: 'Meet Basic', speed: 1, r: 20, personalities: {basic: 10}},
		2: {title: 'Ghost', speed: 1, r: 20, personalities: {basicGhost: 5, basic: 5}},
		3: {title: 'Seekers', speed: 1, r: 20, personalities: {seeker: 3}},
		4: {title: 'Gaurd', speed: 1, r: 20, personalities: {gaurd: 5, basic: 5}}};
var custom = {}, current, userColor = 'lightblue', defaultInterval, scoreStorage = 'bestShapeEscape',
		customStorage = 'customShapeEscape', movement = {x: 0, y: 0}, down = [], playing = false, buffer = 200;

$(document).ready(function() {
	$('#customButtons').hide();
	gameW = $('#game').width(), gameH = $('#game').width();
	if (window.localStorage[customStorage]) {
		custom = JSON.parse(window.localStorage[customStorage])
	}
	var sto = window.localStorage[scoreStorage]
	if (!sto || typeof(JSON.parse(sto)) != 'object' || !JSON.parse(sto)[1]) {
		window.localStorage[scoreStorage] = JSON.stringify({1: 0})
		init(1)
		$('#modalContent').html($('#modalContent').html() + newPersonalityHtml(1) + '<button class="close">Lemme At \'Em!</button>');
		newPersonalityJs(1);
		$('#levelEnd').reveal({
		     animation: 'fadeAndPop',
		     animationspeed: 300,
		     closeonbackgroundclick: true,
		     dismissmodalclass: 'close'
		});
	} else {
		renumberCustom()
		var a = getFinishedLevels();
		if (a.length != Object.keys(levels).length && parseInt(a[a.length - 1]) <= a.length) {
			init(parseInt(a[a.length - 1]) + 1);
		} else {
			init(a[a.length - 1]);
		}
		if (a.length >= 10) {
			$('#custom').show();
		}
	}
	//$("#pop")[0].load();
	//$("#tada")[0].load();
	//$("#tada")[0].volume = .1;
	!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
})

function init(level) {
	playing = true;
	
	d3.select("#game").html('')

	var svg = d3.select("#game").append("svg:svg")
				.attr("width", gameW).attr("height", gameH).attr("id", "svg");
	
	var params = levels[level]
	if (!params) {
		params = custom[level]
		$('#customButtons').show()
		$('#delete').unbind('click');
		$('#delete').click(function() {
			delete custom[level];
			[scoreStorage, customStorage].forEach(function(d) {
				var sto = JSON.parse(window.localStorage[d]);
				delete sto[level];
				window.localStorage[d] = JSON.stringify(sto);
			})
			renumberCustom();
			$('#customButtons').hide();
			var a = getFinishedLevels();
			if (a.length != Object.keys(levels).length) {
				init(parseInt(a[a.length - 1]) + 1);
			} else {
				init(a[a.length - 1]);
			}
		})
	}

	$('#title').html('Level ' + level + ' - ' + params.title);
	$('#current').html('0');
	if (params.contributor) {
		$('#contributor').html('Contributed by ' + params.contributor);
	} else {
		$('#contributor').html('');
	}
	var startXY;
	if (params.start) {
		startXY = params.start;
	} else {
		startXY = defaultStart;
	}
	var best = JSON.parse(window.localStorage[scoreStorage])
	if (!best[level]) {
		best[level] = 0
		window.localStorage[scoreStorage] = JSON.stringify(best)
	}
	layoutPersonalities();
	initLevels(Object.keys(levels).concat(Object.keys(custom)), Object.keys(JSON.parse(window.localStorage[scoreStorage])), level)
	$('#best').html(best[level])
	
	if (Object.keys(custom).indexOf(level.toString()) != -1) {
		current = params;
	} else {
		current = null;
	}
	
	var color = d3.scale.category10();
	
	var nodes = [];
	Object.keys(params.personalities).forEach(function(k) {
		d3.range(params.personalities[k]).forEach(function() {
			var obj = personalities[k];
			var o = Math.random()
			var r = $.isFunction(r) ? obj.r(o) : obj.r;
			var rad = obj.r;
			var xy = startingPosition([r, gameW - r], [r, gameH - r], [startXY.x(gameW, gameH), startXY.y(gameW, gameH)], buffer);
			nodes.push({r: rad,
				x: xy[0],
				y: xy[1],
				sx: xy[0],
				sy: xy[1],
				m: obj.momentum, o: o, color: obj.color,
				physics: obj.physics});
		})
	});
	var userNode = d3.range(1).map(function() {
		return {r: params.r, x: startXY.x(gameW, gameH), y: startXY.y(gameW, gameH), color: userColor};
	});
	
	var shapes = svg.selectAll('.shapes')
		.data(nodes).enter()
		.append('circle')
		.attr('class', 'shapes')
		.attr('r', function(d) { return d.r; })
		.attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; })
		.attr('fill', function(d, i) { return d.color; });
	
	var user = svg.selectAll('.user')
		.data(userNode).enter()
		.append('circle')
		.attr('class', 'user')
		.attr('r', function(d) { return d.r; })
		.attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; })
		.attr('fill', function(d) { return d.color; });
	
	d3.select('body').on("keydown", function() {
			switch(d3.event.keyCode) {
			case 37:
				changeMovement(-1, 0, d3.event.keyCode, true);
				break;
			case 38:
				changeMovement(0, -1, d3.event.keyCode, true);
				break;
			case 39:
				changeMovement(1, 0, d3.event.keyCode, true);
				break;
			case 40:
				changeMovement(0, 1, d3.event.keyCode, true);
				break;
			}
		}).on("keyup", function() {
			switch(d3.event.keyCode) {
			case 37:
				changeMovement(1, 0, d3.event.keyCode, false);
				break;
			case 38:
				changeMovement(0, 1, d3.event.keyCode, false);
				break;
			case 39:
				changeMovement(-1, 0, d3.event.keyCode, false);
				break;
			case 40:
				changeMovement(0, -1, d3.event.keyCode, false);
				break;
			}
		});
	
	function changeMovement(x, y, key, isDown) {
		if (!defaultInterval && isDown && playing) {
			start = new Date().getTime();
			defaultInterval = setInterval(redraw, 1)
		}
		if ((isDown && down.indexOf(key) == -1) || !isDown) {
			movement.x += x;
			movement.y += y;
			if (isDown) {
				down.push(key);
			} else {
				down.splice(down.indexOf(key), 1);
			}
		}
		d3.event.preventDefault();
	}
			
	function redraw() {
		var cur = svg.select('.user').datum();
		var t = Math.floor((new Date().getTime() - start) / 1000);
		shapes.each(function(d) {
			d.a = d.physics.a(d, cur, gameW, gameH);
			d.x = d.physics.dx(d, cur, gameW, gameH);
			d.y = d.physics.dy(d, cur, gameW, gameH);
			if (collide(d, cur)) {
				levelEnd(t, level);
			}
		})
		shapes.attr("transform", function(d) { return 'translate(' + d.x + ', ' + d.y + ')'; });
		user.each(function(d) {
			var r = $.isFunction(d.r) ? d.r(d) : d.r;
			if (d.x + movement.x * params.speed <= gameW - r && d.x + movement.x * params.speed >= r) {
				d.x += movement.x ? movement.x * params.speed / dist(movement.x, movement.y) : 0;
			}
			if (d.y + movement.y * params.speed <= gameH - r && d.y + movement.y * params.speed >= r) {
				d.y += movement.y ? movement.y * params.speed / dist(movement.x, movement.y) : 0;;
			}
		});
		user.attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; });
		if (t > parseInt($('#current').html())) {
			$('#current').html(t);
		}
		if (pass(t)) {
			levelEnd(t, level);
		}
	}
}

function collide(d, e) {
	return dist(d.x - e.x, d.y - e.y) <= e.r + d.r;
}

function dist(x, y) {
	return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
}<commit_msg>Speed can be a function. Added additional levels.<commit_after>/*
 * OPTIONS
 * Required
 * title - Title of the level
 * speed - Speed of the user, can be a function
 * r - Radius of the user, can be a function
 * 
 * Personalities
 * name - Name
 * bio - Short biography
 * r - Radius, can be function
 * momentum - Momentum, can be function
 * color - Shape color
 * physics - Physics object for how shape behaves
 * 
 * Physics
 * a - Function to determine trajectory angle
 * dx - Function to determine change in x on tick
 * dy - Function to determine change in y on tick
 */
var physics = {
	follow: {
		a: function(d, c, w, h) { return Math.atan2(c.y - d.y, c.x - d.x); },
		dx: function(d, c, w, h) { return d.x + ($.isFunction(d.m) ? d.m(d, c, w, h) : d.m) * Math.cos(d.a) / (d.r * d.r); },
		dy: function(d, c, w, h) { return d.y + ($.isFunction(d.m) ? d.m(d, c, w, h) : d.m) * Math.sin(d.a) / (d.r * d.r); }
	}, followGhost: {
		a: function(d, c, w, h) { return Math.atan2(Math.abs(c.y - d.y) > Math.abs(h + c.y - d.y) ? h + c.y - d.y : c.y - d.y, Math.abs(c.x - d.x) > Math.abs(w + c.x - d.x) ? w + c.x - d.x : c.x - d.x) },
		dx: function(d, c, w, h) { return (d.x + ($.isFunction(d.m) ? d.m(d, c, w, h) : d.m) * Math.cos(d.a) / (d.r * d.r) + w) % w; },
		dy: function(d, c, w, h) { return (d.y + ($.isFunction(d.m) ? d.m(d, c, w, h) : d.m) * Math.sin(d.a) / (d.r * d.r) + h) % h; }
	}
}
physics.trajectory = {
	a: function(d, c, w, h) { return Math.atan2(c.y + 200 * movement.y - d.y, c.x + 100 * movement.x - d.x) },
	dx: physics.follow.dx,
	dy: physics.follow.dy
}
physics.gaurd = {
	a: function(d, c, w, h) { return dist(d.sx - c.x, d.sy - c.y) <= 200 ? Math.atan2(c.y - d.y, c.x - d.x) : Math.atan2(d.sy - d.y, d.sx - d.x) },
	dx: physics.follow.dx,
	dy: physics.follow.dy
}
var personalities = {
	basic: {
		name: 'Basic',
		bio: "Basic is your average Joe. He enjoys lounging around, weekends, and chasing you. He likes a relaxing chase, but likes to clear his mind while doing so. He'll go to where you are, but can easily be decieved if you run circles around him.",
		r: 20,
		momentum: 150,
		color: 'gray',
		physics: physics.follow
	},
	basicGhost: {
		name: 'Ghost',
		bio: "Ghost is a run-of-the mill ghost. She puts in about as much effor as Basic, but doesn't care for pesky walls. She'll chase you and it it's faster to go through the wall to get you she will.",
		r: 20,
		momentum: 150,
		color: '#EEE',
		physics: physics.followGhost
	},
	seeker: {
		name: 'Seeker',
		bio: "Seeker's gotten some intel about where you're going and moves to intercept you. Watch out: this guy's sneaky.",
		r: 20,
		momentum: 250,
		color: 'blue',
		physics: physics.trajectory
	},
	gaurd: {
		name: '<NAME>',
		bio: "<NAME> won't bother you if you're far away, but if you get too close to him he'll chase after you. He's very protective of his space.",
		r: 20,
		momentum: 350,
		color: 'green',
		physics: physics.gaurd
	}
}, defaultStart = {
	x: function(w, h) { return w / 2; },
	y: function(w, h) { return h / 2; }
};

var levels = {1: {title: 'Meet Basic', speed: 1, r: 20, personalities: {basic: 10}},
		2: {title: 'Ghost', speed: 1, r: 20, personalities: {basicGhost: 5, basic: 5}},
		3: {title: 'Seeker', speed: 1, r: 20, personalities: {seeker: 1}},
		4: {title: 'Gaurd', speed: 1, r: 20, personalities: {gaurd: 5, basic: 5}},
		5: {title: 'Seeker Pack', speed: 1, r: 20, personalities: {seeker: 4}},
		6: {title: 'Save Your Strength', speed: function(d) { return .2 + Math.max((1000 - d.dist) / 2000, 0); }, r: 20, personalities: {basic: 5}}};
var custom = {}, current, userColor = 'lightblue', defaultInterval, scoreStorage = 'bestShapeEscape',
		customStorage = 'customShapeEscape', movement = {x: 0, y: 0}, down = [], playing = false, buffer = 200;

$(document).ready(function() {
	$('#customButtons').hide();
	gameW = $('#game').width(), gameH = $('#game').width();
	if (window.localStorage[customStorage]) {
		custom = JSON.parse(window.localStorage[customStorage])
	}
	var sto = window.localStorage[scoreStorage]
	if (!sto || typeof(JSON.parse(sto)) != 'object' || !JSON.parse(sto)[1]) {
		window.localStorage[scoreStorage] = JSON.stringify({1: 0})
		init(1)
		$('#modalContent').html($('#modalContent').html() + newPersonalityHtml(1) + '<button class="close">Lemme At \'Em!</button>');
		newPersonalityJs(1);
		$('#levelEnd').reveal({
		     animation: 'fadeAndPop',
		     animationspeed: 300,
		     closeonbackgroundclick: true,
		     dismissmodalclass: 'close'
		});
	} else {
		renumberCustom()
		var a = getFinishedLevels();
		if (a.length != Object.keys(levels).length && parseInt(a[a.length - 1]) <= a.length) {
			init(parseInt(a[a.length - 1]) + 1);
		} else {
			init(a[a.length - 1]);
		}
		if (a.length >= 10) {
			$('#custom').show();
		}
	}
	//$("#pop")[0].load();
	//$("#tada")[0].load();
	//$("#tada")[0].volume = .1;
	!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
});

function init(level) {
	playing = true;
	
	d3.select("#game").html('')

	var svg = d3.select("#game").append("svg:svg")
				.attr("width", gameW).attr("height", gameH).attr("id", "svg");
	
	var params = levels[level]
	if (!params) {
		params = custom[level]
		$('#customButtons').show()
		$('#delete').unbind('click');
		$('#delete').click(function() {
			delete custom[level];
			[scoreStorage, customStorage].forEach(function(d) {
				var sto = JSON.parse(window.localStorage[d]);
				delete sto[level];
				window.localStorage[d] = JSON.stringify(sto);
			})
			renumberCustom();
			$('#customButtons').hide();
			var a = getFinishedLevels();
			if (a.length != Object.keys(levels).length) {
				init(parseInt(a[a.length - 1]) + 1);
			} else {
				init(a[a.length - 1]);
			}
		})
	}

	$('#title').html('Level ' + level + ' - ' + params.title);
	$('#current').html('0');
	if (params.contributor) {
		$('#contributor').html('Contributed by ' + params.contributor);
	} else {
		$('#contributor').html('');
	}
	var startXY;
	if (params.start) {
		startXY = params.start;
	} else {
		startXY = defaultStart;
	}
	var best = JSON.parse(window.localStorage[scoreStorage])
	if (!best[level]) {
		best[level] = 0
		window.localStorage[scoreStorage] = JSON.stringify(best)
	}
	layoutPersonalities();
	initLevels(Object.keys(levels).concat(Object.keys(custom)), Object.keys(JSON.parse(window.localStorage[scoreStorage])), level)
	$('#best').html(best[level])
	
	if (Object.keys(custom).indexOf(level.toString()) != -1) {
		current = params;
	} else {
		current = null;
	}
	
	var color = d3.scale.category10();
	
	var nodes = [];
	Object.keys(params.personalities).forEach(function(k) {
		d3.range(params.personalities[k]).forEach(function() {
			var obj = personalities[k];
			var o = Math.random()
			var r = $.isFunction(r) ? obj.r(o) : obj.r;
			var rad = obj.r;
			var xy = startingPosition([r, gameW - r], [r, gameH - r], [startXY.x(gameW, gameH), startXY.y(gameW, gameH)], buffer);
			nodes.push({r: rad,
				x: xy[0],
				y: xy[1],
				sx: xy[0],
				sy: xy[1],
				m: obj.momentum, o: o, color: obj.color,
				physics: obj.physics});
		})
	});
	var userNode = d3.range(1).map(function() {
		return {r: params.r, x: startXY.x(gameW, gameH), y: startXY.y(gameW, gameH), color: userColor, dist: 0};
	});
	
	var shapes = svg.selectAll('.shapes')
		.data(nodes).enter()
		.append('circle')
		.attr('class', 'shapes')
		.attr('r', function(d) { return d.r; })
		.attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; })
		.attr('fill', function(d, i) { return d.color; });
	
	var user = svg.selectAll('.user')
		.data(userNode).enter()
		.append('circle')
		.attr('class', 'user')
		.attr('r', function(d) { return d.r; })
		.attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; })
		.attr('fill', function(d) { return d.color; });
	
	d3.select('body').on("keydown", function() {
			switch(d3.event.keyCode) {
			case 37:
				changeMovement(-1, 0, d3.event.keyCode, true);
				break;
			case 38:
				changeMovement(0, -1, d3.event.keyCode, true);
				break;
			case 39:
				changeMovement(1, 0, d3.event.keyCode, true);
				break;
			case 40:
				changeMovement(0, 1, d3.event.keyCode, true);
				break;
			}
		}).on("keyup", function() {
			switch(d3.event.keyCode) {
			case 37:
				changeMovement(1, 0, d3.event.keyCode, false);
				break;
			case 38:
				changeMovement(0, 1, d3.event.keyCode, false);
				break;
			case 39:
				changeMovement(-1, 0, d3.event.keyCode, false);
				break;
			case 40:
				changeMovement(0, -1, d3.event.keyCode, false);
				break;
			}
		});
	
	function changeMovement(x, y, key, isDown) {
		if (!defaultInterval && isDown && playing) {
			start = new Date().getTime();
			defaultInterval = setInterval(redraw, 1)
		}
		if ((isDown && down.indexOf(key) == -1) || !isDown) {
			movement.x += x;
			movement.y += y;
			if (isDown) {
				down.push(key);
			} else {
				down.splice(down.indexOf(key), 1);
			}
		}
		d3.event.preventDefault();
	}
			
	function redraw() {
		var cur = svg.select('.user').datum();
		var t = Math.floor((new Date().getTime() - start) / 1000);
		shapes.each(function(d) {
			d.a = d.physics.a(d, cur, gameW, gameH);
			d.x = d.physics.dx(d, cur, gameW, gameH);
			d.y = d.physics.dy(d, cur, gameW, gameH);
			if (collide(d, cur)) {
				levelEnd(t, level);
			}
		})
		shapes.attr("transform", function(d) { return 'translate(' + d.x + ', ' + d.y + ')'; });
		user.each(function(d) {
			var r = $.isFunction(d.r) ? d.r(d) : d.r;
			var s = $.isFunction(params.speed) ? params.speed(d) : params.speed;
			if (d.x + movement.x * s <= gameW - r && d.x + movement.x * s >= r) {
				var move = movement.x ? movement.x * s / dist(movement.x, movement.y) : 0;
				d.x += move;
				d.dist += Math.abs(move);
			}
			if (d.y + movement.y * s <= gameH - r && d.y + movement.y * s >= r) {
				var move = movement.y ? movement.y * s / dist(movement.x, movement.y) : 0;
				d.y += move;
				d.dist += Math.abs(move);
			}
		});
		user.attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; });
		if (t > parseInt($('#current').html())) {
			$('#current').html(t);
		}
		if (pass(t)) {
			levelEnd(t, level);
		}
	}
}

function collide(d, e) {
	return dist(d.x - e.x, d.y - e.y) <= e.r + d.r;
}

function dist(x, y) {
	return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
}
{'fraction_non_alphanumeric': 0.2066309117503657, 'fraction_numerical': 0.01628473915163335, 'mean_word_length': 3.2624688279301743, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 22, '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': '870003', 'n_tokens_mistral': 8893, 'n_tokens_neox': 7940, 'n_words': 1950}