mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-13 16:40:01 +00:00
Update rating algorithm
This commit is contained in:
@@ -241,6 +241,30 @@ function convertRange(value: number, originalRange: number[], targetRange: numbe
|
||||
return (value - originalRange[0]) * (targetRange[1] - targetRange[0]) / (originalRange[1] - originalRange[0]) + targetRange[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate a compound rating for a GameDto based on its criticRating and userRating.
|
||||
* If both ratings are present, a weighted average is calculated (40% critic, 60% user).
|
||||
* If only one rating is present, that rating is returned.
|
||||
* If neither rating is present, 0 is returned.
|
||||
* @param game The GameDto object containing the ratings.
|
||||
* @returns The compound rating as a number between 0 and 100.
|
||||
*/
|
||||
export function compoundRating(game: GameDto): number {
|
||||
const weights = {
|
||||
critic: 0.4,
|
||||
user: 0.6
|
||||
};
|
||||
|
||||
const criticRating = game.criticRating ?? 0;
|
||||
const userRating = game.userRating ?? 0;
|
||||
|
||||
if (criticRating === 0 && userRating === 0) return 0;
|
||||
if (criticRating === 0) return userRating;
|
||||
if (userRating === 0) return criticRating;
|
||||
|
||||
return Math.round((criticRating * weights.critic + userRating * weights.user) * 10) / 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a GameDto's ratings to a star rating out of 5.
|
||||
* If both criticRating and userRating are present, their average is taken.
|
||||
@@ -249,15 +273,11 @@ function convertRange(value: number, originalRange: number[], targetRange: numbe
|
||||
* @returns A string representing the star rating out of 5, or "N/A" if no ratings are available.
|
||||
*/
|
||||
export function gameRatingInStars(game: GameDto) {
|
||||
if (!game.criticRating && !game.userRating) return "N/A";
|
||||
|
||||
const originalRange = [0, 100];
|
||||
const starRange = [1, 5];
|
||||
const ratings = [];
|
||||
|
||||
if (game.criticRating) ratings.push(game.criticRating);
|
||||
if (game.userRating) ratings.push(game.userRating);
|
||||
const avgRating = ratings.reduce((a, b) => a + b, 0) / ratings.length;
|
||||
const rating = compoundRating(game);
|
||||
if (rating === 0) return "N/A";
|
||||
|
||||
return convertRange(avgRating, originalRange, starRange).toFixed(1);
|
||||
return convertRange(rating, originalRange, starRange).toFixed(1);
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import {Fzf} from "fzf";
|
||||
import GameDto from "Frontend/generated/org/gameyfin/app/games/dto/GameDto";
|
||||
import LibraryDto from "Frontend/generated/org/gameyfin/app/libraries/dto/LibraryDto";
|
||||
import CoverGrid from "Frontend/components/general/covers/CoverGrid";
|
||||
import {gameRatingInStars, toTitleCase} from "Frontend/util/utils";
|
||||
import {compoundRating, toTitleCase} from "Frontend/util/utils";
|
||||
|
||||
export default function SearchView() {
|
||||
const games = useSnapshot(gameState).sortedAlphabetically as GameDto[];
|
||||
@@ -138,7 +138,7 @@ export default function SearchView() {
|
||||
|
||||
const [sortKey, sortDirection] = sortBy.split("_");
|
||||
|
||||
return [...games].sort((a, b) => {
|
||||
return games.slice().sort((a, b) => {
|
||||
let cmp: number;
|
||||
|
||||
switch (sortKey) {
|
||||
@@ -149,7 +149,7 @@ export default function SearchView() {
|
||||
cmp = (a.release || "").localeCompare(b.release || "");
|
||||
break;
|
||||
case "rating":
|
||||
cmp = (a.criticRating ?? 0) - (b.criticRating ?? 0);
|
||||
cmp = compoundRating(a) - compoundRating(b);
|
||||
break;
|
||||
case "added":
|
||||
cmp = new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
|
||||
@@ -235,13 +235,11 @@ export default function SearchView() {
|
||||
// Apply minimum rating filter
|
||||
if (minRating > 1) {
|
||||
filtered = filtered.filter(game => {
|
||||
const ratingStr = gameRatingInStars(game);
|
||||
if (ratingStr === "N/A") return false;
|
||||
const ratingNum = parseFloat(ratingStr);
|
||||
const rating = compoundRating(game);
|
||||
if (minRating === 5) {
|
||||
return ratingNum > 4.5;
|
||||
return rating > 4.5;
|
||||
}
|
||||
return ratingNum >= minRating;
|
||||
return rating >= minRating;
|
||||
});
|
||||
}
|
||||
return filtered;
|
||||
|
||||
Reference in New Issue
Block a user