diff options
| author | Paweł Bernaciak <pawelbernaciak@zohomail.eu> | 2023-10-25 20:28:48 +0200 |
|---|---|---|
| committer | Paweł Bernaciak <pawelbernaciak@zohomail.eu> | 2023-10-25 20:34:22 +0200 |
| commit | 1912feb9cfe51deaedbe3abe9239fd1bcf2b37f8 (patch) | |
| tree | 8d7f0e448c0ba1e6e4980e8d99b136ca14391b95 /backend | |
| parent | 2e86ace4593d32a2cb1a4be9a758911ff25e4a89 (diff) | |
Make voting work
Diffstat (limited to 'backend')
4 files changed, 140 insertions, 1 deletions
diff --git a/backend/Elements.Backend/Controllers/SuggestionController.cs b/backend/Elements.Backend/Controllers/SuggestionController.cs index 040b19b..932e774 100644 --- a/backend/Elements.Backend/Controllers/SuggestionController.cs +++ b/backend/Elements.Backend/Controllers/SuggestionController.cs @@ -123,7 +123,7 @@ public class SuggestionController : ControllerBase Icon = ConvertBitmapToPng(Convert.FromBase64String(suggestion.IconBitmap)), FirstElementId = suggestion.FirstElementId, SecondElementId = suggestion.SecondElementId, - VotingEnd = DateTime.UtcNow + TimeSpan.FromSeconds(10), + VotingEnd = DateTime.UtcNow + TimeSpan.FromMinutes(5), UserId = int.Parse(currentUserId) }; await _dbContext.Suggestions.AddAsync(newSuggestion); diff --git a/backend/Elements.Backend/Program.cs b/backend/Elements.Backend/Program.cs index 50e5255..f7b9b4b 100644 --- a/backend/Elements.Backend/Program.cs +++ b/backend/Elements.Backend/Program.cs @@ -1,4 +1,5 @@ using System.Text.Json;
+using Elements.Backend.Services;
using Elements.Data;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.Google;
@@ -44,6 +45,11 @@ builder.Services };
});
+builder.Services.AddScoped<FinishVoteService>();
+builder.Services.AddSingleton<PeriodicService>();
+builder.Services.AddHostedService(
+ provider => provider.GetRequiredService<PeriodicService>());
+
var app = builder.Build();
app.UseHttpsRedirection();
diff --git a/backend/Elements.Backend/Services/FinishVoteService.cs b/backend/Elements.Backend/Services/FinishVoteService.cs new file mode 100644 index 0000000..8486036 --- /dev/null +++ b/backend/Elements.Backend/Services/FinishVoteService.cs @@ -0,0 +1,95 @@ +using Elements.Data; +using Elements.Data.Models; +using Microsoft.EntityFrameworkCore; + +namespace Elements.Backend.Services; + +public class FinishVoteService +{ + private readonly ApplicationDbContext _dbContext; + private readonly ILogger<FinishVoteService> _logger; + + public FinishVoteService(ApplicationDbContext dbContext, ILogger<FinishVoteService> logger) + { + _dbContext = dbContext; + _logger = logger; + } + + public async Task DoSomethingAsync() + { + _logger.LogDebug("Starting finalizing votes"); + List<Suggestion> finishedSuggestions = _dbContext.Suggestions + .Include(s => s.Votes) + .Where(s => DateTime.UtcNow > s.VotingEnd) + .ToList(); + + if (finishedSuggestions.Count == 0) + return; + + bool finished = false; + while (!finished) + { + Suggestion currentSuggestion = finishedSuggestions.First(); + int firstElementId = currentSuggestion.FirstElementId; + int secondElementId = currentSuggestion.SecondElementId; + //Get all suggestions with same recipe as current suggestion + List<Suggestion> sameRecipeSuggestions = finishedSuggestions.Where(s => + (s.FirstElementId == firstElementId && s.SecondElementId == secondElementId) || + (s.FirstElementId == secondElementId && s.SecondElementId == firstElementId)) + .ToList(); + sameRecipeSuggestions.Sort((s1, s2) => s2.Votes.Count.CompareTo(s1.Votes.Count)); + + Suggestion winner; + if (sameRecipeSuggestions.Count > 1 && + sameRecipeSuggestions[0].Votes.Count == sameRecipeSuggestions[1].Votes.Count) + { + List<Suggestion> sameAmountOfVotes = sameRecipeSuggestions + .Where(s => s.Votes.Count == sameRecipeSuggestions[0].Votes.Count) + .OrderBy(s => s.CreationDate) + .ToList(); + + winner = sameAmountOfVotes[0]; + } + else + { + winner = sameRecipeSuggestions[0]; + } + + Element newElement = new() + { + CreationDate = winner.CreationDate, + UserId = winner.UserId, + Name = winner.Name, + State = ElementState.HasColor, + IconPng = winner.Icon + }; + await _dbContext.Elements.AddAsync(newElement); + await _dbContext.SaveChangesAsync(); + + await _dbContext.Recipes.AddAsync(new Recipe + { + FirstElementId = winner.FirstElementId, + SecondElementId = winner.SecondElementId, + ResultElementId = newElement.Id, + }); + + //Delete votes + foreach (Vote vote in sameRecipeSuggestions.SelectMany(suggestion => suggestion.Votes)) + _dbContext.Entry(vote).State = EntityState.Deleted; + + //Delete suggestions + foreach (Suggestion suggestion in sameRecipeSuggestions) + _dbContext.Entry(suggestion).State = EntityState.Deleted; + + await _dbContext.SaveChangesAsync(); + + finishedSuggestions = finishedSuggestions + .Where(s => !(s.FirstElementId == firstElementId && s.SecondElementId == secondElementId) && + !(s.FirstElementId == secondElementId && s.SecondElementId == firstElementId)) + .ToList(); + + if (finishedSuggestions.Count == 0) + finished = true; + } + } +}
\ No newline at end of file diff --git a/backend/Elements.Backend/Services/PeriodicService.cs b/backend/Elements.Backend/Services/PeriodicService.cs new file mode 100644 index 0000000..48cdf2f --- /dev/null +++ b/backend/Elements.Backend/Services/PeriodicService.cs @@ -0,0 +1,38 @@ +namespace Elements.Backend.Services; + +class PeriodicService : BackgroundService +{ + private readonly TimeSpan _period = TimeSpan.FromMinutes(1); + private readonly ILogger<PeriodicService> _logger; + private readonly IServiceScopeFactory _factory; + public bool IsEnabled { get; set; } = true; + + public PeriodicService( + ILogger<PeriodicService> logger, + IServiceScopeFactory factory) + { + _logger = logger; + _factory = factory; + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + using PeriodicTimer timer = new PeriodicTimer(_period); + while ( + !stoppingToken.IsCancellationRequested && + await timer.WaitForNextTickAsync(stoppingToken)) + { + try + { + if (!IsEnabled) continue; + await using AsyncServiceScope asyncScope = _factory.CreateAsyncScope(); + FinishVoteService finishVoteService = asyncScope.ServiceProvider.GetRequiredService<FinishVoteService>(); + await finishVoteService.DoSomethingAsync(); + } + catch (Exception ex) + { + _logger.LogInformation($"Failed to execute periodic service, Error: {ex.Message}."); + } + } + } +}
\ No newline at end of file |
