internal void Calculate(ICalculator calculator)
        {
            Random random         = new Random(Options.SEED);
            int    iterationCount = GetRepeatCount();

            for (int iter = 0; iter < iterationCount; iter++)
            {
                int playerIndex = 0;
                int enemyIndex  = 0;
                IList <UnitSquad> playerSquads  = null;
                General           playerGeneral = null;
                IList <UnitSquad> enemySquads   = null;
                General           enemyGeneral  = null;
                int destroyEnemyCampTime        = 0;

                while (playerIndex < m_playerWaves.Count && enemyIndex < m_enemyWaves.Count)
                {
                    if (iterationCount == 1)
                    {
                        random = new Random(Options.SEED);
                    }

                    if (playerSquads == null)
                    {
                        playerSquads = new List <UnitSquad>();
                        foreach (UnitSquad squad  in m_playerWaves[playerIndex].Squads)
                        {
                            playerSquads.Add(new UnitSquad(squad.Unit, squad.Count));
                        }

                        playerGeneral = m_playerWaves[playerIndex].General;
                        bool emptyWave = true;
                        foreach (UnitSquad squad in playerSquads)
                        {
                            if (squad.Count > 0)
                            {
                                emptyWave = false;
                                break;
                            }
                        }

                        if (emptyWave)
                        {
                            playerSquads = null;
                            playerIndex++;
                            continue;
                        }
                    }

                    if (enemySquads == null)
                    {
                        enemySquads = new List <UnitSquad>();
                        foreach (UnitSquad squad in m_enemyWaves[enemyIndex].Squads)
                        {
                            enemySquads.Add(new UnitSquad(squad.Unit, squad.Count));
                        }
                        enemyGeneral         = m_enemyWaves[enemyIndex].General;
                        destroyEnemyCampTime = (int)m_enemyWaves[enemyIndex].DestroyCampTime;

                        bool emptyWave = true;
                        foreach (UnitSquad squad in enemySquads)
                        {
                            if (squad.Count > 0)
                            {
                                emptyWave = false;
                                break;
                            }
                        }

                        if (emptyWave)
                        {
                            enemySquads = null;
                            enemyIndex++;
                            continue;
                        }
                    }

                    Battle battle = new Battle(playerSquads, playerGeneral, enemySquads, enemyGeneral);
                    battle.PlayerTowerBonus   = m_playerWaves[playerIndex].TowerBonus;
                    battle.EnemyTowerBonus    = m_enemyWaves[enemyIndex].TowerBonus;
                    battle.WinBattleTime      = destroyEnemyCampTime;
                    battle.StatisticsType     = m_statisticsType;
                    calculator.IterationCount = GetBattleIterationCount();
                    Statistics.Statistics statistics = new Statistics.Statistics(battle);
                    calculator.OnBattleComplete += statistics.BattleComplete;
                    calculator.Calculate(battle, random);
                    calculator.OnBattleComplete -= statistics.BattleComplete;
                    if (m_waveCompleteHandler != null)
                    {
                        m_waveCompleteHandler(this, new MultiWaveBatleWaveCompleteArgs(new WaveKey(playerIndex, enemyIndex), statistics));
                    }

                    statistics.Calculate();
                    bool    empty          = true;
                    short[] defenderLosses = GetEnemyLosses(statistics);
                    int     i = 0;
                    int     j = 0;
                    while (i < defenderLosses.Length)
                    {
                        if (enemySquads[j].Count <= 0)
                        {
                            j++;
                            continue;
                        }

                        enemySquads[j].Count -= defenderLosses[i];
                        if (enemySquads[j].Count > 0)
                        {
                            empty = false;
                        }
                        i++;
                        j++;
                    }

                    if (empty)
                    {
                        enemySquads = null;
                        enemyIndex++;
                    }

                    bool enemyEmpty = empty;
                    empty = true;
                    short[] attackerLosses = GetPlayerLosses(statistics);
                    i = 0;
                    j = 0;
                    while (i < attackerLosses.Length)
                    {
                        if (playerSquads[j].Count <= 0)
                        {
                            j++;
                            continue;
                        }

                        playerSquads[j].Count -= attackerLosses[i];
                        if (playerSquads[j].Count > 0)
                        {
                            empty = false;
                        }
                        i++;
                        j++;
                    }

                    if (empty || !enemyEmpty)
                    {
                        playerSquads = null;
                        playerIndex++;
                    }
                }

                //iteration complete
                if (m_battleCompleteHandler != null)
                {
                    m_battleCompleteHandler(this, new EventArgs());
                }
            }
        }