diff --git a/server/src/bin/atlas.rs b/server/src/bin/atlas.rs index fdc48c8d3..a0d5fd7b9 100644 --- a/server/src/bin/atlas.rs +++ b/server/src/bin/atlas.rs @@ -475,7 +475,8 @@ fn query_bodies( } sql.push_str(" ORDER BY system_id, orbit_index"); - let params_ref: Vec<&dyn rusqlite::types::ToSql> = param_values.iter().map(|p| p.as_ref()).collect(); + let params_ref: Vec<&dyn rusqlite::types::ToSql> = + param_values.iter().map(|p| p.as_ref()).collect(); let mut stmt = conn.prepare(&sql).unwrap(); let rows = stmt .query_map(params_ref.as_slice(), |row| { @@ -527,7 +528,8 @@ fn query_stations( } sql.push_str(" ORDER BY system_id, station_id"); - let params_ref: Vec<&dyn rusqlite::types::ToSql> = param_values.iter().map(|p| p.as_ref()).collect(); + let params_ref: Vec<&dyn rusqlite::types::ToSql> = + param_values.iter().map(|p| p.as_ref()).collect(); let mut stmt = conn.prepare(&sql).unwrap(); stmt.query_map(params_ref.as_slice(), |row| { Ok(StationRow { @@ -596,10 +598,22 @@ fn cmd_list_stations(conn: &Connection, system: Option<&str>, station_type: Opti fn cmd_add_body(conn: &Connection, args: &Commands) { let Commands::AddBody { - id, system, r#type, orbit, name, parent, - mass_class, atmosphere, gravity, biome, - inhabited, population, - } = args else { unreachable!() }; + id, + system, + r#type, + orbit, + name, + parent, + mass_class, + atmosphere, + gravity, + biome, + inhabited, + population, + } = args + else { + unreachable!() + }; conn.execute( "INSERT INTO bodies (body_id, system_id, parent_body_id, body_type, orbit_index, @@ -607,9 +621,18 @@ fn cmd_add_body(conn: &Connection, args: &Commands) { biome_summary, inhabited, population) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)", params![ - id, system, parent, r#type, orbit, - name, mass_class, atmosphere, gravity, - biome, *inhabited as i32, population.unwrap_or(0), + id, + system, + parent, + r#type, + orbit, + name, + mass_class, + atmosphere, + gravity, + biome, + *inhabited as i32, + population.unwrap_or(0), ], ) .unwrap_or_else(|e| { @@ -622,17 +645,32 @@ fn cmd_add_body(conn: &Connection, args: &Commands) { fn cmd_add_station(conn: &Connection, args: &Commands) { let Commands::AddStation { - id, system, orbits, r#type, name, - population, docking, gate, - } = args else { unreachable!() }; + id, + system, + orbits, + r#type, + name, + population, + docking, + gate, + } = args + else { + unreachable!() + }; conn.execute( "INSERT INTO stations (station_id, system_id, orbits_body_id, station_type, proper_name, population, docking_class, has_gate_infrastructure) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)", params![ - id, system, orbits, r#type, name, - population.unwrap_or(0), docking, *gate as i32, + id, + system, + orbits, + r#type, + name, + population.unwrap_or(0), + docking, + *gate as i32, ], ) .unwrap_or_else(|e| { @@ -651,17 +689,17 @@ fn cmd_stats(conn: &Connection) { .query_row("SELECT COUNT(*) FROM bodies", [], |r| r.get(0)) .unwrap(); let inhabited_bodies: i64 = conn - .query_row("SELECT COUNT(*) FROM bodies WHERE inhabited = 1", [], |r| r.get(0)) + .query_row("SELECT COUNT(*) FROM bodies WHERE inhabited = 1", [], |r| { + r.get(0) + }) .unwrap(); let stations: i64 = conn .query_row("SELECT COUNT(*) FROM stations", [], |r| r.get(0)) .unwrap(); let systems_with_bodies: i64 = conn - .query_row( - "SELECT COUNT(DISTINCT system_id) FROM bodies", - [], - |r| r.get(0), - ) + .query_row("SELECT COUNT(DISTINCT system_id) FROM bodies", [], |r| { + r.get(0) + }) .unwrap(); let mut bodies_by_type = Vec::new(); @@ -716,7 +754,9 @@ fn cmd_stats(conn: &Connection) { fn parse_wiki_bodies_line(wiki_dir: &str, system_id: &str) -> (Option, i32, i32) { // Try to find the wiki page for this system let sid_slug = system_id.replace(' ', "-"); - let wiki_path = std::path::Path::new(wiki_dir).join(&sid_slug).join("index.md"); + let wiki_path = std::path::Path::new(wiki_dir) + .join(&sid_slug) + .join("index.md"); if !wiki_path.exists() { return (None, 0, 0); } @@ -765,9 +805,7 @@ fn generate_body_matrix( let mut orbit = 1; // Determine planet count from star type if wiki doesn't specify - let spectral_char = spectral - .and_then(|s| s.chars().next()) - .unwrap_or('M'); + let spectral_char = spectral.and_then(|s| s.chars().next()).unwrap_or('M'); // Base planet count by spectral type. // Sol has 8. TRAPPIST-1 (M-dwarf) has 7. Minimum 6 for any star. @@ -776,10 +814,10 @@ fn generate_body_matrix( let known = wiki_hab.max(wiki_inh); match spectral_char { 'O' | 'B' | 'A' => (known + 4).max(6), // hot stars — fewer but still 6+ - 'F' => (known + 5).max(8), // bright — wide system, 8+ - 'G' => (known + 5).max(8), // sol-like — 8 is baseline - 'K' => (known + 4).max(7), // cooler — 7+ typical - 'M' => (known + 4).max(6), // compact but TRAPPIST-1 has 7 + 'F' => (known + 5).max(8), // bright — wide system, 8+ + 'G' => (known + 5).max(8), // sol-like — 8 is baseline + 'K' => (known + 4).max(7), // cooler — 7+ typical + 'M' => (known + 4).max(6), // compact but TRAPPIST-1 has 7 _ => (known + 4).max(6), } } else { @@ -795,7 +833,7 @@ fn generate_body_matrix( }; // Determine if binary — affects naming - let is_binary = star_type.map_or(false, |t| t == "binary"); + let is_binary = star_type == Some("binary"); // Place inner barren rocky planets let inner_barren = if total_planets > wiki_inh + 1 { 1 } else { 0 }; @@ -820,7 +858,10 @@ fn generate_body_matrix( rotation_period_hours: Some(1408.0), atmosphere: Some("none".into()), biome_summary: Some("barren".into()), - hydrosphere: None, economic_role: None, settlement_pattern: None, industrial_corridor: None, + hydrosphere: None, + economic_role: None, + settlement_pattern: None, + industrial_corridor: None, notes: "inner rocky, uninhabited".into(), }); orbit += 1; @@ -848,7 +889,10 @@ fn generate_body_matrix( rotation_period_hours: Some(24.0), atmosphere: Some("breathable".into()), biome_summary: Some("temperate".into()), - hydrosphere: None, economic_role: None, settlement_pattern: None, industrial_corridor: None, + hydrosphere: None, + economic_role: None, + settlement_pattern: None, + industrial_corridor: None, notes: format!("inhabited planet {}/{}", i + 1, wiki_inh), }); orbit += 1; @@ -877,7 +921,10 @@ fn generate_body_matrix( rotation_period_hours: Some(26.0), atmosphere: Some("breathable".into()), biome_summary: Some("temperate".into()), - hydrosphere: None, economic_role: None, settlement_pattern: None, industrial_corridor: None, + hydrosphere: None, + economic_role: None, + settlement_pattern: None, + industrial_corridor: None, notes: "habitable, uninhabited".into(), }); orbit += 1; @@ -907,7 +954,10 @@ fn generate_body_matrix( rotation_period_hours: Some(18.0), atmosphere: Some("thin".into()), biome_summary: Some("frozen".into()), - hydrosphere: None, economic_role: None, settlement_pattern: None, industrial_corridor: None, + hydrosphere: None, + economic_role: None, + settlement_pattern: None, + industrial_corridor: None, notes: "outer rocky/ice, uninhabited".into(), }); orbit += 1; @@ -929,7 +979,10 @@ fn generate_body_matrix( rotation_period_hours: None, atmosphere: None, biome_summary: None, - hydrosphere: None, economic_role: None, settlement_pattern: None, industrial_corridor: None, + hydrosphere: None, + economic_role: None, + settlement_pattern: None, + industrial_corridor: None, notes: "asteroid belt".into(), }); orbit += 1; @@ -957,7 +1010,10 @@ fn generate_body_matrix( rotation_period_hours: Some(10.0), atmosphere: Some("dense".into()), biome_summary: None, - hydrosphere: None, economic_role: None, settlement_pattern: None, industrial_corridor: None, + hydrosphere: None, + economic_role: None, + settlement_pattern: None, + industrial_corridor: None, notes: "gas giant".into(), }); // 2 default moons @@ -976,7 +1032,10 @@ fn generate_body_matrix( rotation_period_hours: Some(3.5 * 24.0 * m as f64), atmosphere: Some("none".into()), biome_summary: Some("barren".into()), - hydrosphere: None, economic_role: None, settlement_pattern: None, industrial_corridor: None, + hydrosphere: None, + economic_role: None, + settlement_pattern: None, + industrial_corridor: None, notes: format!("moon {} of gas giant", m), }); } @@ -999,7 +1058,10 @@ fn generate_body_matrix( rotation_period_hours: None, atmosphere: None, biome_summary: None, - hydrosphere: None, economic_role: None, settlement_pattern: None, industrial_corridor: None, + hydrosphere: None, + economic_role: None, + settlement_pattern: None, + industrial_corridor: None, notes: "oort cloud".into(), }); @@ -1058,8 +1120,16 @@ fn cmd_author(conn: &Connection, system_id: &str, outdir: &str, wiki_dir: &str) let (raw_line, wiki_hab, wiki_inh) = parse_wiki_bodies_line(wiki_dir, &sid); // Use wiki data preferentially, fall back to DB - let hab = if wiki_hab > 0 { wiki_hab } else { db_hab.unwrap_or(0) }; - let inh = if wiki_inh > 0 { wiki_inh } else { db_inh.unwrap_or(0) }; + let hab = if wiki_hab > 0 { + wiki_hab + } else { + db_hab.unwrap_or(0) + }; + let inh = if wiki_inh > 0 { + wiki_inh + } else { + db_inh.unwrap_or(0) + }; let has_belt = db_belt.unwrap_or(0) != 0; let has_gg = db_gg.unwrap_or(0) != 0; let has_horizon = db_horizon.unwrap_or(0) != 0; @@ -1203,26 +1273,19 @@ fn cmd_commit_system(conn: &Connection, path: &str) { }) .count() as i32; - let inhabited_count: i32 = proposal - .bodies - .iter() - .filter(|b| b.inhabited) - .count() as i32 - + proposal.stations.iter().filter(|s| { - s.population.unwrap_or(0) > 0 || s.station_type == "horizon" - }).count() as i32; + let inhabited_count: i32 = proposal.bodies.iter().filter(|b| b.inhabited).count() as i32 + + proposal + .stations + .iter() + .filter(|s| s.population.unwrap_or(0) > 0 || s.station_type == "horizon") + .count() as i32; - let has_gas_giant: i32 = proposal - .bodies - .iter() - .any(|b| b.body_type == "gas_giant") - as i32; + let has_gas_giant: i32 = proposal.bodies.iter().any(|b| b.body_type == "gas_giant") as i32; let has_belt: i32 = proposal .bodies .iter() - .any(|b| b.body_type == "asteroid_belt") - as i32; + .any(|b| b.body_type == "asteroid_belt") as i32; tx.execute( "UPDATE star_systems SET habitable_planet_count = ?1, inhabited_planet_count = ?2, @@ -1345,7 +1408,9 @@ fn cmd_next(conn: &Connection, hop: Option) { }; if target_hop < 0 { - println!(r#"{{"hop": null, "count": 0, "systems": [], "message": "all systems have bodies"}}"#); + println!( + r#"{{"hop": null, "count": 0, "systems": [], "message": "all systems have bodies"}}"# + ); return; } @@ -1428,7 +1493,9 @@ fn cmd_sync_wiki(conn: &Connection, system_id: Option<&str>, wiki_dir: &str) { for sid in &system_ids { let sid_slug = sid.replace(' ', "-"); - let wiki_path = std::path::Path::new(wiki_dir).join(&sid_slug).join("index.md"); + let wiki_path = std::path::Path::new(wiki_dir) + .join(&sid_slug) + .join("index.md"); if !wiki_path.exists() { eprintln!("skip: {} — no wiki page at {}", sid, wiki_path.display()); continue; @@ -1543,7 +1610,8 @@ fn cmd_sync_wiki(conn: &Connection, system_id: Option<&str>, wiki_dir: &str) { // Build the Celestial Bodies section let mut section = String::new(); section.push_str("## Celestial Bodies\n"); - section.push_str("\n\n"); + section + .push_str("\n\n"); // Bodies table if !bodies.is_empty() { @@ -1561,9 +1629,18 @@ fn cmd_sync_wiki(conn: &Connection, system_id: Option<&str>, wiki_dir: &str) { } else { "—".to_string() }; - let grav = b.gravity.map(|g| format!("{:.2}g", g)).unwrap_or_else(|| "—".to_string()); - let year = b.orbital_days.map(|d| format!("{:.0}", d)).unwrap_or_else(|| "—".to_string()); - let day = b.rotation_hours.map(|h| format!("{:.1}", h)).unwrap_or_else(|| "—".to_string()); + let grav = b + .gravity + .map(|g| format!("{:.2}g", g)) + .unwrap_or_else(|| "—".to_string()); + let year = b + .orbital_days + .map(|d| format!("{:.0}", d)) + .unwrap_or_else(|| "—".to_string()); + let day = b + .rotation_hours + .map(|h| format!("{:.1}", h)) + .unwrap_or_else(|| "—".to_string()); section.push_str(&format!( "| {} | `{}` | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} |\n", b.orbit, @@ -1593,9 +1670,18 @@ fn cmd_sync_wiki(conn: &Connection, system_id: Option<&str>, wiki_dir: &str) { } else { "—".to_string() }; - let mgrav = m.gravity.map(|g| format!("{:.2}g", g)).unwrap_or_else(|| "—".to_string()); - let myear = m.orbital_days.map(|d| format!("{:.0}", d)).unwrap_or_else(|| "—".to_string()); - let mday = m.rotation_hours.map(|h| format!("{:.1}", h)).unwrap_or_else(|| "—".to_string()); + let mgrav = m + .gravity + .map(|g| format!("{:.2}g", g)) + .unwrap_or_else(|| "—".to_string()); + let myear = m + .orbital_days + .map(|d| format!("{:.0}", d)) + .unwrap_or_else(|| "—".to_string()); + let mday = m + .rotation_hours + .map(|h| format!("{:.1}", h)) + .unwrap_or_else(|| "—".to_string()); section.push_str(&format!( "| ↳ {}.{} | `{}` | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} |\n", b.orbit, @@ -1664,12 +1750,22 @@ fn cmd_sync_wiki(conn: &Connection, system_id: Option<&str>, wiki_dir: &str) { .find("\n## ") .map(|p| start_pos + marker_start.len() + p + 1) .unwrap_or(content.len()); - format!("{}{}\n{}", &content[..start_pos], section.trim_end(), &content[end_offset..]) + format!( + "{}{}\n{}", + &content[..start_pos], + section.trim_end(), + &content[end_offset..] + ) } else { // Insert before ## Topology if it exists, otherwise before end of file if let Some(topo_pos) = content.find("\n## Topology") { let insert_pos = topo_pos + 1; // after the newline - format!("{}{}\n\n{}", &content[..insert_pos], section.trim_end(), &content[insert_pos..]) + format!( + "{}{}\n\n{}", + &content[..insert_pos], + section.trim_end(), + &content[insert_pos..] + ) } else { // No topology section — append at end format!("{}\n{}", content.trim_end(), section) @@ -1721,22 +1817,33 @@ fn main() { Commands::ShowSystem { system_id } => cmd_show_system(&conn, system_id), Commands::ShowBody { body_id } => cmd_show_body(&conn, body_id), Commands::ShowStation { station_id } => cmd_show_station(&conn, station_id), - Commands::ListBodies { system, r#type, inhabited, unnamed } => { - cmd_list_bodies(&conn, system.as_deref(), r#type.as_deref(), *inhabited, *unnamed) - } + Commands::ListBodies { + system, + r#type, + inhabited, + unnamed, + } => cmd_list_bodies( + &conn, + system.as_deref(), + r#type.as_deref(), + *inhabited, + *unnamed, + ), Commands::ListStations { system, r#type } => { cmd_list_stations(&conn, system.as_deref(), r#type.as_deref()) } cmd @ Commands::AddBody { .. } => cmd_add_body(&conn, cmd), cmd @ Commands::AddStation { .. } => cmd_add_station(&conn, cmd), Commands::Stats => cmd_stats(&conn), - Commands::Author { system_id, outdir, wiki } => cmd_author(&conn, system_id, outdir, wiki), + Commands::Author { + system_id, + outdir, + wiki, + } => cmd_author(&conn, system_id, outdir, wiki), Commands::CommitSystem { path } => cmd_commit_system(&conn, path), Commands::WipeSystem { system_id } => cmd_wipe_system(&conn, system_id), Commands::Unfinished => cmd_unfinished(&conn), Commands::Next { hop } => cmd_next(&conn, *hop), - Commands::SyncWiki { system_id, wiki } => { - cmd_sync_wiki(&conn, system_id.as_deref(), wiki) - } + Commands::SyncWiki { system_id, wiki } => cmd_sync_wiki(&conn, system_id.as_deref(), wiki), } }