Skip to content

Commit

Permalink
feat: Send basic usage statistics to Elympics
Browse files Browse the repository at this point in the history
  • Loading branch information
Dawid Sygocki committed Jul 14, 2023
1 parent 75ef8ce commit 15eed80
Show file tree
Hide file tree
Showing 18 changed files with 165 additions and 7 deletions.
3 changes: 3 additions & 0 deletions Editor/Communication.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Editor/Communication/UsageStatistics.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Editor/Communication/UsageStatistics/Models.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions Editor/Communication/UsageStatistics/Models/PlayRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

namespace Elympics.Editor.Models.UsageStatistics
{
[Serializable]
internal class PlayRequest
{
public string gameId;
public string mode;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions Editor/Communication/UsageStatistics/Models/Routes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Elympics.Editor.Models.UsageStatistics
{
public static class Routes
{
public const string Base = "hello";

public const string Start = "start";
public const string Play = "play";
public const string Stop = "stop";
}
}
3 changes: 3 additions & 0 deletions Editor/Communication/UsageStatistics/Models/Routes.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions Editor/Communication/UsageStatistics/Models/StartRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

namespace Elympics.Editor.Models.UsageStatistics
{
[Serializable]
internal class StartRequest
{
public string gameId;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions Editor/Communication/UsageStatistics/Models/StopRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

namespace Elympics.Editor.Models.UsageStatistics
{
[Serializable]
internal class StopRequest
{
public string gameId;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 45 additions & 0 deletions Editor/Communication/UsageStatistics/UsageStatisticsSender.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Globalization;
using Plugins.Elympics.Plugins.ParrelSync;
using UnityEditor;
using UnityEngine;

namespace Elympics.Editor.Communication.UsageStatistics
{
[InitializeOnLoad]
internal static class UsageStatisticsSender
{
private const string SessionStartKey = "Elympics/SessionStart";
private static readonly TimeSpan ComparisonEpsilon = TimeSpan.FromMinutes(1);

static UsageStatisticsSender()
{
if (ElympicsClonesManager.IsClone())
return;
OnAssemblyReload();
EditorApplication.quitting += OnQuitting;
}

private static void OnAssemblyReload()
{
var currentSessionStart = DateTime.UtcNow - TimeSpan.FromSeconds(EditorApplication.timeSinceStartup);
if (!HasBeenRestarted(currentSessionStart))
return;
ElympicsWebIntegration.PostStartEvent();
PlayerPrefs.SetString(SessionStartKey, currentSessionStart.ToString("o", CultureInfo.InvariantCulture));
}

private static bool HasBeenRestarted(DateTime currentSessionStart)
{
var serializedSessionStart = PlayerPrefs.GetString(SessionStartKey) ?? "";
if (!DateTime.TryParse(serializedSessionStart, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind,
out var savedSessionStart))
return true;
if (savedSessionStart - currentSessionStart > ComparisonEpsilon)
return true; // something's wrong - should reset
return currentSessionStart - savedSessionStart > ComparisonEpsilon;
}

private static void OnQuitting() => ElympicsWebIntegration.PostStopEvent();
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Editor/Config/ElympicsConfigEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
using UnityEngine;
using Object = UnityEngine.Object;

namespace Elympics
namespace Elympics.Editor
{
[CustomEditor(typeof(ElympicsConfig))]
public class ElympicsConfigEditor : Editor
public class ElympicsConfigEditor : UnityEditor.Editor
{
private SerializedProperty _currentGameIndex;
private SerializedProperty _availableGames;

private Object _lastChosenGamePropertyObject;
private Editor _lastChosenGameEditor;
private UnityEditor.Editor _lastChosenGameEditor;
private SerializedProperty _elympicsApiEndpoint;
private SerializedProperty _elympicsLobbyEndpoint;
private SerializedProperty _elympicsGameServersEndpoint;
Expand Down
4 changes: 2 additions & 2 deletions Editor/Config/ElympicsGameConfigEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
using UnityEditor.SceneManagement;
using UnityEngine;

namespace Elympics
namespace Elympics.Editor
{
[CustomEditor(typeof(ElympicsGameConfig))]
internal partial class ElympicsGameConfigEditor : Editor
internal partial class ElympicsGameConfigEditor : UnityEditor.Editor
{
private const int MaxTicks = 128;
private const int MinTicks = 1;
Expand Down
2 changes: 1 addition & 1 deletion Editor/Config/ElympicsGameConfigEditorLabels.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Elympics
namespace Elympics.Editor
{
internal partial class ElympicsGameConfigEditor
{
Expand Down
1 change: 1 addition & 0 deletions Editor/ElympicsEditorWebClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public static UnityWebRequestAsyncOperation SendJsonPostRequestApi(string url, o
var request = new UnityWebRequest(uri, UnityWebRequest.kHttpVerbPOST);
var bodyString = JsonUtility.ToJson(body);
var bodyRaw = Encoding.ASCII.GetBytes(bodyString);
request.timeout = 5; // TODO ~dsygocki 2023-07-15
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
request.downloadHandler = new DownloadHandlerBuffer();

Expand Down
48 changes: 47 additions & 1 deletion Editor/ElympicsWebIntegration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Linq;
using System.Text;
using System.Web;
using Elympics.Editor.Models.UsageStatistics;
using JetBrains.Annotations;
using Newtonsoft.Json;
using UnityEditor;
Expand All @@ -14,10 +15,11 @@
using GamesRoutes = ElympicsApiModels.ApiModels.Games.Routes;
using Regions = ElympicsApiModels.ApiModels.Regions.Routes;
using Routes = ElympicsApiModels.ApiModels.Users.Routes;
using UsageStatisticsRoutes = Elympics.Editor.Models.UsageStatistics.Routes;

namespace Elympics
{
public static class ElympicsWebIntegration
internal static class ElympicsWebIntegration
{
private const string PackFileName = "pack.zip";
private const string DirectoryNameToUpload = "Games";
Expand Down Expand Up @@ -290,6 +292,50 @@ void OnCompleted(UnityWebRequest webRequest)
}
}

public static void PostStartEvent()
{
var gameConfig = ElympicsConfig.LoadCurrentElympicsGameConfig();
PostTelemetryEvent(UsageStatisticsRoutes.Start, new StartRequest { gameId = gameConfig.GameId });
}

public static void PostPlayEvent(string mode)
{
var gameConfig = ElympicsConfig.LoadCurrentElympicsGameConfig();
PostTelemetryEvent(UsageStatisticsRoutes.Play, new PlayRequest
{
gameId = gameConfig.GameId,
mode = mode,
});
}

public static void PostStopEvent()
{
var gameConfig = ElympicsConfig.LoadCurrentElympicsGameConfig();
var requestBody = new StopRequest { gameId = gameConfig.GameId };
var uri = GetCombinedUrl(ElympicsWebEndpoint, UsageStatisticsRoutes.Base, UsageStatisticsRoutes.Stop);
var asyncOperation = ElympicsEditorWebClient.SendJsonPostRequestApi(uri, requestBody, auth: ElympicsConfig.IsLogin);
while (asyncOperation.isDone)
;
}

private static void PostTelemetryEvent(string pathSegment, object requestBody)
{
try
{
CheckAuthTokenAndRefreshIfNeeded(_ => OnContinuation());
}
catch (ElympicsException)
{
OnContinuation();
}

void OnContinuation()
{
var uri = GetCombinedUrl(ElympicsWebEndpoint, UsageStatisticsRoutes.Base, pathSegment);
_ = ElympicsEditorWebClient.SendJsonPostRequestApi(uri, requestBody, null, ElympicsConfig.IsLogin);
}
}

public static void BuildAndUploadGame(Action<UnityWebRequest> completed = null)
{
CheckAuthTokenAndRefreshIfNeeded(OnContinuation);
Expand Down

0 comments on commit 15eed80

Please sign in to comment.