summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2014-12-22 17:27:32 +0000
committeremkael <emkael@tlen.pl>2014-12-22 17:27:32 +0000
commit78b88a41a23a2b4630ca82024664673559623b5a (patch)
tree3cc677f9ab04ee7c58accd09c99c6191d7b3e7f1
parentc113941d5b292a9d65954b0e4b640ffd025d0631 (diff)
* board scorers (matchpoint, IMPs)
git-svn-id: https://svn.emkael.info/an9k@38 05ec0d5d-773b-4d93-9e23-c81a7ac79feb
-rw-r--r--Analizator9000/Analizator9000/BaseScorer.cs65
-rw-r--r--Analizator9000/Analizator9000/IScorer.cs17
-rw-r--r--Analizator9000/Analizator9000/ImpScorer.cs44
-rw-r--r--Analizator9000/Analizator9000/MaxScorer.cs29
4 files changed, 155 insertions, 0 deletions
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
+{
+ /// <summary>
+ /// 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).
+ /// </summary>
+ abstract class BaseScorer : IScorer
+ {
+ public Dictionary<Contract, double> scoreBoard(Dictionary<Contract, long> scores)
+ {
+ Dictionary<Contract, double> result = new Dictionary<Contract, double>();
+ int scoreCount = 0;
+ foreach (KeyValuePair<Contract, long> 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<Contract, long> 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<Contract, long> score in scores)
+ {
+
+ result[score.Key] /= divisor;
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Scoring method for comparing two scores
+ /// </summary>
+ /// <param name="score1">Score to calculate the outcome</param>
+ /// <param name="score2">Score to compare to</param>
+ /// <returns>Score between two scores in the method used</returns>
+ protected abstract double getResultFromScores(long score1, long score2);
+
+ /// <summary>
+ /// Produces averaging factor for specified number of scores on a board
+ /// </summary>
+ /// <param name="scoreCount">Number of scores in the traveller</param>
+ /// <returns>Factor for score average division</returns>
+ 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
+{
+ /// <summary>
+ /// Interface for board scoring utilities
+ /// </summary>
+ interface IScorer
+ {
+ /// <summary>
+ /// Main method, takes dictionary of contract scores and calculates board scores for each contract
+ /// </summary>
+ /// <param name="scores">Dictionary of scored contracts</param>
+ /// <returns>Dictionary containing board scores for each contract</returns>
+ Dictionary<Contract, double> scoreBoard(Dictionary<Contract, long> 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
+{
+ /// <summary>
+ /// International Match Point scoring method
+ /// </summary>
+ class ImpScorer : BaseScorer
+ {
+ /// <summary>
+ /// Scoring method for IMPs
+ /// </summary>
+ /// <param name="score1">Score to calculate the outcome</param>
+ /// <param name="score2">Score to compare to</param>
+ /// <returns></returns>
+ 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;
+ }
+
+ /// <summary>
+ /// Averging method for IMPs
+ /// </summary>
+ /// <param name="scoreCount">Number of scores in the traveller</param>
+ /// <returns>Number of comparisons between scores for every score (n - 1)</returns>
+ 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
+{
+ /// <summary>
+ /// Matchpoint scoring method
+ /// </summary>
+ class MaxScorer : BaseScorer
+ {
+ /// <summary>
+ /// Scoring method for matchpoints
+ /// </summary>
+ /// <param name="score1">Score to calculate the outcome</param>
+ /// <param name="score2">Score to compare to</param>
+ /// <returns>2 matchpoints for a better score, no matchpoints for worse, 1 if scores are the same</returns>
+ override protected double getResultFromScores(long score1, long score2)
+ {
+ return score1 > score2 ? 2.0 : (score1 < score2 ? 0.0 : 1.0);
+ }
+
+ /// <summary>
+ /// Averaging method for matchpoints
+ /// </summary>
+ /// <param name="scoreCount">Number of scores in the traveller</param>
+ /// <returns>Maximum matchpoint score (2 * (n - 1))</returns>
+ protected override double getDivisorFromScoreCount(int scoreCount)
+ {
+ return 2.0 * (scoreCount - 1);
+ }
+ }
+}