summaryrefslogtreecommitdiff
path: root/backend/Elements.Backend
diff options
context:
space:
mode:
Diffstat (limited to 'backend/Elements.Backend')
-rw-r--r--backend/Elements.Backend/Controllers/SuggestionController.cs2
-rw-r--r--backend/Elements.Backend/Program.cs6
-rw-r--r--backend/Elements.Backend/Services/FinishVoteService.cs95
-rw-r--r--backend/Elements.Backend/Services/PeriodicService.cs38
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