Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion modules/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ async def full_check(game: Game, version: str):
ret = parse(*args)
if isinstance(ret, parser.ParserException):
raise msgbox.Exc(*ret.args, **ret.kwargs)
(name, thread_version, developer, type, status, last_updated, score, description, changelog, tags, image_url, downloads) = ret
(name, thread_version, developer, type, status, last_updated, score, votes, description, changelog, tags, image_url, downloads) = ret
if not version:
if thread_version:
version = thread_version
Expand Down Expand Up @@ -656,6 +656,7 @@ async def update_game():
game.last_full_check = last_full_check
game.last_check_version = last_check_version
game.score = score
game.votes = votes
game.finished = finished
game.installed = installed
game.updated = updated
Expand Down
2 changes: 2 additions & 0 deletions modules/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ async def connect():
"tags_highlights": f'TEXT DEFAULT "{{}}"',
"use_parser_processes": f'INTEGER DEFAULT {int(True)}',
"vsync_ratio": f'INTEGER DEFAULT 1',
"weighted_score": f'INTEGER DEFAULT {int(False)}',
"zoom_area": f'INTEGER DEFAULT 50',
"zoom_times": f'REAL DEFAULT 4.0',
"zoom_enabled": f'INTEGER DEFAULT {int(True)}',
Expand Down Expand Up @@ -246,6 +247,7 @@ async def connect():
"last_check_version": f'TEXT DEFAULT ""',
"last_played": f'INTEGER DEFAULT 0',
"score": f'REAL DEFAULT 0',
"votes": f'INTEGER DEFAULT 0',
"rating": f'INTEGER DEFAULT 0',
"finished": f'TEXT DEFAULT ""',
"installed": f'TEXT DEFAULT ""',
Expand Down
25 changes: 22 additions & 3 deletions modules/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -1952,6 +1952,8 @@ def select_callback(selected):
imgui.text_disabled("Forum Score:")
imgui.same_line()
imgui.text(f"{game.score:.1f}/5")
imgui.same_line()
imgui.text_disabled(f"({game.votes})")

imgui.text_disabled("Type:")
imgui.same_line()
Expand Down Expand Up @@ -2785,7 +2787,10 @@ def key(id):
case cols.status_standalone.index:
key = lambda id: globals.games[id].status.value
case cols.score.index:
key = lambda id: - globals.games[id].score
if globals.settings.weighted_score:
key = lambda id: - utils.bayesian_average(globals.games[id].score, globals.games[id].votes)
else:
key = lambda id: - globals.games[id].score
case _: # Name and all others
key = lambda id: globals.games[id].name.lower()
base_ids.sort(key=key, reverse=sort_spec.reverse)
Expand Down Expand Up @@ -3004,7 +3009,13 @@ def draw_games_list(self):
case cols.status_standalone.index:
self.draw_status_widget(game.status)
case cols.score.index:
imgui.text(f"{game.score:.1f}")
with imgui.begin_group():
imgui.text(f"{game.score:.1f}")
imgui.same_line()
imgui.text_disabled(f"({game.votes})")
if imgui.is_item_hovered():
with imgui.begin_tooltip():
imgui.text(f"{utils.bayesian_average(game.score, game.votes):.2f}")
# Row hitbox
imgui.same_line()
imgui.set_cursor_pos_y(imgui.get_cursor_pos_y() - imgui.style.frame_padding.y)
Expand Down Expand Up @@ -3245,7 +3256,7 @@ def _cluster_text(name, text):
imgui.same_line(spacing=pad)
cluster = True
if cols.score.enabled:
_cluster_text(cols.score.name, f"{game.score:.1f}")
_cluster_text(cols.score.name, f"{game.score:.1f} ({game.votes})")
if cols.last_updated.enabled:
_cluster_text(cols.last_updated.name, game.last_updated.display or "Unknown")
if cols.last_played.enabled:
Expand Down Expand Up @@ -4372,6 +4383,14 @@ def select_callback(selected):
draw_settings_label("Confirm when removing:")
draw_settings_checkbox("confirm_on_remove")

draw_settings_label(
"Weighted score:",
"Use weighted rating algorithm when sorting table by forum score.\n"
"You can see the final value used by hovering over the score number."
)
if draw_settings_checkbox("weighted_score"):
self.recalculate_ids = True

draw_settings_label(
"Custom game:",
"Add a custom game that is untied from F95Zone. Useful for games removed for breaking forum rules, or for adding games "
Expand Down
10 changes: 9 additions & 1 deletion modules/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,14 @@ def add_downloads():
elif elem := head.find(is_class("bratr-rating")):
score = float(re.search(r"(\d(?:\.\d\d?)?)", elem.get("title")).group(1))

votes = 0
if elem := html.find(is_class("tabs")):
if match := re.search(r"reviews\s*\((\d+)\)", elem.get_text(), re.M | re.I):
try:
votes = int(match.group(1))
except Exception:
pass

description_html, description_regex = get_long_game_attr("overview", "story")
changelog_html, changelog_regex = get_long_game_attr("changelog", "change-log", "change log")
if len(description_regex) > len(description_html):
Expand Down Expand Up @@ -346,7 +354,7 @@ def add_downloads():
else:
return e

ret = (name, thread_version, developer, type, status, last_updated, score, description, changelog, tags, image_url, downloads)
ret = (name, thread_version, developer, type, status, last_updated, score, votes, description, changelog, tags, image_url, downloads)
if pipe:
pipe.put_nowait(ret)
else:
Expand Down
3 changes: 3 additions & 0 deletions modules/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ class Settings:
tags_highlights : dict[Tag, TagHighlight]
use_parser_processes : bool
vsync_ratio : int
weighted_score : bool
zoom_area : int
zoom_times : float
zoom_enabled : bool
Expand Down Expand Up @@ -745,6 +746,7 @@ class Game:
last_check_version : str
last_played : Datestamp
score : float
votes : int
rating : int
finished : str
installed : str
Expand Down Expand Up @@ -899,6 +901,7 @@ def __setattr__(self, name: str, value: typing.Any):
"last_check_version",
"last_played",
"score",
"votes",
"rating",
"finished",
"installed",
Expand Down
6 changes: 6 additions & 0 deletions modules/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
)


@functools.cache
def bayesian_average(avg_rating, num_votes):
W, C = 100, 0
return ((num_votes * avg_rating) + (W * C)) / (num_votes + W)


def rand_num_str(len=8):
return "".join((random.choice('0123456789') for _ in range(len)))

Expand Down