1
0
mirror of synced 2024-09-24 11:28:24 +02:00

Refactor reward tracking

This commit is contained in:
asesidaa 2022-09-14 16:50:06 +08:00
parent 0fa5dcc2b4
commit fafb353bdb
8 changed files with 146 additions and 115 deletions

View File

@ -1 +1 @@
wwwroot/music_attribute.json wwwroot/data/music_attribute.json

View File

@ -35,4 +35,6 @@ public static class Constants
public const int COSTUME_FLAG_3_ARRAY_SIZE = 156; public const int COSTUME_FLAG_3_ARRAY_SIZE = 156;
public const int COSTUME_FLAG_4_ARRAY_SIZE = 58; public const int COSTUME_FLAG_4_ARRAY_SIZE = 58;
public const int COSTUME_FLAG_5_ARRAY_SIZE = 129; public const int COSTUME_FLAG_5_ARRAY_SIZE = 129;
public static readonly int[] CostumeFlagArraySizes = {154, 140, 156, 58, 129};
} }

View File

@ -1,4 +1,5 @@
using System.Collections.Specialized; using System.Collections;
using System.Collections.Specialized;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace TaikoLocalServer.Common.Utils; namespace TaikoLocalServer.Common.Utils;
@ -106,4 +107,22 @@ public static class FlagCalculator
gotDanFlagList.Add(gotDanFlag.Data); gotDanFlagList.Add(gotDanFlag.Data);
return MemoryMarshal.AsBytes(new ReadOnlySpan<int>(gotDanFlagList.ToArray())).ToArray(); return MemoryMarshal.AsBytes(new ReadOnlySpan<int>(gotDanFlagList.ToArray())).ToArray();
} }
public static byte[] GetBitArrayFromIds(IEnumerable<uint> idArray, int bitArraySize, ILogger logger)
{
var result = new byte[bitArraySize / 8 + 1];
var bitSet = new BitArray(bitArraySize + 1);
foreach (var id in idArray)
{
if (id >= bitArraySize)
{
logger.LogWarning("Id out of range!");
continue;
}
bitSet.Set((int)id, true);
}
bitSet.CopyTo(result, 0);
return result;
}
} }

View File

@ -14,6 +14,6 @@ public static class PathHelper
{ {
throw new ApplicationException(); throw new ApplicationException();
} }
return Path.Combine(parentPath.ToString(), "wwwroot"); return Path.Combine(parentPath.ToString(), "wwwroot", "data");
} }
} }

View File

