Poprawki w rolach zwyciezcow
This commit is contained in:
@@ -195,28 +195,139 @@ public static class DataTransformer
|
|||||||
|
|
||||||
private static string DetermineWinningTeam(string winningFaction, List<PlayerRecordData> playerRecords)
|
private static string DetermineWinningTeam(string winningFaction, List<PlayerRecordData> playerRecords)
|
||||||
{
|
{
|
||||||
// Use WinningFaction from GameHistory if available
|
TownOfUsStatsPlugin.Logger.LogInfo($"DetermineWinningTeam called with winningFaction='{winningFaction}'");
|
||||||
if (!string.IsNullOrEmpty(winningFaction))
|
|
||||||
|
// ALWAYS use PlayerRecords to determine the winning team
|
||||||
|
// WinningFaction field can be stale (contains data from previous game)
|
||||||
|
var winners = playerRecords.Where(r => r.Winner).ToList();
|
||||||
|
|
||||||
|
if (winners.Count == 0)
|
||||||
{
|
{
|
||||||
// Clean HTML tags from winning faction
|
TownOfUsStatsPlugin.Logger.LogWarning("No winners found in PlayerRecords!");
|
||||||
return StripColorTags(winningFaction);
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: Check first winner's team
|
TownOfUsStatsPlugin.Logger.LogInfo($"Found {winners.Count} winner(s)");
|
||||||
var winner = playerRecords.FirstOrDefault(r => r.Winner);
|
|
||||||
if (winner == null)
|
// Group winners by team
|
||||||
|
var winnersByTeam = winners.GroupBy(w => w.TeamString).ToList();
|
||||||
|
|
||||||
|
// Log all winner teams
|
||||||
|
foreach (var group in winnersByTeam)
|
||||||
|
{
|
||||||
|
var roles = string.Join(", ", group.Select(w => ParseFirstRoleFromRoleString(w.RoleString)));
|
||||||
|
TownOfUsStatsPlugin.Logger.LogInfo($" Team '{group.Key}': {group.Count()} winner(s) - Roles: {roles}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case 1: All winners are from the same team
|
||||||
|
if (winnersByTeam.Count == 1)
|
||||||
|
{
|
||||||
|
var teamString = winnersByTeam[0].Key;
|
||||||
|
TownOfUsStatsPlugin.Logger.LogInfo($"All winners from same team: '{teamString}'");
|
||||||
|
|
||||||
|
// For Custom team (solo neutrals, Lovers, etc.), use the role name
|
||||||
|
if (teamString == "Custom")
|
||||||
|
{
|
||||||
|
// If there's only one winner, it's a solo neutral (Werewolf, Glitch, etc.)
|
||||||
|
if (winners.Count == 1)
|
||||||
|
{
|
||||||
|
var roleName = ParseFirstRoleFromRoleString(winners[0].RoleString);
|
||||||
|
TownOfUsStatsPlugin.Logger.LogInfo($"Solo neutral win: '{roleName}'");
|
||||||
|
return roleName;
|
||||||
|
}
|
||||||
|
// If multiple winners with Custom team, it's Lovers
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TownOfUsStatsPlugin.Logger.LogInfo("Multiple Custom team winners: Lovers");
|
||||||
|
return "Lovers";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard team conversions
|
||||||
|
var result = teamString switch
|
||||||
|
{
|
||||||
|
"Crewmate" => "Crewmates",
|
||||||
|
"Impostor" => "Impostors",
|
||||||
|
"Neutral" => "Neutrals",
|
||||||
|
_ => "Unknown",
|
||||||
|
};
|
||||||
|
|
||||||
|
TownOfUsStatsPlugin.Logger.LogInfo($"Determined winning team: '{result}'");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case 2: Mixed teams (e.g., Mercenary winning with Impostors, Jester with Crewmates)
|
||||||
|
// Find the main team (non-Neutral with most winners)
|
||||||
|
TownOfUsStatsPlugin.Logger.LogInfo("Mixed teams detected");
|
||||||
|
|
||||||
|
var mainTeam = winnersByTeam
|
||||||
|
.Where(g => g.Key is "Crewmate" or "Impostor") // Only Crewmate or Impostor
|
||||||
|
.OrderByDescending(g => g.Count())
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (mainTeam != null)
|
||||||
|
{
|
||||||
|
var result = mainTeam.Key switch
|
||||||
|
{
|
||||||
|
"Crewmate" => "Crewmates",
|
||||||
|
"Impostor" => "Impostors",
|
||||||
|
_ => "Unknown",
|
||||||
|
};
|
||||||
|
|
||||||
|
TownOfUsStatsPlugin.Logger.LogInfo($"Main winning team (mixed): '{result}'");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case 3: Only Neutrals won (shouldn't happen, but fallback)
|
||||||
|
TownOfUsStatsPlugin.Logger.LogWarning("Only Neutral/Custom winners, no main team found");
|
||||||
|
return "Neutrals";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses the first role name from RoleString (e.g., "Werewolf (Flash) (2/4) | Alive" → "Werewolf")
|
||||||
|
/// </summary>
|
||||||
|
private static string ParseFirstRoleFromRoleString(string roleString)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(roleString))
|
||||||
{
|
{
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
return winner.TeamString switch
|
// Strip color tags first
|
||||||
|
var cleanString = StripColorTags(roleString);
|
||||||
|
|
||||||
|
// Remove everything after " |" (status info)
|
||||||
|
var pipeIndex = cleanString.IndexOf(" |");
|
||||||
|
if (pipeIndex > 0)
|
||||||
{
|
{
|
||||||
"Crewmate" => "Crewmates",
|
cleanString = cleanString.Substring(0, pipeIndex).Trim();
|
||||||
"Impostor" => "Impostors",
|
}
|
||||||
"Neutral" => "Neutrals",
|
|
||||||
"Custom" => "Custom",
|
// Remove task info like "(0/4)" at the end
|
||||||
_ => "Unknown",
|
cleanString = Regex.Replace(cleanString, @"\s*\(\d+/\d+\)\s*$", "").Trim();
|
||||||
};
|
|
||||||
|
// Remove modifiers in parentheses (e.g., "(Flash)")
|
||||||
|
var parenIndex = cleanString.IndexOf('(');
|
||||||
|
if (parenIndex > 0)
|
||||||
|
{
|
||||||
|
cleanString = cleanString.Substring(0, parenIndex).Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's role history (separated by " > "), get the LAST role
|
||||||
|
if (cleanString.Contains(" > "))
|
||||||
|
{
|
||||||
|
var roles = cleanString.Split(new[] { " > " }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
cleanString = roles.Last().Trim();
|
||||||
|
|
||||||
|
// Remove modifiers again (after extracting last role)
|
||||||
|
parenIndex = cleanString.IndexOf('(');
|
||||||
|
if (parenIndex > 0)
|
||||||
|
{
|
||||||
|
cleanString = cleanString.Substring(0, parenIndex).Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.IsNullOrEmpty(cleanString) ? "Unknown" : cleanString;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetMapName(byte mapId)
|
private static string GetMapName(byte mapId)
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ public static class StatsExporter
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait a short delay to ensure TOU Mira has finished updating all static fields
|
||||||
|
// (including WinningFaction which is set after PlayerRecords)
|
||||||
|
await Task.Delay(100);
|
||||||
|
|
||||||
// Get data from TOU Mira via reflection
|
// Get data from TOU Mira via reflection
|
||||||
var bridge = ReflectionBridgeProvider.GetBridge();
|
var bridge = ReflectionBridgeProvider.GetBridge();
|
||||||
|
|
||||||
@@ -54,6 +58,7 @@ public static class StatsExporter
|
|||||||
var winningFaction = bridge.GetWinningFaction();
|
var winningFaction = bridge.GetWinningFaction();
|
||||||
|
|
||||||
TownOfUsStatsPlugin.Logger.LogInfo($"Collected data: {playerRecords.Count} players, {playerStats.Count} stats entries");
|
TownOfUsStatsPlugin.Logger.LogInfo($"Collected data: {playerRecords.Count} players, {playerStats.Count} stats entries");
|
||||||
|
TownOfUsStatsPlugin.Logger.LogInfo($"WinningFaction from GameHistory: '{winningFaction}'");
|
||||||
|
|
||||||
// Transform to export format
|
// Transform to export format
|
||||||
var gameData = DataTransformer.TransformToExportFormat(
|
var gameData = DataTransformer.TransformToExportFormat(
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ public class TouMiraReflectionBridge
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove "Tou" suffix if present (e.g., "EngineerTou" -> "Engineer", "TrackerTou" -> "Tracker")
|
// Remove "Tou" suffix if present (e.g., "EngineerTou" -> "Engineer", "TrackerTou" -> "Tracker")
|
||||||
if (roleName.EndsWith("Tou"))
|
if (roleName != null && roleName.EndsWith("Tou"))
|
||||||
{
|
{
|
||||||
roleName = roleName.Substring(0, roleName.Length - 3);
|
roleName = roleName.Substring(0, roleName.Length - 3);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user