test(simulation): cover the Some(basin_dirs) threading + clarify on-demand default (T-1047)
Addresses PR #170 review (Hoshe H1/H2). H1: the Some(basin_dirs) path through derive_all_districts was untested (tests only used None). Added derive_all_districts_threads_supplied_basin_directions (synthetic per-district directions propagate to DistrictProfile.basin_direction; unmapped districts fall back to North), and added basin_direction to the cascade determinism loop so the full run_layer1->district chain is guarded. H2: clarified the derive_district on-demand comment — the North default is an accepted limitation (a fallback, not a computed value); the batch path threads the true D8 direction. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -506,6 +506,9 @@ mod tests {
|
||||
assert_eq!(p1.river_threshold, p2.river_threshold);
|
||||
assert_eq!(p1.tectonic_class, p2.tectonic_class);
|
||||
assert_eq!(p1.glaciation_grade, p2.glaciation_grade);
|
||||
// basin_direction threads run_layer1 -> district_basin_dirs -> here;
|
||||
// guard the full chain's determinism (T-1047).
|
||||
assert_eq!(p1.basin_direction, p2.basin_direction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1288,8 +1288,12 @@ pub fn derive_district(
|
||||
);
|
||||
|
||||
// derive_district is the on-demand path (arbitrary DistrictPos, no L1 working
|
||||
// grid); basin_direction defaults to North here. The batch path
|
||||
// (derive_all_districts) threads the true D8 thalweg direction from L1.
|
||||
// grid). basin_direction is an ACCEPTED LIMITATION here: it defaults to North
|
||||
// (a fallback, not a computed value) because the D8 thalweg is only available
|
||||
// from the L1 fdir grid the batch path holds. Production voxel generation runs
|
||||
// through the batch path (derive_all_districts), which threads the true D8
|
||||
// direction from L1; this on-demand path is the fallback for districts derived
|
||||
// outside that pass, where a meaningful basin_direction isn't available.
|
||||
build_district_profile(
|
||||
seed,
|
||||
¶ms,
|
||||
@@ -1505,6 +1509,40 @@ mod tests {
|
||||
assert_eq!(districts.len(), 32, "district count mismatch");
|
||||
}
|
||||
|
||||
/// T-1047: the `Some(basin_dirs)` threading path — supplied per-district D8
|
||||
/// directions propagate to `DistrictProfile.basin_direction`, and districts
|
||||
/// not in the map fall back to the default (North). Guards the path that the
|
||||
/// production cascade actually uses (the existing tests only exercise `None`).
|
||||
#[test]
|
||||
fn derive_all_districts_threads_supplied_basin_directions() {
|
||||
use crate::atlas::scale::BasinDirection;
|
||||
let hm = test_hm();
|
||||
let ta = test_ta(&hm);
|
||||
let params = BodyParams::default();
|
||||
|
||||
// Real DistrictPos keys from a baseline (None) run.
|
||||
let baseline = derive_all_districts(test_seed(), ¶ms, &ta, 8, "test_body", None);
|
||||
let mut keys = baseline.keys().copied();
|
||||
let pos_east = keys.next().expect("at least one district");
|
||||
let pos_south = keys.next().expect("at least two districts");
|
||||
let pos_unmapped = keys.next().expect("at least three districts");
|
||||
|
||||
let mut basin_dirs: BTreeMap<DistrictPos, BasinDirection> = BTreeMap::new();
|
||||
basin_dirs.insert(pos_east, BasinDirection::East);
|
||||
basin_dirs.insert(pos_south, BasinDirection::South);
|
||||
|
||||
let districts =
|
||||
derive_all_districts(test_seed(), ¶ms, &ta, 8, "test_body", Some(&basin_dirs));
|
||||
|
||||
assert_eq!(districts[&pos_east].basin_direction, BasinDirection::East);
|
||||
assert_eq!(districts[&pos_south].basin_direction, BasinDirection::South);
|
||||
// Unmapped districts fall back to the default direction (North).
|
||||
assert_eq!(
|
||||
districts[&pos_unmapped].basin_direction,
|
||||
BasinDirection::North
|
||||
);
|
||||
}
|
||||
|
||||
// --- derive_district (on-demand 2 km, interpolation + detail-scatter) -----
|
||||
|
||||
fn earth_params() -> BodyParams {
|
||||
|
||||
Reference in New Issue
Block a user