__get(value, gram_size) {
		const normalized_value = value.toLowerCase();

		/** @type {Record<string, number>} */
		const matches = {};
		const gram_counts = gram_counter(normalized_value, gram_size);
		const items = this.items[gram_size];
		let sum_of_square_gram_counts = 0;
		let gram;
		let gram_count;
		let i;
		let index;
		let other_gram_count;

		for (gram in gram_counts) {
			gram_count = gram_counts[gram];
			sum_of_square_gram_counts += Math.pow(gram_count, 2);
			if (gram in this.match_dict) {
				for (i = 0; i < this.match_dict[gram].length; ++i) {
					index = this.match_dict[gram][i][0];
					other_gram_count = this.match_dict[gram][i][1];
					if (index in matches) {
						matches[index] += gram_count * other_gram_count;
					} else {
						matches[index] = gram_count * other_gram_count;
					}
				}
			}
		}

		const vector_normal = Math.sqrt(sum_of_square_gram_counts);

		/** @type {MatchTuple[]} */
		let results = [];
		let match_score;

		// build a results list of [score, str]
		for (const match_index in matches) {
			match_score = matches[match_index];
			// @ts-ignore no idea what this code is doing
			results.push([match_score / (vector_normal * items[match_index][0]), items[match_index][1]]);
		}

		results.sort(sort_descending);

		/** @type {MatchTuple[]} */
		let new_results = [];
		const end_index = Math.min(50, results.length);
		// truncate somewhat arbitrarily to 50
		for (let i = 0; i < end_index; ++i) {
			// @ts-ignore no idea what this code is doing
			new_results.push([_distance(results[i][1], normalized_value), results[i][1]]);
		}
		results = new_results;
		results.sort(sort_descending);

		new_results = [];
		for (let i = 0; i < results.length; ++i) {
			if (results[i][0] === results[0][0]) {
				// @ts-ignore no idea what this code is doing
				new_results.push([results[i][0], this.exact_set[results[i][1]]]);
			}
		}

		return new_results;
	}
@param {string} value
@param {number} gram_size
@returns {MatchTuple[]}