Skip to content

Commit

Permalink
Lots of leaderboard and tracking fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
TheCrankLarson committed Aug 20, 2020
1 parent 6771987 commit 747c914
Show file tree
Hide file tree
Showing 15 changed files with 481 additions and 343 deletions.
135 changes: 91 additions & 44 deletions DataCollator/NotificationServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ class NotificationServer
private readonly object _notificationLock = new object();
private int _pruneCounter = 0;
private FileStream _logStream = null;
private Dictionary<Guid, EDRace> _races;

public NotificationServer(string ListenURL, bool EnableDebug = false)
{
if (EnableDebug)
_logStream = File.Open("stream.log", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
URi = ListenURL;
_races = new Dictionary<Guid, EDRace>();
_Listener = new HttpListener();

Start();
Expand Down Expand Up @@ -106,6 +108,14 @@ private void UpdateCommanderStatus(string status)
EDEvent updateEvent = EDEvent.FromJson(status);
if (String.IsNullOrEmpty(updateEvent.Commander))
return;

if (_races.Count > 0)
Task.Run(new Action(() =>
{
foreach (EDRace race in _races.Values)
race.UpdateStatus(updateEvent);
}));

if (!_commanderStatus.ContainsKey(updateEvent.Commander))
{
lock (_notificationLock)
Expand Down Expand Up @@ -170,21 +180,34 @@ public void ListenerCallback(IAsyncResult result)

using (StreamReader reader = new StreamReader(request.InputStream))
sRequest = reader.ReadToEnd();
string requestUri = request.RawUrl.ToLower();

Action action;
if (request.RawUrl.ToLower().StartsWith("/datacollator/status"))
if (requestUri.StartsWith("/datacollator/status"))
{
// This is a request for all known locations/statuses of clients
action = (() => {
SendStatus(context);
});
}
else if (request.RawUrl.ToLower().StartsWith("/datacollator/racestatus"))
else if (requestUri.StartsWith("/datacollator/racestatus"))
{
action = (() => {
SendRaceStatus(context);
});
}
else if (requestUri.StartsWith("/datacollator/startrace"))
{
action = (() => {
StartRace(sRequest, context);
});
}
else if (requestUri.StartsWith("/datacollator/getrace"))
{
action = (() => {
GetRace(sRequest, context);
});
}
else
action = (() => {
DetermineResponse(sRequest, context);
Expand All @@ -195,6 +218,63 @@ public void ListenerCallback(IAsyncResult result)
catch { }
}

private void WriteErrorResponse(HttpListenerResponse httpResponse, HttpStatusCode errorCode)
{
httpResponse.StatusCode = (int)errorCode;
httpResponse.ContentLength64 = 0;
httpResponse.Close();
}

private void WriteResponse(HttpListenerResponse httpResponse, string response)
{
try
{
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(response);
httpResponse.ContentLength64 = buffer.Length;
httpResponse.StatusCode = (int)HttpStatusCode.OK;

using (Stream output = httpResponse.OutputStream)
output.Write(buffer, 0, buffer.Length);
httpResponse.OutputStream.Flush();
httpResponse.KeepAlive = true;
httpResponse.Close();
}
catch { }
}

private void WriteResponse(HttpListenerContext Context, string response)
{
WriteResponse(Context.Response, response);
}

private void StartRace(string request, HttpListenerContext Context)
{
// Client has requested to start race monitoring. The request should be an EDRace json. We return a Guid

try
{
EDRace race = EDRace.FromString(request);
Guid raceId = Guid.NewGuid();
_races.Add(raceId, race);
race.StartRace(true);
WriteResponse(Context, raceId.ToString());
}
catch (Exception ex)
{
WriteResponse(Context,$"Error while initialising race: {ex.Message}");
}
}

private void GetRace(string request, HttpListenerContext Context)
{
Guid raceGuid = Guid.Empty;
Guid.TryParse(request, out raceGuid);
if (raceGuid != Guid.Empty && _races.ContainsKey(raceGuid))
WriteResponse(Context, _races[raceGuid].ToString());
else
WriteErrorResponse(Context.Response, HttpStatusCode.NotFound);
}

private void SendRaceStatus(HttpListenerContext Context)
{
StringBuilder racersStatus = new StringBuilder();
Expand All @@ -209,19 +289,7 @@ private void SendRaceStatus(HttpListenerContext Context)
racersStatus.AppendLine(ex.ToString());
}

try
{
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(racersStatus.ToString());
Context.Response.ContentLength64 = buffer.Length;
Context.Response.StatusCode = (int)HttpStatusCode.OK;

using (Stream output = Context.Response.OutputStream)
output.Write(buffer, 0, buffer.Length);
Context.Response.OutputStream.Flush();
Context.Response.KeepAlive = true;
Context.Response.Close();
}
catch { }
WriteResponse(Context, racersStatus.ToString());
}

private void SendStatus(HttpListenerContext Context)
Expand Down Expand Up @@ -249,30 +317,22 @@ private void SendStatus(HttpListenerContext Context)
Log("All player status requested");
foreach (string id in _playerStatus.Keys)
status.AppendLine(_playerStatus[id].ToJson());

}
else if (_playerStatus.ContainsKey(clientId))
{
Log($"Player status requested: {clientId}");
status.AppendLine(_playerStatus[clientId].ToJson());
}
else
{
Log($"Status requested for invalid client: {clientId}");
WriteErrorResponse(Context.Response, HttpStatusCode.NotFound);
return;
}
}

try
{
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(status.ToString());
Context.Response.ContentLength64 = buffer.Length;
Context.Response.StatusCode = (int)HttpStatusCode.OK;

using (Stream output = Context.Response.OutputStream)
output.Write(buffer, 0, buffer.Length);
Context.Response.OutputStream.Flush();
Context.Response.KeepAlive = true;
Context.Response.Close();
}
catch { }
WriteResponse(Context, status.ToString());
}

