1 using System;
2 
3 namespace TrainManager.Power
4 {
5 	/// <summary>An abstract acceleration curve</summary>
6 	public abstract class AccelerationCurve
7 	{
8 		/// <summary>Gets the acceleration output for this curve</summary>
9 		/// <param name="Speed">The current speed</param>
10 		/// <param name="Loading">A double between 0 (Unloaded) and 1.0 (Loaded) representing the load factor</param>
11 		/// <returns>The acceleration output</returns>
GetAccelerationOutput(double Speed, double Loading)12 		public abstract double GetAccelerationOutput(double Speed, double Loading);
13 
14 		/// <summary>Gets the maximum possible acceleration output for this curve</summary>
15 		// ReSharper disable once UnusedMemberInSuper.Global
16 		public abstract double MaximumAcceleration
17 		{
18 			get;
19 		}
20 	}
21 
22 	/// <summary>Represents a BVE2 / BVE4 format Acceleration Curve</summary>
23 	public class BveAccelerationCurve : AccelerationCurve
24 	{
25 		public double StageZeroAcceleration;
26 		public double StageOneSpeed;
27 		public double StageOneAcceleration;
28 		public double StageTwoSpeed;
29 		public double StageTwoExponent;
30 		public double Multiplier;
31 
GetAccelerationOutput(double Speed, double Loading)32 		public override double GetAccelerationOutput(double Speed, double Loading)
33 		{
34 			if (Speed <= 0.0)
35 			{
36 				return Multiplier * this.StageZeroAcceleration;
37 			}
38 
39 			if (Speed < this.StageOneSpeed)
40 			{
41 				double t = Speed / this.StageOneSpeed;
42 				return Multiplier * (this.StageZeroAcceleration * (1.0 - t) + this.StageOneAcceleration * t);
43 			}
44 
45 			if (Speed < this.StageTwoSpeed)
46 			{
47 				return Multiplier * this.StageOneSpeed * this.StageOneAcceleration / Speed;
48 			}
49 
50 			return Multiplier * this.StageOneSpeed * this.StageOneAcceleration * Math.Pow(this.StageTwoSpeed, this.StageTwoExponent - 1.0) * Math.Pow(Speed, -this.StageTwoExponent);
51 		}
52 
53 		public override double MaximumAcceleration => Math.Max(StageZeroAcceleration, StageOneAcceleration);
54 
Clone(double multiplier)55 		public BveAccelerationCurve Clone(double multiplier)
56 		{
57 			return new BveAccelerationCurve
58 			{
59 				StageZeroAcceleration = this.StageZeroAcceleration,
60 				StageOneSpeed = this.StageOneSpeed,
61 				StageOneAcceleration = this.StageOneAcceleration,
62 				StageTwoSpeed = this.StageTwoSpeed,
63 				StageTwoExponent = this.StageTwoExponent,
64 				Multiplier = multiplier
65 			};
66 		}
67 	}
68 
69 	public class BveDecelerationCurve : AccelerationCurve
70 	{
71 		private readonly double MaxDecelerationOutput;
72 
GetAccelerationOutput(double Speed, double Loading)73 		public override double GetAccelerationOutput(double Speed, double Loading)
74 		{
75 			return this.MaxDecelerationOutput;
76 		}
77 
78 		public override double MaximumAcceleration => MaxDecelerationOutput;
79 
BveDecelerationCurve(double Deceleration)80 		public BveDecelerationCurve(double Deceleration)
81 		{
82 			this.MaxDecelerationOutput = Deceleration;
83 		}
84 	}
85 }
86