Skip to content

Commit

Permalink
Gacha: 排出時に確率を表示するように (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
2RiniaR authored Nov 20, 2024
1 parent fe8d7b6 commit 376d089
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 44 deletions.
51 changes: 18 additions & 33 deletions Common/GachaManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Approvers.King.Common;

public class GachaManager : Singleton<GachaManager>
{
private readonly List<ReplyMessage> _replyMessageTable = new();
private readonly List<GachaProbability> _replyMessageTable = new();

/// <summary>
/// 現在のメッセージに反応する確率
Expand All @@ -14,7 +14,7 @@ public class GachaManager : Singleton<GachaManager>
/// <summary>
/// 各メッセージの確率
/// </summary>
public IReadOnlyList<ReplyMessage> ReplyMessageTable => _replyMessageTable;
public IReadOnlyList<GachaProbability> ReplyMessageTable => _replyMessageTable;

public bool IsTableEmpty => ReplyMessageTable.Count == 0;

Expand All @@ -24,16 +24,7 @@ public async Task LoadAsync()

var probabilities = await app.GachaProbabilities.ToListAsync();
_replyMessageTable.Clear();
foreach (var probability in probabilities)
{
var message = MasterManager.RandomMessageMaster.Find(probability.RandomMessageId);
if (message == null) continue;
_replyMessageTable.Add(new ReplyMessage
{
Rate = probability.Probability,
Message = message
});
}
_replyMessageTable.AddRange(probabilities.Where(x => x.RandomMessage != null));

var rareReplyRatePermillage = await app.AppStates.GetIntAsync(AppStateType.RareReplyProbabilityPermillage);
RareReplyRate = NumberUtility.GetPercentFromPermillage(rareReplyRatePermillage ?? 0);
Expand All @@ -44,11 +35,7 @@ public async Task SaveAsync()
await using var app = AppService.CreateSession();

app.GachaProbabilities.RemoveRange(app.GachaProbabilities);
app.GachaProbabilities.AddRange(_replyMessageTable.Select(x => new GachaProbability
{
RandomMessageId = x.Message.Id,
Probability = x.Rate
}));
app.GachaProbabilities.AddRange(_replyMessageTable);

var rareReplyRatePermillage = NumberUtility.GetPermillageFromPercent(RareReplyRate);
await app.AppStates.SetIntAsync(AppStateType.RareReplyProbabilityPermillage, rareReplyRatePermillage);
Expand All @@ -61,33 +48,37 @@ public void RefreshMessageTable()
_replyMessageTable.Clear();
var messages = MasterManager.RandomMessageMaster
.GetAll(x => x.Type == RandomMessageType.GeneralReply)
.Select(x => new ReplyMessage { Rate = 1f, Message = x });
.Select(x => new GachaProbability()
{
RandomMessageId = x.Id,
Probability = 1f
});
_replyMessageTable.AddRange(messages);
}

public RandomMessage? Roll()
public GachaProbability? Roll()
{
if (RandomUtility.IsHit(RareReplyRate) == false) return null;
return GetRandomResult();
}

public RandomMessage RollWithoutNone()
public GachaProbability RollWithoutNone()
{
return GetRandomResult();
}

private RandomMessage GetRandomResult()
private GachaProbability GetRandomResult()
{
var totalRate = _replyMessageTable.Sum(x => x.Rate);
var totalRate = _replyMessageTable.Sum(x => x.Probability);
var value = RandomUtility.GetRandomFloat(totalRate);

foreach (var element in _replyMessageTable)
{
if (value < element.Rate) return element.Message;
value -= element.Rate;
if (value < element.Probability) return element;
value -= element.Probability;
}

return _replyMessageTable[^1].Message;
return _replyMessageTable[^1];
}

public void ShuffleRareReplyRate()
Expand All @@ -109,16 +100,10 @@ public void ShuffleMessageRates()
borders.Add(100);
var randomIndices = Enumerable.Range(0, _replyMessageTable.Count).Shuffle().ToList();

_replyMessageTable[randomIndices[0]].Rate = borders[0] * 0.01f;
_replyMessageTable[randomIndices[0]].Probability = borders[0] * 0.01f;
for (var i = 1; i < _replyMessageTable.Count; i++)
{
_replyMessageTable[randomIndices[i]].Rate = (borders[i] - borders[i - 1]) * 0.01f;
_replyMessageTable[randomIndices[i]].Probability = (borders[i] - borders[i - 1]) * 0.01f;
}
}

public class ReplyMessage
{
public float Rate { get; set; }
public RandomMessage Message { get; set; }
}
}
6 changes: 6 additions & 0 deletions Common/Models/GachaProbability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@ public class GachaProbability
{
[Key] public string RandomMessageId { get; set; }

Check warning on line 7 in Common/Models/GachaProbability.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'RandomMessageId' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.
public float Probability { get; set; }

private RandomMessage? _randomMessage;

public RandomMessage? RandomMessage => _randomMessage == null || _randomMessage.Id != RandomMessageId
? _randomMessage = MasterManager.RandomMessageMaster.Find(RandomMessageId)
: _randomMessage;
}
6 changes: 3 additions & 3 deletions Common/Models/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ public void ResetMonthlyPurchase()
MonthlyPurchase = 0;
}