private void DetermineResponse(string Request, HttpListenerContext Context)
Expand Down Expand Up @@ -324,23 +384,10 @@ private void SendNotificationsToResponse(HttpListenerResponse Response, string C
Log($"{ClientId} - Sending notifications range {_clientNotificationPointer[ClientId]} to {newIndex}");
}
_clientNotificationPointer[ClientId] = newIndex; // Set the client index pointer


// Send the events to the response stream
try
{
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(notifications);
Response.ContentLength64 = buffer.Length;
Response.StatusCode = (int)HttpStatusCode.OK;
using (Response.OutputStream)
{
if (buffer.Length > 0)
Response.OutputStream.Write(buffer, 0, buffer.Length);
Response.OutputStream.Flush();
}
Response.Close();
}
catch { }
WriteResponse(Response, notifications);
}

private void PruneClients()
Expand Down
7 changes: 4 additions & 3 deletions EDTracking/EDRace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,16 @@ public void SaveToFile(string filename)
}
catch { }
}
public void StartRace()
public void StartRace(bool asServer)
{
if (_raceStarted)
return;
Start = DateTime.Now;
_statuses = new Dictionary<string, EDRaceStatus>();
foreach (string contestant in Contestants)
_statuses.Add(contestant, new EDRaceStatus(contestant, Route));
CommanderWatcher.UpdateReceived += CommanderWatcher_UpdateReceived;
if (!asServer)
CommanderWatcher.UpdateReceived += CommanderWatcher_UpdateReceived;
_raceStarted = true;
}

Expand Down Expand Up @@ -163,7 +164,7 @@ private List<string> RacePositions()
return positions;
}

private void UpdateStatus(EDEvent edEvent)
public void UpdateStatus(EDEvent edEvent)
{
if (_statuses != null)
if (_statuses.ContainsKey(edEvent.Commander))
Expand Down
19 changes: 8 additions & 11 deletions EDTracking/EDRaceStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public class EDRaceStatus
{
{ "Eliminated", "Eliminated" },
{ "Completed", "Completed" },
{ "Pitstop", "Pitstop" }
{ "Pitstop", "Pitstop" },
{ "Ready", "" }
};

public string _lastStatus = "";
Expand All @@ -50,7 +51,7 @@ public class EDRaceStatus
private StringBuilder _raceHistory = new StringBuilder();
private double _nextLogDistanceToWaypoint = double.MaxValue;
private EDLocation _speedCalculationLocation = null;
private DateTime _speedCalculationTimeStamp = DateTime.MinValue;
private DateTime _speedCalculationTimeStamp = DateTime.UtcNow;

public EDRaceStatus(EDEvent baseEvent)
{
Expand Down Expand Up @@ -186,22 +187,18 @@ public void UpdateStatus(EDEvent updateEvent)
if (updateEvent.HasCoordinates())
{
TimeSpan timeBetweenLocations = updateEvent.TimeStamp.Subtract(_speedCalculationTimeStamp);
if (timeBetweenLocations.TotalSeconds > 1)
if (timeBetweenLocations.TotalMilliseconds > 750)
{
// We take a speed calculation once per second
if (_speedCalculationLocation==null)
{
// We don't have a previous timestamp/location yet
_speedCalculationLocation = updateEvent.Location();
_speedCalculationTimeStamp = updateEvent.TimeStamp;
}
else
// We take a speed calculation once every 750 milliseconds
_speedCalculationTimeStamp = updateEvent.TimeStamp;
if (_speedCalculationLocation!=null)
{
double distanceBetweenLocations = EDLocation.DistanceBetween(_speedCalculationLocation, updateEvent.Location());
SpeedInMS = distanceBetweenLocations * (1000 / timeBetweenLocations.TotalMilliseconds);
if (SpeedInMS > MaxSpeedInMS)
MaxSpeedInMS = SpeedInMS;
}
_speedCalculationLocation = updateEvent.Location();
}
Location = updateEvent.Location();
if (WaypointIndex > 0)
Expand Down
Loading

0 comments on commit 747c914

Please sign in to comment.