Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(old chris code) Leaderboard Lightbeam and Stats PSDK thoughts #2884

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Linq;

namespace Beamable.Common.Dependencies
{
public static class BuilderExtensions
{

public static IDependencyBuilder AddSingletonDecorator<TImpl, TInterface, TDecorator>(this IDependencyBuilder builder, Func<TInterface, TDecorator> instanceFactory)
where TImpl : TInterface
where TDecorator : TInterface
{
if (!builder.Has<TImpl>())
builder.AddSingleton<TImpl>();

var singletons = builder.GetSingletonServices();
var entry = singletons.FirstOrDefault(x => x.Interface == typeof(TInterface));

builder.AddSingleton<TDecorator>(p =>
{
return instanceFactory((TInterface)entry.Factory(p));
});

builder.RemoveIfExists<TInterface>();
builder.AddSingleton<TInterface>(p => p.GetService<TDecorator>());
return builder;
}

}
}

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
using Beamable.Api.Autogenerated.Leaderboards;
using Beamable.Api.Autogenerated.Models;
using Beamable.Common;
using Beamable.Common.Content;
using Beamable.Common.Dependencies;
using System;

namespace Beamable.Api.Autogenerated.Leaderboards.Extensions
{
public static class DependencyExtensions
{

public static IDependencyBuilder AddLeaderboardDecorator<T>(this IDependencyBuilder builder, Func<ILeaderboardsApi, T> factory)
where T : LeaderboardsDecoratorApi
{
builder.AddSingletonDecorator<LeaderboardsApi, ILeaderboardsApi, T>(factory);
return builder;
}
}

public class LeaderboardsDecoratorApi : ILeaderboardsApi
{
private readonly ILeaderboardsApi _api;

public LeaderboardsDecoratorApi(ILeaderboardsApi api)
{
_api = api;
}

public virtual Promise<CommonResponse> ObjectDeleteEntries(string objectId)
{
throw new System.NotImplementedException();
}

public Promise<LeaderboardMembershipResponse> ObjectGetMembership(string objectId, long playerId)
{
throw new System.NotImplementedException();
}

public virtual Promise<LeaderBoardViewResponse> ObjectGetRanks(string ids, string objectId, bool includeAuthHeader = true)
{
return _api.ObjectGetRanks(ids, objectId, includeAuthHeader);
}

public Promise<LeaderboardPartitionInfo> ObjectGetPartition(string objectId, long playerId)
{
throw new System.NotImplementedException();
}

public virtual Promise<LeaderBoardViewResponse> ObjectGetFriends(string objectId)
{
return _api.ObjectGetFriends(objectId);
}

public Promise<CommonResponse> ObjectPost(string objectId, LeaderboardCreateRequest gsReq)
{
throw new System.NotImplementedException();
}

public Promise<CommonResponse> ObjectDelete(string objectId)
{
throw new System.NotImplementedException();
}

public Promise<MatchMakingMatchesPvpResponse> ObjectGetMatches(string objectId, int poolSize, int windowSize, int windows, bool includeAuthHeader = true)
{
throw new System.NotImplementedException();
}

public Promise<LeaderboardAssignmentInfo> ObjectGetAssignment(string objectId)
{
throw new System.NotImplementedException();
}

public Promise<CommonResponse> ObjectDeleteAssignment(string objectId, LeaderboardRemoveCacheEntryRequest gsReq)
{
throw new System.NotImplementedException();
}

public Promise<CommonResponse> ObjectPutEntry(string objectId, LeaderboardAddRequest gsReq, bool includeAuthHeader = true)
{
throw new System.NotImplementedException();
}

public Promise<CommonResponse> ObjectDeleteEntry(string objectId, LeaderboardRemoveEntryRequest gsReq)
{
throw new System.NotImplementedException();
}

public Promise<CommonResponse> ObjectPutFreeze(string objectId)
{
throw new System.NotImplementedException();
}

public Promise<LeaderboardDetails> ObjectGetDetails(string objectId, Optional<int> from = null, Optional<int> max = null)
{
throw new System.NotImplementedException();
}

public virtual Promise<LeaderBoardViewResponse> ObjectGetView(string objectId,
Optional<long> focus = null,
Optional<bool> friends = null,
Optional<int> from = null,
Optional<bool> guild = null,
Optional<int> max = null,
Optional<long> outlier = null,
bool includeAuthHeader = true)
{
return _api.ObjectGetView(objectId, focus, friends, from, guild, max, outlier, includeAuthHeader);
}

public Promise<CommonResponse> ObjectPutSwap(string objectId, LeaderboardSwapRequest gsReq)
{
throw new System.NotImplementedException();
}

public Promise<LeaderboardListResponse> GetList(Optional<int> limit = null, Optional<int> skip = null)
{
throw new System.NotImplementedException();
}

public Promise<ListLeaderBoardViewResponse> GetPlayer(long dbid)
{
throw new System.NotImplementedException();
}

public virtual Promise<LeaderboardAssignmentInfo> GetAssignment(string boardId, Optional<bool> joinBoard = null)
{
return _api.GetAssignment(boardId, joinBoard);
}

public Promise<LeaderboardUidResponse> GetUid()
{
throw new System.NotImplementedException();
}
}
}

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using Beamable.Api.Autogenerated.Models;
using Beamable.Common;
using Beamable.Common.Api;
using Beamable.Common.Pooling;
using Beamable.Serialization.SmallerJSON;
using UnityEngine;
using EmptyResponse = Beamable.Api.Autogenerated.Models.EmptyResponse;

