@regolithco/ocr 1.0.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.
@@ -0,0 +1,5 @@
1
+ import Ocr from '@gutenye/ocr-browser';
2
+ import { ShipRockInput, ShipMiningOrderCapture } from '@regolithco/common';
3
+ export declare const initPaddle: () => Promise<Ocr>;
4
+ export declare const parseShipRock: (image: string) => Promise<ShipRockInput>;
5
+ export declare const parseShipMiningOrder: (image: string) => Promise<ShipMiningOrderCapture>;
@@ -0,0 +1,38 @@
1
+ import Ocr from '@gutenye/ocr-browser';
2
+ import { parseShipRock as parseShipRockText } from './parsers/shipRock.js';
3
+ import { parseShipMiningOrder as parseShipMiningOrderText } from './parsers/shipMiningOrder.js';
4
+ import log from 'loglevel';
5
+ let ocrInstance = null;
6
+ export const initPaddle = async () => {
7
+ if (!ocrInstance) {
8
+ // Note: For browser usage, you must provide paths to the ONNX models.
9
+ // Ensure these files are available in your public/assets directory.
10
+ ocrInstance = await Ocr.create({
11
+ models: {
12
+ detectionPath: '/assets/models/ch_PP-OCRv4_det_infer.onnx',
13
+ recognitionPath: '/assets/models/ch_PP-OCRv4_rec_infer.onnx',
14
+ dictionaryPath: '/assets/models/ppocr_keys_v1.txt',
15
+ },
16
+ });
17
+ }
18
+ return ocrInstance;
19
+ };
20
+ const recognizeText = async (image) => {
21
+ const ocr = await initPaddle();
22
+ const results = await ocr.detect(image);
23
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ const fullText = results.map((line) => line.text).join('\n');
25
+ log.debug('--- PADDLE OCR OUTPUT ---');
26
+ log.debug(fullText);
27
+ log.debug('-------------------------');
28
+ return fullText;
29
+ };
30
+ export const parseShipRock = async (image) => {
31
+ const text = await recognizeText(image);
32
+ return parseShipRockText(text);
33
+ };
34
+ export const parseShipMiningOrder = async (image) => {
35
+ const text = await recognizeText(image);
36
+ return parseShipMiningOrderText(text);
37
+ };
38
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,sBAAsB,CAAA;AAEtC,OAAO,EAAE,aAAa,IAAI,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAC1E,OAAO,EAAE,oBAAoB,IAAI,wBAAwB,EAAE,MAAM,8BAA8B,CAAA;AAC/F,OAAO,GAAG,MAAM,UAAU,CAAA;AAE1B,IAAI,WAAW,GAAe,IAAI,CAAA;AAElC,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;IACnC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,sEAAsE;QACtE,oEAAoE;QACpE,WAAW,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAC7B,MAAM,EAAE;gBACN,aAAa,EAAE,2CAA2C;gBAC1D,eAAe,EAAE,2CAA2C;gBAC5D,cAAc,EAAE,kCAAkC;aACnD;SACF,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,WAAW,CAAA;AACpB,CAAC,CAAA;AAED,MAAM,aAAa,GAAG,KAAK,EAAE,KAAa,EAAmB,EAAE;IAC7D,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAA;IAC9B,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACvC,8DAA8D;IAC9D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEjE,GAAG,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAA;IACtC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;IACnB,GAAG,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAA;IAEtC,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,KAAa,EAA0B,EAAE;IAC3E,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAA;IACvC,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAA;AAChC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,EAAE,KAAa,EAAmC,EAAE;IAC3F,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAA;IACvC,OAAO,wBAAwB,CAAC,IAAI,CAAC,CAAA;AACvC,CAAC,CAAA"}
package/dist/node.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import Ocr from '@gutenye/ocr-node';
2
+ import { ShipRockInput, ShipMiningOrderCapture } from '@regolithco/common/dist/gen/schema.types.js';
3
+ export declare const initPaddle: () => Promise<Ocr | null>;
4
+ export declare const recognizeText: (imagePath: string) => Promise<string>;
5
+ export declare const parseShipMiningOrder: (imagePath: string) => Promise<ShipMiningOrderCapture>;
6
+ export declare const parseShipRock: (imagePath: string) => Promise<ShipRockInput>;
package/dist/node.js ADDED
@@ -0,0 +1,29 @@
1
+ import Ocr from '@gutenye/ocr-node';
2
+ import { parseShipMiningOrder as parseShipMiningOrderText } from './parsers/shipMiningOrder.js';
3
+ import { parseShipRock as parseShipRockText } from './parsers/shipRock.js';
4
+ let ocrInstance = null;
5
+ export const initPaddle = async () => {
6
+ if (!ocrInstance) {
7
+ ocrInstance = await Ocr.create();
8
+ }
9
+ return ocrInstance;
10
+ };
11
+ export const recognizeText = async (imagePath) => {
12
+ const ocr = await initPaddle();
13
+ const results = await ocr.detect(imagePath);
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ const fullText = results.map((line) => line.text).join('\n');
16
+ console.log('--- PADDLE OCR OUTPUT ---');
17
+ console.log(fullText);
18
+ console.log('-------------------------');
19
+ return fullText;
20
+ };
21
+ export const parseShipMiningOrder = async (imagePath) => {
22
+ const text = await recognizeText(imagePath);
23
+ return parseShipMiningOrderText(text);
24
+ };
25
+ export const parseShipRock = async (imagePath) => {
26
+ const text = await recognizeText(imagePath);
27
+ return parseShipRockText(text);
28
+ };
29
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,mBAAmB,CAAA;AAEnC,OAAO,EAAE,oBAAoB,IAAI,wBAAwB,EAAE,MAAM,8BAA8B,CAAA;AAC/F,OAAO,EAAE,aAAa,IAAI,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAE1E,IAAI,WAAW,GAAe,IAAI,CAAA;AAElC,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;IACnC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,WAAW,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,CAAA;IAClC,CAAC;IACD,OAAO,WAAW,CAAA;AACpB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,SAAiB,EAAmB,EAAE;IACxE,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAA;IAC9B,MAAM,OAAO,GAAG,MAAM,GAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAC5C,8DAA8D;IAC9D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEjE,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAA;IACxC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACrB,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAA;IAExC,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,EAAE,SAAiB,EAAmC,EAAE;IAC/F,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAA;IAC3C,OAAO,wBAAwB,CAAC,IAAI,CAAC,CAAA;AACvC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,SAAiB,EAA0B,EAAE;IAC/E,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAA;IAC3C,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAA;AAChC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './parsers/shipRock.js';
2
+ export * from './parsers/shipMiningOrder.js';
package/dist/parser.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './parsers/shipRock.js';
2
+ export * from './parsers/shipMiningOrder.js';
3
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AACA,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { ShipMiningOrderCapture } from '@regolithco/common';
2
+ export declare const parseShipMiningOrder: (ocrText: string) => ShipMiningOrderCapture;
@@ -0,0 +1,258 @@
1
+ import { RefineryEnum, RefineryMethodEnum, ShipOreEnum, } from '@regolithco/common';
2
+ import { cleanLine, findBestMatch } from './utils.js';
3
+ export const parseShipMiningOrder = (ocrText) => {
4
+ const lines = ocrText
5
+ .split('\n')
6
+ .map(cleanLine)
7
+ .filter((l) => l.length > 0);
8
+ let refinery;
9
+ let method;
10
+ let processDurationS;
11
+ const shipOres = [];
12
+ const expenses = [];
13
+ const allRefineries = Object.values(RefineryEnum);
14
+ const allMethods = Object.values(RefineryMethodEnum);
15
+ const allOres = Object.values(ShipOreEnum);
16
+ // Pre-calculate partial names for fuzzy matching
17
+ // We derive these directly from the Enum keys to avoid external dependencies
18
+ const refineryReverseLookup = {};
19
+ for (const ref of allRefineries) {
20
+ const enumVal = ref.toString();
21
+ // Strategy 1: The full enum value (normalized elsewhere, but good to have)
22
+ refineryReverseLookup[enumVal.toUpperCase()] = ref;
23
+ // Strategy 2: Split by underscore (e.g. PYRO_CHECKMATE -> PYRO, CHECKMATE)
24
+ const parts = enumVal.split('_');
25
+ for (const part of parts) {
26
+ if (part.length > 3) {
27
+ // e.g. CHECKMATE
28
+ refineryReverseLookup[part.toUpperCase()] = ref;
29
+ }
30
+ // Special case for L-points like CRU_L1 -> L1 (too short) but CRU_L1 -> CRU
31
+ // Actually L1 is not unique. combining CRU and L1 is CRU-L1.
32
+ }
33
+ // Strategy 3: Handle typical "System_Station" pattern
34
+ // If it has underscores, the last part is often the unique station name
35
+ if (parts.length > 1) {
36
+ // e.g. PYRO_CHECKMATE -> CHECKMATE
37
+ const lastPart = parts[parts.length - 1];
38
+ if (lastPart.length > 3) {
39
+ refineryReverseLookup[lastPart.toUpperCase()] = ref;
40
+ }
41
+ }
42
+ // Strategy 4: Cleaned "Human" version approx (CRU_L1 -> CRUL1)
43
+ const normalized = enumVal.replace(/_/g, '').replace(/I/g, '1').replace(/L/g, '1');
44
+ if (normalized.length > 3) {
45
+ refineryReverseLookup[normalized.toUpperCase()] = ref;
46
+ }
47
+ }
48
+ // State for parsing ores
49
+ let inMaterialsSection = false;
50
+ for (let idx = 0; idx < lines.length; idx++) {
51
+ const line = lines[idx];
52
+ const lineUpper = line.toUpperCase();
53
+ // 1. Refinery
54
+ if (!refinery) {
55
+ // Try simple inclusion of any key in our reverse lookup
56
+ for (const [key, ref] of Object.entries(refineryReverseLookup)) {
57
+ // Check if LINE includes KEY (standard) or KEY includes LINE (if line is short/fragmented)
58
+ if (lineUpper.includes(key) || (key.length > 4 && key.includes(lineUpper))) {
59
+ refinery = ref;
60
+ break;
61
+ }
62
+ }
63
+ // Fallback to strict Enum matching if above failed
64
+ if (!refinery) {
65
+ const normalizedLine = lineUpper.replace(/\s/g, '').replace(/-/g, '').replace(/I/g, '1').replace(/L/g, '1');
66
+ if (normalizedLine.length > 3) {
67
+ for (const ref of allRefineries) {
68
+ const normalizedRef = ref.toString().replace(/_/g, '').replace(/I/g, '1').replace(/L/g, '1');
69
+ if (normalizedLine.includes(normalizedRef) || normalizedRef.includes(normalizedLine)) {
70
+ refinery = ref;
71
+ break;
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ // 2. Method
78
+ if (!method) {
79
+ const bestMethod = findBestMatch(lineUpper, allMethods, 3);
80
+ if (bestMethod) {
81
+ method = bestMethod;
82
+ }
83
+ else {
84
+ for (const m of allMethods) {
85
+ const humanM = m.replace(/_/g, ' ');
86
+ if (lineUpper.includes(humanM) || lineUpper.includes(m)) {
87
+ method = m;
88
+ break;
89
+ }
90
+ if (lineUpper.length >= humanM.length) {
91
+ for (let i = 0; i <= lineUpper.length - humanM.length; i++) {
92
+ const substr = lineUpper.substring(i, i + humanM.length);
93
+ const dist = findBestMatch(substr, [m], 3);
94
+ if (dist) {
95
+ method = m;
96
+ break;
97
+ }
98
+ }
99
+ }
100
+ if (method)
101
+ break;
102
+ }
103
+ }
104
+ }
105
+ // 3. Process Time
106
+ if (!processDurationS && (lineUpper.includes('PROCESS TIME') || lineUpper.includes('TIME'))) {
107
+ let d = 0;
108
+ let h = 0;
109
+ let m = 0;
110
+ let found = false;
111
+ const dMatch = lineUpper.match(/(\d+)\s*D/);
112
+ if (dMatch) {
113
+ d = parseInt(dMatch[1], 10);
114
+ found = true;
115
+ }
116
+ const hMatch = lineUpper.match(/(\d+)\s*H/);
117
+ if (hMatch) {
118
+ h = parseInt(hMatch[1], 10);
119
+ found = true;
120
+ }
121
+ const mMatch = lineUpper.match(/(\d+)\s*M/);
122
+ if (mMatch) {
123
+ m = parseInt(mMatch[1], 10);
124
+ found = true;
125
+ }
126
+ if (found) {
127
+ processDurationS = d * 86400 + h * 3600 + m * 60;
128
+ }
129
+ }
130
+ // 3.5. Expenses
131
+ const feeMappings = {
132
+ 'TOTAL COST': 'Refinery Fee',
133
+ 'REFINERY FEE': 'Refinery Fee',
134
+ 'SERVICE FEE': 'Service Fee',
135
+ };
136
+ const fees = Object.keys(feeMappings);
137
+ for (const key of fees) {
138
+ if (lineUpper.includes(key)) {
139
+ const matches = lineUpper.match(/(\d[\d,.]*)/g);
140
+ if (matches) {
141
+ const rawAmount = matches[matches.length - 1].replace(/,/g, '');
142
+ const amount = parseInt(rawAmount);
143
+ if (!isNaN(amount)) {
144
+ const mappedName = feeMappings[key];
145
+ if (!expenses.find((e) => e.name === mappedName)) {
146
+ expenses.push({
147
+ __typename: 'WorkOrderExpense',
148
+ name: mappedName,
149
+ amount,
150
+ ownerScName: 'Unknown',
151
+ });
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+ // 4. Ores Section Management
158
+ let exitingSection = false;
159
+ if (!inMaterialsSection) {
160
+ if (lineUpper.includes('MATERIALS SELECTED') ||
161
+ (lineUpper.includes('YIELD') && lineUpper.includes('REFINE') && !lineUpper.includes('TO REFINE')) ||
162
+ (lineUpper.includes('OTY') && lineUpper.includes('YIELD'))) {
163
+ inMaterialsSection = true;
164
+ continue;
165
+ }
166
+ }
167
+ else {
168
+ // Check for exit conditions but allow processing of current line
169
+ if (lineUpper.includes('TOTAL COST') ||
170
+ lineUpper.includes('USER DETAILS') ||
171
+ lineUpper.includes('PROCESSING TIME') ||
172
+ lineUpper.includes('Select Storage Option'.toUpperCase())) {
173
+ exitingSection = true;
174
+ }
175
+ }
176
+ if (inMaterialsSection) {
177
+ const words = lineUpper.split(/\s+/);
178
+ let oreInLine = null;
179
+ let oreIndex = -1;
180
+ for (let i = 0; i < words.length; i++) {
181
+ const cleanW = words[i].split('(')[0].replace(/[^A-Z]/g, '');
182
+ if (cleanW.length < 3)
183
+ continue;
184
+ const match = findBestMatch(cleanW, allOres, 1);
185
+ if (match) {
186
+ oreInLine = match;
187
+ oreIndex = i;
188
+ break;
189
+ }
190
+ }
191
+ if (oreInLine) {
192
+ let numbers = [];
193
+ for (let i = oreIndex + 1; i < words.length; i++) {
194
+ if (words[i].includes('%'))
195
+ continue;
196
+ const raw = words[i].replace(/[^0-9.]/g, '');
197
+ if (raw.length > 0) {
198
+ const val = parseFloat(raw);
199
+ if (!isNaN(val))
200
+ numbers.push(val);
201
+ }
202
+ }
203
+ // Orphan check: If not enough numbers, check previous line
204
+ if (numbers.length < 2 && idx > 0) {
205
+ const prevLine = lines[idx - 1].toUpperCase();
206
+ // Ensure previous line was not already used (simple check: does it have an Ore?)
207
+ // We re-parse previous line briefly to see if it had an ID'd ore
208
+ let prevLineHasOre = false;
209
+ const prevWords = prevLine.split(/\s+/);
210
+ for (const w of prevWords) {
211
+ const c = w.split('(')[0].replace(/[^A-Z]/g, '');
212
+ if (c.length >= 3 && findBestMatch(c, allOres, 1)) {
213
+ prevLineHasOre = true;
214
+ break;
215
+ }
216
+ }
217
+ if (!prevLineHasOre) {
218
+ // Try to extract numbers from previous line
219
+ const prevNumbers = [];
220
+ for (const w of prevWords) {
221
+ if (w.includes('%'))
222
+ continue;
223
+ const raw = w.replace(/[^0-9.]/g, '');
224
+ if (raw.length > 0) {
225
+ const val = parseFloat(raw);
226
+ if (!isNaN(val))
227
+ prevNumbers.push(val);
228
+ }
229
+ }
230
+ if (prevNumbers.length >= 2) {
231
+ numbers = prevNumbers;
232
+ }
233
+ }
234
+ }
235
+ if (numbers.length >= 2) {
236
+ const yieldVal = numbers[1];
237
+ shipOres.push({
238
+ __typename: 'RefineryRowCapture',
239
+ ore: oreInLine,
240
+ yield: Math.floor(yieldVal),
241
+ });
242
+ }
243
+ }
244
+ if (exitingSection) {
245
+ inMaterialsSection = false;
246
+ }
247
+ }
248
+ }
249
+ return {
250
+ __typename: 'ShipMiningOrderCapture',
251
+ refinery,
252
+ method,
253
+ processDurationS,
254
+ expenses: expenses.length > 0 ? expenses : undefined,
255
+ shipOres,
256
+ };
257
+ };
258
+ //# sourceMappingURL=shipMiningOrder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shipMiningOrder.js","sourceRoot":"","sources":["../../src/parsers/shipMiningOrder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { ShipRockInput } from '@regolithco/common';
2
+ export declare const parseShipRock: (ocrText: string) => ShipRockInput;
@@ -0,0 +1,156 @@
1
+ import { ShipOreEnum, RockStateEnum, AsteroidTypeEnum, DepositTypeEnum, } from '@regolithco/common';
2
+ import { cleanLine, levenshtein } from './utils.js';
3
+ export const parseShipRock = (ocrText) => {
4
+ // Split into lines to preserve spatial context
5
+ const lines = ocrText
6
+ .split('\n')
7
+ .map(cleanLine)
8
+ .filter((l) => l.length > 0);
9
+ // Default values
10
+ let mass = 0;
11
+ let inst;
12
+ let res;
13
+ let rockType;
14
+ const ores = [];
15
+ const allOres = Object.values(ShipOreEnum);
16
+ const asteroidMap = {
17
+ 'M-TYPE': AsteroidTypeEnum.Mtype,
18
+ 'C-TYPE': AsteroidTypeEnum.Ctype,
19
+ 'S-TYPE': AsteroidTypeEnum.Stype,
20
+ 'E-TYPE': AsteroidTypeEnum.Etype,
21
+ 'E TYPE': AsteroidTypeEnum.Etype,
22
+ 'I-TYPE': AsteroidTypeEnum.Itype,
23
+ 'P-TYPE': AsteroidTypeEnum.Ptype,
24
+ 'Q-TYPE': AsteroidTypeEnum.Qtype,
25
+ };
26
+ // Iterate lines to find tokens
27
+ for (const line of lines) {
28
+ const lineUpper = line.toUpperCase();
29
+ // 1. Mass
30
+ if (!mass) {
31
+ // Strict Mass: "MASS: 1234"
32
+ const massMatch = line.match(/Mass\s*[:=\s]\s*([\d,]+(?:\.\d+)?)/i);
33
+ if (massMatch) {
34
+ const val = parseFloat(massMatch[1].replace(/,/g, ''));
35
+ if (!isNaN(val))
36
+ mass = val;
37
+ }
38
+ }
39
+ // 2. Instability
40
+ if (inst === undefined) {
41
+ const match = line.match(/(?:Inst|ABIT|STAB)[^\d]*([\d.]+)/i);
42
+ if (match)
43
+ inst = parseFloat(match[1]);
44
+ }
45
+ // 3. Resistance
46
+ if (res === undefined) {
47
+ // RESISTANCE: 10%
48
+ const match = line.match(/(?:Res|SISTAN|RESIST)[^\d]*([\d.]+)/i);
49
+ if (match) {
50
+ let val = parseFloat(match[1]);
51
+ if (line.includes('%') && val > 1)
52
+ val /= 100;
53
+ res = val;
54
+ }
55
+ }
56
+ // 4. Rock Type
57
+ if (!rockType) {
58
+ for (const [key, value] of Object.entries(asteroidMap)) {
59
+ // Flexible match
60
+ const cleanKey = key.replace(/[- ]/g, '[\\- _\\.]?');
61
+ const regex = new RegExp(cleanKey, 'i');
62
+ if (regex.test(line)) {
63
+ rockType = value;
64
+ break;
65
+ }
66
+ }
67
+ // Deposit types if not asteroid
68
+ if (!rockType) {
69
+ const depositTypes = Object.values(DepositTypeEnum);
70
+ // Only strict match on line for deposit types to avoid noise
71
+ for (const dt of depositTypes) {
72
+ if (lineUpper.includes(dt.toUpperCase())) {
73
+ rockType = dt;
74
+ break;
75
+ }
76
+ }
77
+ }
78
+ }
79
+ // 5. Ores
80
+ // Refined logic: Iterate words in line. Identify Ores. Look for adjacent %.
81
+ const words = lineUpper.split(/\s+/);
82
+ for (let i = 0; i < words.length; i++) {
83
+ const w = words[i].replace(/[^A-Z0-9%.-]/g, ''); // Clean word
84
+ if (w.length < 3)
85
+ continue;
86
+ // Check if w is an Ore (Best match)
87
+ let bestDist = Infinity;
88
+ let bestOre = null;
89
+ for (const ore of allOres) {
90
+ let dist = levenshtein(w, ore.toUpperCase());
91
+ // Special cases
92
+ if (w === 'INERT') {
93
+ if (ore === ShipOreEnum.Inertmaterial)
94
+ dist = 0;
95
+ }
96
+ else if (w === 'MATERIAL' || w === 'MATERIALS') {
97
+ // Context check: previous word INERT?
98
+ if (i > 0 && words[i - 1].toUpperCase().includes('INERT') && ore === ShipOreEnum.Inertmaterial) {
99
+ dist = 0;
100
+ }
101
+ }
102
+ let threshold = 1;
103
+ if (w.length <= 3)
104
+ threshold = 0;
105
+ if (dist <= threshold && dist < bestDist) {
106
+ bestDist = dist;
107
+ bestOre = ore;
108
+ }
109
+ }
110
+ if (bestOre) {
111
+ // We found an ore token. Look for adjacent percentage (i-1 or i+1)
112
+ let percentVal = 0;
113
+ // Check Prev
114
+ if (i > 0) {
115
+ const prev = words[i - 1];
116
+ // Allow bare number ONLY if it is a float (has decimal) or has %
117
+ // This avoids matching "100" (Power) or "70" (Level) as percentage.
118
+ if (prev.includes('%') || prev.includes('.')) {
119
+ const val = parseFloat(prev);
120
+ if (!isNaN(val))
121
+ percentVal = val;
122
+ }
123
+ }
124
+ // Check Next (if not found in prev)
125
+ if (percentVal === 0 && i < words.length - 1) {
126
+ const next = words[i + 1];
127
+ // Next MUST have % to avoid confusion with SCU volume
128
+ if (next.includes('%')) {
129
+ const val = parseFloat(next);
130
+ if (!isNaN(val))
131
+ percentVal = val;
132
+ }
133
+ }
134
+ if (percentVal > 0) {
135
+ if (percentVal > 1)
136
+ percentVal /= 100;
137
+ if (!ores.find((o) => o.ore === bestOre)) {
138
+ ores.push({
139
+ ore: bestOre,
140
+ percent: percentVal,
141
+ });
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ return {
148
+ mass,
149
+ inst,
150
+ res,
151
+ rockType,
152
+ ores,
153
+ state: RockStateEnum.Ready,
154
+ };
155
+ };
156
+ //# sourceMappingURL=shipRock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shipRock.js","sourceRoot":"","sources":["../../src/parsers/shipRock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare const cleanLine: (text: string) => string;
2
+ export declare const levenshtein: (a: string, b: string) => number;
3
+ export declare const findBestMatch: <T extends string>(text: string, candidates: T[], threshold?: number) => T | null;
@@ -0,0 +1,32 @@
1
+ export const cleanLine = (text) => {
2
+ return text.trim();
3
+ };
4
+ export const levenshtein = (a, b) => {
5
+ const matrix = Array.from({ length: a.length + 1 }, () => Array(b.length + 1).fill(0));
6
+ for (let i = 0; i <= a.length; i++)
7
+ matrix[i][0] = i;
8
+ for (let j = 0; j <= b.length; j++)
9
+ matrix[0][j] = j;
10
+ for (let i = 1; i <= a.length; i++) {
11
+ for (let j = 1; j <= b.length; j++) {
12
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
13
+ matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
14
+ }
15
+ }
16
+ return matrix[a.length][b.length];
17
+ };
18
+ export const findBestMatch = (text, candidates, threshold = 2) => {
19
+ let bestDist = Infinity;
20
+ let bestMatch = null;
21
+ const upperText = text.toUpperCase();
22
+ for (const cand of candidates) {
23
+ const upperCand = cand.toUpperCase();
24
+ const dist = levenshtein(upperText, upperCand);
25
+ if (dist < bestDist && dist <= threshold) {
26
+ bestDist = dist;
27
+ bestMatch = cand;
28
+ }
29
+ }
30
+ return bestMatch;
31
+ };
32
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/parsers/utils.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAY,EAAU,EAAE;IAChD,OAAO,IAAI,CAAC,IAAI,EAAE,CAAA;AACpB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE;IAC1D,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IACtF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IAEpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;YAC1C,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;QAClG,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AACnC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAmB,IAAY,EAAE,UAAe,EAAE,YAAoB,CAAC,EAAY,EAAE;IAChH,IAAI,QAAQ,GAAG,QAAQ,CAAA;IACvB,IAAI,SAAS,GAAa,IAAI,CAAA;IAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;IAEpC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QACpC,MAAM,IAAI,GAAG,WAAW,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;QAC9C,IAAI,IAAI,GAAG,QAAQ,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;YACzC,QAAQ,GAAG,IAAI,CAAA;YACf,SAAS,GAAG,IAAI,CAAA;QAClB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA"}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@regolithco/ocr",
3
+ "version": "1.0.0",
4
+ "description": "OCR utilities using PaddleOCR",
5
+ "type": "module",
6
+ "main": "dist/node.js",
7
+ "browser": "dist/browser.js",
8
+ "types": "dist/node.d.ts",
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "engines": {
13
+ "node": ">=22 <24"
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "prepublishOnly": "yarn run build",
21
+ "debug": "tsx scripts/debug_paddle.ts",
22
+ "debug:choose": "tsx scripts/debug_paddle.ts --choose",
23
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
24
+ },
25
+ "keywords": [
26
+ "ocr",
27
+ "paddle",
28
+ "regolith"
29
+ ],
30
+ "author": "",
31
+ "license": "ISC",
32
+ "dependencies": {
33
+ "@gutenye/ocr-browser": "^1.4.8",
34
+ "@gutenye/ocr-node": "^1.4.8",
35
+ "@regolithco/common": "^1.4.7",
36
+ "graphql": "^16.12.0",
37
+ "loglevel": "^1.9.2",
38
+ "onnxruntime-node": "^1.23.2"
39
+ },
40
+ "devDependencies": {
41
+ "@clack/prompts": "^0.11.0",
42
+ "@faker-js/faker": "8",
43
+ "@types/jest": "^30.0.0",
44
+ "@types/lodash": "^4.17.20",
45
+ "@types/node": "^24.5.2",
46
+ "@types/uuid": "9",
47
+ "@typescript-eslint/eslint-plugin": "^8.44.1",
48
+ "@typescript-eslint/parser": "^8.44.1",
49
+ "eslint": "^9.36.0",
50
+ "eslint-config-prettier": "^10.1.8",
51
+ "eslint-config-standard": "^17.1.0",
52
+ "eslint-plugin-import": "^2.32.0",
53
+ "eslint-plugin-n": "^17.23.1",
54
+ "eslint-plugin-node": "^11.1.0",
55
+ "eslint-plugin-prettier": "^5.5.4",
56
+ "eslint-plugin-promise": "^7.2.1",
57
+ "jest": "^30.2.0",
58
+ "prettier": "^3.6.2",
59
+ "ts-jest": "^29.4.4",
60
+ "ts-node": "^10.9.2",
61
+ "tsx": "^4.21.0",
62
+ "typescript": "^5.9.2",
63
+ "uuid": "^13.0.0"
64
+ }
65
+ }