pub fn store_url(appid: u32) -> String {
format!("https://store.steampowered.com/app/{appid}/")
}
pub fn header_image_url(appid: u32) -> String {
format!("https://cdn.akamai.steamstatic.com/steam/apps/{appid}/header.jpg")
}
pub fn format_minutes(minutes: u32) -> String {
if minutes >= 60 {
format!("{}h", minutes / 60)
} else {
format!("{minutes}m")
}
}
pub fn format_count(n: u64) -> String {
if n >= 1_000_000 {
format!("{:.1}M", n as f64 / 1_000_000.0)
} else if n >= 1_000 {
format!("{:.1}k", n as f64 / 1_000.0)
} else {
n.to_string()
}
}
pub fn players_word(n: u64) -> &'static str {
if n == 1 { "player" } else { "players" }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn store_url_includes_appid_path_segment() {
assert_eq!(store_url(730), "https://store.steampowered.com/app/730/");
}
#[test]
fn header_image_url_targets_steam_cdn_with_appid() {
let url = header_image_url(730);
assert!(url.starts_with("https://cdn.akamai.steamstatic.com/"));
assert!(url.contains("/730/header.jpg"));
}
#[test]
fn format_minutes_collapses_minutes_into_hours_above_threshold() {
assert_eq!(format_minutes(0), "0m");
assert_eq!(format_minutes(59), "59m");
assert_eq!(format_minutes(60), "1h");
assert_eq!(format_minutes(90), "1h");
assert_eq!(format_minutes(4830), "80h");
}
#[test]
fn format_count_picks_unit_by_magnitude() {
assert_eq!(format_count(0), "0");
assert_eq!(format_count(950), "950");
assert_eq!(format_count(1_500), "1.5k");
assert_eq!(format_count(1_200_000), "1.2M");
}
#[test]
fn players_word_pluralises_only_for_non_singular() {
assert_eq!(players_word(0), "players");
assert_eq!(players_word(1), "player");
assert_eq!(players_word(2), "players");
}
}