namespace Beamable.Api.Autogenerated.Stats
{
public partial interface IStatsApi
{
// public Promise Write(bool isPublic);
Promise Write(bool isPublic, long playerId, StatUpdateTypedRequest request);
}

public partial class StatsApi
{
public async Promise Write(bool isPublic, long playerId, StatUpdateTypedRequest request)
{
// this.ObjectPostClient()
var objectId = $"client.{(isPublic ? "public" : "private")}.player.{playerId}";

string gsUrl = "/object/stats/{objectId}/client";
gsUrl = gsUrl.Replace("{objectId}", _requester.EscapeURL(objectId.ToString()));
// make the request and return the result

var dict = new ArrayDict();

dict[nameof(StatUpdateRequest.objectId)] = objectId;
dict[nameof(StatUpdateRequest.emitAnalytics)] = request.emitAnalytics.GetOrElse(false);

var addDict = new ArrayDict();
var setDict = new ArrayDict();
dict[nameof(StatUpdateRequest.add)] = addDict;
dict[nameof(StatUpdateRequest.set)] = setDict;

// handle all the adds
if (request.addLongs.HasValue)
{
foreach (var add in request.addLongs.Value)
{
addDict[add.Key] = add.Value;
}
}

// handle all the sets
if (request.setLongs.HasValue)
{
foreach (var set in request.setLongs.Value)
{
setDict[set.Key] = set.Value;
}
}
if (request.setStrings.HasValue)
{
foreach (var set in request.setStrings.Value)
{
setDict[set.Key] = set.Value;
}
}

using var sb = StringBuilderPool.StaticPool.Spawn();
var json = Json.Serialize(dict, sb.Builder);

Debug.Log("WRITING STATS " + json);
var _ = await _requester.Request<EmptyResponse>(Method.POST, gsUrl, json, true, this.Serialize<EmptyResponse>);
}
}
}

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using Beamable.Common.Content;
using Beamable.Serialization.SmallerJSON;
using System;
using System.Collections;
using UnityEngine.Serialization;

