Files
ft/CodexOutput/upserver/B3BatchMigration/M2/C2d修改前快照/087-EventPartnerStatuePlayfabData.cs.txt
Liubing\LB 6813da149a feat(upserver): 保存M2客户端KV迁移至本人统计写检查点
保存独立KV用户服务、固定会话存档与原业务接线,以及C3d资料缓存和C3e本人统计写。
保留原PF/AGG路线、业务公式和时序;榜单读取、好友资料、公告、匹配及首场景闸仍待完成。

验证:ServiceHost两条件各33组646断言;Unity CLI Loop编译0错误269警告。
包含相关方案、评审裁决、测试及状态文档。未操作服务器、正式账号或打包。
2026-09-30 19:19:05 +08:00

113 lines
4.4 KiB
Plaintext

using asap.core;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class EventPartnerStatuePlayfabData
{
readonly game.PlayerDataStorage.IPlayerSaveStore saveStore = GContext.container.Resolve<game.PlayerDataStorage.IPlayerSaveStore>();
public int EventId;
public int TicketCount;
public int BuffFreeMultiplier;
public DateTime BuffPointExpiryTime;
// public List<string> PartnerIdList;
public Dictionary<string, (int self, int partner)> DisplayScoreMap;
public Dictionary<string, (int self, int bot)> RobotScoreMap;
public bool IsFinalRewardClaimed;
public float LureInflationRate;
public bool IsEnableAutoMatch;
/// <summary>UTC 时间,开启自动匹配时记录;用于关闭时的 CD 与 Gather 活动一致。</summary>
public DateTime LastAutoMatchTimeUtc = DateTime.MinValue;
private const char Pipe = '|', Comma = ',';
public const string Key = "EventPartnerStatueData";
public string Serialized()
{
var sb = new StringBuilder();
sb.Append(EventId).Append(Pipe);
sb.Append(TicketCount).Append(Pipe);
sb.Append(BuffFreeMultiplier).Append(Pipe);
sb.Append(BuffPointExpiryTime.ToString()).Append(Pipe);
sb.Append(IsFinalRewardClaimed.ToString()).Append(Pipe);
sb.Append(LureInflationRate).Append(Pipe);
foreach (var kv in DisplayScoreMap)
sb.Append(kv.Key).Append(Comma).Append(kv.Value.self).Append(Comma).Append(kv.Value.partner).Append(Comma);
sb.Append(Pipe);
foreach (var kv in RobotScoreMap)
sb.Append(kv.Key).Append(Comma).Append(kv.Value.self).Append(Comma).Append(kv.Value.bot).Append(Comma);
sb.Append(Pipe);
sb.Append(IsEnableAutoMatch.ToString()).Append(Pipe);
sb.Append(LastAutoMatchTimeUtc.ToString("o"));
return sb.ToString();
}
/// <summary>
/// Will return null if deserialization failed
/// </summary>
/// <param name="s">String from playfab</param>
/// <returns>Playfab Data. Null if fails.</returns>
public static EventPartnerStatuePlayfabData Deserialize(string s)
{
try
{
var arr = s.Trim(Pipe).Split(Pipe);
var res = new EventPartnerStatuePlayfabData();
res.EventId = int.Parse(arr[0]);
res.TicketCount = int.Parse(arr[1]);
res.BuffFreeMultiplier = int.Parse(arr[2]);
res.BuffPointExpiryTime = DateTime.Parse(arr[3]);
res.DisplayScoreMap = new Dictionary<string, (int self, int partner)>();
res.RobotScoreMap = new Dictionary<string, (int self, int bot)>();
res.IsFinalRewardClaimed = bool.Parse(arr[4]);
res.LureInflationRate = float.Parse(arr[5]);
if (arr.Length <= 6)
return res;
if (!string.IsNullOrEmpty(arr[6]))
{
var displayScoreStringList = arr[6].Trim(Comma).Split(Comma);
for (int i = 0; i + 2 < displayScoreStringList.Length; i += 3)
res.DisplayScoreMap.Add(displayScoreStringList[i], (int.Parse(displayScoreStringList[i + 1]), int.Parse(displayScoreStringList[i + 2])));
}
if (arr.Length <= 7)
return res;
if (!string.IsNullOrEmpty(arr[7]))
{
var robotScoreStringList = arr[7].Trim(Comma).Split(Comma);
for (int i = 0; i + 2 < robotScoreStringList.Length; i += 3)
res.RobotScoreMap.Add(robotScoreStringList[i], (int.Parse(robotScoreStringList[i + 1]), int.Parse(robotScoreStringList[i + 2])));
}
if (arr.Length > 8)
res.IsEnableAutoMatch = bool.TryParse(arr[8], out var v) && v;
if (arr.Length > 9 && !string.IsNullOrEmpty(arr[9]) &&
DateTime.TryParse(arr[9], null, System.Globalization.DateTimeStyles.RoundtripKind, out var lastAm))
res.LastAutoMatchTimeUtc = lastAm;
return res;
}
catch (Exception e)
{
Debug.LogWarning(e);
return null;
}
}
public static EventPartnerStatuePlayfabData Load()
{
var s = GContext.container.Resolve<game.PlayerDataStorage.IPlayerSaveStore>().Read(Key).ValueOrThrow();
return Deserialize(s);
}
public void Save()
{
var s = Serialized();
saveStore.Write(Key, s).RequireAccepted();
}
}