refactor(curriculum): drop string-similarity

This commit is contained in:
Mrugesh Mohapatra
2026-04-19 22:25:14 +05:30
parent f4a3d38e73
commit 6b497e48e8
3 changed files with 68 additions and 23 deletions

View File

@@ -65,7 +65,6 @@
"@types/debug": "4.1.12",
"@types/js-yaml": "4.0.5",
"@types/polka": "0.5.7",
"@types/string-similarity": "4.0.2",
"@typescript/vfs-1.6.1": "npm:@typescript/vfs@1.6.4",
"@vitest/ui": "4.0.15",
"eslint": "9.39.1",
@@ -81,7 +80,6 @@
"polka": "0.5.2",
"puppeteer": "22.12.1",
"sirv": "3.0.2",
"string-similarity": "4.0.4",
"typescript-5.9.2": "npm:typescript@5.9.2",
"vitest": "4.0.15"
},

View File

@@ -1,5 +1,3 @@
import comparison from 'string-similarity';
/**
* Filters the superblocks array to include any superblocks with the specified block.
* If no block is provided, returns the original superblocks array.
@@ -125,8 +123,74 @@ export const applyFilters: GenericFilterFunction = createFilterPipeline([
filterByChallengeId
]);
function normalizeForComparison(value: string): string {
return value.toLowerCase().replace(/[^a-z0-9]+/g, '');
}
function createBigrams(value: string): Map<string, number> {
const bigrams = new Map<string, number>();
for (let i = 0; i < value.length - 1; i++) {
const bigram = value.slice(i, i + 2);
bigrams.set(bigram, (bigrams.get(bigram) ?? 0) + 1);
}
return bigrams;
}
function getSimilarityScore(a: string, b: string): number {
if (a === b) {
return 1;
}
if (a.length < 2 || b.length < 2) {
return 0;
}
const aBigrams = createBigrams(a);
let intersection = 0;
for (let i = 0; i < b.length - 1; i++) {
const bigram = b.slice(i, i + 2);
const count = aBigrams.get(bigram);
if (count) {
intersection += 1;
aBigrams.set(bigram, count - 1);
}
}
return (2 * intersection) / (a.length + b.length - 2);
}
export function closestMatch(target: string, xs: string[]): string {
return comparison.findBestMatch(target.toLowerCase(), xs).bestMatch.target;
const [firstCandidate, ...rest] = xs;
if (!firstCandidate) {
return target;
}
const normalizedTarget = normalizeForComparison(target);
let closest = firstCandidate;
let closestScore = getSimilarityScore(
normalizedTarget,
normalizeForComparison(closest)
);
for (const candidate of rest) {
const score = getSimilarityScore(
normalizedTarget,
normalizeForComparison(candidate)
);
if (score > closestScore) {
closest = candidate;
closestScore = score;
}
}
return closest;
}
export function closestFilters(

19
pnpm-lock.yaml generated
View File

@@ -716,9 +716,6 @@ importers:
'@types/polka':
specifier: 0.5.7
version: 0.5.7
'@types/string-similarity':
specifier: 4.0.2
version: 4.0.2
'@typescript/vfs-1.6.1':
specifier: npm:@typescript/vfs@1.6.4
version: '@typescript/vfs@1.6.4(typescript@5.9.3)'
@@ -764,9 +761,6 @@ importers:
sirv:
specifier: 3.0.2
version: 3.0.2
string-similarity:
specifier: 4.0.4
version: 4.0.4
typescript-5.9.2:
specifier: npm:typescript@5.9.2
version: typescript@5.9.2
@@ -4911,9 +4905,6 @@ packages:
'@types/store@2.0.5':
resolution: {integrity: sha512-5NmTKe3GWdOaykzq7no+Ahf6mafJu0oLc9JNhJ3E26+0oFvd6GnksnZQpMXcH526mfG4xDYjFiKzyDL51PzeWQ==}
'@types/string-similarity@4.0.2':
resolution: {integrity: sha512-LkJQ/jsXtCVMK+sKYAmX/8zEq+/46f1PTQw7YtmQwb74jemS1SlNLmARM2Zml9DgdDTWKAtc5L13WorpHPDjDA==}
'@types/superagent@4.1.19':
resolution: {integrity: sha512-McM1mlc7PBZpCaw0fw/36uFqo0YeA6m8JqoyE4OfqXsZCIg0hPP2xdE6FM7r6fdprDZHlJwDpydUj1R++93hCA==}
@@ -11819,10 +11810,6 @@ packages:
resolution: {integrity: sha512-IoHUjcw3Srl8nsPlW04U3qwWPk3oG2ffLM0tN853d/E/JlIvcmZmDY2Kz5HzKp4lEi2T7QD7Zuvjq/1rDw+XcQ==}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
string-similarity@4.0.4:
resolution: {integrity: sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
@@ -18482,8 +18469,6 @@ snapshots:
'@types/store@2.0.5': {}
'@types/string-similarity@4.0.2': {}
'@types/superagent@4.1.19':
dependencies:
'@types/cookiejar': 2.1.2
@@ -18908,7 +18893,7 @@ snapshots:
sirv: 3.0.2
tinyglobby: 0.2.15
tinyrainbow: 3.0.3
vitest: 4.0.15(@opentelemetry/api@1.9.0)(@types/node@25.5.0)(@vitest/ui@4.0.15)(jiti@2.6.1)(jsdom@26.1.0)(msw@2.13.2(@types/node@25.5.0)(typescript@5.9.3))(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.1)
vitest: 4.0.15(@opentelemetry/api@1.9.0)(@types/node@24.10.8)(@vitest/ui@4.0.15)(jiti@2.6.1)(jsdom@16.7.0)(msw@2.13.2(@types/node@24.10.8)(typescript@5.9.3))(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.1)
'@vitest/utils@3.2.4':
dependencies:
@@ -27133,8 +27118,6 @@ snapshots:
lodash.map: 4.6.0
lodash.maxby: 4.6.0
string-similarity@4.0.4: {}
string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0