Skip to content

Commit

Permalink
Fix duplicate rating tags and support migration
Browse files Browse the repository at this point in the history
- Remove old rating tags when rating changes
- Automatically update tags when the following settings change
    - EnableHalfStars
    - RatingSteps
    - ShowZeroRating
    - ShouldApplyRatingTag
    - RatingTagPrefix
- Fix a null-ref except. when adding a tag to a game w/ no existing tags
  • Loading branch information
terrehbyte committed Oct 16, 2022
1 parent 032ad54 commit 1418cd5
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 23 deletions.
42 changes: 30 additions & 12 deletions StarRatings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,18 @@ public override IEnumerable<MainMenuItem> GetMainMenuItems(GetMainMenuItemsArgs
{
MenuSection = "StarRatings",
Description = "Rebuild Rating Tags",
Action = (menuArgs) => ApplyRatingTags(PlayniteApi.Database.Games.ToList()),
Action = (menuArgs) =>
{
ClearRatingTags(PlayniteApi.Database.Games);
ReapplyRatingTags(PlayniteApi.Database.Games);
},
};

yield return new MainMenuItem
{
MenuSection = "StarRatings",
Description = "Clear All Rating Tags",
Action = (menuArgs) => ClearRatingTags(PlayniteApi.Database.Games.ToList()),
Action = (menuArgs) => ClearRatingTags(PlayniteApi.Database.Games),
};
}
}
Expand Down Expand Up @@ -230,8 +234,25 @@ private void ApplyUserScore(IEnumerable<Game> games, int? userScore)
{
foreach (Game game in games)
{
// remove existing tag if needed
if (CurrentSettings.ShouldApplyRatingTag && game.UserScore.HasValue && game.TagIds != null)
{
int originalScore = game.UserScore.Value;

// round down to previous level
if (!scoreToRatingData.ContainsKey(originalScore))
{
int stepSize = 100 / CurrentSettings.RatingSteps;
originalScore = (originalScore / stepSize) * stepSize;
}

game.TagIds.Remove(scoreToRatingData[originalScore].ratingTagId);
}

// set new score
game.UserScore = userScore;

// update tag if needed
if (CurrentSettings.ShouldApplyRatingTag && userScore.HasValue)
{
// create tags if game has none
Expand All @@ -243,33 +264,30 @@ private void ApplyUserScore(IEnumerable<Game> games, int? userScore)
PlayniteApi.Database.Games.Update(games);
}

private void ApplyRatingTags(IEnumerable<Game> games)
public void ReapplyRatingTags(IEnumerable<Game> games)
{
foreach (var game in games)
{
// skip if no score
if(!game.UserScore.HasValue) { continue; }

int userScore = game.UserScore.Value;

// skip if score does not correspond to anything
// TODO: consider rounding down to next applicable score
if (!scoreToRatingData.ContainsKey(userScore)) { continue; }

// create TagIds for game if none exists
if (game.TagIds == null)
// round down to previous level
if (!scoreToRatingData.ContainsKey(userScore))
{
game.TagIds = new List<Guid>();
int stepSize = 100 / CurrentSettings.RatingSteps;
userScore = (userScore / stepSize) * stepSize;
}

// retrieve and stage tag
game.TagIds.Add(scoreToRatingData[userScore].ratingTagId);
}

PlayniteApi.Database.Games.Update(games);
}

private void ClearRatingTags(IEnumerable<Game> games)
public void ClearRatingTags(IEnumerable<Game> games)
{
// cache list of tags to remove
List<Guid> tagsToRemove = new List<Guid>();
Expand Down
34 changes: 23 additions & 11 deletions StarRatingsSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class StarRatingsSettings : ObservableObject
public class StarRatingsSettingsViewModel : ObservableObject, ISettings
{
private readonly StarRatings plugin;
private StarRatingsSettings editingClone { get; set; }
private StarRatingsSettings prevSavedSettings { get; set; }

private StarRatingsSettings settings;
public StarRatingsSettings Settings
Expand All @@ -54,38 +54,50 @@ public StarRatingsSettingsViewModel(StarRatings plugin)
var savedSettings = plugin.LoadPluginSettings<StarRatingsSettings>();

// LoadPluginSettings returns null if not saved data is available.
if (savedSettings != null)
{
Settings = savedSettings;
}
else
{
Settings = new StarRatingsSettings();
}
Settings = savedSettings ?? new StarRatingsSettings();
}

public void BeginEdit()
{
// Code executed when settings view is opened and user starts editing values.
editingClone = Serialization.GetClone(Settings);
prevSavedSettings = Serialization.GetClone(Settings);
}

public void CancelEdit()
{
// Code executed when user decides to cancel any changes made since BeginEdit was called.
// This method should revert any changes made to Option1 and Option2.
Settings = editingClone;
Settings = prevSavedSettings;
}

public void EndEdit()
{
// Code executed when user decides to confirm changes made since BeginEdit was called.
// This method should save settings made to Option1 and Option2.
plugin.SavePluginSettings(Settings);

bool hasChangedRatingScheme = prevSavedSettings.EnableHalfStars != Settings.EnableHalfStars ||
prevSavedSettings.RatingSteps != Settings.RatingSteps ||
prevSavedSettings.ShowZeroRating != Settings.ShowZeroRating ||
prevSavedSettings.ShouldApplyRatingTag != Settings.ShouldApplyRatingTag ||
prevSavedSettings.RatingTagPrefix != Settings.RatingTagPrefix;

// did we have tags enabled before?
if (hasChangedRatingScheme && prevSavedSettings.ShouldApplyRatingTag)
{
plugin.ClearRatingTags(plugin.PlayniteApi.Database.Games);
}

// Reinitialize ratings on edit
// TODO - We could listen for actual changes but this should be fairly cheap
// and uncomplicated to maintain until we need more complexity
plugin.InitializeRatings();

// do we need to apply tags again?
if (hasChangedRatingScheme && Settings.ShouldApplyRatingTag)
{
plugin.ReapplyRatingTags(plugin.PlayniteApi.Database.Games);
}
}

public bool VerifySettings(out List<string> errors)
Expand Down

0 comments on commit 1418cd5

Please sign in to comment.