use astrogram::aaf::parse_file;
const SAMPLE: &str = "\
#: Astrolog 7.80
#A93:*,Lilly,William,11.05.1602,02:00,Diseworth,GB
#B93:2306308.587,52N47,1W11,*,L
#: AAF end
";
const MULTI: &str = "\
#: two charts
#A93:*,Valens,Vettius,08.02.0120,18:35,Antioch,TR
#B93:1764928.174,36N14,36E07,*,L
#A93:*,Haenel,Adele,11.02.1989,16:20,Paris,FR
#B93:2447569.139,48N52,2E07,1E,0
";
#[test]
fn single_chart_parsed() {
let charts = parse_file(SAMPLE).unwrap();
assert_eq!(charts.len(), 1);
}
#[test]
fn multiple_charts_all_parsed() {
let charts = parse_file(MULTI).unwrap();
assert_eq!(charts.len(), 2);
}
#[test]
fn comment_lines_ignored() {
let text =
"#: header\n#A93:*,A,B,01.01.2000,12:00,City,Country\n#B93:0.0,0N0,0E0,0,0\n#: trailer\n";
let charts = parse_file(text).unwrap();
assert_eq!(charts.len(), 1);
}
#[test]
fn empty_file_returns_empty() {
let charts = parse_file("").unwrap();
assert!(charts.is_empty());
}
#[test]
fn name_last_first_combined() {
let charts = parse_file(SAMPLE).unwrap();
assert_eq!(charts[0].name, "Lilly, William");
}
#[test]
fn name_empty_first_uses_last_only() {
let text = "#A93:*,Valens,,08.02.0120,18:35,Antioch,TR\n#B93:0.0,36N14,36E07,*,L\n";
let charts = parse_file(text).unwrap();
assert_eq!(charts[0].name, "Valens");
}
#[test]
fn semicolons_in_name_restored_to_commas() {
let text = "#A93:*,O'Brien; Jr.,Patrick,01.06.1980,08:00,Dublin,IE\n#B93:0.0,53N21,6W15,0,0\n";
let charts = parse_file(text).unwrap();
assert_eq!(charts[0].name, "O'Brien, Jr., Patrick");
}
#[test]
fn city_semicolon_restored() {
let text = "#A93:*,A,B,01.01.2000,00:00,Los Angeles; CA,US\n#B93:0.0,34N3,118W15,8W,0\n";
let charts = parse_file(text).unwrap();
assert_eq!(charts[0].city.as_deref(), Some("Los Angeles, CA"));
}
#[test]
fn date_fields_parsed() {
let charts = parse_file(SAMPLE).unwrap();
let c = &charts[0];
assert_eq!(c.day, 11);
assert_eq!(c.month, 5);
assert_eq!(c.year, 1602);
}
#[test]
fn time_fields_parsed() {
let charts = parse_file(SAMPLE).unwrap();
let c = &charts[0];
assert_eq!(c.hour, 2);
assert_eq!(c.minute, 0);
assert_eq!(c.second, 0);
}
#[test]
fn time_with_seconds_parsed() {
let text = "#A93:*,X,Y,01.01.2000,12:34:56,City,Country\n#B93:0.0,0N0,0E0,0,0\n";
let charts = parse_file(text).unwrap();
assert_eq!(charts[0].second, 56);
}
#[test]
fn latitude_north() {
let charts = parse_file(SAMPLE).unwrap();
let lat = charts[0].latitude.degrees();
assert!((lat - (52.0 + 47.0 / 60.0)).abs() < 1e-6, "got {lat}");
}
#[test]
fn latitude_south() {
let text = "#A93:*,X,Y,01.01.2000,00:00,Sydney,AU\n#B93:0.0,33S51,151E12,10E,0\n";
let charts = parse_file(text).unwrap();
let lat = charts[0].latitude.degrees();
assert!((lat - -(33.0 + 51.0 / 60.0)).abs() < 1e-6, "got {lat}");
}
#[test]
fn longitude_west() {
let charts = parse_file(SAMPLE).unwrap();
let lon = charts[0].longitude.degrees();
assert!((lon - -(1.0 + 11.0 / 60.0)).abs() < 1e-6, "got {lon}");
}
#[test]
fn longitude_east() {
let charts = parse_file(MULTI).unwrap();
let lon = charts[0].longitude.degrees();
assert!((lon - (36.0 + 7.0 / 60.0)).abs() < 1e-6, "got {lon}");
}
#[test]
fn coord_lowercase_hemisphere_accepted() {
let text = "#A93:*,X,Y,01.01.2000,00:00,City,Country\n#B93:0.0,47n36,122w19,8W,0\n";
let charts = parse_file(text).unwrap();
assert!((charts[0].latitude.degrees() - (47.0 + 36.0 / 60.0)).abs() < 1e-6);
assert!((charts[0].longitude.degrees() - -(122.0 + 19.0 / 60.0)).abs() < 1e-6);
}
#[test]
fn coord_with_seconds() {
let text = "#A93:*,X,Y,01.01.2000,00:00,City,Country\n#B93:0.0,47N36:23,122W19:45,8W,0\n";
let charts = parse_file(text).unwrap();
let expected_lat = 47.0 + 36.0 / 60.0 + 23.0 / 3600.0;
let expected_lon = -(122.0 + 19.0 / 60.0 + 45.0 / 3600.0);
assert!((charts[0].latitude.degrees() - expected_lat).abs() < 1e-6);
assert!((charts[0].longitude.degrees() - expected_lon).abs() < 1e-6);
}
#[test]
fn zone_west_no_dst() {
let text = "#A93:*,Strike,Lightning,12.11.1955,22:04,Universal City,US\n#B93:2435424.753,34N08,118W21,8W,0\n";
let charts = parse_file(text).unwrap();
assert!((charts[0].tz_offset_hours - (-8.0)).abs() < 1e-6);
assert!(!charts[0].is_lmt);
}
#[test]
fn zone_lmt_ancient() {
let charts = parse_file(MULTI).unwrap();
assert!(charts[0].is_lmt);
}
#[test]
fn zone_east_with_minutes() {
let charts = parse_file(MULTI).unwrap();
assert!((charts[1].tz_offset_hours - 1.0).abs() < 1e-6);
}
#[test]
fn zone_fractional_east() {
let text = "#A93:*,X,Y,01.01.2000,00:00,City,Country\n#B93:0.0,22N0,78E0,5E30,0\n";
let charts = parse_file(text).unwrap();
assert!((charts[0].tz_offset_hours - 5.5).abs() < 1e-6);
}
#[test]
fn zone_dst_flag_adds_one_hour() {
let text = "#A93:*,X,Y,01.06.2000,00:00,City,Country\n#B93:0.0,47N0,122W0,8W,D\n";
let charts = parse_file(text).unwrap();
assert!((charts[0].tz_offset_hours - (-7.0)).abs() < 1e-6);
assert!(!charts[0].is_lmt);
}
#[test]
fn zone_lmt_from_dst_l() {
let text = "#A93:*,X,Y,01.01.2000,00:00,City,Country\n#B93:0.0,47N36,120W0,*,L\n";
let charts = parse_file(text).unwrap();
assert!((charts[0].tz_offset_hours - (-8.0)).abs() < 1e-6);
assert!(charts[0].is_lmt);
}
#[test]
fn zone_star_is_lmt() {
let text = "#A93:*,X,Y,01.01.2000,00:00,City,Country\n#B93:0.0,47N36,90W0,*,0\n";
let charts = parse_file(text).unwrap();
assert!((charts[0].tz_offset_hours - (-6.0)).abs() < 1e-6);
assert!(charts[0].is_lmt);
}