mirror of
https://github.com/forkless/NotAlterra.git
synced 2026-08-25 19:52:37 +02:00
Initial public release
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
//! Dump GVAS metadata for all .sav/.bak files in `samples/`.
|
||||
//! Run: cargo run --example dump_samples
|
||||
|
||||
use chrono::TimeZone;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
fn main() {
|
||||
let dir = Path::new("samples");
|
||||
let mut entries: Vec<_> = fs::read_dir(dir)
|
||||
.unwrap()
|
||||
.filter_map(|e| e.ok())
|
||||
.filter(|e| {
|
||||
let s = e.file_name().to_string_lossy();
|
||||
s.ends_with(".sav") || s.ends_with(".bak")
|
||||
})
|
||||
.collect();
|
||||
|
||||
entries.sort_by(|a, b| {
|
||||
let ma = a.metadata().ok().and_then(|m| m.modified().ok());
|
||||
let mb = b.metadata().ok().and_then(|m| m.modified().ok());
|
||||
mb.cmp(&ma)
|
||||
.then_with(|| a.file_name().cmp(&b.file_name()))
|
||||
});
|
||||
|
||||
println!(
|
||||
"{:<8} {:<26} {:<6} {:>7} {:<19} {:<28}",
|
||||
"", "Display Name", "Type", "Size", "Date", "File"
|
||||
);
|
||||
println!("{}", "-".repeat(115));
|
||||
|
||||
let mut seen = std::collections::HashSet::new();
|
||||
for entry in &entries {
|
||||
let path = entry.path();
|
||||
let name = entry.file_name().to_string_lossy().to_string();
|
||||
let size = entry.metadata().map(|m| m.len()).unwrap_or(0);
|
||||
let mtime = entry
|
||||
.metadata()
|
||||
.ok()
|
||||
.and_then(|m| m.modified().ok())
|
||||
.and_then(|t| {
|
||||
let secs = t.duration_since(std::time::UNIX_EPOCH).ok()?.as_secs();
|
||||
chrono::Local
|
||||
.timestamp_opt(secs as i64, 0)
|
||||
.single()
|
||||
})
|
||||
.map(|dt| dt.format("%Y-%m-%d %H:%M:%S").to_string());
|
||||
|
||||
let meta = notalterra::gvas::extract_metadata(&path).ok();
|
||||
let slot = meta.as_ref().and_then(|m| m.slot_name.clone()).unwrap_or_else(|| {
|
||||
notalterra::gvas::derive_slot_from_filename(&name).unwrap_or_else(|| "?".into())
|
||||
});
|
||||
let display = meta
|
||||
.as_ref()
|
||||
.and_then(|m| m.display_name.clone())
|
||||
.unwrap_or_else(|| "(unnamed)".into());
|
||||
let is_online = meta.map(|m| m.is_online).unwrap_or(false);
|
||||
|
||||
let label_num = slot.strip_prefix("savegame_").unwrap_or(&slot);
|
||||
let first = seen.insert(slot.clone());
|
||||
let label = if first { format!("Slot {label_num}") } else { String::new() };
|
||||
|
||||
let typ = if is_online { "Online" } else { "Local" };
|
||||
let sz = if size < 1024 {
|
||||
format!("{size} B")
|
||||
} else if size < 1024 * 1024 {
|
||||
format!("{:.0} KB", size as f64 / 1024.0)
|
||||
} else {
|
||||
format!("{:.1} MB", size as f64 / (1024.0 * 1024.0))
|
||||
};
|
||||
|
||||
println!(
|
||||
"{label:<8} {display:<26} {typ:<6} {sz:>7} {:<19} {name:<28}",
|
||||
mtime.as_deref().unwrap_or("?"),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user