howlongtobeat-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +157 -0
  3. package/esm/mod.d.ts +30 -0
  4. package/esm/mod.d.ts.map +1 -0
  5. package/esm/mod.js +31 -0
  6. package/esm/package.json +3 -0
  7. package/esm/src/HowLongToBeat.d.ts +63 -0
  8. package/esm/src/HowLongToBeat.d.ts.map +1 -0
  9. package/esm/src/HowLongToBeat.js +142 -0
  10. package/esm/src/http/client.d.ts +29 -0
  11. package/esm/src/http/client.d.ts.map +1 -0
  12. package/esm/src/http/client.js +250 -0
  13. package/esm/src/parser/json.d.ts +17 -0
  14. package/esm/src/parser/json.d.ts.map +1 -0
  15. package/esm/src/parser/json.js +113 -0
  16. package/esm/src/types.d.ts +179 -0
  17. package/esm/src/types.d.ts.map +1 -0
  18. package/esm/src/types.js +19 -0
  19. package/esm/src/utils/similarity.d.ts +28 -0
  20. package/esm/src/utils/similarity.d.ts.map +1 -0
  21. package/esm/src/utils/similarity.js +127 -0
  22. package/package.json +38 -0
  23. package/script/mod.d.ts +30 -0
  24. package/script/mod.d.ts.map +1 -0
  25. package/script/mod.js +39 -0
  26. package/script/package.json +3 -0
  27. package/script/src/HowLongToBeat.d.ts +63 -0
  28. package/script/src/HowLongToBeat.d.ts.map +1 -0
  29. package/script/src/HowLongToBeat.js +146 -0
  30. package/script/src/http/client.d.ts +29 -0
  31. package/script/src/http/client.d.ts.map +1 -0
  32. package/script/src/http/client.js +258 -0
  33. package/script/src/parser/json.d.ts +17 -0
  34. package/script/src/parser/json.d.ts.map +1 -0
  35. package/script/src/parser/json.js +118 -0
  36. package/script/src/types.d.ts +179 -0
  37. package/script/src/types.d.ts.map +1 -0
  38. package/script/src/types.js +22 -0
  39. package/script/src/utils/similarity.d.ts +28 -0
  40. package/script/src/utils/similarity.d.ts.map +1 -0
  41. package/script/src/utils/similarity.js +133 -0
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ /**
3
+ * String similarity algorithms for HowLongToBeat
4
+ *
5
+ * Provides both Gestalt pattern matching (like Python's difflib.SequenceMatcher)
6
+ * and Levenshtein distance-based similarity.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.calculateSimilarity = calculateSimilarity;
10
+ exports.gestaltSimilarity = gestaltSimilarity;
11
+ exports.levenshteinSimilarity = levenshteinSimilarity;
12
+ exports.createSimilarityCalculator = createSimilarityCalculator;
13
+ /**
14
+ * Calculate similarity using the specified algorithm
15
+ */
16
+ function calculateSimilarity(a, b, algorithm = "gestalt") {
17
+ if (algorithm === "levenshtein") {
18
+ return levenshteinSimilarity(a, b);
19
+ }
20
+ return gestaltSimilarity(a, b);
21
+ }
22
+ /**
23
+ * Gestalt Pattern Matching similarity (like Python's difflib.SequenceMatcher)
24
+ *
25
+ * This implements the Ratcliff/Obershelp algorithm which finds the longest
26
+ * common substring and recursively processes the remaining parts.
27
+ */
28
+ function gestaltSimilarity(a, b) {
29
+ if (a === b)
30
+ return 1.0;
31
+ if (a.length === 0 || b.length === 0)
32
+ return 0.0;
33
+ const matches = countMatchingCharacters(a, b);
34
+ return (2.0 * matches) / (a.length + b.length);
35
+ }
36
+ /**
37
+ * Count matching characters using Ratcliff/Obershelp algorithm
38
+ */
39
+ function countMatchingCharacters(a, b) {
40
+ const [lcs, aStart, aEnd, bStart, bEnd] = findLongestCommonSubstring(a, b);
41
+ if (lcs === 0) {
42
+ return 0;
43
+ }
44
+ let count = lcs;
45
+ // Recursively process left parts
46
+ if (aStart > 0 && bStart > 0) {
47
+ count += countMatchingCharacters(a.substring(0, aStart), b.substring(0, bStart));
48
+ }
49
+ // Recursively process right parts
50
+ if (aEnd < a.length && bEnd < b.length) {
51
+ count += countMatchingCharacters(a.substring(aEnd), b.substring(bEnd));
52
+ }
53
+ return count;
54
+ }
55
+ /**
56
+ * Find the longest common substring between two strings
57
+ * Returns [length, aStart, aEnd, bStart, bEnd]
58
+ */
59
+ function findLongestCommonSubstring(a, b) {
60
+ let longestLength = 0;
61
+ let aStart = 0;
62
+ let bStart = 0;
63
+ // Build a table of matching positions
64
+ const table = Array(a.length + 1)
65
+ .fill(null)
66
+ .map(() => Array(b.length + 1).fill(0));
67
+ for (let i = 1; i <= a.length; i++) {
68
+ for (let j = 1; j <= b.length; j++) {
69
+ if (a[i - 1] === b[j - 1]) {
70
+ table[i][j] = table[i - 1][j - 1] + 1;
71
+ if (table[i][j] > longestLength) {
72
+ longestLength = table[i][j];
73
+ aStart = i - longestLength;
74
+ bStart = j - longestLength;
75
+ }
76
+ }
77
+ }
78
+ }
79
+ return [
80
+ longestLength,
81
+ aStart,
82
+ aStart + longestLength,
83
+ bStart,
84
+ bStart + longestLength,
85
+ ];
86
+ }
87
+ /**
88
+ * Calculate Levenshtein distance between two strings
89
+ */
90
+ function levenshteinDistance(a, b) {
91
+ if (a.length === 0)
92
+ return b.length;
93
+ if (b.length === 0)
94
+ return a.length;
95
+ const matrix = [];
96
+ // Initialize first column
97
+ for (let i = 0; i <= a.length; i++) {
98
+ matrix[i] = [i];
99
+ }
100
+ // Initialize first row
101
+ for (let j = 0; j <= b.length; j++) {
102
+ matrix[0][j] = j;
103
+ }
104
+ // Fill in the rest of the matrix
105
+ for (let i = 1; i <= a.length; i++) {
106
+ for (let j = 1; j <= b.length; j++) {
107
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
108
+ matrix[i][j] = Math.min(matrix[i - 1][j] + 1, // deletion
109
+ matrix[i][j - 1] + 1, // insertion
110
+ matrix[i - 1][j - 1] + cost);
111
+ }
112
+ }
113
+ return matrix[a.length][b.length];
114
+ }
115
+ /**
116
+ * Calculate similarity based on Levenshtein distance
117
+ * Returns a value between 0 and 1, where 1 means identical strings
118
+ */
119
+ function levenshteinSimilarity(a, b) {
120
+ if (a === b)
121
+ return 1.0;
122
+ if (a.length === 0 || b.length === 0)
123
+ return 0.0;
124
+ const distance = levenshteinDistance(a, b);
125
+ const maxLength = Math.max(a.length, b.length);
126
+ return 1 - distance / maxLength;
127
+ }
128
+ /**
129
+ * Create a similarity calculator function with a specific algorithm
130
+ */
131
+ function createSimilarityCalculator(algorithm = "gestalt") {
132
+ return (a, b) => calculateSimilarity(a, b, algorithm);
133
+ }