public void Extend(AcShared previous, AcShared current, TimeSpan time) {
if (current == null) {
_offroad = false;
return;
}
if (previous == null || current.Graphics.Status != AcGameStatus.AcLive) {
CurrentStatus = Status.NotLive;
return;
}
var physics = current.Physics;
var graphics = current.Graphics;
var info = current.StaticInfo;
if (CarId == null) {
CarId = info.CarModel;
TrackId = string.IsNullOrWhiteSpace(info.TrackConfiguration) ? info.Track :
$@"{info.Track}/{info.TrackConfiguration}";
Penalties = info.PenaltiesEnabled == 1;
}
_coordinates = graphics.CarCoordinates;
if (graphics.CurrentTimeMs < previous.Graphics.CurrentTimeMs) {
CurrentStatus = Status.Teleported;
return;
}
var distance = graphics.CarCoordinates - previous.Graphics.CarCoordinates;
var calcSpeed = distance.Length() / 1e3 / time.TotalHours;
if (graphics.IsInPit || physics.NumberOfTyresOut > OptionTyresOutsideAllowed) {
_lapSpoiledId = graphics.CompletedLaps;
}
/* best lap */
if (graphics.CompletedLaps != _completedLaps) {
if (graphics.LastTimeMs == 0) {
Logging.Debug("Lap time: 0");
} else if (graphics.CompletedLaps - 1 > _lapSpoiledId) {
var lastTime = TimeSpan.FromMilliseconds(graphics.LastTimeMs);
if (!BestLap.HasValue || lastTime <= BestLap) {
BestLap = lastTime;
BestLapId = graphics.CompletedLaps - 1;
Logging.Debug("New lap time: " + lastTime.ToProperString());
} else {
Logging.Debug("Lap time is worse or the same");
}
} else {
Logging.Debug("Lap spoiled");
}
_completedLaps = graphics.CompletedLaps;
}
if (distance.Y < OptionFallingThreshold) {
CurrentStatus = Status.Falling;
return;
}
var paused = physics.SpeedKmh > 5 && calcSpeed < physics.SpeedKmh * 0.1d;
if (paused) {
CurrentStatus = Status.Paused;
return;
}
var jumped = calcSpeed > physics.SpeedKmh * 3d + 10;
if (jumped) {
CurrentStatus = Status.Teleported;
return;
}
for (var i = 0; i < 4; i++) {
var d = previous.Physics.TyreWear[i] - physics.TyreWear[i];
if (d > 0 && d < 0.1) {
/* TyreWear’ range is from 0.0 to 100.0 */
TotalTyreWear += d / 100d;
}
}
for (var i = 0; i < 5; i++) {
var d = physics.CarDamage[i] - previous.Physics.CarDamage[i];
if (d > 0.1 && (DateTime.Now - _crashTime).TotalSeconds > 5d) {
TotalCrashes++;
_crashTime = DateTime.Now;
}
}
/* offroad counter */
if (_offroad) {
_offroad = physics.NumberOfTyresOut > 0;
} else if (physics.NumberOfTyresOut > 3) {
_offroad = true;
if ((DateTime.Now - _offroadTime).TotalSeconds > 10) {
GoneOffroad++;
_offroadTime = DateTime.Now;
}
}
if (physics.SpeedKmh > OptionMinSpeedKmh) {
/* status */
var slip = physics.WheelSlip;
var prev = previous.Physics.WheelSlip;
var e0 = Equals(slip[0], prev[0]);
var e1 = Equals(slip[1], prev[1]);
var e2 = Equals(slip[2], prev[2]);
var e3 = Equals(slip[3], prev[3]);
if (e0 && e1) {
if (e2 && e3) {
CurrentStatus = Status.Airborne;
} else if (!e2 && !e3) {
CurrentStatus = Status.Wheelie;
} else {
CurrentStatus = Status.Live;
}
} else if (e0 && e2 && !e3 || e1 && e3 && !e2) {
CurrentStatus = Status.TwoWheels;
} else {
CurrentStatus = Status.Live;
}
/* max speed, driven distance and time */
if (physics.SpeedKmh > MaxSpeed) MaxSpeed = physics.SpeedKmh;
Distance += distance.Length();
Time += time;
/* burnt fuel */
var fuel = previous.Physics.Fuel - current.Physics.Fuel;
if (fuel > 0 && fuel < 0.05) {
FuelBurnt += fuel;
}
} else {
CurrentStatus = Status.Live;
}
}
}