Added Polls and locking raids if not enough users are signed up

needs testing
This commit is contained in:
t.ruspekhofer 2023-01-03 13:53:26 +01:00
parent 32af72a262
commit ccb276a265
14 changed files with 289 additions and 8 deletions

View file

@ -8,6 +8,12 @@
public static readonly int RaidEditPowerLevel = Roles.Moderator.PowerLevel;
public const int REMOVE_MAYBE_MINUTES = 15;
public static class Polls
{
public const string YES = "yes";
public const string NO = "no";
}
public static class Roles
{
public static readonly RoleConstant User = new RoleConstant("user", 20);

View file

@ -306,8 +306,15 @@ namespace Lieb.Data
public static ApiRaid ConvertRaid(Raid raid)
{
string title = raid.Title;
if (raid.SignUps.Count < raid.MinUsers
&& raid.MinUserDeadLineUTC.UtcDateTime > DateTimeOffset.UtcNow)
{
title = $"The raid was canceled because of not enough sign ups.\n\n{raid.Title}";
}
ApiRaid apiRaid = new ApiRaid(){
Title = raid.Title,
Title = title,
Description = raid.Description,
Guild = raid.Guild,
Organizer = raid.Organizer,

View file

@ -2,6 +2,7 @@
using Lieb.Models;
using Lieb.Models.GuildWars2;
using Lieb.Models.GuildWars2.Raid;
using Lieb.Models.Poll;
using Microsoft.EntityFrameworkCore;
namespace Lieb.Data
@ -26,6 +27,9 @@ namespace Lieb.Data
public DbSet<RaidSignUp> RaidSignUps { get; set; }
public DbSet<DiscordRaidMessage> DiscordRaidMessages { get; set; }
public DbSet<DiscordSettings> DiscordSettings { get; set; }
public DbSet<Poll> Polls { get; set; }
public DbSet<PollOption> PollOptions { get; set; }
public DbSet<PollAnswer> PollAnswers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
@ -43,6 +47,9 @@ namespace Lieb.Data
modelBuilder.Entity<RaidSignUp>().ToTable("RaidSignUp");
modelBuilder.Entity<DiscordRaidMessage>().ToTable("DiscordRaidMessage");
modelBuilder.Entity<DiscordSettings>().ToTable("DiscordSettings");
modelBuilder.Entity<Poll>().ToTable("Poll");
modelBuilder.Entity<PollOption>().ToTable("PollOption");
modelBuilder.Entity<PollAnswer>().ToTable("PollAnswer");
}
}
}

113
Lieb/Data/PollService.cs Normal file
View file

@ -0,0 +1,113 @@
using Lieb.Models.GuildWars2.Raid;
using Lieb.Models.Poll;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;
namespace Lieb.Data
{
public class PollService
{
private readonly IDbContextFactory<LiebContext> _contextFactory;
private readonly DiscordService _discordService;
public PollService(IDbContextFactory<LiebContext> contextFactory, DiscordService discordService)
{
_contextFactory = contextFactory;
_discordService = discordService;
}
public Poll GetPoll(int pollId)
{
using var context = _contextFactory.CreateDbContext();
Poll? poll = context.Polls
.Include(p => p.Options)
.Include(p => p.Answers)
.FirstOrDefault(p => p.PollId == pollId);
if (poll != null) return poll;
return new Poll();
}
public List<Poll> GetPollsByRaidId(int raidId)
{
using var context = _contextFactory.CreateDbContext();
return context.Polls
.Include(p => p.Options)
.Include(p => p.Answers)
.Where(p => p.RaidId == raidId).ToList();
}
public async Task<int> CreatePoll(string question, List<string> options, int raidId)
{
using var context = _contextFactory.CreateDbContext();
Raid? raid = context.Raids
.Include(r => r.SignUps)
.FirstOrDefault(r => r.RaidId == raidId);
if (raid == null) return 0;
List<ulong> users = raid.SignUps.Where(s => s.LiebUserId != null).Select(s => (ulong)s.LiebUserId).ToList();
return await CreatePoll(question, options, users, raidId);
}
public async Task<int> CreatePoll(string question, List<string> options, List<ulong> users, int? raidId = null)
{
Poll poll = new Poll()
{
Question = question,
RaidId = raidId
};
foreach(string option in options)
{
poll.Options.Add(new PollOption()
{
Name = option
});
}
foreach(ulong user in users)
{
poll.Answers.Add(new PollAnswer()
{
UserId = user
});
}
using var context = _contextFactory.CreateDbContext();
context.Polls.Add(poll);
await context.SaveChangesAsync();
return poll.PollId;
}
public async Task DeletePoll(int pollId)
{
using var context = _contextFactory.CreateDbContext();
Poll? poll = context.Polls
.Include(p => p.Options)
.Include(p => p.Answers)
.FirstOrDefault(p => p.PollId == pollId);
if(poll == null) return;
context.PollOptions.RemoveRange(poll.Options);
context.PollAnswers.RemoveRange(poll.Answers);
await context.SaveChangesAsync();
poll.Options.Clear();
poll.Answers.Clear();
context.Polls.Remove(poll);
await context.SaveChangesAsync();
}
public async Task UpdateAnswer(int pollId, int pollOptionId, ulong userId)
{
using var context = _contextFactory.CreateDbContext();
Poll? poll = context.Polls
.Include(p => p.Answers)
.FirstOrDefault(p => p.PollId == pollId && p.Answers.Where(a => a.UserId == userId).Any());
if (poll == null) return;
PollAnswer answer = poll.Answers.First(a => a.UserId == userId);
answer.PollOptionId = pollOptionId;
}
}
}

