fix(simulation): orbital rung applies coast_warp_px — one coastline at every rung (T-1160)
The Global/Region rungs sampled the heightmap ocean mask raw while every finer rung samples it at the coast-warped position — a structurally different coastline at the orbital-to-district seam. Audited on all 267 real body heightmaps at region spacing, coastal band only: 5.01% land/ocean classification disagreement (2,911 of 58,073 cells), mean displacement ~6.0 km, max ~18.9 km. Fork taken: APPLY the warp — derive_orbital_at_metres now runs invent_primitives' steps 1-3 (driver climate -> coast character -> coast_warp_px) before sampling, still skipping detail-scatter (its octave ceiling, 32.8 km, is below region spacing; the WARP's octaves reach 262 km, which is why skipping it was wrong). Cost measured: ~784 ns/cell added (~15 ms on an Earth-class Global canvas; low hundreds of ms parallel at the 8.3M-cell ceiling). The ignored audit test preserves the pre-fix baseline for the record. Golden re-pinned — region rows only, district/quarter byte-identical. project.yaml 0.4.2 -> 0.4.3: orbital canvas bytes changed, client disk caches must miss. Awaiting Araminta's review-seat sign-off per ticket. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1928,26 +1928,43 @@ fn derive_at_metres_with_riparian(
|
||||
}
|
||||
|
||||
/// The orbital-rung derivation (T-1152, zoom ladder design doc §2/§4): the
|
||||
/// coarse-granularity twin of [`derive_at_metres`] that skips [`invent_primitives`]
|
||||
/// entirely — **no coastline warp, no detail-scatter octave sum, no classification
|
||||
/// noise call of any kind**. Per the design doc's orbital row: "`region_baseline_at_district`
|
||||
/// only — bilinear blend of 4 region baselines, no `invent_primitives`, no
|
||||
/// classification [driver]." Orbital sample spacing (≥205 km, D-243's region rung
|
||||
/// and coarser) sits below `detail_scatter`'s own octave floor
|
||||
/// (`OCTAVE_WAVELENGTHS_M`'s coarsest entry is 32,768 m ≈ 32.8 km — an order of
|
||||
/// magnitude finer than a region), so the invented terrain has nothing left to
|
||||
/// contribute at this spacing; calling it would burn cycles synthesizing detail
|
||||
/// no orbital pixel can resolve. What DOES vary at orbital spacing is the
|
||||
/// **envelope** the heightmap itself carries (the `TerrainAnalysis` continental
|
||||
/// shape) and the **region climate baseline** — this function samples exactly
|
||||
/// those two, nothing else.
|
||||
/// coarse-granularity twin of [`derive_at_metres`] that skips MOST of
|
||||
/// [`invent_primitives`] — **no detail-scatter octave sum, no classification
|
||||
/// noise call of any kind** — but DOES apply the coast-warp position shift
|
||||
/// (T-1160). Per the design doc's orbital row: "`region_baseline_at_district`
|
||||
/// only — bilinear blend of 4 region baselines, no [detail-scatter]
|
||||
/// invention, no classification [driver]." Orbital sample spacing (≥205 km,
|
||||
/// D-243's region rung and coarser) sits below `detail_scatter`'s own octave
|
||||
/// floor (`OCTAVE_WAVELENGTHS_M`'s coarsest entry is 32,768 m ≈ 32.8 km — an
|
||||
/// order of magnitude finer than a region), so the invented RELIEF texture has
|
||||
/// nothing left to contribute at this spacing; running it would burn cycles
|
||||
/// synthesizing detail no orbital pixel can resolve. The coastline WARP is
|
||||
/// different: `WARP_OCTAVE_WAVELENGTHS_M`'s coarsest entries run up to 262,144 m
|
||||
/// (262 km) — coarser than a region — so the warp is NOT below this rung's
|
||||
/// resolution floor, and (T-1160 audit) skipping it produced a structurally
|
||||
/// different coastline position than every finer rung (5.0% land/ocean
|
||||
/// classification disagreement at coastal-band cells, 267 real bodies; mean
|
||||
/// displacement ~6.0 km / max ~18.9 km at region spacing — see
|
||||
/// `derive_orbital_coastline_divergence_audit`). What varies at orbital
|
||||
/// spacing is therefore the **envelope** the heightmap carries (the
|
||||
/// `TerrainAnalysis` continental shape), sampled at the **coast-warped
|
||||
/// position**, plus the **region climate baseline** — this function samples
|
||||
/// exactly those, nothing else.
|
||||
///
|
||||
/// **Cost model (design doc R1 — measure first):** one `bilinear` (elevation),
|
||||
/// one `bilinear_bool` (ocean mask), one `region_baseline_at_district` call (its
|
||||
/// own cost is 4×`derive_region_baseline_c` on a cache miss, O(1) on a cache hit)
|
||||
/// — no octave sum, no coast-warp trig, no character/envelope computation. See
|
||||
/// `server/tests/zoom_ladder_bench.rs`'s `bench_derive_orbital_at_metres` for the
|
||||
/// measured per-cell figure this claim rests on.
|
||||
/// **Cost model (T-1160 audit, measured on 267 real bodies, release build):**
|
||||
/// the added driver-tier climate + `coast_character_at` + `coast_warp_px` work
|
||||
/// costs ~784 ns/cell (`coast_warp_px` alone: ~528 ns/cell) — roughly half of
|
||||
/// what `invent_primitives`' FULL pipeline costs on top of this function's own
|
||||
/// ~903 ns/cell baseline (`bench_derive_orbital_at_metres_region_spacing`:
|
||||
/// orbital 902.6 ns/cell vs. full `derive_at_metres` 1940.6 ns/cell at the same
|
||||
/// spacing — a 2.15x gap, of which detail-scatter/classification-noise is the
|
||||
/// remainder this function still skips). At the D-255(a) fixed-rung ceiling
|
||||
/// (3,840×2,160 = 8.3M cells) the added cost is ~6.5 s single-threaded / low
|
||||
/// hundreds of ms on the row-chunked parallel serving path (T-1151); at a
|
||||
/// realistic Global-rung Earth-sized-body canvas (195×97 ≈ 18.9K cells) it is
|
||||
/// ~15 ms. Accepted: coastline correctness at the orbital/Region seam is worth
|
||||
/// a sub-millisecond-to-low-second cost that scales with (and is bounded by)
|
||||
/// the same canvas-size ceiling every other rung's cost already respects.
|
||||
///
|
||||
/// Produces the SAME six-field tail every other rung produces (`morphology_zone`,
|
||||
/// `elev_q`, `temperature_c`, `moisture_q`, `vegetation_class`, `glaciation_grade`)
|
||||
@@ -2011,12 +2028,56 @@ pub fn derive_orbital_at_metres(
|
||||
..body_params.clone()
|
||||
};
|
||||
|
||||
// The envelope only — no coast-warp, no detail-scatter. This is exactly
|
||||
// `invent_primitives`' step-1 "driver tier" raw bilinear reads, promoted to
|
||||
// be the FINAL primitives instead of a one-step-stale input to invention.
|
||||
let elev_q =
|
||||
// T-1160: coast-warp the sampling POSITION (steps 1-3 of
|
||||
// `invent_primitives`), but skip step 4 (slope-independent detail-scatter)
|
||||
// — the envelope carries no per-cell slope signal at orbital spacing (see
|
||||
// the function doc's note on `slope_q`, unchanged). Before this fix, this
|
||||
// function sampled `ta.elev_pct`/`ta.ocean_mask` RAW while District/Quarter
|
||||
// sampled the SAME arrays at the coast-warped position — a structurally
|
||||
// different coastline at the orbital-to-district seam (audit: 5.0%
|
||||
// land/ocean classification disagreement at coastal-band cells across 267
|
||||
// real bodies, mean displacement ~6.0 km / max ~18.9 km at region
|
||||
// spacing). Applying the warp here makes the orbital rung sample the SAME
|
||||
// invented coastline every finer rung already draws — coarser density,
|
||||
// same line, not a different line (T-1160).
|
||||
//
|
||||
// Driver tier: raw-bilinear reads feed the coast character exactly as
|
||||
// `invent_primitives` step 1 does (one-step-stale climate driving the
|
||||
// coast personality, never circular on its own warped output).
|
||||
let raw_elev_q =
|
||||
((bilinear(&ta.elev_pct, ta.w, ta.h, px, py) as f64 * 100.0).round() as i32).clamp(0, 100);
|
||||
let ocean_fraction_q = ((bilinear_bool(&ta.ocean_mask, ta.w, ta.h, px, py) as f64 * 100.0)
|
||||
let raw_ocean_q = ((bilinear_bool(&ta.ocean_mask, ta.w, ta.h, px, py) as f64 * 100.0).round()
|
||||
as i32)
|
||||
.clamp(0, 100);
|
||||
let driver_params = BodyParams {
|
||||
elevation_km: (raw_elev_q as f64 / 100.0) * MAX_REGION_ELEVATION_KM,
|
||||
..params.clone()
|
||||
};
|
||||
let driver_temp = derive_temperature_c(&driver_params, climate, seed.seed());
|
||||
let driver_moisture = derive_moisture_q(&driver_params, raw_elev_q, raw_ocean_q, climate);
|
||||
let driver_glaciation = derive_glaciation_grade_from_climate(driver_temp, driver_moisture);
|
||||
|
||||
// Character + invented coastline (steps 2-3): same body-personality
|
||||
// envelope + position character + warp displacement District/Quarter use,
|
||||
// applied to the SAME `(px, py)` this function already resolved.
|
||||
let tectonic = derive_tectonic_class(body_params);
|
||||
let envelope = coast_invention::body_coast_envelope(body_params, tectonic);
|
||||
let ch = coast_invention::coast_character_at(
|
||||
&envelope,
|
||||
seed.seed(),
|
||||
world_x_m,
|
||||
world_y_m,
|
||||
lat_deg,
|
||||
driver_glaciation,
|
||||
driver_moisture,
|
||||
);
|
||||
let (wdx, wdy) = coast_invention::coast_warp_px(seed.seed(), world_x_m, world_y_m, &ch, 0.0);
|
||||
let (spx, spy) = (px + wdx, py + wdy);
|
||||
|
||||
let elev_q =
|
||||
((bilinear(&ta.elev_pct, ta.w, ta.h, spx, spy) as f64 * 100.0).round() as i32)
|
||||
.clamp(0, 100);
|
||||
let ocean_fraction_q = ((bilinear_bool(&ta.ocean_mask, ta.w, ta.h, spx, spy) as f64 * 100.0)
|
||||
.round() as i32)
|
||||
.clamp(0, 100);
|
||||
// No invented ruggedness at orbital spacing (see the function doc's note
|
||||
@@ -3384,13 +3445,14 @@ mod tests {
|
||||
assert_district_profiles_eq(&a, &b);
|
||||
}
|
||||
|
||||
/// The orbital path must NOT run `invent_primitives` — the design doc's
|
||||
/// central constraint (§2: "no invent_primitives at orbital wavelengths").
|
||||
/// Direct proof: `slope_q` is always exactly 0 (invention is the only
|
||||
/// source of nonzero slope_q at this call depth — see
|
||||
/// `derive_orbital_at_metres`'s doc on why slope_q is fixed), sampled
|
||||
/// across enough distinct positions that a nonzero value appearing even
|
||||
/// once would falsify the claim.
|
||||
/// The orbital path must NOT run `invent_primitives`'s detail-scatter/
|
||||
/// relief step (step 4) — the design doc's central constraint (§2: "no
|
||||
/// [relief] invention at orbital wavelengths"), even though it DOES now
|
||||
/// run steps 1-3 (coast-warp, T-1160). Direct proof: `slope_q` is always
|
||||
/// exactly 0 (detail-scatter is the only source of nonzero slope_q at
|
||||
/// this call depth — see `derive_orbital_at_metres`'s doc on why slope_q
|
||||
/// is fixed), sampled across enough distinct positions that a nonzero
|
||||
/// value appearing even once would falsify the claim.
|
||||
#[test]
|
||||
fn derive_orbital_at_metres_never_invents_slope() {
|
||||
let hm = test_hm();
|
||||
@@ -3505,6 +3567,251 @@ mod tests {
|
||||
let _ = prof.glaciation_grade;
|
||||
}
|
||||
|
||||
/// T-1160 audit (historical record — the fix landed; this test documents
|
||||
/// the numbers that justified it and stays as a standing measurement, not
|
||||
/// a regression gate with a hardcoded threshold). Quantifies the
|
||||
/// orbital-vs-district coastline positional divergence that existed
|
||||
/// BEFORE this ticket: `derive_orbital_at_metres` used to sample
|
||||
/// `ta.ocean_mask` raw (no `coast_warp_px`) while District/Quarter warped
|
||||
/// the same mask first (`invent_primitives` step 3). This test
|
||||
/// independently reimplements both the pre-fix raw read (a) and the
|
||||
/// District-style warped read (b) — deliberately NOT calling
|
||||
/// `derive_orbital_at_metres` itself, so the measurement stays valid as a
|
||||
/// historical baseline regardless of that function's current
|
||||
/// implementation — loads every real `heightmap.png` under
|
||||
/// `wiki/star-systems/`, and for a grid of region-spacing sample points on
|
||||
/// each body reports how often (a) and (b) disagree on land/ocean
|
||||
/// classification, the warp displacement converted to real metres, and
|
||||
/// the per-cell cost of computing (b). These are the numbers T-1160's
|
||||
/// fix (applying the warp at orbital sampling, see
|
||||
/// `derive_orbital_at_metres`'s doc) is based on. `#[ignore]`d — reads
|
||||
/// ~267 real wiki heightmap files, run explicitly:
|
||||
/// `cargo test --release -p settled-reach-server derive_orbital_coastline_divergence_audit -- --ignored --nocapture`
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn derive_orbital_coastline_divergence_audit() {
|
||||
use std::path::Path;
|
||||
use std::time::Instant;
|
||||
|
||||
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../wiki/star-systems");
|
||||
let mut heightmaps: Vec<std::path::PathBuf> = Vec::new();
|
||||
collect_heightmaps(&root, &mut heightmaps);
|
||||
heightmaps.sort();
|
||||
assert!(
|
||||
!heightmaps.is_empty(),
|
||||
"expected to find real heightmap.png files under {:?}",
|
||||
root
|
||||
);
|
||||
|
||||
let climate = ClimateConstants::default();
|
||||
let seed = test_seed();
|
||||
let region_m = scale::REGION_M as f64;
|
||||
|
||||
let mut bodies_sampled = 0usize;
|
||||
let mut total_cells = 0u64;
|
||||
let mut disagreements = 0u64;
|
||||
let mut max_displacement_m = 0.0f64;
|
||||
let mut sum_displacement_m = 0.0f64;
|
||||
let mut displacement_samples = 0u64;
|
||||
|
||||
let mut warp_evals = 0u64;
|
||||
let mut warp_only_nanos = 0u64;
|
||||
let mut warp_plus_character_nanos = 0u64;
|
||||
|
||||
for hm_path in &heightmaps {
|
||||
let Ok(file) = std::fs::File::open(hm_path) else {
|
||||
continue;
|
||||
};
|
||||
let Ok(hm) = crate::atlas::heightmap::load_heightmap_reader(file, "audit", 0.4) else {
|
||||
continue;
|
||||
};
|
||||
if hm.width == 0 || hm.height == 0 {
|
||||
continue;
|
||||
}
|
||||
let dr = drainage::analyze(&hm.data, hm.width, hm.height, hm.sea_level);
|
||||
let ta = TerrainAnalysis::analyze(&hm, &dr);
|
||||
|
||||
let body_params = BodyParams {
|
||||
hydrosphere: Some("ocean".into()),
|
||||
atmosphere: Some("breathable".into()),
|
||||
planet_class: Some("temperate".into()),
|
||||
body_radius_km: Some(6371.0),
|
||||
..Default::default()
|
||||
};
|
||||
let circumference_m = std::f64::consts::TAU * 6371.0 * 1000.0;
|
||||
let meridian_m = std::f64::consts::PI * 6371.0 * 1000.0;
|
||||
|
||||
let tectonic = derive_tectonic_class(&body_params);
|
||||
let envelope = coast_invention::body_coast_envelope(&body_params, tectonic);
|
||||
|
||||
// Sample on a region-spacing grid across the whole body — same
|
||||
// spacing the orbital/Region rung actually renders at.
|
||||
let cols = (circumference_m / region_m).floor() as i64;
|
||||
let rows = (meridian_m / region_m).floor() as i64;
|
||||
if cols < 1 || rows < 1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
bodies_sampled += 1;
|
||||
|
||||
for row in 0..rows {
|
||||
for col in 0..cols {
|
||||
let wx = col as f64 * region_m;
|
||||
let wy = row as f64 * region_m;
|
||||
|
||||
let px = (wx / circumference_m).rem_euclid(1.0) * ta.w as f64;
|
||||
let lat_frac = (wy / meridian_m).clamp(-0.5, 0.5);
|
||||
let py = (0.5 + lat_frac) * ta.h.saturating_sub(1) as f64;
|
||||
let lat_deg = -lat_frac * 180.0;
|
||||
|
||||
// (a) raw orbital read — today's derive_orbital_at_metres.
|
||||
let raw_ocean_q = ((bilinear_bool(&ta.ocean_mask, ta.w, ta.h, px, py) as f64
|
||||
* 100.0)
|
||||
.round() as i32)
|
||||
.clamp(0, 100);
|
||||
|
||||
// Only worth measuring displacement near a coastline — a
|
||||
// cell deep in open ocean or deep inland can't flip
|
||||
// classification no matter the (sub-pixel) warp, so
|
||||
// restrict the expensive per-cell warp eval + metre
|
||||
// conversion to the coastal band (0 < raw_ocean_q < 100
|
||||
// OR any 4-neighbor disagrees) — this is also exactly
|
||||
// the "coastal cell" population the ticket's cost
|
||||
// estimate ("~one warp eval per coastal cell") means.
|
||||
let is_coastal_band = {
|
||||
let n = bilinear_bool(&ta.ocean_mask, ta.w, ta.h, px, py - 1.0) > 0.5;
|
||||
let s = bilinear_bool(&ta.ocean_mask, ta.w, ta.h, px, py + 1.0) > 0.5;
|
||||
let e = bilinear_bool(&ta.ocean_mask, ta.w, ta.h, px + 1.0, py) > 0.5;
|
||||
let w = bilinear_bool(&ta.ocean_mask, ta.w, ta.h, px - 1.0, py) > 0.5;
|
||||
let here = raw_ocean_q > 50;
|
||||
here != n || here != s || here != e || here != w
|
||||
};
|
||||
if !is_coastal_band {
|
||||
continue;
|
||||
}
|
||||
|
||||
total_cells += 1;
|
||||
|
||||
// (b) District-style warped read at the SAME position —
|
||||
// mirrors invent_primitives' driver-tier + character +
|
||||
// warp steps, using the real per-body envelope. Timed
|
||||
// separately from the file-I/O/drainage/TerrainAnalysis
|
||||
// setup above — this is the actual per-cell cost T-1160
|
||||
// would add at orbital sampling, not body-load overhead.
|
||||
let cell_start = Instant::now();
|
||||
let raw_elev_q = ((bilinear(&ta.elev_pct, ta.w, ta.h, px, py) as f64 * 100.0)
|
||||
.round() as i32)
|
||||
.clamp(0, 100);
|
||||
let driver_params = BodyParams {
|
||||
elevation_km: (raw_elev_q as f64 / 100.0) * MAX_REGION_ELEVATION_KM,
|
||||
latitude_deg: lat_deg,
|
||||
..body_params.clone()
|
||||
};
|
||||
let driver_temp =
|
||||
derive_temperature_c(&driver_params, &climate, seed.seed());
|
||||
let driver_moisture =
|
||||
derive_moisture_q(&driver_params, raw_elev_q, raw_ocean_q, &climate);
|
||||
let driver_glaciation =
|
||||
derive_glaciation_grade_from_climate(driver_temp, driver_moisture);
|
||||
|
||||
let ch = coast_invention::coast_character_at(
|
||||
&envelope,
|
||||
seed.seed(),
|
||||
wx,
|
||||
wy,
|
||||
lat_deg,
|
||||
driver_glaciation,
|
||||
driver_moisture,
|
||||
);
|
||||
warp_plus_character_nanos += cell_start.elapsed().as_nanos() as u64;
|
||||
|
||||
warp_evals += 1;
|
||||
let warp_call_start = Instant::now();
|
||||
let (wdx, wdy) = coast_invention::coast_warp_px(seed.seed(), wx, wy, &ch, 0.0);
|
||||
warp_only_nanos += warp_call_start.elapsed().as_nanos() as u64;
|
||||
warp_plus_character_nanos += warp_call_start.elapsed().as_nanos() as u64;
|
||||
let (spx, spy) = (px + wdx, py + wdy);
|
||||
let warped_ocean_q = ((bilinear_bool(&ta.ocean_mask, ta.w, ta.h, spx, spy)
|
||||
as f64
|
||||
* 100.0)
|
||||
.round() as i32)
|
||||
.clamp(0, 100);
|
||||
|
||||
if (raw_ocean_q > 50) != (warped_ocean_q > 50) {
|
||||
disagreements += 1;
|
||||
}
|
||||
|
||||
// Displacement converted to real metres at this body's
|
||||
// equator-circumference-derived px scale (constant across
|
||||
// latitude for an equirectangular map's column spacing;
|
||||
// using the equatorial scale is the conservative /
|
||||
// largest-metres-per-pixel case for row spacing too since
|
||||
// meridian_m/ta.h <= circumference_m/ta.w for ta.h<=ta.w/2).
|
||||
let m_per_px = circumference_m / ta.w as f64;
|
||||
let disp_px = (wdx * wdx + wdy * wdy).sqrt();
|
||||
let disp_m = disp_px * m_per_px;
|
||||
sum_displacement_m += disp_m;
|
||||
displacement_samples += 1;
|
||||
if disp_m > max_displacement_m {
|
||||
max_displacement_m = disp_m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mean_displacement_m = if displacement_samples > 0 {
|
||||
sum_displacement_m / displacement_samples as f64
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let disagreement_pct = if total_cells > 0 {
|
||||
100.0 * disagreements as f64 / total_cells as f64
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let ns_per_warp_call = if warp_evals > 0 {
|
||||
warp_only_nanos as f64 / warp_evals as f64
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let ns_per_full_cell_cost = if warp_evals > 0 {
|
||||
warp_plus_character_nanos as f64 / warp_evals as f64
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
eprintln!("=== T-1160 orbital coastline divergence audit ===");
|
||||
eprintln!("bodies sampled: {bodies_sampled}");
|
||||
eprintln!("coastal-band cells sampled: {total_cells}");
|
||||
eprintln!("land/ocean disagreements: {disagreements} ({disagreement_pct:.2}%)");
|
||||
eprintln!("mean warp displacement: {mean_displacement_m:.1} m");
|
||||
eprintln!("max warp displacement: {max_displacement_m:.1} m");
|
||||
eprintln!(
|
||||
"coast_warp_px call cost: {ns_per_warp_call:.1} ns/call ({warp_evals} calls, {warp_only_nanos} ns total)"
|
||||
);
|
||||
eprintln!(
|
||||
"full added cost/cell: {ns_per_full_cell_cost:.1} ns/cell (driver temp/moisture/glaciation + coast_character_at + coast_warp_px)"
|
||||
);
|
||||
|
||||
// Sanity floor — this audit is meaningless if it silently sampled
|
||||
// zero real bodies or zero coastal cells (e.g. a bad path).
|
||||
assert!(bodies_sampled > 10, "too few bodies sampled — check path");
|
||||
assert!(total_cells > 0, "no coastal-band cells found — check masks");
|
||||
}
|
||||
|
||||
fn collect_heightmaps(dir: &std::path::Path, out: &mut Vec<std::path::PathBuf>) {
|
||||
let Ok(entries) = std::fs::read_dir(dir) else {
|
||||
return;
|
||||
};
|
||||
for entry in entries.flatten() {
|
||||
let path = entry.path();
|
||||
if path.is_dir() {
|
||||
collect_heightmaps(&path, out);
|
||||
} else if path.file_name().and_then(|n| n.to_str()) == Some("heightmap.png") {
|
||||
out.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_district_profile_is_deterministic() {
|
||||
let hm = test_hm();
|
||||
|
||||
@@ -95,10 +95,10 @@
|
||||
"glaciation": 0,
|
||||
"precipitation": 3,
|
||||
"slope_q": 0,
|
||||
"elev_q": 26,
|
||||
"elev_q": 27,
|
||||
"ocean_fraction_q": 0,
|
||||
"temperature_dc": 127,
|
||||
"moisture_q": 57,
|
||||
"temperature_dc": 122,
|
||||
"moisture_q": 56,
|
||||
"vegetation": 3
|
||||
},
|
||||
{
|
||||
@@ -248,7 +248,7 @@
|
||||
"glaciation": 2,
|
||||
"precipitation": 1,
|
||||
"slope_q": 0,
|
||||
"elev_q": 62,
|
||||
"elev_q": 63,
|
||||
"ocean_fraction_q": 0,
|
||||
"temperature_dc": -120,
|
||||
"moisture_q": 43,
|
||||
@@ -452,7 +452,7 @@
|
||||
"glaciation": 0,
|
||||
"precipitation": 0,
|
||||
"slope_q": 0,
|
||||
"elev_q": 41,
|
||||
"elev_q": 42,
|
||||
"ocean_fraction_q": 0,
|
||||
"temperature_dc": -2147483648,
|
||||
"moisture_q": 0,
|
||||
@@ -503,7 +503,7 @@
|
||||
"glaciation": 0,
|
||||
"precipitation": 0,
|
||||
"slope_q": 0,
|
||||
"elev_q": 42,
|
||||
"elev_q": 43,
|
||||
"ocean_fraction_q": 0,
|
||||
"temperature_dc": -2147483648,
|
||||
"moisture_q": 0,
|
||||
@@ -707,9 +707,9 @@
|
||||
"glaciation": 0,
|
||||
"precipitation": 3,
|
||||
"slope_q": 0,
|
||||
"elev_q": 28,
|
||||
"elev_q": 29,
|
||||
"ocean_fraction_q": 0,
|
||||
"temperature_dc": 728,
|
||||
"temperature_dc": 723,
|
||||
"moisture_q": 59,
|
||||
"vegetation": 3
|
||||
},
|
||||
@@ -809,9 +809,9 @@
|
||||
"glaciation": 0,
|
||||
"precipitation": 2,
|
||||
"slope_q": 0,
|
||||
"elev_q": 23,
|
||||
"elev_q": 24,
|
||||
"ocean_fraction_q": 0,
|
||||
"temperature_dc": 697,
|
||||
"temperature_dc": 691,
|
||||
"moisture_q": 49,
|
||||
"vegetation": 3
|
||||
},
|
||||
@@ -860,10 +860,10 @@
|
||||
"glaciation": 0,
|
||||
"precipitation": 2,
|
||||
"slope_q": 0,
|
||||
"elev_q": 66,
|
||||
"elev_q": 67,
|
||||
"ocean_fraction_q": 0,
|
||||
"temperature_dc": 300,
|
||||
"moisture_q": 30,
|
||||
"moisture_q": 29,
|
||||
"vegetation": 2
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user