feat(ui-calculator): input validation, load caps, ceil display, modernization layout
- custom load capped at cargo capacity (error when exceeded); full load shows the cargo capacity; zero cargo pins load to empty and disables the toggle - per-input red border + tooltip for every invalid value (blocks, techs, load, MAT, modernization target); no value may be negative; locking a speed is disabled when drive is zero - display every computed number (results + goal-seek back-solved input) rounded up to 3 decimals via a shared pkg/calc Ceil3 bridged to wasm; engine keeps its own round-to-nearest util.Fixed* - modernization total upgrade cost spans two columns (single line) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -170,3 +170,35 @@ function isValidDWSC(value: number): boolean {
|
||||
if (!Number.isFinite(value)) return false;
|
||||
return value === 0 || value >= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* shipClassFieldErrors returns the invalid reason for each offending
|
||||
* block, independently, so the calculator can mark every bad input
|
||||
* (not just the first failure `validateShipClassValues` reports). The
|
||||
* weapons/armament pairing rule flags both fields. The all-zero rule is
|
||||
* a whole-design condition and is left to `validateShipClassValues`.
|
||||
*/
|
||||
export function shipClassFieldErrors(
|
||||
values: ShipClassValues,
|
||||
): Partial<Record<keyof ShipClassValues, ShipClassValueInvalidReason>> {
|
||||
const errors: Partial<
|
||||
Record<keyof ShipClassValues, ShipClassValueInvalidReason>
|
||||
> = {};
|
||||
if (!isValidDWSC(values.drive)) errors.drive = "drive_value";
|
||||
if (!Number.isFinite(values.armament) || values.armament < 0) {
|
||||
errors.armament = "armament_value";
|
||||
} else if (!Number.isInteger(values.armament)) {
|
||||
errors.armament = "armament_not_integer";
|
||||
}
|
||||
if (!isValidDWSC(values.weapons)) errors.weapons = "weapons_value";
|
||||
if (!isValidDWSC(values.shields)) errors.shields = "shields_value";
|
||||
if (!isValidDWSC(values.cargo)) errors.cargo = "cargo_value";
|
||||
if (
|
||||
(values.armament === 0 && values.weapons !== 0) ||
|
||||
(values.armament !== 0 && values.weapons === 0)
|
||||
) {
|
||||
errors.weapons ??= "armament_weapons_pair";
|
||||
errors.armament ??= "armament_weapons_pair";
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user