feat(simulation): T-1119 QuarterFootprintLayer — server half (touch points 1-2) + populated wire fixtures
ZoningType gains PartialOrd/Ord (DistrictType T-994 mirror) for the dominant_zoning declaration-order tie-break. layer_proxy: QuarterFootprintEntry/QuarterFootprintLayer (BTreeMap keyed by city_id; density_avg_pct floor-mean, dominant_* mode with declaration-order tie-break, landmark/corridor counts) + build_quarter_footprint_layer gated None on empty state.quarters; sixth AtlasLayerResponse field wired into all construction sites; growth-ceiling doc updated to say the whole-body budget is consumed (what carries a seventh is T-1124's design, resolved in the same branch's amendment). Placements whose derived Layer4Quarter id is not yet in state.quarters are SKIPPED (skeleton gen is async Low-priority — entries may be a proper subset; client decodes defensively). Stale TODO(#957) removed (premise predates T-957 landing). Tie-break bug caught by its own test: Iterator::max_by_key over a BTreeMap returns the LAST max on ties — backwards from declaration-order-first; replaced with an explicit forward walk that replaces only on strictly-greater count. gen_fixtures: populated RegionGridLayer (T-1118 replay coverage) + QuarterFootprintLayer literals in the ready fixture; msgpack fixtures regenerated via make fixtures. Note: landmark_count is inert on real data today (BlockSkeleton.landmark hardcoded None until landmark placement lands); fixtures use non-zero counts to exercise the logic. 5 new unit tests + populated round-trip; atlas:: 549 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,16 +4,20 @@
|
||||
use settled_reach_server::atlas::body_world_state::{DrainageBasin, RiverNetwork};
|
||||
use settled_reach_server::atlas::layer1::Layer1Output;
|
||||
use settled_reach_server::atlas::layer_proxy::{
|
||||
AtlasLayerResponse, AtlasLayerStatus, RoadGraphEdge, RoadGraphLayer, RoadGraphNode,
|
||||
SettlementEntry, SettlementLayer, SettlementSizeClass,
|
||||
AtlasLayerResponse, AtlasLayerStatus, QuarterFootprintEntry, QuarterFootprintLayer,
|
||||
RegionGridLayer, RoadGraphEdge, RoadGraphLayer, RoadGraphNode, SettlementEntry,
|
||||
SettlementLayer, SettlementSizeClass,
|
||||
};
|
||||
use settled_reach_server::atlas::region_profile::{SeasonPhase, WeatherState};
|
||||
use settled_reach_server::atlas::road_graph::RoadNodeKind;
|
||||
use settled_reach_server::bridge::types::*;
|
||||
use settled_reach_server::simulation::generator::{
|
||||
AttractorType, GeographicAttractor, MaintenanceAuthority, SubBiomeVariant,
|
||||
AttractorType, DistrictType, GeographicAttractor, MaintenanceAuthority, SubBiomeVariant,
|
||||
ZoningType,
|
||||
};
|
||||
use settled_reach_server::simulation::poi::PoiCategory;
|
||||
use settled_reach_server::simulation::time::{DayPhase, TickRate};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
@@ -616,6 +620,53 @@ fn generate_atlas_layer_response_fixtures() {
|
||||
},
|
||||
],
|
||||
};
|
||||
// T-1113: a small populated RegionGridLayer — a 2×1 covering grid, one
|
||||
// temperate region and one airless-style region (mean_temp_dc sentinel),
|
||||
// mirroring the values exercised by
|
||||
// `build_region_grid_encodes_dense_quantized_climate` in layer_proxy.rs.
|
||||
let region_grid = RegionGridLayer {
|
||||
cols: 2,
|
||||
rows: 1,
|
||||
season: vec![SeasonPhase::Summer as u8, SeasonPhase::Winter as u8],
|
||||
weather: vec![WeatherState::Clear as u8, WeatherState::Snow as u8],
|
||||
mean_temp_dc: vec![
|
||||
123,
|
||||
settled_reach_server::atlas::layer_proxy::REGION_TEMP_NONE_DC,
|
||||
],
|
||||
moisture_q: vec![80, 5],
|
||||
};
|
||||
// T-1119 (D-226 T-1112 amendment): a populated QuarterFootprintLayer
|
||||
// covering both fixture settlements — city_id 1 (Port Aldren, a dense
|
||||
// Commercial-dominant quarter with landmarks/corridors) and city_id 2
|
||||
// (Farmstead Rell, a sparse Residential-dominant quarter with neither),
|
||||
// so the fixture exercises both a "rich" entry and a "minimal" entry
|
||||
// rather than only one shape.
|
||||
let quarter_footprints = QuarterFootprintLayer {
|
||||
entries: BTreeMap::from([
|
||||
(
|
||||
1,
|
||||
QuarterFootprintEntry {
|
||||
city_id: 1,
|
||||
density_avg_pct: 62,
|
||||
dominant_district_type: DistrictType::Commercial,
|
||||
dominant_zoning: ZoningType::Commercial,
|
||||
landmark_count: 3,
|
||||
corridor_count: 4,
|
||||
},
|
||||
),
|
||||
(
|
||||
2,
|
||||
QuarterFootprintEntry {
|
||||
city_id: 2,
|
||||
density_avg_pct: 18,
|
||||
dominant_district_type: DistrictType::Residential,
|
||||
dominant_zoning: ZoningType::Residential,
|
||||
landmark_count: 0,
|
||||
corridor_count: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
};
|
||||
|
||||
let ready = AtlasLayerResponse {
|
||||
body_id: "GJ1c".into(),
|
||||
@@ -624,7 +675,8 @@ fn generate_atlas_layer_response_fixtures() {
|
||||
district_grid: None,
|
||||
road_graph: Some(road_graph),
|
||||
settlements: Some(settlements),
|
||||
region_grid: None,
|
||||
region_grid: Some(region_grid),
|
||||
quarter_footprints: Some(quarter_footprints),
|
||||
};
|
||||
write_fixture(
|
||||
"atlas_response_ready",
|
||||
@@ -639,6 +691,7 @@ fn generate_atlas_layer_response_fixtures() {
|
||||
road_graph: None,
|
||||
settlements: None,
|
||||
region_grid: None,
|
||||
quarter_footprints: None,
|
||||
};
|
||||
write_fixture(
|
||||
"atlas_response_pending",
|
||||
@@ -653,6 +706,7 @@ fn generate_atlas_layer_response_fixtures() {
|
||||
road_graph: None,
|
||||
settlements: None,
|
||||
region_grid: None,
|
||||
quarter_footprints: None,
|
||||
};
|
||||
write_fixture(
|
||||
"atlas_response_not_found",
|
||||
|
||||
Reference in New Issue
Block a user