@ -1,6 +1,4 @@
using System.Collections.Generic; using System.Text.Json;
using System.Collections;
using System.Text.Json;
using TaikoLocalServer.Services.Interfaces; using TaikoLocalServer.Services.Interfaces;
using Throw; using Throw;
@ -76,23 +74,9 @@ public class BaidController : BaseController<BaidController>
datum.Difficulty == achievementDisplayDifficulty : datum.Difficulty == achievementDisplayDifficulty :
datum.Difficulty is Difficulty.Oni or Difficulty.UraOni).ToList(); datum.Difficulty is Difficulty.Oni or Difficulty.UraOni).ToList();
var crownCount = new uint[3]; var crownCount = CalculateCrownCount(songCountData);
foreach (var crownType in Enum.GetValues<CrownType>())
{
if (crownType != CrownType.None)
{
crownCount[(int)crownType - 1] = (uint)songCountData.Count(datum => datum.BestCrown == crownType);
}
}
var scoreRankCount = new uint[7]; var scoreRankCount = CalculateScoreRankCount(songCountData);
foreach (var scoreRankType in Enum.GetValues<ScoreRank>())
{
if (scoreRankType != ScoreRank.None)
{
scoreRankCount[(int)scoreRankType - 2] = (uint)songCountData.Count(datum => datum.BestScoreRank == scoreRankType);
}
}
var costumeData = new List<uint>{ 0, 0, 0, 0, 0 }; var costumeData = new List<uint>{ 0, 0, 0, 0, 0 };
@ -124,45 +108,9 @@ public class BaidController : BaseController<BaidController>
// which means database content need to be fixed, so better throw // which means database content need to be fixed, so better throw
costumeArrays.ThrowIfNull("Costume flg should never be null!"); costumeArrays.ThrowIfNull("Costume flg should never be null!");
var costumeFlg1 = new byte[Constants.COSTUME_FLAG_1_ARRAY_SIZE]; var costumeFlagArrays = Constants.CostumeFlagArraySizes
var bitSet = new BitArray(Constants.COSTUME_FLAG_1_ARRAY_SIZE); .Select((size, index) => FlagCalculator.GetBitArrayFromIds(costumeArrays[index], size, Logger))
foreach (var costume in costumeArrays[0]) .ToList();
{
bitSet.Set((int)costume, true);
}
bitSet.CopyTo(costumeFlg1, 0);
var costumeFlg2 = new byte[Constants.COSTUME_FLAG_2_ARRAY_SIZE];
bitSet = new BitArray(Constants.COSTUME_FLAG_2_ARRAY_SIZE);
foreach (var costume in costumeArrays[1])
{
bitSet.Set((int)costume, true);
}
bitSet.CopyTo(costumeFlg2, 0);
var costumeFlg3 = new byte[Constants.COSTUME_FLAG_3_ARRAY_SIZE];
bitSet = new BitArray(Constants.COSTUME_FLAG_3_ARRAY_SIZE);
foreach (var costume in costumeArrays[2])
{
bitSet.Set((int)costume, true);
}
bitSet.CopyTo(costumeFlg3, 0);
var costumeFlg4 = new byte[Constants.COSTUME_FLAG_4_ARRAY_SIZE];
bitSet = new BitArray(Constants.COSTUME_FLAG_4_ARRAY_SIZE);
foreach (var costume in costumeArrays[3])
{
bitSet.Set((int)costume, true);
}
bitSet.CopyTo(costumeFlg4, 0);
var costumeFlg5 = new byte[Constants.COSTUME_FLAG_5_ARRAY_SIZE];
bitSet = new BitArray(Constants.COSTUME_FLAG_5_ARRAY_SIZE);
foreach (var costume in costumeArrays[4])
{
bitSet.Set((int)costume, true);
}
bitSet.CopyTo(costumeFlg5, 0);
var danData = await danScoreDatumService.GetDanScoreDatumByBaid(baid); var danData = await danScoreDatumService.GetDanScoreDatumByBaid(baid);
@ -199,11 +147,11 @@ public class BaidController : BaseController<BaidController>
Costume4 = costumeData[3], Costume4 = costumeData[3],
Costume5 = costumeData[4] Costume5 = costumeData[4]
}, },
CostumeFlg1 = costumeFlg1, CostumeFlg1 = costumeFlagArrays[0],
CostumeFlg2 = costumeFlg2, CostumeFlg2 = costumeFlagArrays[1],
CostumeFlg3 = costumeFlg3, CostumeFlg3 = costumeFlagArrays[2],
CostumeFlg4 = costumeFlg4, CostumeFlg4 = costumeFlagArrays[3],
CostumeFlg5 = costumeFlg5, CostumeFlg5 = costumeFlagArrays[4],
LastPlayDatetime = userData.LastPlayDatetime.ToString(Constants.DATE_TIME_FORMAT), LastPlayDatetime = userData.LastPlayDatetime.ToString(Constants.DATE_TIME_FORMAT),
IsDispDanOn = userData.DisplayDan, IsDispDanOn = userData.DisplayDan,
GotDanMax = maxDan, GotDanMax = maxDan,
@ -227,4 +175,32 @@ public class BaidController : BaseController<BaidController>
return Ok(response); return Ok(response);
} }
private static uint[] CalculateScoreRankCount(IReadOnlyCollection<SongBestDatum> songCountData)
{
var scoreRankCount = new uint[7];
foreach (var scoreRankType in Enum.GetValues<ScoreRank>())
{
if (scoreRankType != ScoreRank.None)
{
scoreRankCount[(int)scoreRankType - 2] =
(uint)songCountData.Count(datum => datum.BestScoreRank == scoreRankType);
}
}
return scoreRankCount;
}
private static uint[] CalculateCrownCount(IReadOnlyCollection<SongBestDatum> songCountData)
{
var crownCount = new uint[3];
foreach (var crownType in Enum.GetValues<CrownType>())
{
if (crownType != CrownType.None)
{
crownCount[(int)crownType - 1] = (uint)songCountData.Count(datum => datum.BestCrown == crownType);
}
}
return crownCount;
}
} }

View File

