use anyhow::Context;
use clap::{Parser, Subcommand};
use sde::builder::parser::{ParserConfig, ProjectedAxis};
use sde::builder::{extract, http, parser, schema, sde_index};
use std::path::PathBuf;
const SDE_URL: &str = "https://developers.eveonline.com/static-data/tranquility/";
const MAPS_URL: &str = "http://evemaps.dotlan.net/svg/";
const SDE_VARIANT: &str = "jsonl";
#[derive(Parser)]
#[command(
name = "sde-builder",
version,
about = "Builds/updates sde.db from EVE Online's Static Data Export"
)]
struct Cli {
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
Build {
#[arg(long)]
force: bool,
#[arg(short, long)]
quiet: bool,
#[arg(short, long, default_value = "sde.db")]
output: PathBuf,
#[arg(long)]
with_third_party: bool,
},
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
let Command::Build {
force,
quiet,
output,
with_third_party,
} = cli.command;
let client = http::build_client().context("building the HTTP client")?;
let data_dir = PathBuf::from("data");
let sde_dir = PathBuf::from("sde");
let changed = sde_index::update_as_needed(&client, &data_dir, SDE_URL, SDE_VARIANT)
.await
.context("checking for a new SDE build")?;
if !force && !changed && output.exists() {
println!(
"sde: {} is already up to date, nothing to do",
output.display()
);
return Ok(());
}
if output.exists() {
std::fs::remove_file(&output).context("removing the previous database")?;
println!(
"sde: removing the previous {}, a new SDE build is available",
output.display()
);
}
let zip_path = data_dir.join(format!("sde-{SDE_VARIANT}.zip"));
extract::prepare_sde_directory(&zip_path, &sde_dir).context("decompressing the SDE zip")?;
let mut connection = rusqlite::Connection::open(&output).context("creating the database")?;
schema::create_schema(&connection).context("creating the schema")?;
let parser_config = ParserConfig {
language: "en".to_string(),
force_isometric_position_2d: true,
isometric_projected_axis: ProjectedAxis::Y,
map_kspace: true,
map_wspace: true,
map_abyssal: true,
map_void: true,
with_gates: true,
with_moons: true,
verbose: !quiet,
with_third_party,
};
let sde_parser = parser::Parser::new(&sde_dir, parser_config);
let _summary = sde_parser
.build_database(&mut connection, &client, MAPS_URL)
.await
.context("building the database")?;
println!("sde: Parse complete");
let third_party_note = if with_third_party {
" (with community-maintained third-party data)"
} else {
" (canonical SDE only)"
};
println!(
"sde: build complete{third_party_note} -> {}",
output.display()
);
Ok(())
}