From 81864d4947caf111940cd5e4381c3ff47ab73d21 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sun, 22 Feb 2026 19:19:44 +0800 Subject: [PATCH] =?UTF-8?q?improve:=E7=82=B9=E5=90=8D=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Windows/NewStyleRollCallWindow.cs | 69 +++++++++++--------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/Ink Canvas/Windows/NewStyleRollCallWindow.cs b/Ink Canvas/Windows/NewStyleRollCallWindow.cs index 86f16a7e..c4eabbb8 100644 --- a/Ink Canvas/Windows/NewStyleRollCallWindow.cs +++ b/Ink Canvas/Windows/NewStyleRollCallWindow.cs @@ -180,6 +180,9 @@ namespace Ink_Canvas private const double PROBABILITY_RECOVERY_RATE = 0.2; private const double FREQUENCY_BOOST_FACTOR = 2.0; + private const int MaxGapThreshold = 3; + private const int MinCandidatePoolSize = 2; + // 单次抽相关 private bool isSingleDrawMode = false; private Random singleDrawRandom = new Random(); @@ -630,46 +633,52 @@ namespace Ink_Canvas if (validCandidates.Count == 0) return null; if (validCandidates.Count == 1) return validCandidates[0]; - // 检查极差:当极差达到3时,从被抽选次数最少的人中抽选 - if (historyData.NameFrequency != null && historyData.NameFrequency.Count > 0) + // 获取所有候选人员的被抽选次数(用于极差保护与平均值过滤) + var candidateFrequencies = new Dictionary(); + foreach (string name in validCandidates) { - // 获取所有候选人员的被抽选次数 - var candidateFrequencies = new Dictionary(); - foreach (string name in validCandidates) - { - int count = historyData.NameFrequency.ContainsKey(name) ? historyData.NameFrequency[name] : 0; - candidateFrequencies[name] = count; - } + int freq = (historyData?.NameFrequency != null && historyData.NameFrequency.ContainsKey(name)) + ? historyData.NameFrequency[name] : 0; + candidateFrequencies[name] = freq; + } - // 计算极差(最大值 - 最小值) - if (candidateFrequencies.Count > 0) - { - int maxCount = candidateFrequencies.Values.Max(); - int minCount = candidateFrequencies.Values.Min(); - int range = maxCount - minCount; + if (candidateFrequencies.Count > 0) + { + int maxCount = candidateFrequencies.Values.Max(); + int minCount = candidateFrequencies.Values.Min(); + int range = maxCount - minCount; - // 当极差达到3时,只从被抽选次数最少的人中抽选 - if (range >= 3) + if (range >= MaxGapThreshold) + { + var leastSelectedNames = candidateFrequencies + .Where(kvp => kvp.Value == minCount) + .Select(kvp => kvp.Key) + .ToList(); + + if (leastSelectedNames.Count > 0) { - var leastSelectedNames = candidateFrequencies - .Where(kvp => kvp.Value == minCount) - .Select(kvp => kvp.Key) - .ToList(); - - if (leastSelectedNames.Count > 0) - { - // 只从被抽选次数最少的人中不放回随机选择 - int randomIndex = random.Next(0, leastSelectedNames.Count); - return leastSelectedNames[randomIndex]; - } + int randomIndex = random.Next(0, leastSelectedNames.Count); + return leastSelectedNames[randomIndex]; } } } - // 获取每个候选人员的概率 + List poolForSelection = validCandidates; + if (candidateFrequencies.Count > 0) + { + double avgCount = candidateFrequencies.Values.Average(); + var averageFiltered = candidateFrequencies + .Where(kvp => kvp.Value <= avgCount) + .Select(kvp => kvp.Key) + .ToList(); + if (averageFiltered.Count >= MinCandidatePoolSize) + poolForSelection = averageFiltered; + } + + // 获取每个候选人员的概率(在过滤后的候选池上计算,实现冷启动与频率平衡) var nameProbabilities = new Dictionary(); - foreach (string name in validCandidates) + foreach (string name in poolForSelection) { // 获取基础概率 double baseProbability = GetNameProbability(name);