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
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -207,17 +244,11 @@ export function rollSparkTable(meta: SparkTableMeta): SparkTableResult {
|
|||
const roll = rollFormula(meta.notation);
|
||||
const rolledValue = roll.result.total;
|
||||
|
||||
// Find the row matching the rolled value — compare as integers,
|
||||
// falling back to string comparison.
|
||||
// Find the row matching the rolled value
|
||||
let value = `(no row for ${rolledValue})`;
|
||||
for (const row of meta.rows) {
|
||||
const diceCell = row[0] ?? "";
|
||||
const cellNum = parseInt(diceCell.trim(), 10);
|
||||
const match =
|
||||
!isNaN(cellNum) && rolledValue === cellNum
|
||||
? true
|
||||
: String(rolledValue) === diceCell.trim();
|
||||
if (match) {
|
||||
if (matchesCell(diceCell, rolledValue)) {
|
||||
value = row[colIdx + 1] ?? "";
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue