From 7ed7b944d043861f00d7a81e2ede2c934a8515a8 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Wed, 14 Feb 2024 20:16:50 +0200 Subject: [PATCH 1/5] Update RulesetHelper.cs --- PerformanceCalculatorGUI/RulesetHelper.cs | 45 ++++++++++++++++------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/PerformanceCalculatorGUI/RulesetHelper.cs b/PerformanceCalculatorGUI/RulesetHelper.cs index c99ad0b9d..d92332e5e 100644 --- a/PerformanceCalculatorGUI/RulesetHelper.cs +++ b/PerformanceCalculatorGUI/RulesetHelper.cs @@ -127,19 +127,38 @@ private static Dictionary generateOsuHitResults(double accuracy, } else { - // Let Great=6, Good=2, Meh=1, Miss=0. The total should be this. - var targetTotal = (int)Math.Round(accuracy * totalResultCount * 6); - - // Start by assuming every non miss is a meh - // This is how much increase is needed by greats and goods - var delta = targetTotal - (totalResultCount - countMiss); - - // Each great increases total by 5 (great-meh=5) - countGreat = delta / 5; - // Each good increases total by 1 (good-meh=1). Covers remaining difference. - countGood = delta % 5; - // Mehs are left over. Could be negative if impossible value of amountMiss chosen - countMeh = totalResultCount - countGreat - countGood - countMiss; + // Accuracy if we will remove misses + int relevantResultCount = totalResultCount - countMiss; + double relevantAccuracy = accuracy * totalResultCount / relevantResultCount; + relevantAccuracy = Math.Clamp(relevantAccuracy, 0, 1); + + if (relevantAccuracy < 1.0 / 6) // in that case we have only 50s or misses + { + double count50estimate = 6 * relevantResultCount * relevantAccuracy; + + countGood = 0; + countMeh = (int?)Math.Round(count50estimate); + countMiss = (int)(totalResultCount - countMeh); + } + else if (relevantAccuracy < 0.25) // point where we have no 300s + { + double count100estimate = 6 * relevantResultCount * relevantAccuracy - relevantResultCount; + double count50estimate = relevantResultCount - count100estimate; + + countGood = (int?)Math.Round(count100estimate); + countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); + } + else + { + double ratio50to100 = Math.Pow(1 - (relevantAccuracy - 0.25) / 0.75, 2); + double count100estimate = 6 * relevantResultCount * (1 - relevantAccuracy) / (5 * ratio50to100 + 4); + double count50estimate = count100estimate * ratio50to100; + + countGood = (int?)Math.Round(count100estimate); + countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); + } + + countGreat = (int)(totalResultCount - countGood - countMeh - countMiss); } return new Dictionary From 54088b59431fb2c515a7b9929ab2ec489cd519ae Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Wed, 14 Feb 2024 21:24:46 +0200 Subject: [PATCH 2/5] Added VERY detailed commentaries on algorithm --- PerformanceCalculatorGUI/RulesetHelper.cs | 36 +++++++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/PerformanceCalculatorGUI/RulesetHelper.cs b/PerformanceCalculatorGUI/RulesetHelper.cs index d92332e5e..0369f3ca3 100644 --- a/PerformanceCalculatorGUI/RulesetHelper.cs +++ b/PerformanceCalculatorGUI/RulesetHelper.cs @@ -127,37 +127,67 @@ private static Dictionary generateOsuHitResults(double accuracy, } else { - // Accuracy if we will remove misses + // Total result count excluding countMiss int relevantResultCount = totalResultCount - countMiss; + + // Accuracy excluding countMiss. We need that because we're trying to achieve target accuracy without touching countMiss + // So it's better to pretened that there were 0 misses in the 1st place double relevantAccuracy = accuracy * totalResultCount / relevantResultCount; + + // Clamp accuracy to account for user trying to break the algorithm by inputting impossible values relevantAccuracy = Math.Clamp(relevantAccuracy, 0, 1); - if (relevantAccuracy < 1.0 / 6) // in that case we have only 50s or misses + // If accuracy is less than 16.67% - it means that we have only 50s or misses + // Assuming that we removed misses in the 1st place - that means that we need to add additional misses to achieve target accuracy + if (relevantAccuracy < 1.0 / 6) { + // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c300 = c100 = 0 double count50estimate = 6 * relevantResultCount * relevantAccuracy; + // We have 0 100s, because we can't start adding 100s again after reaching "only 50s" point countGood = 0; + + // Round it to get int number of 50s countMeh = (int?)Math.Round(count50estimate); + + // Fill the rest results with misses overwriting initial countMiss countMiss = (int)(totalResultCount - countMeh); } - else if (relevantAccuracy < 0.25) // point where we have no 300s + // If accuracy is between 16.67% and 25% - we assume that we have no 300s + else if (relevantAccuracy < 0.25) { + // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c300 = 0 double count100estimate = 6 * relevantResultCount * relevantAccuracy - relevantResultCount; + + // We only had 100s and 50s in that scenario so rest of the hits are 50s double count50estimate = relevantResultCount - count100estimate; + // Round it to get int number of 100s countGood = (int?)Math.Round(count100estimate); + + // Get number of 50s as difference between total mistimed hits and count100 countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); } + // Main curve for accuracy > 25%, the closer accuracy is to 25% - the more 50s it adds else { + // Main curve. Zero 50s if accuracy is 100%, one 50 per 9 100s if accuracy is 75% (excluding misses), 4 50s per 9 100s if accuracy is 50% double ratio50to100 = Math.Pow(1 - (relevantAccuracy - 0.25) / 0.75, 2); + + // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c50 = c100 * ratio50to100 double count100estimate = 6 * relevantResultCount * (1 - relevantAccuracy) / (5 * ratio50to100 + 4); + + // Get count50 according to c50 = c100 * ratio50to100 double count50estimate = count100estimate * ratio50to100; + // Round it to get int number of 100s countGood = (int?)Math.Round(count100estimate); + + // Get number of 50s as difference between total mistimed hits and count100 countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); } + // Rest of the hits are 300s countGreat = (int)(totalResultCount - countGood - countMeh - countMiss); } From 07e31803a0967c56b35181facc56bc015c4d83a0 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Fri, 2 Aug 2024 13:51:36 +0300 Subject: [PATCH 3/5] Added formula to the non GUI too and changed the order a bit to be more readable --- .../Simulate/OsuSimulateCommand.cs | 75 +++++++++++++++---- PerformanceCalculatorGUI/RulesetHelper.cs | 48 ++++++------ 2 files changed, 86 insertions(+), 37 deletions(-) diff --git a/PerformanceCalculator/Simulate/OsuSimulateCommand.cs b/PerformanceCalculator/Simulate/OsuSimulateCommand.cs index 3fdf0f307..25c0e9d10 100644 --- a/PerformanceCalculator/Simulate/OsuSimulateCommand.cs +++ b/PerformanceCalculator/Simulate/OsuSimulateCommand.cs @@ -62,19 +62,68 @@ protected override Dictionary GenerateHitResults(double accuracy } else { - // Let Great=6, Good=2, Meh=1, Miss=0. The total should be this. - var targetTotal = (int)Math.Round(accuracy * totalResultCount * 6); - - // Start by assuming every non miss is a meh - // This is how much increase is needed by greats and goods - var delta = targetTotal - (totalResultCount - countMiss); - - // Each great increases total by 5 (great-meh=5) - countGreat = delta / 5; - // Each good increases total by 1 (good-meh=1). Covers remaining difference. - countGood = delta % 5; - // Mehs are left over. Could be negative if impossible value of amountMiss chosen - countMeh = totalResultCount - countGreat - countGood - countMiss; + // Total result count excluding countMiss + int relevantResultCount = totalResultCount - countMiss; + + // Accuracy excluding countMiss. We need that because we're trying to achieve target accuracy without touching countMiss + // So it's better to pretened that there were 0 misses in the 1st place + double relevantAccuracy = accuracy * totalResultCount / relevantResultCount; + + // Clamp accuracy to account for user trying to break the algorithm by inputting impossible values + relevantAccuracy = Math.Clamp(relevantAccuracy, 0, 1); + + // Main curve for accuracy > 25%, the closer accuracy is to 25% - the more 50s it adds + if (relevantAccuracy >= 0.25) + { + // Main curve. Zero 50s if accuracy is 100%, one 50 per 9 100s if accuracy is 75% (excluding misses), 4 50s per 9 100s if accuracy is 50% + double ratio50to100 = Math.Pow(1 - (relevantAccuracy - 0.25) / 0.75, 2); + + // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c50 = c100 * ratio50to100 + double count100estimate = 6 * relevantResultCount * (1 - relevantAccuracy) / (5 * ratio50to100 + 4); + + // Get count50 according to c50 = c100 * ratio50to100 + double count50estimate = count100estimate * ratio50to100; + + // Round it to get int number of 100s + countGood = (int?)Math.Round(count100estimate); + + // Get number of 50s as difference between total mistimed hits and count100 + countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); + } + // If accuracy is between 16.67% and 25% - we assume that we have no 300s + else if (relevantAccuracy >= 1.0 / 6) + { + // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c300 = 0 + double count100estimate = 6 * relevantResultCount * relevantAccuracy - relevantResultCount; + + // We only had 100s and 50s in that scenario so rest of the hits are 50s + double count50estimate = relevantResultCount - count100estimate; + + // Round it to get int number of 100s + countGood = (int?)Math.Round(count100estimate); + + // Get number of 50s as difference between total mistimed hits and count100 + countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); + } + // If accuracy is less than 16.67% - it means that we have only 50s or misses + // Assuming that we removed misses in the 1st place - that means that we need to add additional misses to achieve target accuracy + else + { + // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c300 = c100 = 0 + double count50estimate = 6 * relevantResultCount * relevantAccuracy; + + // We have 0 100s, because we can't start adding 100s again after reaching "only 50s" point + countGood = 0; + + // Round it to get int number of 50s + countMeh = (int?)Math.Round(count50estimate); + + // Fill the rest results with misses overwriting initial countMiss + countMiss = (int)(totalResultCount - countMeh); + } + + // Rest of the hits are 300s + countGreat = (int)(totalResultCount - countGood - countMeh - countMiss); } return new Dictionary diff --git a/PerformanceCalculatorGUI/RulesetHelper.cs b/PerformanceCalculatorGUI/RulesetHelper.cs index 0369f3ca3..3fd40021c 100644 --- a/PerformanceCalculatorGUI/RulesetHelper.cs +++ b/PerformanceCalculatorGUI/RulesetHelper.cs @@ -137,24 +137,26 @@ private static Dictionary generateOsuHitResults(double accuracy, // Clamp accuracy to account for user trying to break the algorithm by inputting impossible values relevantAccuracy = Math.Clamp(relevantAccuracy, 0, 1); - // If accuracy is less than 16.67% - it means that we have only 50s or misses - // Assuming that we removed misses in the 1st place - that means that we need to add additional misses to achieve target accuracy - if (relevantAccuracy < 1.0 / 6) + // Main curve for accuracy > 25%, the closer accuracy is to 25% - the more 50s it adds + if (relevantAccuracy >= 0.25) { - // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c300 = c100 = 0 - double count50estimate = 6 * relevantResultCount * relevantAccuracy; + // Main curve. Zero 50s if accuracy is 100%, one 50 per 9 100s if accuracy is 75% (excluding misses), 4 50s per 9 100s if accuracy is 50% + double ratio50to100 = Math.Pow(1 - (relevantAccuracy - 0.25) / 0.75, 2); - // We have 0 100s, because we can't start adding 100s again after reaching "only 50s" point - countGood = 0; + // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c50 = c100 * ratio50to100 + double count100estimate = 6 * relevantResultCount * (1 - relevantAccuracy) / (5 * ratio50to100 + 4); - // Round it to get int number of 50s - countMeh = (int?)Math.Round(count50estimate); + // Get count50 according to c50 = c100 * ratio50to100 + double count50estimate = count100estimate * ratio50to100; - // Fill the rest results with misses overwriting initial countMiss - countMiss = (int)(totalResultCount - countMeh); + // Round it to get int number of 100s + countGood = (int?)Math.Round(count100estimate); + + // Get number of 50s as difference between total mistimed hits and count100 + countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); } // If accuracy is between 16.67% and 25% - we assume that we have no 300s - else if (relevantAccuracy < 0.25) + else if (relevantAccuracy >= 1.0 / 6) { // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c300 = 0 double count100estimate = 6 * relevantResultCount * relevantAccuracy - relevantResultCount; @@ -168,23 +170,21 @@ private static Dictionary generateOsuHitResults(double accuracy, // Get number of 50s as difference between total mistimed hits and count100 countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); } - // Main curve for accuracy > 25%, the closer accuracy is to 25% - the more 50s it adds + // If accuracy is less than 16.67% - it means that we have only 50s or misses + // Assuming that we removed misses in the 1st place - that means that we need to add additional misses to achieve target accuracy else { - // Main curve. Zero 50s if accuracy is 100%, one 50 per 9 100s if accuracy is 75% (excluding misses), 4 50s per 9 100s if accuracy is 50% - double ratio50to100 = Math.Pow(1 - (relevantAccuracy - 0.25) / 0.75, 2); - - // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c50 = c100 * ratio50to100 - double count100estimate = 6 * relevantResultCount * (1 - relevantAccuracy) / (5 * ratio50to100 + 4); + // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c300 = c100 = 0 + double count50estimate = 6 * relevantResultCount * relevantAccuracy; - // Get count50 according to c50 = c100 * ratio50to100 - double count50estimate = count100estimate * ratio50to100; + // We have 0 100s, because we can't start adding 100s again after reaching "only 50s" point + countGood = 0; - // Round it to get int number of 100s - countGood = (int?)Math.Round(count100estimate); + // Round it to get int number of 50s + countMeh = (int?)Math.Round(count50estimate); - // Get number of 50s as difference between total mistimed hits and count100 - countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); + // Fill the rest results with misses overwriting initial countMiss + countMiss = (int)(totalResultCount - countMeh); } // Rest of the hits are 300s From 0da2a18ffe70e5bd414b96e7a09ddbecfbd1d404 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Fri, 2 Aug 2024 13:53:48 +0300 Subject: [PATCH 4/5] trimmed whitespace (CI fix) --- PerformanceCalculatorGUI/RulesetHelper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PerformanceCalculatorGUI/RulesetHelper.cs b/PerformanceCalculatorGUI/RulesetHelper.cs index 3fd40021c..b58232155 100644 --- a/PerformanceCalculatorGUI/RulesetHelper.cs +++ b/PerformanceCalculatorGUI/RulesetHelper.cs @@ -138,7 +138,7 @@ private static Dictionary generateOsuHitResults(double accuracy, relevantAccuracy = Math.Clamp(relevantAccuracy, 0, 1); // Main curve for accuracy > 25%, the closer accuracy is to 25% - the more 50s it adds - if (relevantAccuracy >= 0.25) + if (relevantAccuracy >= 0.25) { // Main curve. Zero 50s if accuracy is 100%, one 50 per 9 100s if accuracy is 75% (excluding misses), 4 50s per 9 100s if accuracy is 50% double ratio50to100 = Math.Pow(1 - (relevantAccuracy - 0.25) / 0.75, 2); @@ -156,7 +156,7 @@ private static Dictionary generateOsuHitResults(double accuracy, countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); } // If accuracy is between 16.67% and 25% - we assume that we have no 300s - else if (relevantAccuracy >= 1.0 / 6) + else if (relevantAccuracy >= 1.0 / 6) { // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c300 = 0 double count100estimate = 6 * relevantResultCount * relevantAccuracy - relevantResultCount; From 04596f6db5066cd8a24aa61ea6a1d61dff1e69aa Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Fri, 30 Aug 2024 21:49:33 +0300 Subject: [PATCH 5/5] fixed CI naming problems --- .../Simulate/OsuSimulateCommand.cs | 22 +++++++++---------- PerformanceCalculatorGUI/RulesetHelper.cs | 22 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/PerformanceCalculator/Simulate/OsuSimulateCommand.cs b/PerformanceCalculator/Simulate/OsuSimulateCommand.cs index 25c0e9d10..2f8954511 100644 --- a/PerformanceCalculator/Simulate/OsuSimulateCommand.cs +++ b/PerformanceCalculator/Simulate/OsuSimulateCommand.cs @@ -76,47 +76,47 @@ protected override Dictionary GenerateHitResults(double accuracy if (relevantAccuracy >= 0.25) { // Main curve. Zero 50s if accuracy is 100%, one 50 per 9 100s if accuracy is 75% (excluding misses), 4 50s per 9 100s if accuracy is 50% - double ratio50to100 = Math.Pow(1 - (relevantAccuracy - 0.25) / 0.75, 2); + double ratio50To100 = Math.Pow(1 - (relevantAccuracy - 0.25) / 0.75, 2); // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c50 = c100 * ratio50to100 - double count100estimate = 6 * relevantResultCount * (1 - relevantAccuracy) / (5 * ratio50to100 + 4); + double count100Estimate = 6 * relevantResultCount * (1 - relevantAccuracy) / (5 * ratio50To100 + 4); // Get count50 according to c50 = c100 * ratio50to100 - double count50estimate = count100estimate * ratio50to100; + double count50Estimate = count100Estimate * ratio50To100; // Round it to get int number of 100s - countGood = (int?)Math.Round(count100estimate); + countGood = (int?)Math.Round(count100Estimate); // Get number of 50s as difference between total mistimed hits and count100 - countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); + countMeh = (int?)(Math.Round(count100Estimate + count50Estimate) - countGood); } // If accuracy is between 16.67% and 25% - we assume that we have no 300s else if (relevantAccuracy >= 1.0 / 6) { // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c300 = 0 - double count100estimate = 6 * relevantResultCount * relevantAccuracy - relevantResultCount; + double count100Estimate = 6 * relevantResultCount * relevantAccuracy - relevantResultCount; // We only had 100s and 50s in that scenario so rest of the hits are 50s - double count50estimate = relevantResultCount - count100estimate; + double count50Estimate = relevantResultCount - count100Estimate; // Round it to get int number of 100s - countGood = (int?)Math.Round(count100estimate); + countGood = (int?)Math.Round(count100Estimate); // Get number of 50s as difference between total mistimed hits and count100 - countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); + countMeh = (int?)(Math.Round(count100Estimate + count50Estimate) - countGood); } // If accuracy is less than 16.67% - it means that we have only 50s or misses // Assuming that we removed misses in the 1st place - that means that we need to add additional misses to achieve target accuracy else { // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c300 = c100 = 0 - double count50estimate = 6 * relevantResultCount * relevantAccuracy; + double count50Estimate = 6 * relevantResultCount * relevantAccuracy; // We have 0 100s, because we can't start adding 100s again after reaching "only 50s" point countGood = 0; // Round it to get int number of 50s - countMeh = (int?)Math.Round(count50estimate); + countMeh = (int?)Math.Round(count50Estimate); // Fill the rest results with misses overwriting initial countMiss countMiss = (int)(totalResultCount - countMeh); diff --git a/PerformanceCalculatorGUI/RulesetHelper.cs b/PerformanceCalculatorGUI/RulesetHelper.cs index b58232155..66c79229e 100644 --- a/PerformanceCalculatorGUI/RulesetHelper.cs +++ b/PerformanceCalculatorGUI/RulesetHelper.cs @@ -141,47 +141,47 @@ private static Dictionary generateOsuHitResults(double accuracy, if (relevantAccuracy >= 0.25) { // Main curve. Zero 50s if accuracy is 100%, one 50 per 9 100s if accuracy is 75% (excluding misses), 4 50s per 9 100s if accuracy is 50% - double ratio50to100 = Math.Pow(1 - (relevantAccuracy - 0.25) / 0.75, 2); + double ratio50To100 = Math.Pow(1 - (relevantAccuracy - 0.25) / 0.75, 2); // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c50 = c100 * ratio50to100 - double count100estimate = 6 * relevantResultCount * (1 - relevantAccuracy) / (5 * ratio50to100 + 4); + double count100Estimate = 6 * relevantResultCount * (1 - relevantAccuracy) / (5 * ratio50To100 + 4); // Get count50 according to c50 = c100 * ratio50to100 - double count50estimate = count100estimate * ratio50to100; + double count50Estimate = count100Estimate * ratio50To100; // Round it to get int number of 100s - countGood = (int?)Math.Round(count100estimate); + countGood = (int?)Math.Round(count100Estimate); // Get number of 50s as difference between total mistimed hits and count100 - countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); + countMeh = (int?)(Math.Round(count100Estimate + count50Estimate) - countGood); } // If accuracy is between 16.67% and 25% - we assume that we have no 300s else if (relevantAccuracy >= 1.0 / 6) { // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c300 = 0 - double count100estimate = 6 * relevantResultCount * relevantAccuracy - relevantResultCount; + double count100Estimate = 6 * relevantResultCount * relevantAccuracy - relevantResultCount; // We only had 100s and 50s in that scenario so rest of the hits are 50s - double count50estimate = relevantResultCount - count100estimate; + double count50Estimate = relevantResultCount - count100Estimate; // Round it to get int number of 100s - countGood = (int?)Math.Round(count100estimate); + countGood = (int?)Math.Round(count100Estimate); // Get number of 50s as difference between total mistimed hits and count100 - countMeh = (int?)(Math.Round(count100estimate + count50estimate) - countGood); + countMeh = (int?)(Math.Round(count100Estimate + count50Estimate) - countGood); } // If accuracy is less than 16.67% - it means that we have only 50s or misses // Assuming that we removed misses in the 1st place - that means that we need to add additional misses to achieve target accuracy else { // Derived from the formula: Accuracy = (6 * c300 + 2 * c100 + c50) / (6 * totalHits), assuming that c300 = c100 = 0 - double count50estimate = 6 * relevantResultCount * relevantAccuracy; + double count50Estimate = 6 * relevantResultCount * relevantAccuracy; // We have 0 100s, because we can't start adding 100s again after reaching "only 50s" point countGood = 0; // Round it to get int number of 50s - countMeh = (int?)Math.Round(count50estimate); + countMeh = (int?)Math.Round(count50Estimate); // Fill the rest results with misses overwriting initial countMiss countMiss = (int)(totalResultCount - countMeh);