diff --git a/ConsistencyTracker.cs b/ConsistencyTracker.cs index b253b96..f3b5cdd 100644 --- a/ConsistencyTracker.cs +++ b/ConsistencyTracker.cs @@ -858,7 +858,7 @@ private void EventsOnRunStarted() { } private void EventsOnRunEnded(bool died, bool won) { - ChokeRateStat.ChokeRateData = null; //Reset caching + StatManager.InvalidateCachedStats(); IngameOverlay?.SetGoldenState(false); } private void Events_OnChangedRoom(string roomName, bool isPreviousRoom) { @@ -930,8 +930,8 @@ private void ChangeChapter(Session session) { //fix for SpeedrunTool savestate inconsistency TouchedBerries.Clear(); - //Reset caching of choke rate data - ChokeRateStat.ChokeRateData = null; + //Reset caching + StatManager.InvalidateCachedStats(); //Cause initial stats calculation SetNewRoom(CurrentRoomName, false); @@ -1591,7 +1591,7 @@ public void RemoveRoomGoldenBerryDeaths(bool removeOne = false) { } //Reset cached choke rate data for graph - ChokeRateStat.ChokeRateData = null; + ChokeRateStat.InvalidateCache(); SaveChapterStats(); } public void WipeChapterGoldenBerryDeaths() { diff --git a/ConsistencyTrackerSettings.cs b/ConsistencyTrackerSettings.cs index 8cf339f..0442c05 100644 --- a/ConsistencyTrackerSettings.cs +++ b/ConsistencyTrackerSettings.cs @@ -1175,6 +1175,9 @@ public void CreateExternalOverlayEntry(TextMenu menu, bool inGame) { [SettingIgnore] public bool IngameOverlayGraphShowGoldenPbBar { get; set; } = true; + [SettingIgnore] + public bool IngameOverlayGraphShowSuccessRateColors { get; set; } = false; + [SettingIgnore] public bool IngameOverlayGraphCurrentRoomExplicit { get; set; } = true; @@ -1434,6 +1437,13 @@ public void CreateIngameOverlayEntry(TextMenu menu, bool inGame) { } }); subMenu.AddDescription(menu, menuItem, "Shows your PB room as a golden bar at the bottom of the graph."); + + subMenu.Add(menuItem = new TextMenu.OnOff("Graph Show Success Rate Colors", IngameOverlayGraphShowSuccessRateColors) { + OnValueChange = v => { + IngameOverlayGraphShowSuccessRateColors = v; + } + }); + subMenu.AddDescription(menu, menuItem, "Colors bars in graph to match room success rate color."); subMenu.Add(menuItem = new TextMenu.OnOff("Graph Current Room Indicator Explicit", IngameOverlayGraphCurrentRoomExplicit) { OnValueChange = v => { diff --git a/Entities/GraphOverlay.cs b/Entities/GraphOverlay.cs index b949eef..c5a079a 100644 --- a/Entities/GraphOverlay.cs +++ b/Entities/GraphOverlay.cs @@ -29,6 +29,7 @@ public class GraphOverlay : Entity { private static int BackgroundDim => Mod.ModSettings.IngameOverlayGraphBackgroundDim; private Dictionary> ChokeRateData { get; set; } + private Dictionary SuccessRateData { get; set; } private int HighestDifficulty { get; set; } private RoomInfo PbRoom { get; set; } private RoomInfo PbRoomSession { get; set; } @@ -43,6 +44,7 @@ public GraphOverlay() { } private void EventsOnAfterSavingStats() { + StatManager.InvalidateCachedStats(); UpdateOverlay(); } @@ -55,6 +57,7 @@ public void UpdateOverlay() { if (path == null || stats == null) return; ChokeRateData = ChokeRateStat.GetRoomData(path, stats); + SuccessRateData = SuccessRateStat.GetRoomData(path, stats); PbRoom = StatsUtil.GetFurthestGoldenRun(path, stats); PbRoomSession = StatsUtil.GetFurthestGoldenRunSession(path, stats); @@ -121,6 +124,8 @@ public override void Render() { int availableBarHeight = Height - (ShowGoldenPbBar ? 3 + 1 : 0) - (currentRoomIndicatorExplicit ? 3 + 1 : 0); int barWidth = (availableBarWidth - ((barCount - 1) * BarSpacing)) / barCount; int paddingX = (availableBarWidth - (barWidth * barCount) - ((barCount - 1) * BarSpacing)) / 2; + + bool showSuccessRateColors = Mod.ModSettings.IngameOverlayGraphShowSuccessRateColors; //Walk path and draw the bars int barsDrawn = 0; @@ -152,6 +157,31 @@ public override void Render() { if (!visitedCurrent) { barColor = Color.Gray; } + + //Color code for success rate display + if (showSuccessRateColors) { + barHeight = Math.Max(3, barHeight); + + if (SuccessRateData.ContainsKey(rInfo)) { + float successRate = SuccessRateData[rInfo]; + if (float.IsNaN(successRate)) { + barColor = Color.Gray; + } else if (successRate > ((float)Mod.ModSettings.LiveDataChapterBarLightGreenPercent / 100 - 0.001)) { + // Light green + barColor = Color.LightGreen; + } else if (successRate > ((float)Mod.ModSettings.LiveDataChapterBarGreenPercent / 100 - 0.001)) { + // Green + barColor = Color.Green; + } else if (successRate > ((float)Mod.ModSettings.LiveDataChapterBarYellowPercent / 100 - 0.001)) { + // Yellow + barColor = Color.Yellow; + } else { + // Red + barColor = Color.Red; + } + + } + } //Draw checkpoint indicator over the empty space before this bar if (!isFirstCheckpoint && rInfo.RoomNumberInCP == 1 && Mod.ModSettings.IngameOverlayGraphShowCheckpointIndicator) { @@ -286,4 +316,4 @@ private static Vector2 ResolvePosition(StatTextPosition pos, int width, int heig return position; } } -} \ No newline at end of file +} diff --git a/Models/ChapterStats.cs b/Models/ChapterStats.cs index 36fa73e..ac3029c 100644 --- a/Models/ChapterStats.cs +++ b/Models/ChapterStats.cs @@ -745,6 +745,8 @@ public void AddAttempt(bool success) { } PreviousAttempts.Add(success); + + SuccessRateStat.InvalidateCache(); } public void RemoveLastAttempt() { @@ -752,6 +754,8 @@ public void RemoveLastAttempt() { return; } PreviousAttempts.RemoveAt(PreviousAttempts.Count-1); + + SuccessRateStat.InvalidateCache(); } public long GetTimeForCategory(TimeCategory category) { diff --git a/Stats/ChokeRateStat.cs b/Stats/ChokeRateStat.cs index d2bc377..6e8aaa0 100644 --- a/Stats/ChokeRateStat.cs +++ b/Stats/ChokeRateStat.cs @@ -265,7 +265,7 @@ public override string FormatSummary(PathInfo chapterPath, ChapterStats chapterS return null; } - public static Dictionary> ChokeRateData { get; set; } = null; + private static Dictionary> ChokeRateData = null; /// /// Gets the following data for every room: Golden Entries, Golden Success Rate, Golden Entries Session, Golden Success Rate Session /// @@ -320,6 +320,12 @@ public static Dictionary> GetRoomData(Pa ChokeRateData = roomData; return roomData; } + /// + /// Deletes cached room choke rate data, resulting in it being recomputed next time it is requested. + /// + public static void InvalidateCache() { + ChokeRateData = null; + } /// /// Gets the following data for every room: Golden Entries Session, Golden Success Rate Session diff --git a/Stats/StatManager.cs b/Stats/StatManager.cs index 6ff4d91..1bd1235 100644 --- a/Stats/StatManager.cs +++ b/Stats/StatManager.cs @@ -419,6 +419,15 @@ public bool DeleteFormat(string formatName) { Mod.SaveChapterStats(); return true; } + + /// + /// Resets the caches used by stats shown in the graph overlay. + /// Currently, resets cache for `ChokeRateStat` and `SuccessRateStat`. + /// + public static void InvalidateCachedStats() { + ChokeRateStat.InvalidateCache(); + SuccessRateStat.InvalidateCache(); + } #endregion #region Format file IO diff --git a/Stats/SuccessRateStat.cs b/Stats/SuccessRateStat.cs index 65622c4..0f0bf23 100644 --- a/Stats/SuccessRateStat.cs +++ b/Stats/SuccessRateStat.cs @@ -80,6 +80,34 @@ public override string FormatSummary(PathInfo chapterPath, ChapterStats chapterS return null; } + private static Dictionary SuccessRateData = null; + /// + /// Gets the success rate data (based on fraction of successes in latest `StatManager.AttemptCount` attempts) for each room. + /// + public static Dictionary GetRoomData(PathInfo chapterPath, ChapterStats chapterStats) { + if (SuccessRateData != null) return SuccessRateData; + + int attemptCount = StatManager.AttemptCount; + var roomData = new Dictionary(); + + foreach (CheckpointInfo cpInfo in chapterPath.Checkpoints) { + foreach (RoomInfo rInfo in cpInfo.Rooms) { + RoomStats data = chapterStats.GetRoom(rInfo); + float successRate = data.AverageSuccessOverN(attemptCount); + roomData.Add(rInfo, successRate); + } + } + + SuccessRateData = roomData; + return roomData; + } + /// + /// Deletes cached room success rate data, resulting in it being recomputed next time it is requested. + /// + public static void InvalidateCache() { + SuccessRateData = null; + } + //success-rate;Room SR: {room:successRate} | CP: {checkpoint:successRate} | Total: {chapter:successRate} public override List> GetPlaceholderExplanations() {