1
0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-06-01 18:43:33 +02:00
VVVVVV/desktop_version/src/UtilityClass.h
Dav999-v 3e36bfd56f Simplify time formatting functions
Here's my notes on all the existing functions and what kind of time
formats they output:

- Game::giventimestring(int hrs, int min, int sec)
	H:MM:SS
	MM:SS

- Game::timestring()
// uses game.hours/minutes/seconds
	H:MM:SS
	MM:SS

- Game::partimestring()
// uses game.timetrialpar (seconds)
	MM:SS

- Game::resulttimestring()
// uses game.timetrialresulttime (sec) + timetrialresultframes (1/30s)
	MM:SS.CC

- Game::timetstring(int t)
// t = seconds
	MM:SS

- Game::timestringcenti(char* buffer, const size_t buffer_size)
// uses game.hours/minutes/seconds/frames
	H:MM:SS.CC
	MM:SS.CC

- UtilityClass::timestring(int t)
// t = frames, 30 frames = 1 second
	S:CC
	M:SS:CC

This is kind of a mess, and there's a lot of functions that do the same
thing except using different variables. For localization, I also want
translators to be able to localize all these time formats - many
languages use the decimal comma instead of the decimal point (12:34,56)
maybe some languages really prefer something like 1時02分11秒44瞬...
Which I don't know to be correct, but it's good to be prepared for it
and not restrict translators arbitrarily to only changing ":" and "."
when we can start making the system better in the first place.

I added a new function, UtilityClass::format_time. This is the place
where all time formats come together, given the number of seconds and
optionally frames. I have simplified the above-mentioned functions
somewhat, but I haven't given them a complete refactor or renaming -
I mainly made sure that they all use the same backend so I can make the
formats consistent and properly localizable.

(And before we start shoving more temporary char buffers everywhere
just to get rid of the std::string's, maybe we need to think of a
globally used working buffer of size SCREEN_WIDTH_CHARS+1, as a
register of sorts, for when any line of text needs to be made or
processed, then printed, and then goes unused. Maybe help.textrow,
or something like that.)

As for this commit, the available time formats are now more consistent
and changed a little in some places. Leading zeroes for the first unit
are now no longer included, time trial results and the Super Gravitron
can now display hours when they went to 60 minutes before, and we now
always use .CC instead of :CC. These are the formats:
- H:MM:SS
- H:MM:SS.CC
- M:SS
- M:SS.CC
- S.CC  (only used when always_minutes=false, for the Gravitrons)

Here's what changes to the current functions:
- Game::partimestring() is removed - it was used in two places, and
  could be replaced by game.timetstring(game.timetrialpar)
- Game::giventimestring(h,m,s) and Game::timestring() are now wrappers
  for the other functions
- The four remaining functions (Game::resulttimestring(),
  Game::timetstring(t), Game::timestringcenti(buffer, buffer_size)
  and UtilityClass::timestring(t)) are now wrappers for the "central
  function", UtilityClass::format_time.
- UtilityClass::twodigits(int t) is now unused so it's also removed.
- I also added int UtilityClass::hms_to_seconds(int h, int m, int s)
2021-12-25 11:38:12 -08:00

121 lines
2.6 KiB
C++

#ifndef UTILITYCLASS_H
#define UTILITYCLASS_H
#include <SDL.h>
#include <string>
#include <vector>
int ss_toi(const std::string& str);
bool next_split(
size_t* start,
size_t* len,
const char* str,
const char delim
);
bool next_split_s(
char buffer[],
const size_t buffer_size,
size_t* start,
const char* str,
const char delim
);
bool is_number(const char* str);
bool is_positive_num(const char* str, const bool hex);
bool endsWith(const char* str, const char* suffix);
void VVV_fillstring(
char* buffer,
const size_t buffer_size,
const char fillchar
);
#define INBOUNDS_VEC(index, vector) ((int) index >= 0 && (int) index < (int) vector.size())
#define INBOUNDS_ARR(index, array) ((int) index >= 0 && (int) index < (int) SDL_arraysize(array))
#define WHINE_ONCE(message) \
static bool whine = true; \
if (whine) \
{ \
whine = false; \
vlog_error(message); \
} \
do { } while (false)
/* Don't call this directly; use the VVV_between macro. */
void _VVV_between(
const char* original,
const size_t left_length,
char* middle,
const size_t right_length,
const size_t middle_size
);
/* If original is "LEFTMIDDLERIGHT", VVV_between(original, "LEFT", buffer, "RIGHT")
* will put "MIDDLE" into buffer - assuming that sizeof(buffer) refers to length
* of buffer and not length of pointer to buffer.
*/
#define VVV_between(original, left, middle, right) \
_VVV_between( \
original, \
SDL_arraysize(left) - 1, \
middle, \
SDL_arraysize(right) - 1, \
sizeof(middle) \
)
#define MAYBE_FAIL(expr) \
do \
{ \
if (!expr) \
{ \
goto fail; \
} \
} \
while (false)
/* Positive modulo, because C/C++'s modulo operator sucks and is negative given
* negative divisors.
* WARNING! This double- and triple- evaluates. */
#define POS_MOD(a, b) (((a) % (b) + (b)) % (b))
//helperClass
class UtilityClass
{
public:
UtilityClass(void);
static std::string String(int _v);
static int Int(const char* str, int fallback = 0);
static std::string GCString(const std::vector<SDL_GameControllerButton>& buttons);
int hms_to_seconds(int h, int m, int s);
void format_time(char* buffer, const size_t buffer_size, int seconds, int frames, bool always_minutes);
std::string timestring(int t);
std::string number_words(int _t);
static bool intersects( SDL_Rect A, SDL_Rect B );
void updateglow(void);
int glow;
int slowsine;
int glowdir;
};
#ifndef HELP_DEFINITION
extern UtilityClass help;
#endif
#endif /* UTILITYCLASS_H */