129 lines
3.4 KiB
JavaScript
129 lines
3.4 KiB
JavaScript
export function rectFromPoints(start, end) {
|
|
return {
|
|
x: Math.round(Math.min(start.x, end.x)),
|
|
y: Math.round(Math.min(start.y, end.y)),
|
|
width: Math.round(Math.abs(end.x - start.x)),
|
|
height: Math.round(Math.abs(end.y - start.y)),
|
|
};
|
|
}
|
|
|
|
export function resolveFieldRect(anchorPosition, field) {
|
|
return {
|
|
x: Math.round(anchorPosition.x + field.offsetX),
|
|
y: Math.round(anchorPosition.y + field.offsetY),
|
|
width: Math.round(field.width),
|
|
height: Math.round(field.height),
|
|
};
|
|
}
|
|
|
|
export function combineRects(first, second) {
|
|
const x = Math.min(first.x, second.x);
|
|
const y = Math.min(first.y, second.y);
|
|
return {
|
|
x,
|
|
y,
|
|
width: Math.max(first.x + first.width, second.x + second.width) - x,
|
|
height: Math.max(first.y + first.height, second.y + second.height) - y,
|
|
};
|
|
}
|
|
|
|
export function normalizeOcrText(text) {
|
|
return text.replace(/\s+/g, " ").trim();
|
|
}
|
|
|
|
export function parseFieldValue(type, text) {
|
|
const normalized = normalizeOcrText(text);
|
|
|
|
if (type !== "price" && type !== "quantity") {
|
|
return normalized;
|
|
}
|
|
|
|
const digits = normalized.replace(/\D/g, "");
|
|
return digits ? Number(digits) : null;
|
|
}
|
|
|
|
export function parseStoreHeaderText(text) {
|
|
const normalized = normalizeOcrText(text);
|
|
const match = normalized.match(
|
|
/private\s*store.*?\b(buy|sell)\b.*?[-–—]\s*(.+)$/i,
|
|
);
|
|
|
|
if (!match?.[2]?.trim()) return null;
|
|
|
|
return {
|
|
side: match[1].toLowerCase(),
|
|
merchant: match[2].trim(),
|
|
rawText: normalized,
|
|
};
|
|
}
|
|
|
|
export function parseTooltipText(text) {
|
|
const lines = text
|
|
.split(/\r?\n/)
|
|
.map(normalizeOcrText)
|
|
.filter(Boolean);
|
|
const priceIndex = lines.findIndex(
|
|
(line) =>
|
|
/\d[\d\s,.'`]*\s*adena/i.test(line) ||
|
|
/pr[i1l]ce\s*[:;]?\s*\d/i.test(line) ||
|
|
/^\s*\d[\d\s,.'`]*\s*$/.test(line),
|
|
);
|
|
|
|
if (priceIndex < 0) return null;
|
|
|
|
const priceLine = lines[priceIndex];
|
|
const priceText =
|
|
priceLine.match(/([\d][\d\s,.'`]*)\s*adena/i)?.[1] ??
|
|
priceLine.match(/pr[i1l]ce\s*[:;]?\s*([\d][\d\s,.'`]*)/i)?.[1] ??
|
|
priceLine.match(/^\s*([\d][\d\s,.'`]*)\s*$/)?.[1] ??
|
|
"";
|
|
const digits = priceText.replace(/\D/g, "");
|
|
let name = lines.slice(0, priceIndex).find((line) => !/^pr[i1l]ce\s*[:;]?$/i.test(line)) ?? "";
|
|
|
|
if (!name) {
|
|
name = priceLine.slice(0, priceLine.search(/pr[i1l]ce/i)).trim();
|
|
}
|
|
|
|
if (!name || !digits) return null;
|
|
|
|
const quantityMatches = [...name.matchAll(/\(([\d][\d\s,.]*)\)/g)];
|
|
const quantityMatch = quantityMatches.at(-1);
|
|
const quantityText = quantityMatch?.[1].replace(/\D/g, "") ?? "";
|
|
if (quantityMatch) {
|
|
name = `${name.slice(0, quantityMatch.index)} ${name.slice(quantityMatch.index + quantityMatch[0].length)}`
|
|
.replace(/\s+/g, " ")
|
|
.trim();
|
|
}
|
|
|
|
return {
|
|
name,
|
|
quantity: quantityText ? Number(quantityText) : 1,
|
|
priceAdena: Number(digits),
|
|
rawText: lines.join("\n"),
|
|
};
|
|
}
|
|
|
|
export function isCalibrationReady(calibration) {
|
|
return Boolean(
|
|
calibration?.saleAnchor?.image &&
|
|
calibration.saleAnchor.width >= 4 &&
|
|
calibration.saleAnchor.height >= 4 &&
|
|
calibration.storeHeaderRegion &&
|
|
calibration.tooltipSearchRegion &&
|
|
calibration.tooltipAnchor?.image &&
|
|
calibration.itemNameRegion &&
|
|
calibration.itemPriceRegion,
|
|
);
|
|
}
|
|
|
|
export function isRectInside(rect, width, height) {
|
|
return (
|
|
rect.x >= 0 &&
|
|
rect.y >= 0 &&
|
|
rect.width > 0 &&
|
|
rect.height > 0 &&
|
|
rect.x + rect.width <= width &&
|
|
rect.y + rect.height <= height
|
|
);
|
|
}
|