LibAC-dart/lib/utils/TimeUtils.dart

253 lines
5.5 KiB
Dart

/// [Time] is used as a way to serialize and deserialize time based notations.
///
/// When interacting with this, you can even parse Durations
class Time {
int days;
int hours;
int minutes;
int seconds;
Time(
{required this.days,
required this.hours,
required this.minutes,
required this.seconds}) {
autofix();
}
static Time fromDuration(Duration duration) {
int days = duration.inDays;
int hours = duration.inHours.remainder(24);
int minutes = duration.inMinutes.remainder(60);
int seconds = duration.inSeconds.remainder(60);
return Time(days: days, hours: hours, minutes: minutes, seconds: seconds);
}
Duration toDuration() {
return Duration(
days: days, hours: hours, minutes: minutes, seconds: seconds);
}
int getTotalSeconds() {
int current = 0;
current += seconds;
current += (minutes * 60); // 60 seconds in a minute
current += (hours * 60 * 60); // 60 seconds, 60 minutes in an hour
return current;
}
void add(Time time) {
seconds += time.getTotalSeconds();
autofix();
}
void subtract(Time time) {
int sec = getTotalSeconds();
sec -= time.getTotalSeconds();
apply(sec);
}
void tickDown() {
int sec = getTotalSeconds();
sec--;
apply(sec);
}
void tickUp() {
int sec = getTotalSeconds();
sec++;
apply(sec);
}
void apply(int seconds) {
hours = 0;
minutes = 0;
this.seconds = seconds;
if (this.seconds < 0) this.seconds = 0;
autofix();
}
void autofix() {
int totalSeconds = getTotalSeconds();
if (totalSeconds < 0) totalSeconds = 0;
int one_day = (1 * 60 * 60 * 24);
int one_hour = (1 * 60 * 60);
int one_minute = (1 * 60);
int days = (totalSeconds / 60 / 60 / 24).round();
totalSeconds -= (days * one_day);
int hours = (totalSeconds / 60 / 60).round();
totalSeconds -= (hours * one_hour);
int minutes = (totalSeconds / 60).round();
totalSeconds -= (minutes * one_minute);
int seconds = totalSeconds;
this.days = days;
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
}
Time copy() {
return Time(days: days, hours: hours, minutes: minutes, seconds: seconds);
}
factory Time.copy(Time other) {
return Time(
days: other.days,
hours: other.hours,
minutes: other.minutes,
seconds: other.seconds);
}
factory Time.fromNotation(String notation) {
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
List<String> current = [];
String val = notation;
if (val.indexOf('d') == -1) {
days = 0;
} else {
current = val.split('d');
days = int.parse(current[0]);
if (current.length == 2) {
val = current[1];
} else
val = "";
}
if (val.indexOf('h') == -1) {
hours = 0;
} else {
current = val.split('h');
hours = int.parse(current[0]);
if (current.length == 2)
val = current[1];
else
val = "";
}
if (val.indexOf('m') == -1) {
minutes = 0;
} else {
current = val.split('m');
minutes = int.parse(current[0]);
if (current.length == 2)
val = current[1];
else
val = "";
}
if (val.indexOf('s') == -1) {
seconds = 0;
} else {
current = val.split('s');
seconds = int.parse(current[0]);
if (current.length == 2)
val = current[1];
else
val = "";
}
if (val != "") {
seconds += int.parse(val);
}
return Time(days: days, hours: hours, minutes: minutes, seconds: seconds);
}
@override
String toString() {
List<String> parts = [];
if (days > 0) parts.add('${days}d');
if (hours > 0) parts.add('${hours}h');
if (minutes > 0) parts.add('${minutes}m');
if (seconds > 0) parts.add('${seconds}s');
return parts.join(' ');
}
}
/// Provides some functionality dart lacks internally.
///
/// WARNING: A potential race condition can be met by using the nano time here.
///
/// Long run times may eventually reach a maximum possible value. To prevent this, code should make use of the resetNanoTime function.
class TimeUtils {
/// This locks the internal timer and stops execution
bool _tslock = false;
int _ns = 0;
TimeUtils._();
static TimeUtils? _inst;
factory TimeUtils() {
_inst ??= TimeUtils._();
return _inst!;
}
/// Returns a unix timestamp
static int getUnixTimestamp() {
return (DateTime.now().millisecondsSinceEpoch / 1000).round();
}
/// Converts a unix timestamp back into DateTime format.
static DateTime parseTimestamp(int unixTimestamp) {
return DateTime.fromMillisecondsSinceEpoch(unixTimestamp * 1000);
}
/// Starts the time tracker.
static void initTimeTracker() {
TimeUtils tu = TimeUtils();
tu._tslock = false;
tu._timeLoop();
}
/// Stops the time tracker
static void stopTimeTracker() {
TimeUtils tu = TimeUtils();
tu._tslock = true;
}
/// Resets the currently tracked nanoTime.
static void resetNanoTime() {
TimeUtils tu = TimeUtils();
tu._ns = 0;
}
/// This is the loop which will keep a facsimile of nanoseconds since start.
Future<void> _timeLoop() async {
_ns = 0;
while (!_tslock) {
await Future.delayed(
Duration(microseconds: 1)); // Simulate 1 microsecond delay
_ns += 1000; // Increment by 1000 nanoseconds (1 microsecond)
}
}
/// Returns the current simulated nanotime.
static int getNanoTime() {
TimeUtils tu = TimeUtils();
return tu._ns;
}
}