namespace Beamable.Api.Autogenerated.Models
{
[Serializable]
public partial class StatUpdateTypedRequest
{
public OptionalMapOfLong addLongs = new OptionalMapOfLong();
public OptionalBool emitAnalytics = new OptionalBool();
public OptionalMapOfLong setLongs = new OptionalMapOfLong();
public OptionalMapOfString setStrings = new OptionalMapOfString();
}

public partial class BatchReadStatsResponse
{
public BatchReadStatsPlayerResponseDictionary playerIdToStats = new BatchReadStatsPlayerResponseDictionary();
}

[Serializable]
public class
BatchReadStatsPlayerResponseDictionary : SerializableDictionary<long, BatchReadStatsPlayerResponse>
{

}

[Serializable]
public class BatchReadStatsPlayerResponse
{
public long id;
public SerializableDictionaryStringToLong longStats = new MapOfLong();
public SerializableDictionaryStringToBool boolStats = new MapOfBool();
public SerializableDictionaryStringToString stringStats = new MapOfString();
}
public class StatsBatchResponseSerializer : ICustomSerializer<BatchReadStatsResponse>
{


public BatchReadStatsResponse Deserialize(string data)
{
var x = Json.Deserialize(data) as ArrayDict;
var dict = new BatchReadStatsPlayerResponseDictionary();
var res = new BatchReadStatsResponse {playerIdToStats = dict};
if (!x.TryGetValue(nameof(BatchReadStatsResponse.results), out var results) || !(results is IList resultsList))
{
return res;
}

foreach (var elem in resultsList)
{
if (!(elem is ArrayDict elemDict)) continue;

if (!elemDict.TryGetValue("id", out var playerIdObject) || !(playerIdObject is long playerId)) continue;

if (!elemDict.TryGetValue("stats", out var statsObj) || !(statsObj is ArrayDict statsDict)) continue;

var playerStats = dict[playerId] = new BatchReadStatsPlayerResponse {id = playerId};
foreach (var statKvp in statsDict)
{
var valueObj = statKvp.Value;
var keyStr = statKvp.Key;

switch (valueObj)
{
case string stringStat:
playerStats.stringStats[keyStr] = stringStat;
break;
case long intStat:
playerStats.longStats[keyStr] = intStat;
break;
case bool boolStat:
playerStats.boolStats[keyStr] = boolStat;
break;
default:
break;
}

}
}
return res;
}

}
}

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

Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public static void RegisterOpenApis(IDependencyBuilder builder)
// ApiSchedulerJobNextExecutionsGetSchedulerResponse
// content requires special CSV parsing, and this allows us to inject an override.
builder.AddSingleton<ICustomSerializer<ClientManifestCsvResponse>, ClientManifestCsvResponseSerializer>();
builder.AddSingleton<ICustomSerializer<BatchReadStatsResponse>, StatsBatchResponseSerializer>();
builder.AddSingleton<ICustomSerializer<ApiSchedulerJobsGetSchedulerResponse>, ArrayResponseSerializer<ApiSchedulerJobsGetSchedulerResponse, JobDefinition>>();
builder.AddSingleton<ICustomSerializer<ApiSchedulerJobActivityGetSchedulerResponse>, ArrayResponseSerializer<ApiSchedulerJobActivityGetSchedulerResponse, JobActivity>>();
builder.AddSingleton<ICustomSerializer<ApiSchedulerJobNextExecutionsGetSchedulerResponse>, ArrayDateTimeResponseSerializer<ApiSchedulerJobNextExecutionsGetSchedulerResponse>>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ public virtual int GetBroadcastChecksum()
}
}

public abstract class AbsRefreshableObservable : DefaultObservable, IRefreshable
public abstract class AbsRefreshableObservable : AbsRefreshableObservableRoot
{

}

public abstract class AbsRefreshableObservableRoot : DefaultObservable, IRefreshable
{
/// <summary>
/// An event that happens when the <see cref="Refresh"/> method starts.
Expand Down
3 changes: 3 additions & 0 deletions client/Packages/com.beamable/Common/Runtime/Util.meta

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

13 changes: 13 additions & 0 deletions client/Packages/com.beamable/Common/Runtime/Util/BeamUtil.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Runtime.CompilerServices;

namespace Beamable.Common
{
public static class BeamUtil
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int CombineHashCodes(int h1, int h2)
{
return (((h1 << 5) + h1) ^ h2);
}
}
}