public static double NextGaussian(double mu = 0, double sigma = 1) { double x, u, v, s; if (isStored) { isStored = !isStored; return(prevGauss * sigma + mu); } do { u = 2 * StaticRandom.NextDouble() - 1; v = 2 * StaticRandom.NextDouble() - 1; s = u * u + v * v; } while (s >= 1 || s == 0); x = Math.Sqrt(-2 * Math.Log(s) / s); prevGauss = x * u; isStored = !isStored; return(x * v * sigma + mu); }
/// <summary> /// Вычисляет время прохождения отсечки k биатлонистом под номером curAthlete /// </summary> /// <param name="curSection">Текущая отсечка</param> /// <param name="curAthlete">Номер биатлониста</param> /// <returns>Возвращает время в формате TimeSpan</returns> private TimeSpan sectionPassTime(int curAthlete, int lap, int k) { double curSection = course.Sections[k]; double prevSection = course.Sections[k - 1]; int j = 1; int stamina; int gStamina = athletes[curAthlete].Stamina; double result = 0.0; double[] points = new double[course.Profile.Count]; course.Profile.Keys.CopyTo(points, 0); while (points[j] <= prevSection) { j++; } do { stamina = athletes[curAthlete].CurStamina; double speed = 0.0; double height = course.Profile[points[j]] - course.Profile[points[j - 1]]; // Вычисление коэффициента double tg = height / (points[j] - points[j - 1]); // наклона участка double length = Math.Min(points[j], curSection) - Math.Max(points[j - 1], prevSection); double rand = StaticRandom.RandGaussian(stamina / (double)gStamina * 0.12 + 0.94 + (lap - Laps / 2.0) / 50.0, 0.02); speed = rand * calcSpeed(athletes[curAthlete], tg) / 60; var time = results[curAthlete].TimeStamps[lap, k - 1].Value.TotalMinutes; if (stamina < 5) { speed -= speed / 10.0; } if (weather.Type.ToString().Contains("Frost")) { if (Type == RaceTypes.Individual || Type == RaceTypes.Sprint) { speed += (speed / 20.0) * (time + curAthlete * 0.5) / 100; } else { speed += (speed / 20.0) * time / 100; } } else if (weather.Type.ToString().Contains("Sun")) { if (Type == RaceTypes.Individual || Type == RaceTypes.Sprint) { speed -= (speed / 25.0) * (time + curAthlete * 0.5) / 100; } else { speed -= (speed / 25.0) * time / 100; } } else if (weather.Type.ToString().Contains("Rain")) { speed -= speed / 15.0; } speed *= StaticRandom.RandDouble(1, athletes[curAthlete].Skis.Quality / 100.0 + 1); athletes[curAthlete].Attributes.calculateStamina(tg, rand, length); /* * if (tg < -0.02) // * { // * speed = StaticRandom.NextDouble(0.99, 1.01) * // * athletes[curAthlete].Attributes.DescentSpeed / 60.0; // Вычисление скорости в км/мин * if ((2 * rand < stamina) && (stamina > 30)) // * { * //speedup = '+';// * rand = StaticRandom.NextDouble(); * speed += rand * speed / 20.0; // Ускорение с потерей * athletes[curAthlete].Attributes.Tired(rand * (-1 / tg) / 200, 0.1); // выносливости * } // * else // * athletes[curAthlete].Attributes.Rest(length); // Восстановление выносливости * if (stamina < 5) // * speed -= speed / 10.0; // При низкой выносливости - * } // снижение скорости * else // * if (tg > 0.02) // * { // * speed = StaticRandom.NextDouble(0.99, 1.01) * // * athletes[curAthlete].Attributes.AscentSpeed / 60.0; // Вычисление скорости в км/мин * if (2 * rand < stamina) // * { * //speedup = '+';// * rand = StaticRandom.NextDouble(); * speed += rand*speed / 20.0; // Ускорение с потерей * athletes[curAthlete].Attributes.Tired(rand * 2 * tg, length); // выносливости * } // * else // Стандартная потеря * athletes[curAthlete].Attributes.Tired(tg, length); // выносливости при подъеме * if (stamina < 5) // При низкой выносливости - * speed -= speed / 10.0; // снижение скорости * } // * else // * { // * speed = StaticRandom.NextDouble(0.99, 1.01) * // * athletes[curAthlete].Attributes.PlainSpeed / 60.0; // Вычисление скорости в км/мин * if (2 * rand < stamina) // * { * //speedup = '+';// * rand = StaticRandom.NextDouble(); * speed += rand * speed / 20.0; // Ускорение с потерей * athletes[curAthlete].Attributes.Tired(rand * tg, length); // выносливости * } // * if (stamina < 5) // При низкой выносливости - * speed -= speed / 10.0; // снижение скорости * } //*/ result += length / speed; // Вычисление времени // прохождения участка } while (points[j++] < curSection); delay(result * 1000); staminas.stamina[curAthlete, lap *(course.Sections.Length - 1) + k - 1] = athletes[curAthlete].CurStamina; return(TimeSpan.FromMinutes(result)); }
/// <summary> /// Вычисляет результат стрельбы и затраченное на неё время /// </summary> /// <param name="curLap">Текущий круг</param> /// <param name="curAthlete">Номер биатлониста</param> /// <returns>Возвращает время в формате TimeSpan</returns> private TimeSpan range(int curAthlete, int curLap) { int penaltyLaps = 0; double curAcc = 0.0; double curPrep = 0.0; double shootingSpeed = 0.0; double result = 0.0; double windVelocity = 0.0; double time = results[curAthlete].TimeStamps.Last(curLap).Value.TotalMinutes; if (type.Type == RaceTypes.Individual) { time -= results[curAthlete].Range.Misses(curLap); } if (RangeDistr[curLap] == 'p') { curAcc = athletes[curAthlete].ProneAccuracy; // Точность, скорость стрельбы curPrep = athletes[curAthlete].PronePreparation / 60.0; // (в секундах) shootingSpeed = athletes[curAthlete].ProneSpeed; // и время подготовки } // (в минутах) else // в зависимости от типа стрельбы { // curAcc = athletes[curAthlete].StandingAccuracy; // curPrep = athletes[curAthlete].StandingPreparation / 60.0; // shootingSpeed = athletes[curAthlete].StandingSpeed; // } result += curPrep; delay(curPrep * 1000 / 2); if (Type == RaceTypes.Individual || Type == RaceTypes.Sprint) // Вычисление силы ветра { time += curAthlete * 0.5; // в данный момент времени } for (int i = 0; i < 5; i++) { windVelocity = // Сила ветра во время weather.WindSpeed[(int)Math.Floor(time / 100 * weather.WindSpeed.Length)]; // выстрела double shotTime = (shootingSpeed / 5 + windVelocity * 0.5 * // Вычисление времени, (StaticRandom.RandDouble() - 0.25)) / 60.0; // затраченного на выстрел delay(shotTime * 1000); time += shotTime; double shotAcc = curAcc - Math.Pow(windVelocity / 10.0, 2) * // Вычисление точности стрельбы (1 - athletes[curAthlete].WindResistance / 100.0); // при данных ветровых условиях double a = StaticRandom.RandDouble(); // Вычисление попадания if (a < shotAcc) // и количества штрафных { results[curAthlete].Hit(curLap, i); // кругов } else // { penaltyLaps++; // } result += shotTime; } delay(curPrep * 1000 / 2); if (Type == RaceTypes.Individual) { time = penaltyLaps; } else { athletes[curAthlete].Attributes.calculateStamina(0, 1, penaltyLaps * penaltyLap / 1000); time = penaltyLaps * (penaltyLap / 1000 / (athletes[curAthlete].PlainSpeed / 60.0)); delay(time * 1000); } athletes[curAthlete].Attributes.Rest(0.2); result += time; return(TimeSpan.FromMinutes(result)); }