[gnome-tetravex] Use double for saving game duration.
- From: Arnaud B. <arnaudb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-tetravex] Use double for saving game duration.
- Date: Fri, 11 Oct 2019 01:36:53 +0000 (UTC)
commit d990d04848d0af0054a52042c174d6e94516c73d
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date: Tue Sep 24 17:57:16 2019 +0200
Use double for saving game duration.
src/gnome-tetravex.vala | 5 +--
src/history.vala | 104 ++++++++++++++++++++++++++++++++++--------------
src/score-dialog.vala | 11 ++---
src/score-overlay.vala | 24 +++++------
4 files changed, 92 insertions(+), 52 deletions(-)
---
diff --git a/src/gnome-tetravex.vala b/src/gnome-tetravex.vala
index 7d958f4..1e268a3 100644
--- a/src/gnome-tetravex.vala
+++ b/src/gnome-tetravex.vala
@@ -416,7 +416,7 @@ private class Tetravex : Gtk.Application
{
int elapsed = 0;
if (puzzle_init_done)
- elapsed = (int) (puzzle.elapsed + 0.5);
+ elapsed = (int) puzzle.elapsed; // felt better when + 0.5, but as the clock is still displayed
while the score-overlay displays the exact time, that is regularly feeling odd
int hours = elapsed / 3600;
int minutes = (elapsed - hours * 3600) / 60;
int seconds = elapsed - hours * 3600 - minutes * 60;
@@ -457,8 +457,7 @@ private class Tetravex : Gtk.Application
private void show_end_game_cb (Puzzle puzzle)
{
DateTime date = new DateTime.now_local ();
- uint duration = (uint) (puzzle.elapsed + 0.5);
- last_history_entry = new HistoryEntry (date, puzzle.size, duration);
+ last_history_entry = new HistoryEntry (date, puzzle.size, puzzle.elapsed, /* old history format */
false);
if (!puzzle_is_finished) // Ctrl-n has been hit before the animation finished
return;
diff --git a/src/history.vala b/src/history.vala
index 157c054..13547c7 100644
--- a/src/history.vala
+++ b/src/history.vala
@@ -26,7 +26,7 @@ private class History : Object
out HistoryEntry? other_entry_1,
out HistoryEntry? other_entry_2)
{
- entries.insert_sorted (entry, HistoryEntry.compare_entries);
+ entries.insert_sorted (entry, compare_entries);
entry_added (entry);
save ();
@@ -146,15 +146,18 @@ private class History : Object
continue;
uint8 size = (uint8) test;
- if (!uint64.try_parse (tokens [2], out test))
+ double duration;
+ bool int_duration;
+ if (uint64.try_parse (tokens [2], out duration))
+ int_duration = true;
+ else if (double.try_parse (tokens [2], out duration))
+ int_duration = false;
+ else
continue;
- if (test > uint.MAX)
- continue;
- uint duration = (uint) test;
- entries.prepend (new HistoryEntry ((!) date, size, duration));
+ entries.prepend (new HistoryEntry ((!) date, size, duration, int_duration));
}
- entries.sort (HistoryEntry.compare_entries);
+ entries.sort (compare_entries);
}
/*\
@@ -167,7 +170,11 @@ private class History : Object
foreach (HistoryEntry entry in entries)
{
- string line = "%s %hu %u\n".printf (entry.date.to_string (), entry.size, entry.duration);
+ string line;
+ if (entry.int_duration)
+ line = "%s %hu %u\n".printf (entry.date.to_string (), entry.size, (uint) entry.duration);
+ else
+ line = "%s %hu %s\n".printf (entry.date.to_string (), entry.size, entry.duration.to_string
());
contents += line;
}
@@ -181,45 +188,84 @@ private class History : Object
warning ("Failed to save history: %s", e.message);
}
}
+
+ /*\
+ * * comparing
+ \*/
+
+ private static int compare_entries (HistoryEntry a, HistoryEntry b)
+ {
+ /* in size order, 2 first */
+ if (a.size != b.size)
+ return (int) a.size - (int) b.size;
+
+ /* not in the same second, easy */
+ if ((uint) a.duration < (uint) b.duration)
+ return -1;
+ if ((uint) a.duration > (uint) b.duration)
+ return 1;
+
+ /* old history format after, to renew a bit the challenge (it might logically be more at duration -
0.5) */
+ if (a.int_duration && !b.int_duration)
+ return 1;
+ if (b.int_duration && !a.int_duration)
+ return -1;
+
+ /* compare duration */
+ if (a.duration < b.duration)
+ return -1;
+ if (a.duration > b.duration)
+ return 1;
+
+ /* newer on the top */
+ return -1 * a.date.compare (b.date);
+ }
}
private class HistoryEntry : Object // TODO make struct? needs using HistoryEntry? for the List...
{
- [CCode (notify = false)] public DateTime date { internal get; protected construct; }
- [CCode (notify = false)] public uint8 size { internal get; protected construct; }
- [CCode (notify = false)] public uint duration { internal get; protected construct; }
+ [CCode (notify = false)] public DateTime date { internal get; protected construct; }
+ [CCode (notify = false)] public uint8 size { internal get; protected construct; }
+ [CCode (notify = false)] public double duration { internal get; protected construct; }
+ [CCode (notify = false)] public bool int_duration { internal get; protected construct; }
- internal HistoryEntry (DateTime date, uint8 size, uint duration)
+ internal HistoryEntry (DateTime date, uint8 size, double duration, bool int_duration)
{
- Object (date: date, size: size, duration: duration);
+ Object (date: date, size: size, duration: duration, int_duration: int_duration);
}
/*\
* * utilities
\*/
- internal static string get_duration_string (uint duration)
+ internal static string get_duration_string (HistoryEntry entry)
{
- if (duration >= 3600)
+ if (entry.duration >= 3600.0)
/* Translators: that is the duration of a game, as seen in the Scores dialog, if game has taken
one hour or more; the %u are replaced by the hours (h), minutes (m) and seconds (s); as an example, you might
want to use "%u:%.2u:%.2u", that is quite international (the ".2" meaning "two digits, padding with 0") */
- return _("%uh %um %us").printf (duration / 3600, (duration / 60) % 60, duration % 60);
+ return _("%uh %um %us").printf ((uint) entry.duration / 3600, ((uint) entry.duration / 60) % 60,
(uint) entry.duration % 60);
- if (duration >= 60)
+ if (entry.duration >= 60.0)
/* Translators: that is the duration of a game, as seen in the Scores dialog, if game has taken
between one minute and one hour; the %u are replaced by the minutes (m) and seconds (s); as an example, you
might want to use "%.2u:%.2u", that is quite international (the ".2" meaning "two digits, padding with 0") */
- return _("%um %us").printf (duration / 60, duration % 60);
+ return _("%um %us").printf ((uint) entry.duration / 60, (uint) entry.duration % 60);
- else
- /* Translators: that is the duration of a game, as seen in the Scores dialog, if game has taken
less than one minute; the %u is replaced by the number of seconds (s) it has taken; as an example, you might
want to use "00:%.2u", that is quite international (the ".2" meaning "two digits, padding with 0") */
- return _("%us").printf (duration);
- }
+ else if (entry.int_duration)
+ /* Translators: that is the duration of a game, as seen in the Scores dialog, if game has taken
less than one minute; the %u is replaced by the number of seconds (s) it has taken */
+ return _("%us").printf ((uint) entry.duration);
+
+ else if (entry.duration >= 20.0)
+ /* Translators: that is the duration of a game, as seen in the Scores dialog, if game has taken
less than one minute; the %.0f is replaced by the number of seconds (s) it has taken */
+ return _("%.0fs").printf (Math.floor (entry.duration));
+
+ else if (entry.duration >= 10.0)
+ /* Translators: that is the duration of a game, as seen in the Scores dialog, if game has taken
less than one minute; the %.1f is replaced by the number of seconds (s) it has taken, including deciseconds
(1 digits after comma, so the .1) */
+ return _("%.1fs").printf (Math.floor (entry.duration * 10.0) / 10.0);
+
+ else if (entry.duration >= 5.0)
+ /* Translators: that is the duration of a game, as seen in the Scores dialog, if game has taken
less than one minute; the %.2f is replaced by the number of seconds (s) it has taken, including centiseconds
(2 digits after comma, so the .2) */
+ return _("%.2fs").printf (Math.floor (entry.duration * 100.0) / 100.0);
- internal static int compare_entries (HistoryEntry a, HistoryEntry b)
- {
- if (a.size != b.size)
- return (int) a.size - (int) b.size;
- if (a.duration != b.duration)
- return (int) a.duration - (int) b.duration;
else
- return a.date.compare (b.date);
+ /* Translators: that is the duration of a game, as seen in the Scores dialog, if game has taken
less than one minute; the %.3f is replaced by the number of seconds (s) it has taken, including milliseconds
(3 digits after comma, so the .3) */
+ return _("%.3fs").printf (Math.floor (entry.duration * 1000.0) / 1000.0);
}
}
diff --git a/src/score-dialog.vala b/src/score-dialog.vala
index 49560ae..ebfa756 100644
--- a/src/score-dialog.vala
+++ b/src/score-dialog.vala
@@ -75,9 +75,7 @@ private class ScoreDialog : Dialog
scores.show ();
scroll.add (scores);
- List<unowned HistoryEntry> entries = history.entries.copy ();
- entries.sort (HistoryEntry.compare_entries);
- foreach (HistoryEntry entry in entries)
+ foreach (HistoryEntry entry in history.entries)
entry_added_cb (entry);
TreeIter iter;
@@ -89,10 +87,7 @@ private class ScoreDialog : Dialog
{
score_model.clear ();
- List<unowned HistoryEntry> entries = history.entries.copy ();
- entries.sort (HistoryEntry.compare_entries);
-
- foreach (HistoryEntry entry in entries)
+ foreach (HistoryEntry entry in history.entries)
{
if (entry.size != size)
continue;
@@ -100,7 +95,7 @@ private class ScoreDialog : Dialog
/* "the preferred date representation for the current locale without the time" */
string date_label = entry.date.format ("%x");
- string time_label = HistoryEntry.get_duration_string (entry.duration);
+ string time_label = HistoryEntry.get_duration_string (entry);
int weight = Pango.Weight.NORMAL;
if (entry == selected_entry)
diff --git a/src/score-overlay.vala b/src/score-overlay.vala
index 27e2ccc..398b406 100644
--- a/src/score-overlay.vala
+++ b/src/score-overlay.vala
@@ -46,26 +46,26 @@ private class ScoreOverlay : Grid
case 1:
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has been the fastest for a puzzle of this size; introduces the game time */
score_0.set_place_label (_("New best time!"));
- score_0.set_value_label (HistoryEntry.get_duration_string (entry.duration), true);
+ score_0.set_value_label (HistoryEntry.get_duration_string (entry), true);
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has been the fastest for a puzzle of this size; introduces the old best time */
score_1.set_place_label (_("Second:"));
if (other_entry_0 != null)
- score_1.set_value_label (HistoryEntry.get_duration_string (((!)
other_entry_0).duration));
+ score_1.set_value_label (HistoryEntry.get_duration_string ((!) other_entry_0));
else
score_1.set_value_label (null);
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has been the fastest for a puzzle of this size; introduces the old second best time */
score_2.set_place_label (_("Third:"));
if (other_entry_1 != null)
- score_2.set_value_label (HistoryEntry.get_duration_string (((!)
other_entry_1).duration));
+ score_2.set_value_label (HistoryEntry.get_duration_string ((!) other_entry_1));
else
score_2.set_value_label (null);
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has been the fastest for a puzzle of this size; introduces the old third best time */
score_3.set_place_label (_("Out of podium:"));
if (other_entry_2 != null)
- score_3.set_value_label (HistoryEntry.get_duration_string (((!)
other_entry_2).duration));
+ score_3.set_value_label (HistoryEntry.get_duration_string ((!) other_entry_2));
else
score_3.set_value_label (null);
break;
@@ -75,23 +75,23 @@ private class ScoreOverlay : Grid
assert_not_reached ();
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has made the second best time for a puzzle of this size; introduces the best time ever */
score_0.set_place_label (_("Best time:"));
- score_0.set_value_label (HistoryEntry.get_duration_string (((!) other_entry_0).duration));
+ score_0.set_value_label (HistoryEntry.get_duration_string ((!) other_entry_0));
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has made the second best time for a puzzle of this size; introduces the game time */
score_1.set_place_label (_("Your time:"));
- score_1.set_value_label (HistoryEntry.get_duration_string (entry.duration), true);
+ score_1.set_value_label (HistoryEntry.get_duration_string (entry), true);
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has made the second best time for a puzzle of this size; introduces the old second best time */
score_2.set_place_label (_("Third:"));
if (other_entry_1 != null)
- score_2.set_value_label (HistoryEntry.get_duration_string (((!)
other_entry_1).duration));
+ score_2.set_value_label (HistoryEntry.get_duration_string ((!) other_entry_1));
else
score_2.set_value_label (null);
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has made the second best time for a puzzle of this size; introduces the old third best time */
score_3.set_place_label (_("Out of podium:"));
if (other_entry_2 != null)
- score_3.set_value_label (HistoryEntry.get_duration_string (((!)
other_entry_2).duration));
+ score_3.set_value_label (HistoryEntry.get_duration_string ((!) other_entry_2));
else
score_3.set_value_label (null);
break;
@@ -101,7 +101,7 @@ private class ScoreOverlay : Grid
assert_not_reached ();
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has not made the first or second best time for a puzzle of this size; introduces the best time
ever */
score_0.set_place_label (_("Best time:"));
- score_0.set_value_label (HistoryEntry.get_duration_string (((!) other_entry_0).duration));
+ score_0.set_value_label (HistoryEntry.get_duration_string ((!) other_entry_0));
if (position == 3)
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has not made the first or second best time for a puzzle of this size; introduces the second best
time */
@@ -114,16 +114,16 @@ private class ScoreOverlay : Grid
else
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has not made the first or second best time for a puzzle of this size; the %u is replaced by the
rank before the one of the game played */
score_1.set_place_label (_("Place %u:").printf (position - 1));
- score_1.set_value_label (HistoryEntry.get_duration_string (((!) other_entry_1).duration));
+ score_1.set_value_label (HistoryEntry.get_duration_string ((!) other_entry_1));
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has not made the first or second best time for a puzzle of this size; introduces the game time */
score_2.set_place_label (_("Your time:"));
- score_2.set_value_label (HistoryEntry.get_duration_string (entry.duration), true);
+ score_2.set_value_label (HistoryEntry.get_duration_string (entry), true);
/* Translators: text of the score overlay, displayed after a puzzle is complete; appears if
the player has not made the first or second best time for a puzzle of this size; the %u is replaced by the
rank after the one of the game played */
score_3.set_place_label (_("Place %u:").printf (position + 1));
if (other_entry_2 != null)
- score_3.set_value_label (HistoryEntry.get_duration_string (((!)
other_entry_2).duration));
+ score_3.set_value_label (HistoryEntry.get_duration_string ((!) other_entry_2));
else
score_3.set_value_label (null);
break;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]