public CaptureLeaderBoard(OverlayData overlayData, CommentaryMessages commentaryMessages, RemovalEdits removalEdits) { this.overlayData = overlayData; this.captureLeaderBoardFirstLap = new CaptureLeaderBoardFirstLap(this, overlayData); this.captureLeaderBoardLastLap = new CaptureLeaderBoardLastLap(this, overlayData, commentaryMessages); this.captureLeaderBoardMiddleLaps = new CaptureLeaderBoardMiddleLaps(this, overlayData, removalEdits, commentaryMessages); }
internal OverlayData.LeaderBoard CreateLeaderBoard(DataSample data, TimeSpan relativeTime, OverlayData.Driver[] drivers) { var session = data.SessionData.SessionInfo.Sessions[data.Telemetry.SessionNum]; var timespan = raceStartTimeOffset == 0 ? TimeSpan.FromSeconds(session._SessionTime) : TimeSpan.FromSeconds(data.Telemetry.SessionTimeRemain + raceStartTimeOffset); var raceLapsPosition = string.Format("Lap {0}/{1}", data.Telemetry.RaceLaps, session.ResultsLapsComplete); var raceTimePosition = (timespan.TotalSeconds <= 0 ? TimeSpan.FromSeconds(0) : timespan).ToString(@"mm\:ss"); var raceLapCounter = string.Format("Lap {0}", data.Telemetry.RaceLaps); OverrideRacePositionDetails(data, session, ref raceLapsPosition, ref raceLapCounter); return new OverlayData.LeaderBoard { StartTime = relativeTime.TotalSeconds, Drivers = drivers, RacePosition = session.IsLimitedSessionLaps ? raceLapsPosition : raceTimePosition, LapCounter = session.IsLimitedSessionLaps ? null : raceLapCounter }; }
private void DrawCurrentDriverRow(Graphics g, OverlayData.Driver p) { var position = p.Position != null ? p.Position.Value.ToString() : ""; var indicator = p.Position != null ? p.Position.Value.Ordinal() : ""; var offset = 2; g.InRectangle(1920 / 2 - 440 / 2, 980, 70, 40) .WithBrush(Styles.YellowBrush) .WithPen(Styles.BlackPen) .DrawRectangleWithBorder() .WithFont(fontName, 24, FontStyle.Bold) .WithBrush(Styles.BlackBrush) .WithStringFormat(StringAlignment.Near) .Center(cg => cg .DrawText(position, topOffset: offset) .AfterText(position) .MoveRight(3) .WithFont(fontName, 18, FontStyle.Bold) .DrawText(indicator, topOffset: offset) ) .ToRight(width: 70) .WithLinearGradientBrush(Styles.White, Styles.WhiteSmoke, LinearGradientMode.BackwardDiagonal) .DrawRectangleWithBorder() .WithStringFormat(StringAlignment.Center) .WithBrush(Styles.BlackBrush) .DrawText(p.CarNumber, topOffset: offset) .ToRight(width: 300) .WithLinearGradientBrush(Styles.White, Styles.WhiteSmoke, LinearGradientMode.BackwardDiagonal) .DrawRectangleWithBorder() .WithStringFormat(StringAlignment.Center) .WithBrush(Styles.BlackBrush) .DrawText(p.UserName, topOffset: offset); }
void DrawLeaderboard(Graphics g, OverlayData.LeaderBoard sample, TimeSpan timeInSeconds) { var maxRows = sample.LapCounter == null ? 22 : 21; var showPitStopCount = timeInSeconds.Minutes % 3 == 0 && timeInSeconds.Seconds < 30 && sample.Drivers.Take(maxRows).Any(d => d.PitStopCount > 0); var r = g.InRectangle(80, 80, showPitStopCount ? 219 : 189, 35) .With(SimpleWhiteBox()) .DrawText(sample.RacePosition, topOffset: 3); if (sample.LapCounter != null) r = r.ToBelow() .With(SimpleWhiteBox()) .DrawText(sample.LapCounter, topOffset: 3); r = r.ToBelow(width: 36, height: 23); var headerSize = 12; var size = 17; var offset = 4; var n1 = r.With(ColourBox(Styles.LightYellow, headerSize)) .DrawText("Pos", topOffset: offset) .ToRight(width: 58) .With(SimpleWhiteBox(headerSize)) .DrawText("Num", topOffset: offset); if (showPitStopCount) n1 = n1.ToRight(width: 30) .With(SimpleWhiteBox(headerSize)) .DrawText("Pit", topOffset: offset); n1.ToRight(width: 95) .With(SimpleWhiteBox(headerSize)) .WithStringFormat(StringAlignment.Near) .DrawText("Name", leftOffset: 10, topOffset: offset); foreach (var d in sample.Drivers.Take(maxRows)) { r = r.ToBelow(width: 36, height: 32); var position = d.Position != null ? d.Position.Value.ToString() : ""; var n = r.With(ColourBox(Styles.LightYellow, size)) .DrawText(position, topOffset: offset) .ToRight(width: 58) .With(SimpleWhiteBox(size)) .DrawText(d.CarNumber, topOffset: offset); var pitStopCount = d.PitStopCount != 0 ? d.PitStopCount.ToString() : " "; if( showPitStopCount ) n = n.ToRight(width: 30) .With(SimpleWhiteBox(size)) .DrawText(pitStopCount, topOffset: offset); n.ToRight(width: 95) .With(SimpleWhiteBox(size)) .WithStringFormat(StringAlignment.Near) .DrawText(d.ShortName.ToUpper(), leftOffset: 10, topOffset: offset); } }
public void SetReplayConfig(OverlayData data) { this.data = data; }
public CommentaryMessages(OverlayData overlayData) { this.messageStates = overlayData.MessageStates; }
static OverlayData BuildData() { var result = new OverlayData(); result.SessionData = new SessionData { DriverInfo = new SessionData._DriverInfo { Drivers = Enumerable.Range(0, 24).Select( i => new SessionData._DriverInfo._Drivers { CarNumberRaw = i, CarNumber = i.ToString(), CarIdx = i, UserName = "******" + i.ToString(), }).ToArray() }, WeekendInfo = new SessionData._WeekendInfo { TrackDisplayName = "Mount Panorama Circuit", TrackCity = "Bathurst", TrackCountry = "Australia" }, SessionInfo = new SessionData._SessionInfo { Sessions = new[] { new SessionData._SessionInfo._Sessions { SessionType = "Open Qualify", ResultsPositions = Enumerable.Range(1, 22).Select( i => new iRacingSDK.SessionData._SessionInfo._Sessions._ResultsPositions { FastestTime = 127.02, Position = i, CarIdx = i }).ToArray() }, new SessionData._SessionInfo._Sessions { SessionType = "Race", ResultsPositions = Enumerable.Range(1, 22).Select( i => new iRacingSDK.SessionData._SessionInfo._Sessions._ResultsPositions { FastestTime = 127.02, Position = i, CarIdx = i, Time = i * 10 }).ToArray() } } } }; for (var i = 24.5; i < 30.0; i += 1.0 / 59.9) { if (i >= 20.0 && i < 21.0) { result.MessageStates.Add(new OverlayData.MessageState{ Time = 20d, Messages = new[] { "Message1" } }); } else if (i >= 21.0 && i < 23.0) { result.MessageStates.Add(new OverlayData.MessageState{Time = 21d, Messages = new[] { "Message1", "Message 2" }}); } else if (i >= 24.0 && i < 25.432454699999997) { result.MessageStates.Add(new OverlayData.MessageState{Time = 24d, Messages = new[] { "Message1", "Message 2", "Messages 3" }}); } else if (i >= 25.432454699999997 && i < 27.0) { result.MessageStates.Add(new OverlayData.MessageState{Time = 25.432454699999997d, Messages = new[] { "Message1", "Message 2", "Messages 3", "Messages 4" }}); } else if (i >= 27.0 && i < 28.0) { result.MessageStates.Add(new OverlayData.MessageState{Time = 27d, Messages = new[] { "Message 2", "Messages 3", "Messages 4", "Message 5" }}); } } result.FastestLaps = new List<OverlayData.FastLap>() { new OverlayData.FastLap() { StartTime = 10, Driver = new OverlayData.Driver { CarNumber = "888", UserName = "******" }, Time = TimeSpan.FromSeconds(65.345).TotalSeconds } }; result.LeaderBoards = new List<OverlayData.LeaderBoard>() { new OverlayData.LeaderBoard { LapCounter = "Lap 2", StartTime = 0, Drivers = Enumerable.Range(1, 21).Select( i => new OverlayData.Driver { CarNumber = "888", UserName = "******", Position = i, PitStopCount = i == 3 ? 1 : 0}).ToArray(), RacePosition = "39:34", } }; result.CamDrivers = new List<OverlayData.CamDriver>() { new OverlayData.CamDriver { StartTime = 0, CurrentDriver = new OverlayData.Driver { Position = 13, CarNumber = "888", UserName = "******" }, } }; return result; }
public SessionDataCapture(OverlayData overlayData) { this.overlayData = overlayData; }
string SaveOverlayData(OverlayData overlayData, List<CapturedVideoFile> files) { string firstFileName; if (files.Count == 0) firstFileName = workingFolder + "/unknown_capture-{0}".F(DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")); else firstFileName = files.First().FileName; var overlayFile = Path.ChangeExtension(firstFileName, ".replayscript"); Trace.WriteLine("Saving overlay data to {0}".F(overlayFile)); if (this.introVideo != null) files = new [] { new CapturedVideoFile { FileName = this.introVideo, isIntroVideo = true } } .Concat(files).ToList(); overlayData.VideoFiles = files; overlayData.SaveTo(overlayFile); return overlayFile; }
public CaptureCamDriver(OverlayData overlayData) { this.overlayData = overlayData; }
public static VideoDetails TestFor(OverlayData data) { return TestFor(data.VideoFiles.Last().FileName); }
public RecordFastestLaps(OverlayData overlayData) { this.overlayData = overlayData; }
void AssignDriverInstance(object driverInstance, OverlayData.Driver driver) { SetField(driverInstance, "CarNumber", driver.CarNumber); SetField(driverInstance, "UserName", driver.UserName); SetField(driverInstance, "PitStopCount", driver.PitStopCount); SetField(driverInstance, "ShortName", driver.ShortName); SetField(driverInstance, "Position", driver.Position); SetField(driverInstance, "DriverDetails", data.SessionData.DriverInfo.CompetingDrivers.FirstOrDefault(d => d.CarIdx == driver.CarIdx)); }
object CreateDriverInstance(Type driversDataType, OverlayData.Driver driver) { var driverInstance = Activator.CreateInstance(driversDataType); AssignDriverInstance(driverInstance, driver); return driverInstance; }
internal void _CaptureRaceTest(Action<string> onComplete, IEnumerable<DataSample> samples) { var overlayData = new OverlayData(); var removalEdits = new RemovalEdits(overlayData.RaceEvents); var commentaryMessages = new CommentaryMessages(overlayData); var videoCapture = new VideoCapture(); var recordPitStop = new RecordPitStop(commentaryMessages); var fastestLaps = new RecordFastestLaps(overlayData); var replayControl = new ReplayControl(samples.First().SessionData, incidents, removalEdits, TrackCameras); var sessionDataCapture = new SessionDataCapture(overlayData); var captureLeaderBoardEveryHalfSecond = new SampleFilter(TimeSpan.FromSeconds(0.5), new CaptureLeaderBoard(overlayData, commentaryMessages, removalEdits).Process); var captureCamDriverEveryQuaterSecond = new SampleFilter(TimeSpan.FromSeconds(0.25), new CaptureCamDriver(overlayData).Process); ApplyFirstLapCameraDirection(samples, replayControl); samples = samples .VerifyReplayFrames() .WithCorrectedPercentages() .WithCorrectedDistances() .WithFastestLaps() .WithFinishingStatus() .WithPitStopCounts() .TakeUntil(3.Seconds()).After(d => d.Telemetry.RaceCars.All(c => c.HasSeenCheckeredFlag || c.HasRetired || c.TrackSurface != TrackLocation.OnTrack)) .TakeUntil(3.Seconds()).AfterReplayPaused(); if (shortTestOnly) { samples = samples.AtSpeed(Settings.Default.TimingFactorForShortTest); Settings.AppliedTimingFactor = 1.0 / Settings.Default.TimingFactorForShortTest; } videoCapture.Activate(workingFolder); var startTime = DateTime.Now; foreach (var data in samples) { var relativeTime = DateTime.Now - startTime; replayControl.Process(data); sessionDataCapture.Process(data); captureLeaderBoardEveryHalfSecond.Process(data, relativeTime); captureCamDriverEveryQuaterSecond.Process(data, relativeTime); recordPitStop.Process(data, relativeTime); fastestLaps.Process(data, relativeTime); removalEdits.Process(data, relativeTime); } var files = videoCapture.Deactivate(); removalEdits.Stop(); var overlayFile = SaveOverlayData(overlayData, files); iRacing.Replay.SetSpeed(0); AltTabBackToApp(); if (files.Count == 0) throw new Exception("Unable to find video files in '{0}' - possible wrong working folder".F(workingFolder)); _WithOverlayFile(overlayFile); onComplete(overlayFile); }
static void SliceEvent(List<_RaceEvent> result, List<OverlayData.RaceEvent> raceEvents, OverlayData.RaceEvent left, OverlayData.RaceEvent right, int level = 1) { var middleTime = (left.EndTime + right.StartTime) / 2; var middleEvent = raceEvents .Where( r => r.StartTime >= left.StartTime && r.StartTime <= right.EndTime) .OrderBy(r => Math.Abs(middleTime - r.StartTime)).FirstOrDefault(); if( middleEvent == null ) return; result.Add(new _RaceEvent { RaceEvent = middleEvent, Level = level }); raceEvents.Remove(middleEvent); SliceEvent(result, raceEvents, left, middleEvent, level + 1); SliceEvent(result, raceEvents, middleEvent, right, level + 1); }
private static double ExtractUptoTargetDuration(List<OverlayData.RaceEvent> raceEvents, double duration, double targetDuration, OverlayData.RaceEvent firstEvent, OverlayData.RaceEvent lastEvent, List<_RaceEvent> orderRaceEvents, List<OverlayData.RaceEvent> result) { SliceEvent(orderRaceEvents, raceEvents.Where(rc => rc.WithOvertake /* && rc.Position == p*/).ToList(), firstEvent, lastEvent, 1); duration = SelectOrderByLevel(orderRaceEvents, targetDuration, result, duration); orderRaceEvents.Clear(); SliceEvent(orderRaceEvents, raceEvents.Where(rc => !rc.WithOvertake /*&& rc.Position == p */).ToList(), firstEvent, lastEvent, 1); duration = SelectOrderByLevel(orderRaceEvents, targetDuration, result, duration); orderRaceEvents.Clear(); return duration; }
private void DrawRaceMessages(Graphics g, double timeInSeconds, OverlayData.MessageState messageState) { Func<GraphicRect, GraphicRect> blueBox = rr => rr.WithBrush(Styles.TransparentLightBlueBrush) .WithPen(Styles.BlackPen) .DrawRectangleWithBorder() .WithBrush(Styles.BlackBrush) .WithFont(fontName, 20, FontStyle.Bold) .WithStringFormat(StringAlignment.Near); var shiftFactor = (double)Math.Min(timeInSeconds - messageState.Time, 1d); var offset = (int)(34 * shiftFactor); offset = offset + (messageState.Messages.Length - 1) * 34; var row4Top = 900 + 34 * 3; offset = row4Top - offset; var r = g.InRectangle(80, offset, 450, 34); g.SetClip(new Rectangle(80, 900, 450, 34 + 34 + 34)); foreach (var msg in messageState.Messages) r = r.With(blueBox) .DrawText(" " + msg) .ToBelow(); g.ResetClip(); }
public void SetReplayConfig(string filePath) { this.data = OverlayData.FromFile(filePath); }