Add a Statistics tab with a card for every soundtrack
Part of #41. The top bar has Quiz and Statistics tabs instead of the Statistics button. The Statistics tab replaces the quiz below the top bar (the song keeps playing) and shows every soundtrack as a card with its plays, last played date and most and least played songs, loaded from the new GET /api/v1/statistics/soundtracks. The cards can be searched (with the Search popup's matching, now in SoundtrackSearch), filtered on played or never played, and sorted A-Z, Z-A, most or least played. Clicking a card opens a popup with all its songs. Screenshots of the other states only differ in the top bar, and the layout baseline is taken again with the new statistics states.
This commit is contained in:
1 parent
f7619baf34
commit
a21b6e9b22
30 files changed
+25379
-2306
No files matched your search
@@ -410,6 +410,8 @@ func test_endpoint_paths_and_methods() -> void:
|
||||
"/download/linux", HTTPClient.METHOD_GET],
|
||||
[func() -> void: MusicServerClient.cleanup_tokens(noop),
|
||||
"/token/cleanup", HTTPClient.METHOD_POST],
|
||||
[func() -> void: MusicServerClient.fetch_soundtrack_statistics(noop),
|
||||
"/statistics/soundtracks", HTTPClient.METHOD_GET],
|
||||
[func() -> void: MusicServerClient.fetch_statistics_summary(noop),
|
||||
"/statistics/summary", HTTPClient.METHOD_GET],
|
||||
[func() -> void: MusicServerClient.fetch_most_played_soundtracks(5, noop),
|
||||
@@ -467,6 +469,22 @@ func test_most_played_soundtracks_are_typed_with_their_songs() -> void:
|
||||
assert_array(received[1].songs).is_empty()
|
||||
|
||||
|
||||
func test_soundtrack_statistics_are_typed() -> void:
|
||||
_server.respond_json("/statistics/soundtracks", [
|
||||
{"soundtrack_name": "Chrono Trigger", "soundtrack_played": 2,
|
||||
"songs": [{"song_name": "Frog's Theme", "times_played": 2}]},
|
||||
{"soundtrack_name": "Lufia II", "soundtrack_played": 0, "songs": []},
|
||||
])
|
||||
var received: Array[SoundtrackWithSongs] = []
|
||||
|
||||
MusicServerClient.fetch_soundtrack_statistics(
|
||||
func(list: Array[SoundtrackWithSongs]) -> void: received.append_array(list))
|
||||
|
||||
assert_int(received.size()).is_equal(2)
|
||||
assert_str(received[0].songs[0].song_name).is_equal("Frog's Theme")
|
||||
assert_int(received[1].soundtrack_played).is_equal(0)
|
||||
|
||||
|
||||
func test_most_played_songs_are_typed() -> void:
|
||||
_server.respond_json("/statistics/songs/most-played?limit=1", [
|
||||
{"song_uuid": "so-1", "song_name": "Dancing Mad", "times_played": 12},
|
||||
@@ -484,7 +502,7 @@ func test_statistics_calls_on_failed_on_server_error() -> void:
|
||||
var outcome: Array[String] = []
|
||||
var on_done: Callable = func(_data: Variant) -> void: outcome.append("done")
|
||||
var on_failed: Callable = func() -> void: outcome.append("failed")
|
||||
for path: String in ["/statistics/summary",
|
||||
for path: String in ["/statistics/summary", "/statistics/soundtracks",
|
||||
"/statistics/soundtracks/most-played?limit=3",
|
||||
"/statistics/soundtracks/least-played?limit=3",
|
||||
"/statistics/soundtracks/last-played?limit=3",
|
||||
@@ -497,7 +515,7 @@ func test_statistics_calls_on_failed_on_server_error() -> void:
|
||||
_call_every_statistics_endpoint(on_done, on_failed)
|
||||
|
||||
assert_array(outcome).contains_exactly(["failed", "failed", "failed", "failed", "failed",
|
||||
"failed", "failed", "failed"])
|
||||
"failed", "failed", "failed", "failed"])
|
||||
|
||||
|
||||
func test_statistics_calls_on_failed_when_token_is_refused() -> void:
|
||||
@@ -509,11 +527,12 @@ func test_statistics_calls_on_failed_when_token_is_refused() -> void:
|
||||
|
||||
assert_array(_server.requested_paths).is_empty()
|
||||
assert_array(outcome).contains_exactly(["failed", "failed", "failed", "failed", "failed",
|
||||
"failed", "failed", "failed"])
|
||||
"failed", "failed", "failed", "failed"])
|
||||
|
||||
|
||||
func _call_every_statistics_endpoint(on_done: Callable, on_failed: Callable) -> void:
|
||||
MusicServerClient.fetch_statistics_summary(on_done, on_failed)
|
||||
MusicServerClient.fetch_soundtrack_statistics(on_done, on_failed)
|
||||
MusicServerClient.fetch_most_played_soundtracks(3, on_done, on_failed)
|
||||
MusicServerClient.fetch_least_played_soundtracks(3, on_done, on_failed)
|
||||
MusicServerClient.fetch_last_played_soundtracks(3, on_done, on_failed)
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
extends GdUnitTestSuite
|
||||
## How the search popup finds and orders matching soundtracks.
|
||||
## How SoundtrackSearch, used by the Search popup and the statistics view, finds and
|
||||
## orders matching soundtracks.
|
||||
|
||||
const SearchWindowScript: GDScript = preload("res://popups/search_popup.gd")
|
||||
|
||||
var _search: Control
|
||||
var _search: SoundtrackSearch
|
||||
|
||||
|
||||
func before_test() -> void:
|
||||
_search = auto_free(SearchWindowScript.new())
|
||||
_search.set_soundtracks([
|
||||
_search = SoundtrackSearch.new()
|
||||
_search.set_names([
|
||||
"Chrono Trigger",
|
||||
"Final Fantasy VI",
|
||||
"Mario & Luigi: Superstar Saga",
|
||||
@@ -60,5 +59,20 @@ func test_no_matches() -> void:
|
||||
|
||||
|
||||
func test_clean_term() -> void:
|
||||
assert_str(_search.clean_term("Rock 'n Roll Racing")).is_equal("rockandrollracing")
|
||||
assert_str(_search.clean_term("Ys I & II")).is_equal("ysiandii")
|
||||
assert_str(SoundtrackSearch.clean_term("Rock 'n Roll Racing")).is_equal("rockandrollracing")
|
||||
assert_str(SoundtrackSearch.clean_term("Ys I & II")).is_equal("ysiandii")
|
||||
|
||||
|
||||
func test_search_popup_searches_with_soundtrack_search() -> void:
|
||||
var popup: SearchPopup = auto_free(load("res://popups/SearchPopup.tscn").instantiate())
|
||||
add_child(popup)
|
||||
popup.set_soundtracks(["Chrono Trigger", "Super Mario 64"])
|
||||
popup.show_all_soundtracks()
|
||||
|
||||
popup.perform_search("smr")
|
||||
|
||||
var shown: Array[String] = []
|
||||
for label: Label in popup.search_list.get_children():
|
||||
if label.visible:
|
||||
shown.append(label.text)
|
||||
assert_array(shown).contains_exactly(["Super Mario 64"])
|
||||
File renamed without changes.
Reference in new issue
Block a user