public RandomMessage? RollGachaOnce()
public GachaProbability? RollGachaOnce()
{
MonthlyPurchase += MasterManager.SettingMaster.PricePerGachaOnce;
return GachaManager.Instance.Roll();
}

public RandomMessage RollGachaOnceCertain()
public GachaProbability RollGachaOnceCertain()
{
MonthlyPurchase += MasterManager.SettingMaster.PricePerGachaOnceCertain;
return GachaManager.Instance.RollWithoutNone();
}

public List<RandomMessage?> RollGachaTenTimes()
public List<GachaProbability?> RollGachaTenTimes()
{
const int pickCount = 10;
MonthlyPurchase += MasterManager.SettingMaster.PricePerGachaTenTimes;
Expand Down
5 changes: 5 additions & 0 deletions Common/NumberUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ public static DateTime GetBaseDateTime()
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
}

public static bool IsApproximate(this float a, float b)
{
return Math.Abs(a - b) < float.Epsilon;
}

public static float GetSecondsFromMilliseconds(float milliseconds)
{
return milliseconds / 1000f;
Expand Down
8 changes: 6 additions & 2 deletions Events/GachaCommandPresenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@ protected override async Task MainAsync()
await app.SaveChangesAsync();
}

private async Task SendReplyAsync(User user, IReadOnlyList<RandomMessage?> results)
private async Task SendReplyAsync(User user, IReadOnlyList<GachaProbability?> results)
{
var builder = new StringBuilder();
builder.AppendLine($"↓↓↓ いっそう{results.Count}連おみくじ ↓↓↓");
foreach (var result in results)
{
builder.AppendLine(result != null ? Format.Bold($"・{result.Content}") : Format.Code("x"));
builder.AppendLine(result != null
? Format.Bold(
$"・{result.RandomMessage?.Content ?? MessageConst.MissingMessage} ({result.Probability:P0})")
: Format.Code("x"));
}

// 爆死してたら煽る
if (results.All(x => x == null))
{
builder.AppendLine();
Expand Down
5 changes: 3 additions & 2 deletions Events/GachaUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ public static class GachaUtility
public static EmbedBuilder GetInfoEmbedBuilder()
{
var records = GachaManager.Instance.ReplyMessageTable
.OrderByDescending(x => x.Rate)
.Select(x => (x.Message.Content, x.Rate.ToString("P0")));
.OrderByDescending(x => x.Probability)
.Where(x => x.Probability.IsApproximate(0f) == false)
.Select(x => (x.RandomMessage?.Content ?? MessageConst.MissingMessage, x.Probability.ToString("P0")));
return new EmbedBuilder()
.WithTitle(
$"{IssoUtility.SmileStamp}{IssoUtility.SmileStamp}{IssoUtility.SmileStamp} 本日のいっそう {IssoUtility.SmileStamp}{IssoUtility.SmileStamp}{IssoUtility.SmileStamp}")
Expand Down
2 changes: 1 addition & 1 deletion Events/InteractReplyPresenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ protected override async Task MainAsync()
var user = await app.FindOrCreateUserAsync(Message.Author.Id);

var message = user.RollGachaOnceCertain();
await SendReplyAsync(message.Content);
await SendReplyAsync(message.RandomMessage?.Content ?? MessageConst.MissingMessage);

await app.SaveChangesAsync();
}
Expand Down
4 changes: 2 additions & 2 deletions Events/MasterReloadPresenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ protected override async Task MainAsync()

private async Task UpdateGachaTableAsync()
{
var beforeTable = GachaManager.Instance.ReplyMessageTable.Select(x => x.Message.Id).ToHashSet();
var beforeTable = GachaManager.Instance.ReplyMessageTable.Select(x => x.RandomMessageId).ToHashSet();
GachaManager.Instance.RefreshMessageTable();
var afterTable = GachaManager.Instance.ReplyMessageTable.Select(x => x.Message.Id).ToHashSet();
var afterTable = GachaManager.Instance.ReplyMessageTable.Select(x => x.RandomMessageId).ToHashSet();

// テーブルに差分がある場合は排出率を更新する
var hasDiff = beforeTable.SetEquals(afterTable);
Expand Down
6 changes: 6 additions & 0 deletions Events/MessageConst.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Approvers.King.Events;

public static class MessageConst
{
public const string MissingMessage = "[不明なメッセージ]";
}
2 changes: 1 addition & 1 deletion Events/RareReplyPresenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ protected override async Task MainAsync()
var message = user.RollGachaOnce();
if (message != null)
{
await SendReplyAsync(message.Content);
await SendReplyAsync(message.RandomMessage?.Content ?? MessageConst.MissingMessage);
}

await app.SaveChangesAsync();
Expand Down

0 comments on commit 376d089

Please sign in to comment.