private static void InsertCardData(
            HtmlRenderer htmlWriter,
            string title,
            CardGameSubset gameSubset,
            MapOfCardsForGameSubset <ForwardAndReversePerTurnPlayerCounters> statsPerCard,
            ForwardAndReversePerTurnPlayerCounters turnCounts,
            int playerIndex,
            int throughTurn)
        {
            Card[]    cards       = gameSubset.OrderBy(card => card.DefaultCoinCost).ToArray();
            string[]  seriesLabel = new string[cards.Length];
            int[]     xAxis       = Enumerable.Range(1, throughTurn).ToArray();
            float[][] seriesData  = new float[cards.Length][];

            for (int i = 0; i < cards.Length; i++)
            {
                seriesLabel[i] = cards[i].name;
                seriesData[i]  = statsPerCard[cards[i]].forwardTotal.GetAveragePerTurn(playerIndex, throughTurn, turnCounts.forwardTotal);
            }

            htmlWriter.InsertExpander(title, delegate()
            {
                htmlWriter.InsertLineGraph(title, "Turn", seriesLabel, xAxis, seriesData);
            }, collapseByDefault: true);
        }
 // all of the objects are in fact JSON objects.
 public static object GetLineGraphOptions(
     string title,
     string player1Name,
     string player2Name,
     ForwardAndReversePerTurnPlayerCounters forwardAndReverseCounters,
     ForwardAndReversePerTurnPlayerCounters turnCounters,
     int throughTurn)
 {
     return GetLineGraphOptions(
         title,
         "Turn",
         player1Name,
         player2Name,
         Enumerable.Range(1, throughTurn).ToArray(),
         forwardAndReverseCounters.forwardTotal.GetAveragePerTurn(0, throughTurn, turnCounters.forwardTotal),
         forwardAndReverseCounters.forwardTotal.GetAveragePerTurn(1, throughTurn, turnCounters.forwardTotal));
 }
        private static void InsertLineGraph(
            HtmlRenderer htmlWriter,
            string title,
            PlayerAction player1,
            PlayerAction player2,
            ForwardAndReversePerTurnPlayerCounters forwardAndReverseCounters,
            ForwardAndReversePerTurnPlayerCounters turnCounters,
            int throughTurn,
            bool colllapsebyDefault     = true,
            HtmlContentInserter content = null)
        {
            if (forwardAndReverseCounters.forwardTotal.HasNonZeroData)
            {
                htmlWriter.InsertExpander(title, delegate()
                {
                    htmlWriter.InsertLineGraph(
                        title,
                        "Turn",
                        player1.PlayerName,
                        player2.PlayerName,
                        Enumerable.Range(1, throughTurn).ToArray(),
                        forwardAndReverseCounters.forwardTotal.GetAveragePerTurn(0, throughTurn, turnCounters.forwardTotal),
                        forwardAndReverseCounters.forwardTotal.GetAveragePerTurn(1, throughTurn, turnCounters.forwardTotal)
                        );
                    htmlWriter.InsertExpander("Counting back from the end of the Game ...", delegate()
                    {
                        htmlWriter.InsertLineGraph(
                            title,
                            "Turn",
                            player1.PlayerName,
                            player2.PlayerName,
                            Enumerable.Range(0, throughTurn).Select(turn => - turn).ToArray(),
                            forwardAndReverseCounters.reverseTotal.GetAveragePerTurn(0, throughTurn, turnCounters.reverseTotal),
                            forwardAndReverseCounters.reverseTotal.GetAveragePerTurn(1, throughTurn, turnCounters.reverseTotal)
                            );
                    });

                    if (content != null)
                    {
                        content();
                    }
                },
                                          collapseByDefault: colllapsebyDefault);
            }
        }
        protected object GetLineGraphData(
            StrategyComparisonResults comparisonResults,
            string title,
            ForwardAndReversePerTurnPlayerCounters counters)
        {
            if (!counters.forwardTotal.HasNonZeroData)
            {
                return null;
            }

            int maxTurn = comparisonResults.gameEndOnTurnHistogramData.GetXAxisValueCoveringUpTo(97);

            var options = GoogleChartsHelper.GetLineGraphOptions(
               "title",
               comparisonResults.comparison.playerActions[0].PlayerName,
               comparisonResults.comparison.playerActions[1].PlayerName,
               counters,
               comparisonResults.statGatherer.turnCounters,
               maxTurn);

            return options;
        }
        protected object GetLineGraphData(
            StrategyComparisonResults comparisonResults,
            string title,
            ForwardAndReversePerTurnPlayerCounters counters)
        {
            if (!counters.forwardTotal.HasNonZeroData)
            {
                return(null);
            }

            int maxTurn = comparisonResults.gameEndOnTurnHistogramData.GetXAxisValueCoveringUpTo(97);

            var options = GoogleChartsHelper.GetLineGraphOptions(
                "title",
                comparisonResults.comparison.playerActions[0].PlayerName,
                comparisonResults.comparison.playerActions[1].PlayerName,
                counters,
                comparisonResults.statGatherer.turnCounters,
                maxTurn);

            return(options);
        }
        public StatsPerTurnGameLog(int playerCount, CardGameSubset gameSubset)
        {
            this.turnCounters = new ForwardAndReversePerTurnPlayerCounters(playerCount);
            this.coinToSpend = new ForwardAndReversePerTurnPlayerCounters(playerCount);
            this.cardsGained = new ForwardAndReversePerTurnPlayerCounters(playerCount);
            this.ruinsGained = new ForwardAndReversePerTurnPlayerCounters(playerCount);
            this.cursesGained = new ForwardAndReversePerTurnPlayerCounters(playerCount);
            this.cursesTrashed = new ForwardAndReversePerTurnPlayerCounters(playerCount);
            this.victoryPointTotal = new ForwardAndReversePerTurnPlayerCounters(playerCount);
            this.deckShuffleCount = new ForwardAndReversePerTurnPlayerCounters(playerCount);
            this.oddsOfBeingAheadOnRoundEnd = new ForwardAndReversePerTurnPlayerCounters(playerCount);

            this.oddsOfHittingAtLeastACoinAmount = new ForwardAndReversePerTurnPlayerCounters[9];
            for (int i = 0; i < this.oddsOfHittingAtLeastACoinAmount.Length; ++i)
            {
                this.oddsOfHittingAtLeastACoinAmount[i] = new ForwardAndReversePerTurnPlayerCounters(playerCount);
            }

            this.cardGameSubset = gameSubset;

            this.cardsTotalCount = ContstructCounterPerTurn(playerCount, gameSubset);
            this.carsGainedOnTurn = ContstructCounterPerTurn(playerCount, gameSubset);
            this.endOfGameCardCount = ContstructCounter(playerCount, gameSubset);
        }
        private MapOfCardsForGameSubset<ForwardAndReversePerTurnPlayerCounters> ContstructCounterPerTurn(int playerCount, CardGameSubset gameSubset)
        {
            var result = new MapOfCardsForGameSubset<ForwardAndReversePerTurnPlayerCounters>(gameSubset);
            foreach (Card card in gameSubset)
            {
                result[card] = new ForwardAndReversePerTurnPlayerCounters(playerCount);
            }

            return result;
        }
        private static void InsertLineGraph(
            HtmlRenderer htmlWriter,
            string title,
            PlayerAction player1,
            PlayerAction player2,
            ForwardAndReversePerTurnPlayerCounters forwardAndReverseCounters,
            ForwardAndReversePerTurnPlayerCounters turnCounters,
            int throughTurn,
            bool colllapsebyDefault = true,
            HtmlContentInserter content = null)
        {
            if (forwardAndReverseCounters.forwardTotal.HasNonZeroData)
            {
                htmlWriter.InsertExpander(title, delegate()
                {
                    htmlWriter.InsertLineGraph(
                                title,
                                "Turn",
                                player1.PlayerName,
                                player2.PlayerName,
                                Enumerable.Range(1, throughTurn).ToArray(),
                                forwardAndReverseCounters.forwardTotal.GetAveragePerTurn(0, throughTurn, turnCounters.forwardTotal),
                                forwardAndReverseCounters.forwardTotal.GetAveragePerTurn(1, throughTurn, turnCounters.forwardTotal)
                                );
                    htmlWriter.InsertExpander("Counting back from the end of the Game ...", delegate()
                    {
                        htmlWriter.InsertLineGraph(
                                title,
                                "Turn",
                                player1.PlayerName,
                                player2.PlayerName,
                                Enumerable.Range(0, throughTurn).Select(turn => -turn).ToArray(),
                                forwardAndReverseCounters.reverseTotal.GetAveragePerTurn(0, throughTurn, turnCounters.reverseTotal),
                                forwardAndReverseCounters.reverseTotal.GetAveragePerTurn(1, throughTurn, turnCounters.reverseTotal)
                                );
                    });

                    if (content != null)
                    {
                        content();
                    }
                },
                collapseByDefault: colllapsebyDefault);
            }
        }
        private static void InsertCardData(
            HtmlRenderer htmlWriter,
            string title,
            CardGameSubset gameSubset,
            MapOfCardsForGameSubset<ForwardAndReversePerTurnPlayerCounters> statsPerCard,
            ForwardAndReversePerTurnPlayerCounters turnCounts,
            int playerIndex,
            int throughTurn)
        {
            Card[] cards = gameSubset.OrderBy(card => card.DefaultCoinCost).ToArray();
            string[] seriesLabel = new string[cards.Length];
            int[] xAxis = Enumerable.Range(1, throughTurn).ToArray();
            float[][] seriesData = new float[cards.Length][];

            for (int i = 0; i < cards.Length; i++)
            {
                seriesLabel[i] = cards[i].name;
                seriesData[i] = statsPerCard[cards[i]].forwardTotal.GetAveragePerTurn(playerIndex, throughTurn, turnCounts.forwardTotal);
            }

            htmlWriter.InsertExpander(title, delegate()
            {
                htmlWriter.InsertLineGraph(title, "Turn", seriesLabel, xAxis, seriesData);
            }, collapseByDefault: true);
        }