public string CompleteLaps(List <string> commandArgs)
    {
        StringBuilder sb = new StringBuilder();

        int additionalLaps = int.Parse(commandArgs[0]);

        if (this.CurrentLap + additionalLaps > this.LapsNumber)
        {
            return($"There is no time! On lap {CurrentLap}.");
        }

        CurrentLap += additionalLaps;

        // complete the specified number of laps
        for (int i = 0; i < additionalLaps; i++)
        {
            foreach (Driver driver in Drivers)
            {
                try
                {
                    double lapTimeAddition = 60 / (this.TrackLength / driver.Speed);
                    driver.TotalTime += lapTimeAddition;
                    driver.Car.BurnFuel(driver.FuelConsumptionPerKm * TrackLength);
                    driver.Car.Tyre.ReduceDegradation();
                    driver.ParticipatedInOvertakingInCurrentRound = false;
                }
                catch (Exception ex)
                {
                    driver.FailureReason = ex.Message;
                    FailedDrivers.Add(driver);
                }
            }

            sb.AppendLine(CalculateOvertaking());

            Drivers.RemoveAll(x => !string.IsNullOrWhiteSpace(x.FailureReason));
        }

        return(sb.ToString());
    }
    private string CalculateOvertaking()
    {
        StringBuilder overtakingSb  = new StringBuilder();
        List <Driver> sortedDrivers = Drivers.OrderByDescending(x => x.TotalTime).ToList();

        for (int i = 0; i < Drivers.Count - 1; i++)
        {
            Driver firstDriver = sortedDrivers[0];

            if (!string.IsNullOrWhiteSpace(firstDriver.FailureReason))
            {
                continue;
            }

            Driver secondDriver = sortedDrivers[1];

            if (firstDriver.GetType() == typeof(AggressiveDriver) && firstDriver.Car.Tyre.GetType() == typeof(UltrasoftTyre))
            {
                if (this.Weather == "Foggy")
                {
                    firstDriver.FailureReason = "Crashed";
                    FailedDrivers.Add(firstDriver);
                    continue;
                }
            }

            if (firstDriver.GetType() == typeof(EnduranceDriver) && firstDriver.Car.Tyre.GetType() == typeof(HardTyre))
            {
                if (this.Weather == "Rainy")
                {
                    firstDriver.FailureReason = "Crashed";
                    FailedDrivers.Add(firstDriver);
                    continue;
                }
            }

            if (Math.Abs(firstDriver.TotalTime - secondDriver.TotalTime) <= 3)
            {
                if (firstDriver.GetType() == typeof(AggressiveDriver) && firstDriver.Car.Tyre.GetType() == typeof(UltrasoftTyre))
                {
                    firstDriver.TotalTime  -= 3;
                    secondDriver.TotalTime += 3;
                    overtakingSb.AppendFormat($"{firstDriver.Name} has overtaken {secondDriver.Name} on lap {this.CurrentLap}");
                    continue;
                }

                if (firstDriver.GetType() == typeof(EnduranceDriver) && firstDriver.Car.Tyre.GetType() == typeof(HardTyre))
                {
                    firstDriver.TotalTime  -= 3;
                    secondDriver.TotalTime += 3;
                    overtakingSb.AppendFormat($"{firstDriver.Name} has overtaken {secondDriver.Name} on lap {this.CurrentLap}");
                    continue;
                }
            }

            if (Math.Abs(firstDriver.TotalTime - secondDriver.TotalTime) <= 2)
            {
                firstDriver.TotalTime  -= 2;
                secondDriver.TotalTime += 2;
                overtakingSb.AppendFormat($"{firstDriver.Name} has overtaken {secondDriver.Name} on lap {this.CurrentLap}");
            }
        }

        Drivers.RemoveAll(x => !string.IsNullOrWhiteSpace(x.FailureReason));
        return(overtakingSb.ToString());
    }