From 78b88a41a23a2b4630ca82024664673559623b5a Mon Sep 17 00:00:00 2001 From: emkael Date: Mon, 22 Dec 2014 17:27:32 +0000 Subject: * board scorers (matchpoint, IMPs) git-svn-id: https://svn.emkael.info/an9k@38 05ec0d5d-773b-4d93-9e23-c81a7ac79feb --- Analizator9000/Analizator9000/BaseScorer.cs | 65 +++++++++++++++++++++++++++++ Analizator9000/Analizator9000/IScorer.cs | 17 ++++++++ Analizator9000/Analizator9000/ImpScorer.cs | 44 +++++++++++++++++++ Analizator9000/Analizator9000/MaxScorer.cs | 29 +++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 Analizator9000/Analizator9000/BaseScorer.cs create mode 100644 Analizator9000/Analizator9000/IScorer.cs create mode 100644 Analizator9000/Analizator9000/ImpScorer.cs create mode 100644 Analizator9000/Analizator9000/MaxScorer.cs diff --git a/Analizator9000/Analizator9000/BaseScorer.cs b/Analizator9000/Analizator9000/BaseScorer.cs new file mode 100644 index 0000000..d291e47 --- /dev/null +++ b/Analizator9000/Analizator9000/BaseScorer.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; + +namespace Analizator9000 +{ + /// + /// Base scoring utility, for scoring methods which produce the board scores comparing all scores with each other and averaging over the results (e.g. matchpoints, Cavendish IMP). + /// + abstract class BaseScorer : IScorer + { + public Dictionary scoreBoard(Dictionary scores) + { + Dictionary result = new Dictionary(); + int scoreCount = 0; + foreach (KeyValuePair score in scores) + { + if (score.Key.Frequency > 0) + { + // Accumulating number of scores in a board + scoreCount += score.Key.Frequency; + result[score.Key] = 0; + foreach (KeyValuePair otherScore in scores) + { + if (score.Key != otherScore.Key) // all different scores are compared with the score + { + result[score.Key] += this.getResultFromScores(score.Value, otherScore.Value) * otherScore.Key.Frequency; + } + else // and all but one (the score we're calculating) from the same scores + { + result[score.Key] += this.getResultFromScores(score.Value, otherScore.Value) * (score.Key.Frequency - 1); + } + } + } + } + // Averaging every score by dividing by a certain factor + double divisor = this.getDivisorFromScoreCount(scoreCount); + if (divisor > 0) + { + foreach (KeyValuePair score in scores) + { + + result[score.Key] /= divisor; + } + } + return result; + } + + /// + /// Scoring method for comparing two scores + /// + /// Score to calculate the outcome + /// Score to compare to + /// Score between two scores in the method used + protected abstract double getResultFromScores(long score1, long score2); + + /// + /// Produces averaging factor for specified number of scores on a board + /// + /// Number of scores in the traveller + /// Factor for score average division + virtual protected double getDivisorFromScoreCount(int scoreCount) + { + return scoreCount; + } + } +} diff --git a/Analizator9000/Analizator9000/IScorer.cs b/Analizator9000/Analizator9000/IScorer.cs new file mode 100644 index 0000000..601a822 --- /dev/null +++ b/Analizator9000/Analizator9000/IScorer.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace Analizator9000 +{ + /// + /// Interface for board scoring utilities + /// + interface IScorer + { + /// + /// Main method, takes dictionary of contract scores and calculates board scores for each contract + /// + /// Dictionary of scored contracts + /// Dictionary containing board scores for each contract + Dictionary scoreBoard(Dictionary scores); + } +} diff --git a/Analizator9000/Analizator9000/ImpScorer.cs b/Analizator9000/Analizator9000/ImpScorer.cs new file mode 100644 index 0000000..83bef94 --- /dev/null +++ b/Analizator9000/Analizator9000/ImpScorer.cs @@ -0,0 +1,44 @@ +using System; +namespace Analizator9000 +{ + /// + /// International Match Point scoring method + /// + class ImpScorer : BaseScorer + { + /// + /// Scoring method for IMPs + /// + /// Score to calculate the outcome + /// Score to compare to + /// + protected override double getResultFromScores(long score1, long score2) + { + double result = 0.0; + long difference = Math.Abs(score1 - score2); // given the absolute difference between scores... + int[] thresholds = { 20, 50, 90, 130, 170, 220, 270, 320, 370, 430, 500, 600, 750, 900, 1100, 1300, 1500, 1750, 2000, 2250, 2500, 3000, 3500, 4000 }; + foreach (int t in thresholds) // ... add 1 IMP for every threshold that the difference is over + { + if (difference >= t) + { + result++; + } + } + if (score1 < score2) // if the score is worse, reverse the score + { + result = -result; + } + return result; + } + + /// + /// Averging method for IMPs + /// + /// Number of scores in the traveller + /// Number of comparisons between scores for every score (n - 1) + protected override double getDivisorFromScoreCount(int scoreCount) + { + return scoreCount - 1; + } + } +} diff --git a/Analizator9000/Analizator9000/MaxScorer.cs b/Analizator9000/Analizator9000/MaxScorer.cs new file mode 100644 index 0000000..8d3b8a9 --- /dev/null +++ b/Analizator9000/Analizator9000/MaxScorer.cs @@ -0,0 +1,29 @@ +namespace Analizator9000 +{ + /// + /// Matchpoint scoring method + /// + class MaxScorer : BaseScorer + { + /// + /// Scoring method for matchpoints + /// + /// Score to calculate the outcome + /// Score to compare to + /// 2 matchpoints for a better score, no matchpoints for worse, 1 if scores are the same + override protected double getResultFromScores(long score1, long score2) + { + return score1 > score2 ? 2.0 : (score1 < score2 ? 0.0 : 1.0); + } + + /// + /// Averaging method for matchpoints + /// + /// Number of scores in the traveller + /// Maximum matchpoint score (2 * (n - 1)) + protected override double getDivisorFromScoreCount(int scoreCount) + { + return 2.0 * (scoreCount - 1); + } + } +} -- cgit v1.2.3