diff --git a/ginos-gelato/server/Controllers/OrderQueueController.cs b/ginos-gelato/server/Controllers/OrderQueueController.cs
new file mode 100644
index 0000000..3be353f
--- /dev/null
+++ b/ginos-gelato/server/Controllers/OrderQueueController.cs
@@ -0,0 +1,60 @@
+using Microsoft.AspNetCore.Mvc;
+using GinosGelato.Models;
+using GinosGelato.Services;
+
+namespace GinosGelato.Controllers
+{
+ [Route("api/[controller]")]
+ [ApiController]
+ public class OrderQueueController : ControllerBase
+ {
+ private readonly OrderQueueService _orderQueueService;
+
+ public OrderQueueController(OrderQueueService orderQueueService)
+ {
+ _orderQueueService = orderQueueService;
+ }
+
+ ///
+ /// Returns the current queue status, including the number of pending orders
+ /// and the estimated wait time in minutes.
+ ///
+ [HttpGet("status")]
+ public ActionResult GetQueueStatus()
+ {
+ return Ok(_orderQueueService.GetQueueStatus());
+ }
+
+ ///
+ /// Returns the average preparation time in minutes based on completed orders.
+ ///
+ [HttpGet("averagetime")]
+ public ActionResult GetAveragePreparationTime()
+ {
+ return Ok(_orderQueueService.GetAveragePreparationTimeMinutes());
+ }
+
+ ///
+ /// Returns all queue entries (pending and completed).
+ ///
+ [HttpGet]
+ public ActionResult> GetQueueEntries()
+ {
+ return Ok(_orderQueueService.GetAllEntries());
+ }
+
+ ///
+ /// Marks an order as completed, recording its actual preparation time.
+ ///
+ [HttpPost("{orderId}/complete")]
+ public ActionResult CompleteOrder(int orderId)
+ {
+ var success = _orderQueueService.CompleteOrder(orderId);
+ if (!success)
+ {
+ return NotFound(new { message = $"Pending order with id {orderId} not found in queue." });
+ }
+ return NoContent();
+ }
+ }
+}
diff --git a/ginos-gelato/server/Models/OrderQueueEntry.cs b/ginos-gelato/server/Models/OrderQueueEntry.cs
new file mode 100644
index 0000000..14d37dc
--- /dev/null
+++ b/ginos-gelato/server/Models/OrderQueueEntry.cs
@@ -0,0 +1,21 @@
+namespace GinosGelato.Models
+{
+ public enum OrderQueueStatus
+ {
+ Pending,
+ Completed
+ }
+
+ public class OrderQueueEntry
+ {
+ public int OrderId { get; set; }
+ public DateTime EnqueuedAt { get; set; }
+ public DateTime? CompletedAt { get; set; }
+ public OrderQueueStatus Status { get; set; } = OrderQueueStatus.Pending;
+
+ public double? PreparationTimeMinutes =>
+ CompletedAt.HasValue
+ ? (CompletedAt.Value - EnqueuedAt).TotalMinutes
+ : null;
+ }
+}
diff --git a/ginos-gelato/server/Program.cs b/ginos-gelato/server/Program.cs
index 7746fd5..f738f56 100644
--- a/ginos-gelato/server/Program.cs
+++ b/ginos-gelato/server/Program.cs
@@ -16,6 +16,7 @@
options.UseInMemoryDatabase("GinosGelatoDb")); // Using in-memory database for simplicity
// Add custom services
+builder.Services.AddSingleton();
builder.Services.AddScoped();
// Add Swagger/OpenAPI
diff --git a/ginos-gelato/server/Services/OrderQueueService.cs b/ginos-gelato/server/Services/OrderQueueService.cs
new file mode 100644
index 0000000..1e4e653
--- /dev/null
+++ b/ginos-gelato/server/Services/OrderQueueService.cs
@@ -0,0 +1,105 @@
+using GinosGelato.Models;
+
+namespace GinosGelato.Services
+{
+ public class OrderQueueService
+ {
+ private readonly List _queue = new();
+ private readonly object _lock = new();
+
+ // Default estimated preparation time when no historical data is available (minutes)
+ private const double DefaultPreparationTimeMinutes = 5.0;
+
+ // Maximum number of completed entries to retain for average calculation
+ private const int MaxCompletedEntries = 100;
+
+ public void EnqueueOrder(int orderId)
+ {
+ lock (_lock)
+ {
+ _queue.Add(new OrderQueueEntry
+ {
+ OrderId = orderId,
+ EnqueuedAt = DateTime.UtcNow,
+ Status = OrderQueueStatus.Pending
+ });
+ }
+ }
+
+ public bool CompleteOrder(int orderId)
+ {
+ lock (_lock)
+ {
+ var entry = _queue.FirstOrDefault(e => e.OrderId == orderId && e.Status == OrderQueueStatus.Pending);
+ if (entry == null)
+ return false;
+
+ entry.CompletedAt = DateTime.UtcNow;
+ entry.Status = OrderQueueStatus.Completed;
+
+ // Prune oldest completed entries beyond the retention limit
+ var completed = _queue.Where(e => e.Status == OrderQueueStatus.Completed).ToList();
+ while (completed.Count > MaxCompletedEntries)
+ {
+ var oldest = completed[0];
+ _queue.Remove(oldest);
+ completed.RemoveAt(0);
+ }
+
+ return true;
+ }
+ }
+
+ public double GetAveragePreparationTimeMinutes()
+ {
+ lock (_lock)
+ {
+ return CalculateAveragePreparationTime();
+ }
+ }
+
+ public QueueStatusResponse GetQueueStatus()
+ {
+ lock (_lock)
+ {
+ var pendingCount = _queue.Count(e => e.Status == OrderQueueStatus.Pending);
+ var averagePrep = CalculateAveragePreparationTime();
+
+ return new QueueStatusResponse
+ {
+ PendingOrderCount = pendingCount,
+ AveragePreparationTimeMinutes = Math.Round(averagePrep, 1),
+ EstimatedWaitMinutes = Math.Round(pendingCount * averagePrep, 1)
+ };
+ }
+ }
+
+ public IReadOnlyList GetAllEntries()
+ {
+ lock (_lock)
+ {
+ return _queue.ToList().AsReadOnly();
+ }
+ }
+
+ // Must be called within a lock
+ private double CalculateAveragePreparationTime()
+ {
+ var completedTimes = _queue
+ .Where(e => e.Status == OrderQueueStatus.Completed && e.PreparationTimeMinutes.HasValue)
+ .Select(e => e.PreparationTimeMinutes!.Value)
+ .ToList();
+
+ return completedTimes.Count > 0
+ ? completedTimes.Average()
+ : DefaultPreparationTimeMinutes;
+ }
+ }
+
+ public class QueueStatusResponse
+ {
+ public int PendingOrderCount { get; set; }
+ public double AveragePreparationTimeMinutes { get; set; }
+ public double EstimatedWaitMinutes { get; set; }
+ }
+}
diff --git a/ginos-gelato/server/Services/OrderService.cs b/ginos-gelato/server/Services/OrderService.cs
index cc87625..2b51940 100644
--- a/ginos-gelato/server/Services/OrderService.cs
+++ b/ginos-gelato/server/Services/OrderService.cs
@@ -10,10 +10,12 @@ namespace GinosGelato.Services
public class OrderService
{
private readonly ApplicationDbContext _context;
+ private readonly OrderQueueService _orderQueueService;
- public OrderService(ApplicationDbContext context)
+ public OrderService(ApplicationDbContext context, OrderQueueService orderQueueService)
{
_context = context;
+ _orderQueueService = orderQueueService;
}
public async Task CreateOrderAsync(List iceCreams)
@@ -28,6 +30,8 @@ public async Task CreateOrderAsync(List iceCreams)
_context.Orders.Add(order);
await _context.SaveChangesAsync();
+ _orderQueueService.EnqueueOrder(order.Id);
+
return order;
}