@ -1,7 +1,6 @@
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Globalization; using System.Globalization;
using System.Text.Json; using System.Text.Json;
using TaikoLocalServer.Entities;
using TaikoLocalServer.Services.Interfaces; using TaikoLocalServer.Services.Interfaces;
using Throw; using Throw;
@ -66,7 +65,7 @@ public class PlayResultController : BaseController<PlayResultController>
if (playMode == PlayMode.AiBattle) if (playMode == PlayMode.AiBattle)
{ {
await UpdateAiBattleData(request, stageData); // await UpdateAiBattleData(request, stageData);
// Update AI win count here somewhere, or in UpdatePlayData? // Update AI win count here somewhere, or in UpdatePlayData?
// I have no clue how to update input median or variance // I have no clue how to update input median or variance
} }
@ -75,7 +74,7 @@ public class PlayResultController : BaseController<PlayResultController>
await UpdatePlayData(request, songNumber, stageData, lastPlayDatetime); await UpdatePlayData(request, songNumber, stageData, lastPlayDatetime);
} }
return Ok(response); return Ok(response);
} }
@ -193,23 +192,80 @@ public class PlayResultController : BaseController<PlayResultController>
userdata.LastPlayDatetime = lastPlayDatetime; userdata.LastPlayDatetime = lastPlayDatetime;
userdata.LastPlayMode = playResultData.PlayMode; userdata.LastPlayMode = playResultData.PlayMode;
var toneFlgData = JsonSerializer.Deserialize<List<uint>>(userdata.ToneFlgArray); userdata.ToneFlgArray =
toneFlgData?.AddRange(playResultData.GetToneNoes ?? new uint[0]); UpdateJsonUintFlagArray(userdata.ToneFlgArray, playResultData.GetToneNoes, nameof(userdata.ToneFlgArray));
userdata.ToneFlgArray = JsonSerializer.Serialize(toneFlgData);
var titleFlgData = JsonSerializer.Deserialize<List<uint>>(userdata.TitleFlgArray); userdata.TitleFlgArray =
titleFlgData?.AddRange(playResultData.GetTitleNoes ?? new uint[0]); UpdateJsonUintFlagArray(userdata.TitleFlgArray, playResultData.GetTitleNoes,
userdata.TitleFlgArray = JsonSerializer.Serialize(titleFlgData); nameof(userdata.TitleFlgArray));
var costumeFlgData = JsonSerializer.Deserialize<List<List<uint>>>(userdata.CostumeFlgArray);
costumeFlgData?[0].AddRange(playResultData.GetCostumeNo1s ?? new uint[0]); userdata.CostumeFlgArray = UpdateJsonCostumeFlagArray(userdata.CostumeFlgArray,
costumeFlgData?[1].AddRange(playResultData.GetCostumeNo2s ?? new uint[0]); new[]
costumeFlgData?[2].AddRange(playResultData.GetCostumeNo3s ?? new uint[0]); {
costumeFlgData?[3].AddRange(playResultData.GetCostumeNo4s ?? new uint[0]); playResultData.GetCostumeNo1s,
costumeFlgData?[4].AddRange(playResultData.GetCostumeNo5s ?? new uint[0]); playResultData.GetCostumeNo2s,
userdata.CostumeFlgArray = JsonSerializer.Serialize(costumeFlgData); playResultData.GetCostumeNo3s,
playResultData.GetCostumeNo4s,
playResultData.GetCostumeNo5s
});
await userDatumService.UpdateUserDatum(userdata); await userDatumService.UpdateUserDatum(userdata);
} }
private string UpdateJsonUintFlagArray(string originalValue, IReadOnlyCollection<uint>? newValue, string fieldName)
{
var flgData = new List<uint>();
try
{
flgData = JsonSerializer.Deserialize<List<uint>>(originalValue);
}
catch (JsonException e)
{
Logger.LogError(e, "Parsing {FieldName} json data failed", fieldName);
}
flgData?.AddRange(newValue ?? Array.Empty<uint>());
var flgArray = flgData ?? new List<uint>();
return JsonSerializer.Serialize(flgArray);
}
private string UpdateJsonCostumeFlagArray(string originalValue, IReadOnlyList<IReadOnlyCollection<uint>?>? newValue)
{
var flgData = new List<List<uint>>();
try
{
flgData = JsonSerializer.Deserialize<List<List<uint>>>(originalValue);
}
catch (JsonException e)
{
Logger.LogError(e, "Parsing Costume flag json data failed");
}
if (flgData is null)
{
flgData = new List<List<uint>>();
}
for (var index = 0; index < flgData.Count; index++)
{
var subFlgData = flgData[index];
subFlgData.AddRange(newValue?[index] ?? Array.Empty<uint>());
}
if (flgData.Count >= 5)
{
return JsonSerializer.Serialize(flgData);
}
Logger.LogWarning("Costume flag array count less than 5!");
flgData = new List<List<uint>>
{
new(), new(), new(), new(), new()
};
return JsonSerializer.Serialize(flgData);
}
private async Task UpdateBestData(PlayResultRequest request, StageData stageData, private async Task UpdateBestData(PlayResultRequest request, StageData stageData,
IEnumerable<SongBestDatum> bestData) IEnumerable<SongBestDatum> bestData)
{ {
@ -231,7 +287,8 @@ public class PlayResultController : BaseController<PlayResultController>
await songBestDatumService.UpdateOrInsertSongBestDatum(bestDatum); await songBestDatumService.UpdateOrInsertSongBestDatum(bestDatum);
} }
private async Task UpdateAiBattleData(PlayResultRequest request, StageData stageData) // TODO: AI battle
/*private async Task UpdateAiBattleData(PlayResultRequest request, StageData stageData)
{ {
for (int i = 0; i < stageData.ArySectionDatas.Count; i++) for (int i = 0; i < stageData.ArySectionDatas.Count; i++)
{ {
@ -242,7 +299,7 @@ public class PlayResultController : BaseController<PlayResultController>
// if any aspect of the section is higher than the previous best, update it // if any aspect of the section is higher than the previous best, update it
// Similar to Dan best play updates // Similar to Dan best play updates
} }
} }*/
private static CrownType PlayResultToCrown(StageData stageData) private static CrownType PlayResultToCrown(StageData stageData)
{ {

View File

@ -1,5 +1,4 @@
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Collections;
using System.Text.Json; using System.Text.Json;
using TaikoLocalServer.Services.Interfaces; using TaikoLocalServer.Services.Interfaces;
using Throw; using Throw;
@ -28,21 +27,11 @@ public class UserDataController : BaseController<UserDataController>
var musicAttributeManager = MusicAttributeManager.Instance; var musicAttributeManager = MusicAttributeManager.Instance;
var releaseSongArray = new byte[Constants.MUSIC_FLAG_ARRAY_SIZE]; var releaseSongArray =
var bitSet = new BitArray(Constants.MUSIC_ID_MAX); FlagCalculator.GetBitArrayFromIds(musicAttributeManager.Musics, Constants.MUSIC_ID_MAX, Logger);
foreach (var music in musicAttributeManager.Musics)
{ var uraSongArray =
bitSet.Set((int)music, true); FlagCalculator.GetBitArrayFromIds(musicAttributeManager.MusicsWithUra, Constants.MUSIC_ID_MAX, Logger);
}
bitSet.CopyTo(releaseSongArray, 0);
var uraSongArray = new byte[Constants.MUSIC_FLAG_ARRAY_SIZE];
bitSet.SetAll(false);
foreach (var music in musicAttributeManager.MusicsWithUra)
{
bitSet.Set((int)music, true);
}
bitSet.CopyTo(uraSongArray, 0);
var userData = await userDatumService.GetFirstUserDatumOrDefault(request.Baid); var userData = await userDatumService.GetFirstUserDatumOrDefault(request.Baid);
@ -60,13 +49,7 @@ public class UserDataController : BaseController<UserDataController>
// which means database content need to be fixed, so better throw // which means database content need to be fixed, so better throw
toneFlg.ThrowIfNull("Tone flg should never be null!"); toneFlg.ThrowIfNull("Tone flg should never be null!");
var toneArray = new byte[Constants.TONE_UID_MAX]; var toneArray = FlagCalculator.GetBitArrayFromIds(toneFlg, Constants.TONE_UID_MAX, Logger);
bitSet = new BitArray(Constants.TONE_UID_MAX);
foreach (var tone in toneFlg)
{
bitSet.Set((int)tone, true);
}
bitSet.CopyTo(toneArray, 0);
var titleFlg = Array.Empty<uint>(); var titleFlg = Array.Empty<uint>();
try try
@ -82,13 +65,7 @@ public class UserDataController : BaseController<UserDataController>
// which means database content need to be fixed, so better throw // which means database content need to be fixed, so better throw
titleFlg.ThrowIfNull("Title flg should never be null!"); titleFlg.ThrowIfNull("Title flg should never be null!");
var titleArray = new byte[Constants.TITLE_UID_MAX]; var titleArray = FlagCalculator.GetBitArrayFromIds(titleFlg, Constants.TITLE_UID_MAX, Logger);
bitSet = new BitArray(Constants.TITLE_UID_MAX);
foreach (var title in titleFlg)
{
bitSet.Set((int)title, true);
}
bitSet.CopyTo(titleArray, 0);
var recentSongs = (await songPlayDatumService.GetSongPlayDatumByBaid(request.Baid)) var recentSongs = (await songPlayDatumService.GetSongPlayDatumByBaid(request.Baid))
.AsEnumerable() .AsEnumerable()

View File

@ -38,7 +38,7 @@
<Content Update="wwwroot\dan_data.json"> <Content Update="wwwroot\dan_data.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Update="wwwroot\music_attribute.json"> <Content Update="wwwroot\data\music_attribute.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>