add code for exporting historic races to a file.
this includes creating an export manager, file exporter interface (WIP) the History pages now use the Model to have a dynamic list of exporters based on plugins available through export manager. extended race session object to have FastestLap FastestPilotId and FastestPilotName.
This commit is contained in:
parent
80894ffe0d
commit
96e067153b
7
RaceLapTimer/Interfaces/ExportProviderDetails.cs
Normal file
7
RaceLapTimer/Interfaces/ExportProviderDetails.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Interfaces
|
||||
{
|
||||
public class ExportProviderDetails
|
||||
{
|
||||
public string Type { get; set; }
|
||||
}
|
||||
}
|
||||
14
RaceLapTimer/Interfaces/IExportManager.cs
Normal file
14
RaceLapTimer/Interfaces/IExportManager.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Interfaces
|
||||
{
|
||||
public interface IExportManager
|
||||
{
|
||||
List<IFileExporter> GetExporters();
|
||||
|
||||
Stream Export(string fileContent, string baseUrl);
|
||||
|
||||
List<ExportProviderDetails> GetExporterDetails();
|
||||
}
|
||||
}
|
||||
11
RaceLapTimer/Interfaces/IFileExporter.cs
Normal file
11
RaceLapTimer/Interfaces/IFileExporter.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Interfaces
|
||||
{
|
||||
public interface IFileExporter
|
||||
{
|
||||
Stream Export(string fileContent, string baseUrl);
|
||||
|
||||
ExportProviderDetails GetDetails();
|
||||
}
|
||||
}
|
||||
@ -40,10 +40,13 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ExportProviderDetails.cs" />
|
||||
<Compile Include="IConfigFilePathProvider.cs" />
|
||||
<Compile Include="IContainerHelper.cs" />
|
||||
<Compile Include="IDbProvider.cs" />
|
||||
<Compile Include="IExportManager.cs" />
|
||||
<Compile Include="ILoggerService.cs" />
|
||||
<Compile Include="IFileExporter.cs" />
|
||||
<Compile Include="IPluginInformation.cs" />
|
||||
<Compile Include="IPluginLocator.cs" />
|
||||
<Compile Include="IPluginPathProvider.cs" />
|
||||
|
||||
@ -16,5 +16,8 @@ namespace Interfaces
|
||||
public int TimePenaltyPerSatellite { get; set; }
|
||||
public bool HotSeatEnabled { get; set; }
|
||||
public int IdleTimeSeconds { get; set; }
|
||||
public double FastestLap { get; set; }
|
||||
public int FastestPilotId { get; set; }
|
||||
public string FastestPilotName { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,9 @@
|
||||
{
|
||||
public class SatelliteLog
|
||||
{
|
||||
public int RaceSessionId { get; set; }
|
||||
public int TransponderToken { get; set; }
|
||||
public int LapTimeMs { get; set; }
|
||||
public int UserId { get; set; }
|
||||
}
|
||||
}
|
||||
@ -7,10 +7,12 @@ namespace RaceLapTimer.ApiControllers
|
||||
public class SatelliteApiModule:NancyModule
|
||||
{
|
||||
private readonly IDbProvider _provider;
|
||||
public SatelliteApiModule(IDbProvider provider) : base("/api/satellite")
|
||||
private readonly ILoggerService _logger;
|
||||
|
||||
public SatelliteApiModule(IDbProvider provider, ILoggerService logger) : base("/api/v1/satellite")
|
||||
{
|
||||
_provider = provider;
|
||||
|
||||
_logger = logger;
|
||||
Get[""] = args => LogNewLapSatelliteTime();
|
||||
}
|
||||
|
||||
@ -23,6 +25,7 @@ namespace RaceLapTimer.ApiControllers
|
||||
TransponderToken = transponderToken,
|
||||
LapTimeMs = lapTimeMs
|
||||
};
|
||||
_logger.Trace("New Lap Time for Transponder Token: {0}. Lap Time: {1}", transponderToken, lapTimeMs);
|
||||
_provider.StoreTransponderLog(logObj);
|
||||
return HttpStatusCode.OK;
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Interfaces;
|
||||
using Nancy;
|
||||
using Nancy.Authentication.Forms;
|
||||
@ -6,8 +7,10 @@ using Nancy.Bootstrapper;
|
||||
using Nancy.Bootstrappers.Ninject;
|
||||
using Nancy.Conventions;
|
||||
using Nancy.Diagnostics;
|
||||
using Nancy.ViewEngines.Razor;
|
||||
using Ninject;
|
||||
using RaceLapTimer.Extensions;
|
||||
using RaceLapTimer.Extensions.FileExport;
|
||||
using RaceLapTimer.Extensions.Notifications;
|
||||
using RaceLapTimer.Extensions.SystemControl;
|
||||
using RaceLapTimer.Extensions.TransponderUtilities;
|
||||
@ -41,8 +44,22 @@ namespace RaceLapTimer
|
||||
container.Bind<ISystemControlManager>().To<SystemControlManager>().InSingletonScope();
|
||||
container.Bind<ITransponderUtilityManager>().To<TransponderUtilityManager>().InSingletonScope();
|
||||
|
||||
var tu = container.Get<ITransponderUtilityManager>();
|
||||
var id = tu.GetLastScannedId();
|
||||
//unused code, trying to get a friggin html to pdf converter working well. :(
|
||||
container.Bind<IExportManager>().To<FileExportManager>().InSingletonScope();
|
||||
|
||||
//var testHtml = "<html><body><img src=\"http://knockoutjs.com/img/ko-logo.png\" alt=\"Syncfusion_logo\" width=\"200\" height=\"70\"><p>Hello World</p></body></html>";
|
||||
//var tu = container.Get<IExportManager>();
|
||||
//var id = tu.Export(testHtml, "http://localhost:8800");
|
||||
//File.Delete("testpdf.pdf");
|
||||
//using (FileStream fs = new FileStream("testpdf.pdf", FileMode.CreateNew))
|
||||
//{
|
||||
// id.Seek(0, SeekOrigin.Begin);
|
||||
// id.CopyTo(fs);
|
||||
// id.Close();
|
||||
// id.Dispose();
|
||||
// fs.Flush(true);
|
||||
// fs.Close();
|
||||
//}
|
||||
}
|
||||
|
||||
protected override void ConfigureRequestContainer(IKernel container, NancyContext context)
|
||||
@ -98,4 +115,21 @@ namespace RaceLapTimer
|
||||
);
|
||||
}
|
||||
}
|
||||
public class RazorConfig : IRazorConfiguration
|
||||
{
|
||||
public IEnumerable<string> GetAssemblyNames()
|
||||
{
|
||||
yield return "Interfaces";
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetDefaultNamespaces()
|
||||
{
|
||||
yield return "Interfaces";
|
||||
}
|
||||
|
||||
public bool AutoIncludeModelNamespace
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Interfaces;
|
||||
|
||||
namespace RaceLapTimer.Extensions.FileExport
|
||||
{
|
||||
class FileExportManager:IExportManager
|
||||
{
|
||||
private readonly List<IFileExporter> _exporters;
|
||||
|
||||
public FileExportManager(IPluginLocator locator)
|
||||
{
|
||||
_exporters = locator.Locate<IFileExporter>();
|
||||
}
|
||||
|
||||
public List<IFileExporter> GetExporters()
|
||||
{
|
||||
return _exporters;
|
||||
}
|
||||
|
||||
public Stream Export(string fileContent, string baseUrl)
|
||||
{
|
||||
if(_exporters.Any())
|
||||
return _exporters.First().Export(fileContent, baseUrl);
|
||||
return new MemoryStream();
|
||||
}
|
||||
|
||||
public List<ExportProviderDetails> GetExporterDetails()
|
||||
{
|
||||
var ret = new List<ExportProviderDetails>();
|
||||
foreach (var exporter in _exporters)
|
||||
{
|
||||
ret.Add(exporter.GetDetails());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.IO;
|
||||
using Interfaces;
|
||||
using Nancy;
|
||||
using Nancy.Responses;
|
||||
using Nancy.ViewEngines;
|
||||
|
||||
namespace RaceLapTimer.Modules
|
||||
{
|
||||
public class HistoryModule:NancyModule
|
||||
{
|
||||
public HistoryModule():base("/history")
|
||||
private IContainerHelper _helper;
|
||||
public HistoryModule(IContainerHelper helper):base("/history")
|
||||
{
|
||||
_helper = helper;
|
||||
Get[""] = args => GetHistoryHomePage();
|
||||
Get["/pdf/{id}"] = args => GetPdfFile(args);
|
||||
}
|
||||
@ -34,14 +39,19 @@ namespace RaceLapTimer.Modules
|
||||
content = reader.ReadToEnd();
|
||||
}
|
||||
};
|
||||
var filePath = string.Empty;
|
||||
throw new NotImplementedException();
|
||||
return Response.AsFile(filePath);
|
||||
}
|
||||
|
||||
private dynamic GetHistoryHomePage()
|
||||
{
|
||||
dynamic model = new ExpandoObject();
|
||||
var eM = _helper.Get<IExportManager>();
|
||||
|
||||
model.ExportTypes = eM.GetExporterDetails();//new List<ExportProviderDetails> {new ExportProviderDetails {Type="PDF"} };
|
||||
|
||||
return View["HistoryIndex.cshtml"];
|
||||
return View["HistoryIndex.cshtml", model];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,6 +114,7 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Extensions\FileExport\FileExportManager.cs" />
|
||||
<Compile Include="Extensions\PluginLocator.cs" />
|
||||
<Compile Include="Extensions\SystemControl\SystemControlManager.cs" />
|
||||
<Compile Include="Extensions\TransponderUtilities\TransponderUtilityManager.cs" />
|
||||
|
||||
@ -9,6 +9,7 @@ namespace RaceLapTimer
|
||||
{
|
||||
private readonly List<Pilot> _pilots;
|
||||
private readonly List<RaceSession> _sessions;
|
||||
private readonly List<SatelliteLog> _transponderLogs;
|
||||
|
||||
public TestProvider()
|
||||
{
|
||||
@ -55,7 +56,7 @@ namespace RaceLapTimer
|
||||
#region Session 2
|
||||
new RaceSession
|
||||
{
|
||||
Active = true,
|
||||
Active = false,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
HotSeatEnabled = false,
|
||||
Id = 2,
|
||||
@ -114,6 +115,7 @@ namespace RaceLapTimer
|
||||
#endregion
|
||||
};
|
||||
#endregion
|
||||
_transponderLogs = new List<SatelliteLog>();
|
||||
}
|
||||
|
||||
public List<RaceSession> GetRaceSessions(bool getActive)
|
||||
@ -121,6 +123,11 @@ namespace RaceLapTimer
|
||||
return getActive ? _sessions.Where(x => x.Active == getActive).ToList() : _sessions;
|
||||
}
|
||||
|
||||
public RaceSession GetRaceSession(int id)
|
||||
{
|
||||
return _sessions.FirstOrDefault(x => x.Id == id);
|
||||
}
|
||||
|
||||
public bool CreateRaceSession(RaceSession session)
|
||||
{
|
||||
_sessions.Add(session);
|
||||
@ -209,7 +216,39 @@ namespace RaceLapTimer
|
||||
|
||||
public void StoreTransponderLog(SatelliteLog log)
|
||||
{
|
||||
//do nothing.
|
||||
var sessionId = GetCurrentRaceSessionId();
|
||||
var session = GetRaceSession(sessionId);
|
||||
log.RaceSessionId = sessionId;
|
||||
//Store the log..
|
||||
_transponderLogs.Add(log);
|
||||
// check fastest pilot!
|
||||
var fastestLapTime = GetFastestLapTimeMs(sessionId);
|
||||
var user = GetUserByTransponder(fastestLapTime.TransponderToken);
|
||||
session.FastestLap = fastestLapTime.LapTimeMs;
|
||||
session.FastestPilotId = user.Id;
|
||||
session.FastestPilotName = user.Name;
|
||||
}
|
||||
|
||||
private SatelliteLog GetFastestLapTimeMs(int sessionId)
|
||||
{
|
||||
var sessionLogs = _transponderLogs.Where(x => x.RaceSessionId == sessionId);
|
||||
sessionLogs = sessionLogs.OrderByDescending(x => x.LapTimeMs);
|
||||
var fastestLog = sessionLogs.First();
|
||||
return fastestLog;
|
||||
}
|
||||
|
||||
private int GetCurrentRaceSessionId()
|
||||
{
|
||||
var activeSessions = _sessions.Where(x => x.Active).ToList();
|
||||
if (activeSessions.Any() || activeSessions.Count > 1)
|
||||
return -1; //either dont have any, or have more than 1!!!
|
||||
var session = activeSessions.First();
|
||||
return session.Id;
|
||||
}
|
||||
|
||||
private Pilot GetUserByTransponder(int token)
|
||||
{
|
||||
return _pilots.FirstOrDefault(x => x.TransponderToken == token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<dynamic>
|
||||
|
||||
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<dynamic>
|
||||
@{
|
||||
Layout = "razor-layout.cshtml";
|
||||
ViewBag.Title = "History";
|
||||
@ -26,7 +27,25 @@
|
||||
<td class="text-center col-md-1 vertical-center">5</td>
|
||||
<td class="col-md-3 text-center">
|
||||
<button type="button" class="btn btn-warning" data-bind="click: $root.deleteSession">Delete</button>
|
||||
<button type="button" class="btn btn-default">Export as PDF</button>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
|
||||
@{ if (Model.ExportTypes == null || Model.ExportTypes.Count == 0)
|
||||
{
|
||||
@: disabled
|
||||
}
|
||||
}>
|
||||
Export <span class="caret"></span>
|
||||
</button>
|
||||
@if (Model.ExportTypes != null)
|
||||
{
|
||||
<ul class="dropdown-menu">
|
||||
@foreach (Interfaces.ExportProviderDetails eT in Model.ExportTypes)
|
||||
{
|
||||
<li><a data-bind="click: $root.CreateExport(id(), '@eT.Type')">@eT.Type</a></li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
<td class="vertical-center">
|
||||
<span data-bind="attr:{id:'expIcon'+id()}" class="glyphicon glyphicon-plus"></span>
|
||||
@ -48,8 +67,8 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td data-bind="text: maxLaps">12</td>
|
||||
<td>30.0s</td>
|
||||
<td>a pilot</td>
|
||||
<td data-bind="text: fastestLap()">30.0s</td>
|
||||
<td data-bind="text: fastestPilotName()">a pilot</td>
|
||||
<td>35.0s</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@ -15,4 +15,7 @@
|
||||
self.timePenaltyPerSatellite = ko.observable(data.timePenaltyPerSatellite);
|
||||
self.hotSeatEnabled = ko.observable(data.hotSeatEnabled);
|
||||
self.idleTimeSeconds = ko.observable(data.idleTimeSeconds);
|
||||
self.fastestLap = ko.observable(data.fastestLap);
|
||||
self.fastestPilotName = ko.observable(data.fastestPilotName);
|
||||
self.fastestPilotId = ko.observable(data.fastestPilotId);
|
||||
}
|
||||
@ -15,6 +15,10 @@
|
||||
});
|
||||
self.toggleIcon = function(e) {
|
||||
$(e).toggleClass("glyphicon-plus glyphicon-minus");
|
||||
}
|
||||
};
|
||||
self.CreateExport = function(sessionId, exportType) {
|
||||
console.log(sessionId);
|
||||
console.log(exportType);
|
||||
};
|
||||
};
|
||||
ko.applyBindings(new ViewModel());
|
||||
@ -93,7 +93,13 @@
|
||||
<PostBuildEvent>copy /B /Y "$(SolutionDir)UdpNotifier\$(OutDir)UdpNotifier.dll" "$(TargetDir)Plugins\UdpNotifier.dll"
|
||||
copy /B /Y "$(SolutionDir)IrDaemonNotifier\$(OutDir)IrDaemonNotifier.dll" "$(TargetDir)Plugins\IrDaemonNotifier.dll"
|
||||
copy /B /Y "$(TargetDir)NLogConfig.xml" "$(TargetDir)Configs\NLogConfig.xml"
|
||||
copy /B /Y "$(SolutionDir)RaceLapTimer\$(OutDir)Ninject.Extensions.Xml.dll" "$(TargetDir)Ninject.Extensions.Xml.dll"</PostBuildEvent>
|
||||
copy /B /Y "$(SolutionDir)RaceLapTimer\$(OutDir)Ninject.Extensions.Xml.dll" "$(TargetDir)Ninject.Extensions.Xml.dll"
|
||||
copy /B /Y "$(SolutionDir)PDFExporter\$(OutDir)PDFExporter.dll" "$(TargetDir)Plugins\PDFExporter.dll"
|
||||
copy /B /Y "$(SolutionDir)PDFExporter\$(OutDir).dll" "$(TargetDir)Plugins\PDFExporter.dll"
|
||||
copy /B /Y "$(SolutionDir)PDFExporter\$(OutDir)Syncfusion.HtmlConverter.Base.dll" "$(TargetDir)Syncfusion.HtmlConverter.Base.dll"
|
||||
copy /B /Y "$(SolutionDir)PDFExporter\$(OutDir)Syncfusion.Pdf.Base.dll" "$(TargetDir)Syncfusion.Pdf.Base.dll"
|
||||
copy /B /Y "$(SolutionDir)PDFExporter\$(OutDir)Syncfusion.Compression.Base.dll" "$(TargetDir)Syncfusion.Compression.Base.dll"
|
||||
copy /B /Y "$(SolutionDir)PDFExporter\$(OutDir)Microsoft.mshtml.dll" "$(TargetDir)Microsoft.mshtml.dll"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user