Ejemplo n.º 1
0
        /// <summary>
        /// Check whether the entire board for specific deal can be scored
        /// </summary>
        /// <param name="dealNo">Deal number</param>
        private void checkScoring(long dealNo)
        {
            // Don't score as long as there are some unscored contracts
            foreach (KeyValuePair <Contract, long> scoreTable in this.scores[dealNo])
            {
                if (scoreTable.Value == long.MinValue)
                {
                    return;
                }
            }
            this.dealsScored++;
            // IMP scores for every contract in the traveller
            Dictionary <Contract, double> impScores = this.impScorer.scoreBoard(this.scores[dealNo]);

            foreach (KeyValuePair <Contract, double> result in impScores)
            {
                this.impScoreSums[result.Key] += result.Key.Frequency > 0 ? result.Value : 0;
            }
            // Matchpoint scores for every contract in the traveller
            Dictionary <Contract, double> maxScores = this.maxScorer.scoreBoard(this.scores[dealNo]);

            foreach (KeyValuePair <Contract, double> result in maxScores)
            {
                this.maxScoreSums[result.Key] += result.Key.Frequency > 0 ? result.Value : 0;
            }
            this.logScores(impScores, dealNo, Form1.GetResourceManager().GetString("ScoreAccumulator_IMP", Form1.GetCulture()));
            this.logScores(maxScores, dealNo, Form1.GetResourceManager().GetString("ScoreAccumulator_MP", Form1.GetCulture()));
            this.form.updateContractTable(this.trickSums, this.scoreSums, this.successSums, this.maxScoreSums, this.impScoreSums, this.dealsScored);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Returns user-readable summary of analysis
        /// </summary>
        /// <param name="full">Append matchpoint/IMP scores summary</param>
        /// <returns>Formatted log string</returns>
        protected override String getString(bool full = false)
        {
            String output = base.getString(full);

            if (full)
            {
                StringWriter sw = new StringWriter();
                sw.WriteLine();
                sw.WriteLine(Form1.GetResourceManager().GetString("ScoreAccumulator_vulnerability", Form1.GetCulture()) + ": {0}", this.vulnerabilities[this.vulnerability]);
                sw.WriteLine(Form1.GetResourceManager().GetString("ScoreAccumulator_txtHeader", Form1.GetCulture()));
                foreach (KeyValuePair <Contract, long> tricks in this.trickSums)
                {
                    double maxAv = this.maxScoreSums[tricks.Key] / this.dealsScored;
                    double impAv = this.impScoreSums[tricks.Key] / this.dealsScored;
                    if (tricks.Key.Declarer == Contract.DECLARER_EAST || tricks.Key.Declarer == Contract.DECLARER_WEST)
                    {
                        maxAv = 1.0 - maxAv;
                        impAv = -impAv;
                    }
                    sw.WriteLine(" {0,6} (x{1,3}) {2,5:0.00} {3,9:0.00} {6,5:0.00} {4,5:0.00} {5,7:0.00} ",
                                 this.getContractLogLine(tricks.Key), tricks.Key.Frequency,
                                 (double)tricks.Value / this.dealsScored, (double)this.scoreSums[tricks.Key] / this.dealsScored,
                                 maxAv, impAv,
                                 (double)this.successSums[tricks.Key] / this.dealsScored);
                }
                sw.Close();
                output += sw.ToString();
            }
            return(output);
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Sets the trump denomination.
 /// </summary>
 /// <param name="trumpSuit">Trump denomination, in numeric format.</param>
 public void setTrump(int trumpSuit)
 {
     if (trumpSuit < 0)
     {
         throw new Exception(Form1.GetResourceManager().GetString("BCalcWrapper_trumpError", Form1.GetCulture()) + ": " + trumpSuit);
     }
     BCalcWrapper.bcalcDDS_setTrumpAndReset(solver, trumpSuit);
     this.errorCheck();
     this.trumps = trumpSuit;
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Dealer wrapper class constructor.
 /// </summary>
 /// <param name="scriptname">Input script file name.</param>
 /// <param name="debugForm">Calling interface form.</param>
 /// <param name="produce">Number of deals to produce.</param>
 public DealerWrapper(String scriptname, Form1 debugForm, long produce)
 {
     if (!File.Exists(scriptname))
     {
         throw new Exception(Form1.GetResourceManager().GetString("DealerWrapper_errorFileNotFound", Form1.GetCulture()) + ": " + scriptname);
     }
     if (produce < 1)
     {
         throw new Exception(Form1.GetResourceManager().GetString("DealerWrapper_errorInvalidDealCount", Form1.GetCulture()));
     }
     this.scriptname = scriptname;
     this.debugForm  = debugForm;
     this.produce    = produce;
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Runs the single contract analysis.
        /// </summary>
        /// <param name="declarer">Declaring player, in numeric format.</param>
        /// <returns>Result structur for the contract.</returns>
        //TODO substitute from actual number of tricks to analyze, rather than 13, maybe.
        public BCalcResult run(int declarer)
        {
            if (declarer < 0)
            {
                throw new Exception(Form1.GetResourceManager().GetString("BCalcWrapper_declarerError", Form1.GetCulture()) + ": " + declarer);
            }
            int l = (declarer + 1) % 4;

            BCalcWrapper.bcalcDDS_setPlayerOnLeadAndReset(solver, l);
            this.errorCheck();
            int result = BCalcWrapper.bcalcDDS_getTricksToTake(this.solver);

            this.errorCheck();
            return(new BCalcResult(BCalcWrapper.denominations[this.trumps], BCalcWrapper.table[declarer], 13 - result, this.dealNo));
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Worker method for a single deal.
 /// </summary>
 /// <param name="deal">Deal in BCalc's "NESW" format, with deal number prepended.</param>
 private void analyzeDeal(String deal)
 {
     try
     {
         this.form.addStatusLine(deal);
         BCalcWrapper solver = new BCalcWrapper(deal);
         foreach (KeyValuePair <int, List <int> > row in this.contracts)
         {
             try
             {
                 solver.setTrump(row.Key);
             }
             catch (Exception ex)
             {
                 this.form.addStatusLine(Form1.GetResourceManager().GetString("Form1_error", Form1.GetCulture()) + ": " + ex.Message);
             }
             foreach (int entry in row.Value)
             {
                 try
                 {
                     BCalcResult result = solver.run(entry);
                     if (!this.abort)
                     {
                         String line = "#" + result.dealNo + ", " + result.declarer + " " +
                                       Form1.GetResourceManager().GetString("Accumulator_playsIn", Form1.GetCulture()) + " " + result.trumpSuit + ", " +
                                       Form1.GetResourceManager().GetString("Accumulator_tricks", Form1.GetCulture()) + ": " + result.tricks;
                         this.form.addStatusLine(line);
                         this.outputFile.WriteLine(line);
                         this.update(result);
                         this.form.setResult(this.getString());
                     }
                 }
                 catch (Exception ex)
                 {
                     this.form.addStatusLine(Form1.GetResourceManager().GetString("Form1_error", Form1.GetCulture()) + ": " + ex.Message);
                 }
             }
         }
         solver.destroy();
     }
     catch (Exception ex)
     {
         this.outputFile.WriteLine(ex.Message);
         this.form.addStatusLine(Form1.GetResourceManager().GetString("Form1_error", Form1.GetCulture()) + ": " + ex.Message);
     }
 }
Ejemplo n.º 7
0
 /// <summary>
 /// Callback method for worker threads, ends the single deal analysis, updates the total result and fires next analysis if necessary.
 /// </summary>
 /// <param name="methodResult">Method invokation result from the worker method.</param>
 private void endAnalyze(IAsyncResult methodResult)
 {
     ((Action <String>)methodResult.AsyncState).EndInvoke(methodResult);
     lock (this.threadLock)
     {
         bool finished = false;
         if (this.abort)
         {
             this.form.setProgress(0);
             this.form.addStatusLine(Form1.GetResourceManager().GetString("Accumulator_analysisInterrupted", Form1.GetCulture())
                                     + ": " + this.filename);
             finished = true;
         }
         else
         {
             this.threadsRunning--;
             this.analyzed++;
             this.form.setProgress((int)(100 * this.analyzed / this.toAnalyze));
             if (threadsRunning == 0 && this.deals.Count == 0)
             {
                 this.form.setProgress(100);
                 this.form.addStatusLine(Form1.GetResourceManager().GetString("Accumulator_analysisFinished", Form1.GetCulture())
                                         + ": " + this.filename);
                 finished = true;
             }
             if (threadsRunning < this.portionSize)
             {
                 // Increasing the parameter would cause exponential thread creation rate. Funny.
                 this.run(1);
             }
         }
         if (finished)
         {
             try
             {
                 this.outputFile.WriteLine(this.getString(true));
                 this.outputFile.Close();
             }
             catch (Exception) { };
             this.form.endAnalysis();
         }
     }
 }
Ejemplo n.º 8
0
 /// <summary>
 /// Constructor of class instance for single deal analysis.
 /// </summary>
 /// <param name="deal">Deal distribution prefixed with deal number.</param>
 public BCalcWrapper(String deal)
 {
     try
     {
         Match dealMatch = Regex.Match(deal, @"^(\d+): (.*)$");
         if (!dealMatch.Success)
         {
             throw new Exception();
         }
         this.deal   = dealMatch.Groups[2].Value;
         this.dealNo = Convert.ToInt64(dealMatch.Groups[1].Value);
     }
     catch (Exception)
     {
         throw new Exception(Form1.GetResourceManager().GetString("BCalcWrapper_dealLoadError", Form1.GetCulture()) + ": " + deal);
     }
     this.solver = BCalcWrapper.bcalcDDS_new(Marshal.StringToHGlobalAnsi(BCalcWrapper.table), Marshal.StringToHGlobalAnsi(this.deal), 0, 0);
     this.errorCheck();
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Accumulator constructor.
 /// </summary>
 /// <param name="deals">Array of deals to process, in BCalc's "NESW" format with prepended deal number for orientation.</param>
 /// <param name="contracts">List of denomination-declarer pairs (structures).</param>
 /// <param name="form">GUI instance.</param>
 public Accumulator(String[] deals, List <Contract> contracts, Form1 form)
 {
     this.deals = new Stack <String>(deals);
     if (this.deals.Count == 0)
     {
         throw new Exception(Form1.GetResourceManager().GetString("Accumulator_errorNoDeals", Form1.GetCulture()));
     }
     this.toAnalyze = deals.LongLength;
     this.form      = form;
     this.sums      = new Dictionary <int, Dictionary <int, long[]> >();
     for (int den = 0; den < BCalcWrapper.denominations.Length; den++)
     {
         this.sums.Add(den, new Dictionary <int, long[]>());
         for (int hand = 0; hand < BCalcWrapper.table.Length; hand++)
         {
             if (contracts.Contains(new Contract(den, hand)))
             {
                 this.sums[den].Add(hand, new long[] { 0, 0, 0 });
             }
             else
             {
                 this.sums[den].Add(hand, new long[] { -1, -1, 0 });
             }
         }
     }
     this.contracts = new Dictionary <int, List <int> >();
     foreach (Contract contract in contracts)
     {
         if (!this.contracts.ContainsKey(contract.Denomination))
         {
             this.contracts.Add(contract.Denomination, new List <int>());
         }
         this.contracts[contract.Denomination].Add(contract.Declarer);
     }
     this.filename   = Utils.getFilename("result");
     this.outputFile = TextWriter.Synchronized(File.AppendText(@"files\" + this.filename));
 }
Ejemplo n.º 10
0
 /// <summary>
 /// Handling single DD analysis result
 /// </summary>
 /// <param name="result">BCalc analysis result</param>
 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 <Contract, long>();
             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() + " " + Form1.GetResourceManager().GetString("Accumulator_tricks", Form1.GetCulture()) + ", " + 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;
                 if ((sC.Declarer == Contract.DECLARER_NORTH || sC.Declarer == Contract.DECLARER_SOUTH) != (score < 0)) // NS plays XOR negative score (NS plays and positive score or EW plays and negative score)
                 {
                     this.successSums[sC]++;
                 }
             }
         }
         // check if the entire board can already be scored
         this.checkScoring(result.dealNo);
     }
 }
Ejemplo n.º 11
0
        /// <summary>
        /// Loads the input script file and parses it. Parses out everything outside of predeal/condition/produce/generate/action sections.
        /// </summary>
        /// <param name="file">Filename of the script.</param>
        public void loadFile(String file)
        {
            String[] contents = File.ReadAllLines(file);
            Dictionary <String, int> keyLines = new Dictionary <String, int>();

            String[] keywords = { "predeal", "condition", "generate", "produce", "action" };
            for (int i = 0; i < contents.Length; i++)
            {
                String line   = contents[i];
                int    lineNo = Array.IndexOf(keywords, line.Trim());
                if (lineNo >= 0)
                {
                    keyLines.Add(keywords[lineNo], i);
                }
            }
            keyLines = keyLines.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
            for (int i = 0; i < keyLines.Count; i++)
            {
                KeyValuePair <String, int> keyline = keyLines.ElementAt(i);
                String[] section = new String[contents.Length - keyline.Value];
                if (i + 1 < keyLines.Count)
                {
                    Array.Copy(contents, keyline.Value, section, 0, keyLines.ElementAt(i + 1).Value - keyline.Value);
                }
                else
                {
                    Array.Copy(contents, keyline.Value, section, 0, contents.Length - keyline.Value);
                }
                section[0] = Regex.Replace(section[0], "^" + keyline.Key, "").Trim();
                section    = section.Where(str => str != null && str.Trim().Length > 0).ToArray();
                switch (keyline.Key)
                {
                case "predeal":
                    String[] players = { "north", "east", "south", "west" };
                    char[]   suits   = { 'S', 'H', 'D', 'C' };
                    foreach (String l in section)
                    {
                        String line   = l.Trim();
                        int    player = Array.IndexOf(players, line.Substring(0, line.IndexOf(' ')));
                        if (player >= 0)
                        {
                            String[] chunks = Regex.Replace(line, "^" + players[player], "").Split(',');
                            String[] hand   = new String[4];
                            foreach (String chunk in chunks)
                            {
                                int suit = Array.IndexOf(suits, chunk.Trim().ToUpper()[0]);
                                if (suit >= 0)
                                {
                                    hand[suit] = chunk.Trim().Substring(1);
                                }
                            }
                            this.predeal.Add(players[player], hand);
                        }
                    }
                    break;

                case "condition":
                    this.condition = section.Aggregate((a, b) => a + "\n" + b);
                    break;

                case "generate":
                    if (section.Length > 1)
                    {
                        throw new Exception(Form1.GetResourceManager().GetString("DealerParser_errorTooManyGenerate", Form1.GetCulture()));
                    }
                    if (section.Length == 1)
                    {
                        try
                        {
                            this.generate = Convert.ToInt64(section[0]);
                        }
                        catch (OverflowException)
                        {
                            throw new Exception(Form1.GetResourceManager().GetString("DealerParser_errorGenerateOverflow", Form1.GetCulture()));
                        }
                    }
                    break;

                case "produce":
                    if (section.Length > 1)
                    {
                        throw new Exception(Form1.GetResourceManager().GetString("DealerParser_errorTooManyProduce", Form1.GetCulture()));
                    }
                    if (section.Length == 1)
                    {
                        try
                        {
                            this.produce = Convert.ToInt64(section[0]);
                        }
                        catch (OverflowException)
                        {
                            throw new Exception(Form1.GetResourceManager().GetString("DealerParser_errorProduceOverflow", Form1.GetCulture()));
                        }
                    }
                    break;

                case "action":
                    Regex           pattern = new Regex(@"(?<comma>,)|(?<open>\()|(?<close>\))|(?<token>[^,\(\)]*)");
                    MatchCollection matches = pattern.Matches(section.Aggregate((a, b) => a + b));
                    List <String>   tokens  = new List <String>();
                    foreach (Match match in matches)
                    {
                        int groupNo = 0;
                        foreach (Group group in match.Groups)
                        {
                            if (group.Success && groupNo > 0)
                            {
                                tokens.Add(group.Value);
                            }
                            groupNo++;
                        }
                    }
                    int           open          = 0;
                    List <String> actions       = new List <String>();
                    String        currentAction = "";
                    foreach (String token in tokens)
                    {
                        switch (token)
                        {
                        case "(":
                            open++;
                            currentAction += token;
                            break;

                        case ")":
                            open--;
                            currentAction += token;
                            break;

                        case ",":
                            if (open == 0)
                            {
                                actions.Add(currentAction.Trim());
                                currentAction = "";
                            }
                            else
                            {
                                currentAction += token;
                            }
                            break;

                        default:
                            currentAction += token;
                            break;
                        }
                    }
                    actions.Add(currentAction.Trim());
                    this.actions = actions.Where(s => s.StartsWith("average")).ToList();
                    break;
                }
            }
        }