feat: add range support for spark table cell matching
This commit is contained in:
parent
03671583cd
commit
376dde44b5
|
|
@ -188,6 +188,43 @@ export function scanSparkTables(
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Range parsing
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a cell value like "1-3", "4-6", or "10-20" into { min, max }.
|
||||||
|
* Returns null if the cell doesn't represent a range.
|
||||||
|
*/
|
||||||
|
function parseRange(cell: string): { min: number; max: number } | null {
|
||||||
|
const trimmed = cell.trim();
|
||||||
|
const m = /^(\d+)\s*-\s*(\d+)$/.exec(trimmed);
|
||||||
|
if (!m) return null;
|
||||||
|
const min = parseInt(m[1], 10);
|
||||||
|
const max = parseInt(m[2], 10);
|
||||||
|
if (isNaN(min) || isNaN(max)) return null;
|
||||||
|
return { min, max };
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Test whether a rolled total matches a cell value */
|
||||||
|
function matchesCell(diceCell: string, rolledValue: number): boolean {
|
||||||
|
const trimmed = diceCell.trim();
|
||||||
|
|
||||||
|
// Exact integer match
|
||||||
|
const cellNum = parseInt(trimmed, 10);
|
||||||
|
if (!isNaN(cellNum) && rolledValue === cellNum) return true;
|
||||||
|
|
||||||
|
// Exact string match (for non-numeric labels)
|
||||||
|
if (String(rolledValue) === trimmed) return true;
|
||||||
|
|
||||||
|
// Range match (e.g. "1-3")
|
||||||
|
const range = parseRange(trimmed);
|
||||||
|
if (range && rolledValue >= range.min && rolledValue <= range.max)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Rolling
|
// Rolling
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
@ -207,17 +244,11 @@ export function rollSparkTable(meta: SparkTableMeta): SparkTableResult {
|
||||||
const roll = rollFormula(meta.notation);
|
const roll = rollFormula(meta.notation);
|
||||||
const rolledValue = roll.result.total;
|
const rolledValue = roll.result.total;
|
||||||
|
|
||||||
// Find the row matching the rolled value — compare as integers,
|
// Find the row matching the rolled value
|
||||||
// falling back to string comparison.
|
|
||||||
let value = `(no row for ${rolledValue})`;
|
let value = `(no row for ${rolledValue})`;
|
||||||
for (const row of meta.rows) {
|
for (const row of meta.rows) {
|
||||||
const diceCell = row[0] ?? "";
|
const diceCell = row[0] ?? "";
|
||||||
const cellNum = parseInt(diceCell.trim(), 10);
|
if (matchesCell(diceCell, rolledValue)) {
|
||||||
const match =
|
|
||||||
!isNaN(cellNum) && rolledValue === cellNum
|
|
||||||
? true
|
|
||||||
: String(rolledValue) === diceCell.trim();
|
|
||||||
if (match) {
|
|
||||||
value = row[colIdx + 1] ?? "";
|
value = row[colIdx + 1] ?? "";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue