diff --git a/apps/worker/src/jobs.ts b/apps/worker/src/jobs.ts index 5edc117..39e668a 100644 --- a/apps/worker/src/jobs.ts +++ b/apps/worker/src/jobs.ts @@ -281,6 +281,18 @@ function parseGpsParts(parts: number[]): number | null { return sign * value; } +function parseGpsFraction(input: string): number | null { + const trimmed = input.trim(); + if (!trimmed) return null; + const match = trimmed.match(/^(-?\d+(?:\.\d+)?)\s*\/\s*(\d+(?:\.\d+)?)$/); + if (!match) return null; + const numerator = Number(match[1]); + const denominator = Number(match[2]); + if (!Number.isFinite(numerator) || !Number.isFinite(denominator)) return null; + if (denominator === 0) return null; + return numerator / denominator; +} + function parseGpsValue(value: unknown): number | null { if (typeof value === "number") { return Number.isFinite(value) ? value : null; @@ -291,6 +303,8 @@ function parseGpsValue(value: unknown): number | null { if (!trimmed) return null; const direct = Number(trimmed); if (!Number.isNaN(direct)) return direct; + const fraction = parseGpsFraction(trimmed); + if (fraction !== null) return fraction; const parts = trimmed.match(/-?\d+(?:\.\d+)?/g); if (!parts) return null; return parseGpsParts(parts.map((part) => Number(part)).filter(Number.isFinite)); @@ -300,7 +314,19 @@ function parseGpsValue(value: unknown): number | null { const parts = value .map((part) => { if (typeof part === "number") return part; - if (typeof part === "string") return Number(part); + if (typeof part === "string") { + const fraction = parseGpsFraction(part); + if (fraction !== null) return fraction; + return Number(part); + } + if (typeof part === "object" && part !== null) { + const candidate = part as Record; + const numerator = Number(candidate.numerator); + const denominator = Number(candidate.denominator); + if (Number.isFinite(numerator) && Number.isFinite(denominator) && denominator !== 0) { + return numerator / denominator; + } + } return NaN; }) .filter(Number.isFinite); @@ -310,9 +336,13 @@ function parseGpsValue(value: unknown): number | null { return null; } -function applyRefSign(value: number, ref: unknown): number { - if (typeof ref !== "string") return value; - const normalized = ref.trim().toUpperCase(); +function applyRefSign(value: number, ref: unknown, valueRaw: unknown): number { + const refChar = typeof ref === "string" ? ref.trim().toUpperCase() : ""; + const rawChar = + typeof valueRaw === "string" + ? (valueRaw.trim().match(/[NSEW]/i)?.[0]?.toUpperCase() ?? "") + : ""; + const normalized = refChar || rawChar; if (normalized === "S" || normalized === "W") return -Math.abs(value); if (normalized === "N" || normalized === "E") return Math.abs(value); return value; @@ -325,7 +355,7 @@ function parseGpsCoord( ): number | null { const parsed = parseGpsValue(value); if (parsed === null) return null; - const signed = applyRefSign(parsed, ref); + const signed = applyRefSign(parsed, ref, value); if (!Number.isFinite(signed)) return null; if (kind === "lat") { return signed >= -90 && signed <= 90 ? signed : null;