public void Calculate()
        {
            for (int i = 0; i < ExercisesStat.Length; i++)
            {
                var stat = ExercisesStat[i];
                var rank = HrustRequirements.GetRank(i + 1, stat.Record);
                stat.Rank = Rank.GetByIndex((int)rank);
                var requirement = HrustRequirements.GetRequirement(i + 1, rank);
                stat.IsCheated = requirement > 0 && stat.Record > requirement * 1.2 + 100;
            }

            ExercisesTotalMileage = ExercisesStat.Sum(x => x.Mileage);

            ExercisesRecordsSum = ExercisesStat.Where(x => !x.IsCheated).Sum(x => x.Record);

            TotalExercisesRank = Rank.GetByIndex(ExercisesStat.Min(x => x.Rank.Index));

            var nextRankNumber = TotalExercisesRank.Index + 1;

            if (nextRankNumber < 5)
            {
                nextRankNumber = 5;
            }

            Progress = ExercisesStat.Count(x => x.Rank.Index >= nextRankNumber);
        }
        public async Task <List <string> > UpdateHrustyashki()
        {
            Rank.SetMaxRank(Rank.Tachyon);
            List <string> filePaths       = new List <string>();
            const int     minTotalMileage = 3000;

            FileStream fs = new FileStream(xlsPath, FileMode.Open, FileAccess.Write);

            fs.Close();

            if (successService == null)
            {
                return(null);
            }

            await successService.UpdateSuccesses();

            List <User> users = successService.Successes.Where(x => x.TotalMileage >= minTotalMileage).OrderByDescending(x => x.TotalMileage).Select(x => new User(x.Id, x.Nick)).ToList();

            var threeLastVocs = HrustConstants.ModeIds.Skip(HrustConstants.ModeIds.Length - 3).ToList();
            var threeLastVocsRacerRequirements = Enumerable.Range(22, 3).Select(x => HrustRequirements.GetRequirement(x, HrustRank.Racer)).ToList();

            ModeStatSettings modeStatInput = new ModeStatSettings()
            {
                ModeIds = threeLastVocs, NeedPeriodStat = true
            };
            var tops = await topService.GetBulkTop(modeStatInput, Period.Week);

            for (int i = 1; i < tops.Count; i++)
            {
                var topPlayers = tops[i].Where(x => x.TopResult >= threeLastVocsRacerRequirements[i]);
                foreach (var player in topPlayers)
                {
                    if (!users.Any(x => x.Id == player.UserId))
                    {
                        users.Add(new User(player.UserId, ""));
                    }
                }
            }

            if (File.Exists(addPlayersPath))
            {
                var lines   = File.ReadAllLines(addPlayersPath, Encoding.UTF8);
                var players = lines.Select(x => int.TryParse(x, out int result) ? result : 0).Where(x => x > 0);

                foreach (var playerId in players)
                {
                    if (!users.Any(x => x.Id == playerId))
                    {
                        users.Add(new User(playerId, ""));
                    }
                }
            }

            List <HrustPlayer> results = await GetHrustResults(users);

            string hrTable = BuildTable(results);

            File.WriteAllText(txtPath, hrTable, Encoding.UTF8);

            // если что-то пошло не так, можно считать таблицу с txt файла
            //string HrTable = File.ReadAllText(txtPath, Encoding.UTF8);

            hrTable = hrTable.Replace('\t', ';').Replace(" / ", " / ");

            Excel.Application excelapp = new Excel.Application();
            excelapp.DisplayAlerts = false;
            string xlsBigPath = AppDomain.CurrentDomain.BaseDirectory + "\\" + xlsPath;

            Excel.Workbook excelworkbook = excelapp.Workbooks.Open(xlsBigPath, 0, false, 5,
                                                                   "", "", false, Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
            excelapp.Calculation = Excel.XlCalculation.xlCalculationManual;
            Excel.Worksheet wsh = (Excel.Worksheet)excelworkbook.Worksheets.get_Item("Статистика всех игроков");
            wsh.Activate();

            Excel.Range range1 = wsh.Range[wsh.Cells[5, 3], wsh.Cells[5, 3]];
            range1.Select();
            ClipboardService.SetText(hrTable);

            wsh.Paste();

            Excel.Range range2 = wsh.Range[wsh.Cells[5, 3], wsh.Cells[5 + results.Count - 1, 3]];
            range2.TextToColumns(
                range2,
                Excel.XlTextParsingType.xlDelimited,
                Excel.XlTextQualifier.xlTextQualifierNone,
                false,
                false,
                true
                );
            excelworkbook.Save();

            // Копирование картинок из Excel
            int firstPlaceRow = 4;
            int imageHeight   = 44; // lines
            int passed_24     = results.Count(x => x.TotalExercisesRank.Index >= 5);
            int passed_21_23  = results.Count(x => x.ExercisesStat.Count(y => y.Rank.Index >= 5) >= 21);
            int imageCounter  = 0;

            for (int stRow = firstPlaceRow - 1, endRow = 0;
                 endRow != firstPlaceRow + passed_21_23;
                 stRow += imageHeight)
            {
                if (stRow < firstPlaceRow + passed_24)
                {
                    endRow = stRow + imageHeight - 1;
                    if (endRow > passed_24 + firstPlaceRow)
                    {
                        endRow = firstPlaceRow + passed_24;
                    }
                }
                else
                {
                    stRow  = firstPlaceRow + passed_24 + 1;
                    endRow = firstPlaceRow + passed_21_23;
                }

                Excel.Range range3 = wsh.Range[wsh.Cells[stRow, 4], wsh.Cells[endRow, 38]];
                range3.Copy();
                Image image = ClipboardService.GetImage();

                // Обрезка изображения
                Bitmap    bmp      = new Bitmap(image);
                Rectangle cropArea = new Rectangle(1, 1, bmp.Width - 1, bmp.Height - 1);
                image = bmp.Clone(cropArea, bmp.PixelFormat);

                image.Save(++imageCounter + ".png", ImageFormat.Png);
                filePaths.Add(imageCounter + ".png");
            }

            excelworkbook.Close();
            excelapp.Quit();

            Rank.SetMaxRank(Rank.ExtraCyber);
            return(filePaths);
        }