From 743f0b0113a000364eb5a568378fb7125121752e Mon Sep 17 00:00:00 2001 From: emkael Date: Tue, 23 Dec 2014 11:40:35 +0000 Subject: * scored contracts accumulator git-svn-id: https://svn.emkael.info/an9k@41 05ec0d5d-773b-4d93-9e23-c81a7ac79feb --- Analizator9000/Analizator9000/ScoreAccumulator.cs | 178 ++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 Analizator9000/Analizator9000/ScoreAccumulator.cs diff --git a/Analizator9000/Analizator9000/ScoreAccumulator.cs b/Analizator9000/Analizator9000/ScoreAccumulator.cs new file mode 100644 index 0000000..14d89a1 --- /dev/null +++ b/Analizator9000/Analizator9000/ScoreAccumulator.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Analizator9000 +{ + /// + /// Analysis accumulator for scoreing contracts + /// + class ScoreAccumulator : Accumulator + { + /// + /// Vulneraility setting of the analysis + /// + private int vulnerability; + /// + /// List of contracts coming from GUI table + /// + private List contractsToScore; + /// + /// Scores for the contracts + /// + private Dictionary> scores; + /// + /// Counter of deals already fully scored + /// + private long dealsScored = 0; + /// + /// Number of tricks accumulator + /// + private Dictionary trickSums; + /// + /// Sum of scores accumulator + /// + private Dictionary scoreSums; + /// + /// Matchpoint score accumulator + /// + private Dictionary maxScoreSums; + /// + /// IMP score accumulator + /// + private Dictionary impScoreSums; + /// + /// Scorer instance for matchpoints + /// + private IScorer maxScorer; + /// + /// Scorer instance for IMPs + /// + private IScorer impScorer; + /// + /// Constructor for score accumulator + /// + /// Base class parameter + /// Base class parameter (contracts for BCalc engine) + /// List of contracts in board traveller + /// Vulnerability setting for analysis + /// Base class parameter + public ScoreAccumulator(String[] deals, List contracts, List contractsToScore, int vulnerability, Form1 form) : base(deals, contracts, form) { + this.contractsToScore = contractsToScore; + this.vulnerability = vulnerability; + this.scores = new Dictionary>(); + this.trickSums = new Dictionary(); + this.scoreSums = new Dictionary(); + this.maxScoreSums = new Dictionary(); + this.maxScorer = new MaxScorer(); + this.impScoreSums = new Dictionary(); + this.impScorer = new ImpScorer(); + foreach (Contract sC in this.contractsToScore) + { + if (sC.Frequency > 0) + { + this.trickSums[sC] = 0; + this.scoreSums[sC] = 0; + this.maxScoreSums[sC] = 0; + this.impScoreSums[sC] = 0; + } + } + } + + /// + /// Handling single DD analysis result + /// + /// BCalc analysis result + protected override void update(BCalcResult result) { + base.update(result); + lock (this.contractsToScore) + { + if (!this.scores.Keys.Contains(result.dealNo)) // first time we see such deal, so we should initialize some stuff + { + this.scores[result.dealNo] = new Dictionary(); + foreach (Contract sC in this.contractsToScore) + { + this.scores[result.dealNo][sC] = sC.Level > 0 ? long.MinValue : 0; // All Pass contracts are already scored, other are set as "empty" (MinValue) + } + } + foreach (Contract sC in this.contractsToScore) + { + // if the analysis result matches the contract, to score, score it + if (sC.Level > 0 && BCalcWrapper.table[sC.Declarer] == result.declarer && BCalcWrapper.denominations[sC.Denomination] == result.trumpSuit) + { + int score = sC.getScore(result, this.vulnerability); + string logLine = "#" + result.dealNo.ToString() + ", " + this.getContractLogLine(sC) + ": " + result.tricks.ToString() + " lew, " + score.ToString(); + this.form.addStatusLine(logLine); + this.outputFile.WriteLine(logLine); + this.scores[result.dealNo][sC] = score; + this.trickSums[sC] += result.tricks; + this.scoreSums[sC] += score; + } + } + // check if the entire board can already be scored + this.checkScoring(result.dealNo); + } + } + + /// + /// Check whether the entire board for specific deal can be scored + /// + /// Deal number + private void checkScoring(long dealNo) + { + // Don't score as long as there are some unscored contracts + foreach (KeyValuePair scoreTable in this.scores[dealNo]) + { + if (scoreTable.Value == long.MinValue) + { + return; + } + } + this.dealsScored++; + // IMP scores for every contract in the traveller + Dictionary impScores = this.impScorer.scoreBoard(this.scores[dealNo]); + foreach (KeyValuePair result in impScores) + { + this.impScoreSums[result.Key] += result.Key.Frequency > 0 ? result.Value : 0; + } + // Matchpoint scores for every contract in the traveller + Dictionary maxScores = this.maxScorer.scoreBoard(this.scores[dealNo]); + foreach (KeyValuePair result in maxScores) + { + this.maxScoreSums[result.Key] += result.Key.Frequency > 0 ? result.Value : 0; + } + this.logScores(impScores, dealNo, "IMP"); + this.logScores(maxScores, dealNo, "max"); + this.form.updateContractTable(this.trickSums, this.scoreSums, this.maxScoreSums, this.impScoreSums, this.dealsScored); + } + + /// + /// Helper method for logging entire board scores + /// + /// Scored board + /// Deal number + /// Score suffix + private void logScores(Dictionary scores, long dealNo, string type) + { + foreach (KeyValuePair score in scores) { + string logLine = "#" + dealNo.ToString() + ", " + this.getContractLogLine(score.Key) + ": " + score.Value.ToString("0.##") + " " + type; + this.form.addStatusLine(logLine); + this.outputFile.WriteLine(logLine); + } + } + + /// + /// Generates human-readable representation of a contract (level, denomination, modifiers, declarer) + /// + /// Contract to transform + /// Representation of the contract, e.g. 3Hx N, PASS 1Nxx S, 7S E + private string getContractLogLine(Contract contract) + { + if (contract.Level == 0) + { + return "PASS"; + } + return contract.Level.ToString() + BCalcWrapper.denominations[contract.Denomination] + new String('x', contract.Modifiers) + " " + BCalcWrapper.table[contract.Declarer]; + } + } +} -- cgit v1.2.3