<commit_before>// Word-based drills
// =================

// Takes parameters:
//
// - `drill`: look up in TypeJig.WordSets.  Can have multiple
// drills which will be merged together.
//
// - `timeLimit`: floating-point minutes.
//
// - `type`:
//   - not present: drill words once in order (normal text).
//   - `randomly`: drill words in random order until `timeLimit`.
//   - `shuffled`: drill words once in a random order.

function wordDrill(params) {
	var words = getDrillWords(params.drill);
	if(!words.length) return;
	var name = words.name;

	var timeLimit = 0;

	var first = +params.first || 0;
	var count = +params.count || words.length;
	if(first !== 0 || count !== words.length) {
		words = words.slice(first, first+count);
		name += ' ' + first + ' to ' + (first+count);
	}
	var randomly = (params.type === 'randomly');

	if(params.type === 'randomly') {
		timeLimit = Math.round(60 * params.timeLimit);
		name = timeString(params.timeLimit) + ' of Random ' + name;
	} else if(params.type === 'shuffled') {
		name = 'Randomized ' + name;
		shuffleTail(words, words.length);
	}

	exercise = new TypeJig.Exercise(words, timeLimit, randomly, params.select);
	exercise.name = name;
	return exercise;
}

function getDrillWords(drills) {
	if(!Array.isArray(drills)) drills = [drills];
	var name = ''; words = [];
	for(let i=0; i<drills.length; ++i) {
		var w = TypeJig.WordSets[drills[i]]
		if(w) {
			var last = (i === drills.length-1);
			name = nameAnd(name, last, drills[i]);
			words = words.concat(w);
		}
	}
	words.name = name;
	return words;<commit_msg>Word drill: ask for a lot of words?<commit_after>// Word-based drills
// =================

// Takes parameters:
//
// - `drill`: look up in TypeJig.WordSets.  Can have multiple
// drills which will be merged together.
//
// - `timeLimit`: floating-point minutes.
//
// - `type`:
//   - not present: drill words once in order (normal text).
//   - `randomly`: drill words in random order until `timeLimit`.
//   - `shuffled`: drill words once in a random order.

function wordDrill(params) {
	var words = getDrillWords(params.drill, +params.count || 0);
	if(!words.length) return;
	var name = words.name;

	var timeLimit = 0;

	var first = +params.first || 0;
	var count = +params.count || words.length;
	if(first !== 0 || count !== words.length) {
		words = words.slice(first, first+count);
		name += ' ' + first + ' to ' + (first+count);
	}
	var randomly = (params.type === 'randomly');

	if(params.type === 'randomly') {
		timeLimit = Math.round(60 * params.timeLimit);
		name = timeString(params.timeLimit) + ' of Random ' + name;
	} else if(params.type === 'shuffled') {
		name = 'Randomized ' + name;
		shuffleTail(words, words.length);
	}

	exercise = new TypeJig.Exercise(words, timeLimit, randomly, params.select);
	exercise.name = name;
	return exercise;
}

function getDrillWords(drills, count) {
	if(!count) count = 1000;
	if(!Array.isArray(drills)) drills = [drills];
	var name = ''; words = [];
	for(let i=0; i<drills.length; ++i) {
		var w = TypeJig.WordSets[drills[i]]
		if(typeof w === 'function') {
			const generateWord = w;
			const n = Math.floor(count*(i+1)/drills.length) - Math.floor(count*i/drills.length);
			w = [];  for(let j=0; j<n; ++j) w.push(generateWord());
		}
		if(w) {
			var last = (i === drills.length-1);
			name = nameAnd(name, last, drills[i]);
			words = words.concat(w);
		}
	}
	words.name = name;
	return words;
{'fraction_non_alphanumeric': 0.18335766423357663, 'fraction_numerical': 0.006131386861313868, 'mean_word_length': 3.519788918205805, 'pattern_counts': {'":': 0, '<': 6, '<?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': '1248113', 'n_tokens_mistral': 1284, 'n_tokens_neox': 1190, 'n_words': 312}