Feature: Use real-time "wallclock" timekeeping units (#11341)

This commit is contained in:
Tyler Trahan
2024-01-23 11:36:09 -05:00
committed by GitHub
parent bbdbf9a589
commit fd9e72a7e7
30 changed files with 546 additions and 140 deletions

View File

@@ -33,6 +33,30 @@ TimerGameCalendar::Month TimerGameCalendar::month = {};
TimerGameCalendar::Date TimerGameCalendar::date = {};
TimerGameCalendar::DateFract TimerGameCalendar::date_fract = {};
/**
* Converts a Date to a Year, Month & Day.
* @param date the date to convert from
* @returns YearMonthDay representation of the Date.
*/
/* static */ TimerGameCalendar::YearMonthDay TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::Date date)
{
/* This wrapper function only exists because economy time sometimes does things differently, when using wallclock units. */
return CalendarConvertDateToYMD(date);
}
/**
* Converts a tuple of Year, Month and Day to a Date.
* @param year is a number between 0..MAX_YEAR
* @param month is a number between 0..11
* @param day is a number between 1..31
* @returns The equivalent date.
*/
/* static */ TimerGameCalendar::Date TimerGameCalendar::ConvertYMDToDate(TimerGameCalendar::Year year, TimerGameCalendar::Month month, TimerGameCalendar::Day day)
{
/* This wrapper function only exists because economy time sometimes does things differently, when using wallclock units. */
return CalendarConvertYMDToDate(year, month, day);
}
/**
* Set the date.
* @param date New date

View File

@@ -34,6 +34,8 @@ public:
static Date date; ///< Current date in days (day counter).
static DateFract date_fract; ///< Fractional part of the day.
static YearMonthDay ConvertDateToYMD(Date date);
static Date ConvertYMDToDate(Year year, Month month, Day day);
static void SetDate(Date date, DateFract fract);
};

View File

@@ -63,7 +63,7 @@ static constexpr uint16_t _accum_days_for_month[] = {
* @returns YearMonthDay representation of the Date.
*/
template <class T>
/* static */ typename TimerGame<T>::YearMonthDay TimerGame<T>::ConvertDateToYMD(Date date)
/* static */ typename TimerGame<T>::YearMonthDay TimerGame<T>::CalendarConvertDateToYMD(Date date)
{
/* Year determination in multiple steps to account for leap
* years. First do the large steps, then the smaller ones.
@@ -118,9 +118,10 @@ template <class T>
* @param year is a number between 0..MAX_YEAR
* @param month is a number between 0..11
* @param day is a number between 1..31
* @returns The equivalent date.
*/
template <class T>
/* static */ typename TimerGame<T>::Date TimerGame<T>::ConvertYMDToDate(Year year, Month month, Day day)
/* static */ typename TimerGame<T>::Date TimerGame<T>::CalendarConvertYMDToDate(Year year, Month month, Day day)
{
/* Day-offset in a leap year */
int days = _accum_days_for_month[month] + day - 1;
@@ -133,8 +134,8 @@ template <class T>
/* Create instances of the two template variants that we have.
* This is needed, as this templated functions are not in a header-file. */
template TimerGame<struct Calendar>::YearMonthDay TimerGame<struct Calendar>::ConvertDateToYMD(Date date);
template TimerGame<struct Economy>::YearMonthDay TimerGame<struct Economy>::ConvertDateToYMD(Date date);
template TimerGame<struct Calendar>::YearMonthDay TimerGame<struct Calendar>::CalendarConvertDateToYMD(Date date);
template TimerGame<struct Economy>::YearMonthDay TimerGame<struct Economy>::CalendarConvertDateToYMD(Date date);
template TimerGame<struct Calendar>::Date TimerGame<struct Calendar>::ConvertYMDToDate(Year year, Month month, Day day);
template TimerGame<struct Economy>::Date TimerGame<struct Economy>::ConvertYMDToDate(Year year, Month month, Day day);
template TimerGame<struct Calendar>::Date TimerGame<struct Calendar>::CalendarConvertYMDToDate(Year year, Month month, Day day);
template TimerGame<struct Economy>::Date TimerGame<struct Economy>::CalendarConvertYMDToDate(Year year, Month month, Day day);

View File

@@ -66,8 +66,8 @@ public:
return year_as_int % 4 == 0 && (year_as_int % 100 != 0 || year_as_int % 400 == 0);
}
static YearMonthDay ConvertDateToYMD(Date date);
static Date ConvertYMDToDate(Year year, Month month, Day day);
static YearMonthDay CalendarConvertDateToYMD(Date date);
static Date CalendarConvertYMDToDate(Year year, Month month, Day day);
/**
* Calculate the year of a given date.

View File

@@ -38,6 +38,41 @@ TimerGameEconomy::Month TimerGameEconomy::month = {};
TimerGameEconomy::Date TimerGameEconomy::date = {};
TimerGameEconomy::DateFract TimerGameEconomy::date_fract = {};
/**
* Converts a Date to a Year, Month & Day.
* @param date the date to convert from
* @returns YearMonthDay representation of the Date.
*/
/* static */ TimerGameEconomy::YearMonthDay TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::Date date)
{
/* If we're not using wallclock units, we keep the economy date in sync with the calendar. */
if (!UsingWallclockUnits()) return CalendarConvertDateToYMD(date);
/* If we're using wallclock units, economy months have 30 days and an economy year has 360 days. */
TimerGameEconomy::YearMonthDay ymd;
ymd.year = TimerGameEconomy::date.base() / EconomyTime::DAYS_IN_ECONOMY_YEAR;
ymd.month = (TimerGameEconomy::date.base() % EconomyTime::DAYS_IN_ECONOMY_YEAR) / EconomyTime::DAYS_IN_ECONOMY_MONTH;
ymd.day = TimerGameEconomy::date.base() % EconomyTime::DAYS_IN_ECONOMY_MONTH;
return ymd;
}
/**
* Converts a tuple of Year, Month and Day to a Date.
* @param year is a number between 0..MAX_YEAR
* @param month is a number between 0..11
* @param day is a number between 1..31
* @returns The equivalent date.
*/
/* static */ TimerGameEconomy::Date TimerGameEconomy::ConvertYMDToDate(TimerGameEconomy::Year year, TimerGameEconomy::Month month, TimerGameEconomy::Day day)
{
/* If we're not using wallclock units, we keep the economy date in sync with the calendar. */
if (!UsingWallclockUnits()) return CalendarConvertYMDToDate(year, month, day);
/* If we're using wallclock units, economy months have 30 days and an economy year has 360 days. */
const int total_months = (year.base() * EconomyTime::MONTHS_IN_YEAR) + month;
return (total_months * EconomyTime::DAYS_IN_ECONOMY_MONTH) + day - 1; // Day is 1-indexed but Date is 0-indexed, hence the - 1.
}
/**
* Set the date.
* @param date The new date
@@ -54,6 +89,18 @@ TimerGameEconomy::DateFract TimerGameEconomy::date_fract = {};
TimerGameEconomy::month = ymd.month;
}
/**
* Check if we are using wallclock units.
* @param newgame Should we check the settings for a new game (since we are in the main menu)?
* @return True if the game is using wallclock units, or false if the game is using calendar units.
*/
/* static */ bool TimerGameEconomy::UsingWallclockUnits(bool newgame)
{
if (newgame) return (_settings_newgame.economy.timekeeping_units == TKU_WALLCLOCK);
return (_settings_game.economy.timekeeping_units == TKU_WALLCLOCK);
}
template<>
void IntervalTimer<TimerGameEconomy>::Elapsed(TimerGameEconomy::TElapsed trigger)
{

View File

@@ -37,12 +37,19 @@ public:
static Date date; ///< Current date in days (day counter).
static DateFract date_fract; ///< Fractional part of the day.
static YearMonthDay ConvertDateToYMD(Date date);
static Date ConvertYMDToDate(Year year, Month month, Day day);
static void SetDate(Date date, DateFract fract);
static bool UsingWallclockUnits(bool newgame = false);
};
/**
* Storage class for Economy time constants.
*/
class EconomyTime : public TimerGameConst<struct Economy> {};
class EconomyTime : public TimerGameConst<struct Economy> {
public:
static constexpr int DAYS_IN_ECONOMY_YEAR = 360; ///< Days in an economy year, when in wallclock timekeeping mode.
static constexpr int DAYS_IN_ECONOMY_MONTH = 30; ///< Days in an economy month, when in wallclock timekeeping mode.
};
#endif /* TIMER_GAME_ECONOMY_H */