Fix rating calculation

This commit is contained in:
grimsi
2025-09-04 18:58:07 +02:00
parent 24eacc0196
commit 6c7bf4399e
3 changed files with 17 additions and 14 deletions
+12 -9
View File
@@ -238,6 +238,7 @@ export function metadataCompleteness(game: GameDto) {
* @returns The scaled number * @returns The scaled number
*/ */
function convertRange(value: number, originalRange: number[], targetRange: number[]): number { function convertRange(value: number, originalRange: number[], targetRange: number[]): number {
if (originalRange[0] === targetRange[0] && originalRange[1] === targetRange[1]) return value;
return (value - originalRange[0]) * (targetRange[1] - targetRange[0]) / (originalRange[1] - originalRange[0]) + targetRange[0]; return (value - originalRange[0]) * (targetRange[1] - targetRange[0]) / (originalRange[1] - originalRange[0]) + targetRange[0];
} }
@@ -247,22 +248,25 @@ function convertRange(value: number, originalRange: number[], targetRange: numbe
* If only one rating is present, that rating is returned. * If only one rating is present, that rating is returned.
* If neither rating is present, 0 is returned. * If neither rating is present, 0 is returned.
* @param game The GameDto object containing the ratings. * @param game The GameDto object containing the ratings.
* @returns The compound rating as a number between 0 and 100. * @param scale The scale to convert the rating to (default is [0, 100]).
* @returns The compound rating.
*/ */
export function compoundRating(game: GameDto): number { export function compoundRating(game: GameDto, scale = [0, 100]): number {
const weights = { const weights = {
critic: 0.4, critic: 0.4,
user: 0.6 user: 0.6
}; };
const originalRange = [0, 100];
const criticRating = game.criticRating ?? 0; const criticRating = game.criticRating ?? 0;
const userRating = game.userRating ?? 0; const userRating = game.userRating ?? 0;
if (criticRating === 0 && userRating === 0) return 0; if (criticRating === 0 && userRating === 0) return 0;
if (criticRating === 0) return userRating; if (criticRating === 0) return convertRange(userRating, originalRange, scale);
if (userRating === 0) return criticRating; if (userRating === 0) return convertRange(criticRating, originalRange, scale);
return Math.round((criticRating * weights.critic + userRating * weights.user) * 10) / 10; const avgRating = Math.round((criticRating * weights.critic + userRating * weights.user) * 10) / 10;
return convertRange(avgRating, originalRange, scale);
} }
/** /**
@@ -272,12 +276,11 @@ export function compoundRating(game: GameDto): number {
* @param game The GameDto object containing the ratings. * @param game The GameDto object containing the ratings.
* @returns A string representing the star rating out of 5, or "N/A" if no ratings are available. * @returns A string representing the star rating out of 5, or "N/A" if no ratings are available.
*/ */
export function gameRatingInStars(game: GameDto) { export function starRatingAsString(game: GameDto) {
const originalRange = [0, 100];
const starRange = [1, 5]; const starRange = [1, 5];
const rating = compoundRating(game); const rating = compoundRating(game, starRange);
if (rating === 0) return "N/A"; if (rating === 0) return "N/A";
return convertRange(rating, originalRange, starRange).toFixed(1); return rating.toFixed(1);
} }
+2 -2
View File
@@ -5,7 +5,7 @@ import {GameCover} from "Frontend/components/general/covers/GameCover";
import ComboButton, {ComboButtonOption} from "Frontend/components/general/input/ComboButton"; import ComboButton, {ComboButtonOption} from "Frontend/components/general/input/ComboButton";
import ImageCarousel from "Frontend/components/general/covers/ImageCarousel"; import ImageCarousel from "Frontend/components/general/covers/ImageCarousel";
import {Accordion, AccordionItem, addToast, Button, Chip, Link, Tooltip, useDisclosure} from "@heroui/react"; import {Accordion, AccordionItem, addToast, Button, Chip, Link, Tooltip, useDisclosure} from "@heroui/react";
import {gameRatingInStars, humanFileSize, isAdmin, toTitleCase} from "Frontend/util/utils"; import {humanFileSize, isAdmin, starRatingAsString, toTitleCase} from "Frontend/util/utils";
import {DownloadEndpoint} from "Frontend/endpoints/endpoints"; import {DownloadEndpoint} from "Frontend/endpoints/endpoints";
import {gameState} from "Frontend/state/GameState"; import {gameState} from "Frontend/state/GameState";
import {useSnapshot} from "valtio/react"; import {useSnapshot} from "valtio/react";
@@ -108,7 +108,7 @@ export default function GameView() {
</p> </p>
<div className="flex flex-row gap-1 mb-0.5 text-default-500"> <div className="flex flex-row gap-1 mb-0.5 text-default-500">
<Star weight="fill"/> <Star weight="fill"/>
{gameRatingInStars(game)} {starRatingAsString(game)}
</div> </div>
</div> </div>
<div className="flex flex-row items-center gap-2"> <div className="flex flex-row items-center gap-2">
+3 -3
View File
@@ -235,11 +235,11 @@ export default function SearchView() {
// Apply minimum rating filter // Apply minimum rating filter
if (minRating > 1) { if (minRating > 1) {
filtered = filtered.filter(game => { filtered = filtered.filter(game => {
const rating = compoundRating(game); const starRating = compoundRating(game, [1, 5]);
if (minRating === 5) { if (minRating === 5) {
return rating > 4.5; return starRating > 4.5;
} }
return rating >= minRating; return starRating >= minRating;
}); });
} }
return filtered; return filtered;