Only list played songs in the statistics song list
Songs never played are left out of the song list, so the Show menu is hidden while it is shown.
This commit is contained in:
1 parent
a4e6da4c28
commit
84e137e16a
4 files changed
+464
-471
No files matched your search
@@ -1,8 +1,8 @@
|
||||
class_name StatisticsView
|
||||
extends Panel
|
||||
## Shows every soundtrack on the server as a card with its play statistics, or every
|
||||
## song in a list with its soundtrack. Either can be searched, filtered on whether it has
|
||||
## been played, and sorted.
|
||||
## played song in a list with its soundtrack. Both can be searched and sorted, and the
|
||||
## cards filtered on whether the soundtrack has been played.
|
||||
##
|
||||
## Shown instead of the quiz when the Statistics tab is chosen.
|
||||
|
||||
@@ -36,6 +36,7 @@ var _songs_ready: bool = false
|
||||
|
||||
@onready var search_field: LineEdit = %SearchField
|
||||
@onready var clear_button: Button = %ClearButton
|
||||
@onready var show_label: Label = $Toolbar/ShowLabel
|
||||
@onready var show_option: OptionButton = %ShowOption
|
||||
@onready var sort_option: OptionButton = %SortOption
|
||||
@onready var count_label: Label = %CountLabel
|
||||
@@ -81,6 +82,9 @@ func set_mode(new_mode: Mode) -> void:
|
||||
songs_mode_button.set_pressed_no_signal(mode == Mode.SONGS)
|
||||
card_scroll.visible = mode == Mode.SOUNDTRACKS
|
||||
song_list.visible = mode == Mode.SONGS
|
||||
# The song list only has played songs, so there is nothing to filter
|
||||
show_label.visible = mode == Mode.SOUNDTRACKS
|
||||
show_option.visible = mode == Mode.SOUNDTRACKS
|
||||
search_field.placeholder_text = "Search soundtracks" if mode == Mode.SOUNDTRACKS \
|
||||
else "Search songs and soundtracks"
|
||||
apply_sort()
|
||||
@@ -167,11 +171,10 @@ func _on_song_pressed(song: SongInfoForStats) -> void:
|
||||
soundtrack_selected.emit(_soundtracks[song.soundtrack_name])
|
||||
|
||||
|
||||
# Shows the songs matching the search text and the show menu, in the sort menu's order
|
||||
# Shows the songs matching the search text, in the sort menu's order
|
||||
func _show_songs() -> void:
|
||||
_prepare_songs()
|
||||
var search_text: String = search_field.text.strip_edges()
|
||||
var filter: ShowFilter = show_option.selected as ShowFilter
|
||||
var song_names: Dictionary = {}
|
||||
var soundtrack_names: Dictionary = {}
|
||||
if !search_text.is_empty():
|
||||
@@ -182,18 +185,18 @@ func _show_songs() -> void:
|
||||
var shown: Array[SongInfoForStats] = []
|
||||
for song: SongInfoForStats in songs_in_order(_songs_a_to_z,
|
||||
sort_option.selected as SortOrder):
|
||||
if (search_text.is_empty() || song_names.has(song.song_name)
|
||||
|| soundtrack_names.has(song.soundtrack_name)) \
|
||||
&& _song_passes_filter(song, filter):
|
||||
if search_text.is_empty() || song_names.has(song.song_name) \
|
||||
|| soundtrack_names.has(song.soundtrack_name):
|
||||
shown.append(song)
|
||||
song_list.show_songs(shown, search_text)
|
||||
if shown.size() == _songs_a_to_z.size():
|
||||
count_label.text = "%d songs" % shown.size()
|
||||
count_label.text = "%d played songs" % shown.size()
|
||||
else:
|
||||
count_label.text = "%d of %d songs" % [shown.size(), _songs_a_to_z.size()]
|
||||
count_label.text = "%d of %d played songs" % [shown.size(), _songs_a_to_z.size()]
|
||||
|
||||
|
||||
# Lists every song once after loading, sorted A to Z, which the other orders start from
|
||||
# Lists every played song once after loading, sorted A to Z, which the other orders
|
||||
# start from. Songs never played are left out: there are many and they say nothing.
|
||||
func _prepare_songs() -> void:
|
||||
if _songs_ready:
|
||||
return
|
||||
@@ -202,6 +205,8 @@ func _prepare_songs() -> void:
|
||||
var names: Dictionary = {}
|
||||
for soundtrack: SoundtrackWithSongs in _soundtracks.values():
|
||||
for song: SongInfoForStats in soundtrack.songs:
|
||||
if song.times_played == 0:
|
||||
continue
|
||||
# The song list finds a song's soundtrack by its name
|
||||
song.soundtrack_name = soundtrack.soundtrack_name
|
||||
_songs_a_to_z.append(song)
|
||||
@@ -243,15 +248,6 @@ static func songs_in_order(
|
||||
return a_to_z
|
||||
|
||||
|
||||
static func _song_passes_filter(song: SongInfoForStats, filter: ShowFilter) -> bool:
|
||||
match filter:
|
||||
ShowFilter.PLAYED:
|
||||
return song.times_played > 0
|
||||
ShowFilter.NEVER_PLAYED:
|
||||
return song.times_played == 0
|
||||
return true
|
||||
|
||||
|
||||
func _on_load_failed() -> void:
|
||||
_loading = false
|
||||
if cards.is_empty():
|
||||
|
||||
+421
-421
File diff suppressed because it is too large.
Load diff
@@ -267,6 +267,8 @@ func run(on_state: Callable) -> void:
|
||||
statistics_view.apply_filter()
|
||||
await _settle()
|
||||
await on_state.call("statistics_search", statistics_view)
|
||||
# Chrono Trigger has never been played, so the song list searches for another
|
||||
statistics_view.search_field.text = "zelda"
|
||||
statistics_view.set_mode(StatisticsView.Mode.SONGS)
|
||||
await _settle()
|
||||
await on_state.call("statistics_songs_search", statistics_view)
|
||||
|
||||
@@ -339,19 +339,19 @@ func _search(text: String) -> void:
|
||||
_view.apply_filter()
|
||||
|
||||
|
||||
func test_songs_button_shows_every_song_a_to_z_instead_of_the_cards() -> void:
|
||||
func test_songs_button_shows_every_played_song_a_to_z_instead_of_the_cards() -> void:
|
||||
await _show_songs_mode()
|
||||
|
||||
assert_bool(_view.song_list.visible).is_true()
|
||||
assert_bool(_view.card_scroll.visible).is_false()
|
||||
assert_bool(_view.songs_mode_button.button_pressed).is_true()
|
||||
assert_bool(_view.soundtracks_mode_button.button_pressed).is_false()
|
||||
# Songs never played are left out
|
||||
assert_array(_listed_songs()).contains_exactly([
|
||||
"Battle with Magus", "Corridors of Time", "Dancing Mad", "Frog's Theme",
|
||||
"Peaceful Days", "Schala's Theme", "To Far Away Times", "Underworld", "Wind Scene",
|
||||
"Zeal Palace",
|
||||
"Peaceful Days", "Schala's Theme", "Zeal Palace",
|
||||
])
|
||||
assert_str(_view.count_label.text).is_equal("10 songs")
|
||||
assert_str(_view.count_label.text).is_equal("7 played songs")
|
||||
assert_str(_view.search_field.placeholder_text).is_equal("Search songs and soundtracks")
|
||||
|
||||
|
||||
@@ -362,7 +362,7 @@ func test_song_rows_show_the_song_its_soundtrack_and_plays() -> void:
|
||||
assert_str(row.song_label.get_parsed_text()).is_equal("Battle with Magus")
|
||||
assert_str(row.soundtrack_label.get_parsed_text()).is_equal("Chrono Trigger")
|
||||
assert_str(row.played_label.text).is_equal("2")
|
||||
assert_int(_view.song_list.shown_rows().size()).is_equal(10)
|
||||
assert_int(_view.song_list.shown_rows().size()).is_equal(7)
|
||||
|
||||
|
||||
func test_soundtracks_button_shows_the_cards_again() -> void:
|
||||
@@ -373,6 +373,7 @@ func test_soundtracks_button_shows_the_cards_again() -> void:
|
||||
assert_bool(_view.card_scroll.visible).is_true()
|
||||
assert_bool(_view.song_list.visible).is_false()
|
||||
assert_str(_view.count_label.text).is_equal("4 soundtracks")
|
||||
assert_bool(_view.show_option.visible).is_true()
|
||||
|
||||
|
||||
func test_song_search_finds_song_names_and_soundtrack_names() -> void:
|
||||
@@ -380,7 +381,7 @@ func test_song_search_finds_song_names_and_soundtrack_names() -> void:
|
||||
|
||||
_search("magus")
|
||||
assert_array(_listed_songs()).contains_exactly(["Battle with Magus"])
|
||||
assert_str(_view.count_label.text).is_equal("1 of 10 songs")
|
||||
assert_str(_view.count_label.text).is_equal("1 of 7 played songs")
|
||||
|
||||
# Every song of a soundtrack whose name matches
|
||||
_search("final fantasy")
|
||||
@@ -403,24 +404,17 @@ func test_typing_a_song_search_waits_for_a_pause() -> void:
|
||||
|
||||
_view.search_field.text = "magus"
|
||||
_view.search_field.text_changed.emit("magus")
|
||||
assert_int(_view.song_list.songs.size()).is_equal(10)
|
||||
assert_int(_view.song_list.songs.size()).is_equal(7)
|
||||
|
||||
await await_millis(300)
|
||||
assert_array(_listed_songs()).contains_exactly(["Battle with Magus"])
|
||||
|
||||
|
||||
func test_show_filter_for_songs() -> void:
|
||||
func test_show_menu_is_hidden_for_songs() -> void:
|
||||
await _show_songs_mode()
|
||||
|
||||
_view.show_option.select(StatisticsView.ShowFilter.NEVER_PLAYED)
|
||||
_view.show_option.item_selected.emit(StatisticsView.ShowFilter.NEVER_PLAYED)
|
||||
assert_array(_listed_songs()).contains_exactly(
|
||||
["To Far Away Times", "Underworld", "Wind Scene"])
|
||||
|
||||
_view.show_option.select(StatisticsView.ShowFilter.PLAYED)
|
||||
_view.show_option.item_selected.emit(StatisticsView.ShowFilter.PLAYED)
|
||||
assert_int(_listed_songs().size()).is_equal(7)
|
||||
assert_str(_view.count_label.text).is_equal("7 of 10 songs")
|
||||
assert_bool(_view.show_option.visible).is_false()
|
||||
assert_bool(_view.get_node("Toolbar/ShowLabel").visible).is_false()
|
||||
|
||||
|
||||
func test_song_sort_orders() -> void:
|
||||
@@ -428,13 +422,12 @@ func test_song_sort_orders() -> void:
|
||||
var expected: Dictionary = {
|
||||
StatisticsView.SortOrder.MOST_PLAYED: ["Schala's Theme", "Frog's Theme",
|
||||
"Battle with Magus", "Corridors of Time", "Dancing Mad", "Peaceful Days",
|
||||
"Zeal Palace", "To Far Away Times", "Underworld", "Wind Scene"],
|
||||
StatisticsView.SortOrder.LEAST_PLAYED: ["To Far Away Times", "Underworld",
|
||||
"Wind Scene", "Corridors of Time", "Dancing Mad", "Peaceful Days",
|
||||
"Zeal Palace", "Battle with Magus", "Frog's Theme", "Schala's Theme"],
|
||||
StatisticsView.SortOrder.Z_TO_A: ["Zeal Palace", "Wind Scene", "Underworld",
|
||||
"To Far Away Times", "Schala's Theme", "Peaceful Days", "Frog's Theme",
|
||||
"Dancing Mad", "Corridors of Time", "Battle with Magus"],
|
||||
"Zeal Palace"],
|
||||
StatisticsView.SortOrder.LEAST_PLAYED: ["Corridors of Time", "Dancing Mad",
|
||||
"Peaceful Days", "Zeal Palace", "Battle with Magus", "Frog's Theme",
|
||||
"Schala's Theme"],
|
||||
StatisticsView.SortOrder.Z_TO_A: ["Zeal Palace", "Schala's Theme", "Peaceful Days",
|
||||
"Frog's Theme", "Dancing Mad", "Corridors of Time", "Battle with Magus"],
|
||||
}
|
||||
for order: StatisticsView.SortOrder in expected:
|
||||
_view.sort_option.select(order)
|
||||
@@ -445,8 +438,10 @@ func test_song_sort_orders() -> void:
|
||||
|
||||
func test_songs_with_the_same_name_are_sorted_by_soundtrack() -> void:
|
||||
_server.respond_json("/statistics/soundtracks", [
|
||||
{"soundtrack_name": "Lufia II", "songs": [{"song_name": "Main Theme"}]},
|
||||
{"soundtrack_name": "Earthbound", "songs": [{"song_name": "Main Theme"}]},
|
||||
{"soundtrack_name": "Lufia II",
|
||||
"songs": [{"song_name": "Main Theme", "times_played": 1}]},
|
||||
{"soundtrack_name": "Earthbound",
|
||||
"songs": [{"song_name": "Main Theme", "times_played": 1}]},
|
||||
])
|
||||
await _show_songs_mode()
|
||||
|
||||
@@ -469,25 +464,25 @@ func test_clicking_a_song_shows_its_soundtrack() -> void:
|
||||
|
||||
func test_songs_stay_shown_when_statistics_are_loaded_again() -> void:
|
||||
await _show_songs_mode()
|
||||
_server.respond_json("/statistics/soundtracks", STATISTICS.slice(1, 2))
|
||||
_server.respond_json("/statistics/soundtracks", STATISTICS.slice(3, 4))
|
||||
|
||||
_view.refresh()
|
||||
|
||||
assert_bool(_view.song_list.visible).is_true()
|
||||
assert_array(_listed_songs()).contains_exactly(["Underworld"])
|
||||
assert_array(_listed_songs()).contains_exactly(["Dancing Mad"])
|
||||
|
||||
|
||||
func test_only_the_rows_on_screen_are_made_for_many_songs() -> void:
|
||||
var songs: Array[Dictionary] = []
|
||||
for i: int in 5000:
|
||||
songs.append({"song_name": "Song %04d" % i, "times_played": i % 7})
|
||||
songs.append({"song_name": "Song %04d" % i, "times_played": i % 7 + 1})
|
||||
_server.respond_json("/statistics/soundtracks",
|
||||
[{"soundtrack_name": "Big", "songs": songs}])
|
||||
await _show_songs_mode()
|
||||
|
||||
var rows: int = _view.song_list.rows_area.get_child_count()
|
||||
assert_int(rows).is_less(60)
|
||||
assert_str(_view.count_label.text).is_equal("5000 songs")
|
||||
assert_str(_view.count_label.text).is_equal("5000 played songs")
|
||||
|
||||
_view.song_list.scroll_to(2500)
|
||||
await _runner.simulate_frames(1)
|
||||
@@ -498,7 +493,7 @@ func test_only_the_rows_on_screen_are_made_for_many_songs() -> void:
|
||||
func test_mouse_wheel_scrolls_the_songs() -> void:
|
||||
var songs: Array[Dictionary] = []
|
||||
for i: int in 200:
|
||||
songs.append({"song_name": "Song %03d" % i})
|
||||
songs.append({"song_name": "Song %03d" % i, "times_played": 1})
|
||||
_server.respond_json("/statistics/soundtracks",
|
||||
[{"soundtrack_name": "Big", "songs": songs}])
|
||||
await _show_songs_mode()
|
||||
|
||||
Reference in new issue
Block a user