View file

@ -1,6 +1,7 @@
using Lieb.Models;
using Lieb.Models.GuildWars2;
using Lieb.Models.GuildWars2.Raid;
using Lieb.Models.Poll;
using Microsoft.EntityFrameworkCore;
namespace Lieb.Data
@ -9,11 +10,13 @@ namespace Lieb.Data
{
private readonly IDbContextFactory<LiebContext> _contextFactory;
private readonly DiscordService _discordService;
private readonly PollService _pollService;
public RaidService(IDbContextFactory<LiebContext> contextFactory, DiscordService discordService)
public RaidService(IDbContextFactory<LiebContext> contextFactory, DiscordService discordService, PollService pollService)
{
_contextFactory = contextFactory;
_discordService = discordService;
_pollService = pollService;
}
public List<Raid> GetRaids()
@ -444,6 +447,7 @@ namespace Lieb.Data
errorMessage = string.Empty;
using var context = _contextFactory.CreateDbContext();
Raid? raid = context.Raids
.Include(r => r.SignUps)
.AsNoTracking()
.FirstOrDefault(r => r.RaidId == raidId);
if(raid == null)
@ -451,6 +455,14 @@ namespace Lieb.Data
errorMessage = "Raid not found.";
return false;
}
if (raid.SignUps.Count < raid.MinUsers
&& raid.MinUserDeadLineUTC.UtcDateTime > DateTimeOffset.UtcNow)
{
errorMessage = $"The raid was canceled because of not enough sign ups.";
return false;
}
LiebUser? user = context.LiebUsers
.Include(u => u.RoleAssignments)
.ThenInclude(a => a.LiebRole)
@ -670,5 +682,49 @@ namespace Lieb.Data
await context.SaveChangesAsync();
}
}
public async Task CheckMinUsers()
{
using var context = _contextFactory.CreateDbContext();
List<Raid> raids = context.Raids
.Include(r => r.SignUps)
.Where(r => r.SignUps.Count < r.MinUsers && r.MinUserPollId == null).ToList();
foreach (Raid raid in raids.Where(r => r.MinUserDeadLineUTC < DateTimeOffset.UtcNow && r.StartTimeUTC > DateTimeOffset.UtcNow))
{
raid.MinUserPollId = await _pollService.CreatePoll(
"The raid has not the required users, do you want to raid anyway?",
new List<string>() {Constants.Polls.YES, Constants.Polls.NO }, raid.RaidId);
await context.SaveChangesAsync();
await _discordService.PostRaidMessage(raid.RaidId);
}
}
public async Task CheckMinUserPollResult()
{
using var context = _contextFactory.CreateDbContext();
List<Raid> raids = context.Raids
.Include(r => r.SignUps)
.Where(r => r.SignUps.Count < r.MinUsers && r.MinUserPollId != null).ToList();
foreach (Raid raid in raids.Where(r => r.MinUserDeadLineUTC < DateTimeOffset.UtcNow && r.StartTimeUTC > DateTimeOffset.UtcNow))
{
Poll poll = _pollService.GetPoll(raid.MinUserPollId.Value);
if (poll.Answers.Count == 0) continue;
if (poll.Answers.Where(a => a.PollOptionId == null).Any()) continue;
int noOptionId = poll.Options.First(o => o.Name == Constants.Polls.NO).PollOptionId;
if(poll.Answers.Where(a => a.PollOptionId == noOptionId).Any())
{
await _discordService.SendMessageToRaidUsers("The raid is canceled.", raid);
}
else
{
raid.MinUsers = 0;
await context.SaveChangesAsync();
await _discordService.SendMessageToRaidUsers("The raid will take place. Signing up is allowed again.", raid);
await _discordService.PostRaidMessage(raid.RaidId);
}
}
}
}
}

View file

@ -49,6 +49,8 @@ namespace Lieb.Data
.GetRequiredService<RaidService>();
await raidService.SendReminders();
await raidService.RemoveMaybes();
await raidService.CheckMinUsers();
await raidService.CheckMinUserPollResult();
}
}