Game/Idle/IdleFormat.cs
using System;
/// <summary>
/// Number formatting helpers for the Reactor (Idle) mode.
/// Idle economies overflow int/long fast, so every currency is a double and
/// gets rendered through here — never with ToString("N0").
/// </summary>
public static class IdleFormat
{
static readonly string[] Suffixes =
{
"", "K", "M", "B", "T", "Qa", "Qi", "Sx", "Sp", "Oc", "No",
"Dc", "Ud", "Dd", "Td", "Qad", "Qid", "Sxd", "Spd", "Ocd", "Nod", "Vg"
};
/// <summary>Compact currency label — 1234 => "1.23K", 5.2e9 => "5.20B".</summary>
public static string Short( double v )
{
if ( double.IsNaN( v ) || double.IsInfinity( v ) ) return "0";
if ( v < 0 ) return "-" + Short( -v );
if ( v < 1000 ) return v < 10 && v % 1 != 0 ? v.ToString( "F1" ) : ((long)v).ToString();
int tier = (int)MathF.Floor( (float)Math.Log10( v ) / 3f );
if ( tier >= Suffixes.Length ) tier = Suffixes.Length - 1;
double scaled = v / Math.Pow( 1000, tier );
// Keep 3 significant digits so the number never jitters in width
string num = scaled >= 100 ? scaled.ToString( "F0" )
: scaled >= 10 ? scaled.ToString( "F1" )
: scaled.ToString( "F2" );
return num + Suffixes[tier];
}
/// <summary>Rate label — "12.4K /s".</summary>
public static string Rate( double perSecond ) => Short( perSecond ) + " /s";
/// <summary>"2h 14m", "48s" — used by the offline report and cooldowns.</summary>
public static string Duration( double seconds )
{
if ( seconds < 0 ) seconds = 0;
int total = (int)seconds;
int d = total / 86400;
int h = (total % 86400) / 3600;
int m = (total % 3600) / 60;
int s = total % 60;
if ( d > 0 ) return $"{d}d {h}h";
if ( h > 0 ) return $"{h}h {m}m";
if ( m > 0 ) return $"{m}m {s}s";
return $"{s}s";
}
/// <summary>Clock style "04:31" — used for short live countdowns.</summary>
public static string Clock( double seconds )
{
if ( seconds < 0 ) seconds = 0;
int m = (int)(seconds / 60);
int s = (int)(seconds % 60);
return $"{m:00}:{s:00}";
}
/// <summary>Percentage with no decimals — 0.35 => "35%".</summary>
public static string Pct( float f ) => $"{(int)MathF.Round( f * 100f )}%";
}