Skip to content

Commit 4278072

Browse files
committed
Add anchor management functionality with user assignments and daily tracking
1 parent 984c008 commit 4278072

16 files changed

Lines changed: 2773 additions & 10 deletions

.github/copilot-instructions.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Instead of using `dotnet run`, use `dotnet watch` to endable hot reloading.
2+
This allows you to see changes in real-time without needing to restart the application.
3+
4+
If there's a blazor webassembly project and a blazor server project, don't try to run the webassembly project directly. Instead, run the server project which will handle the webassembly project as well.
5+
6+
There should always be a blank line of whitespace between each method. New html elements should be on a new line.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using HomeSpeaker.Server2.Services;
2+
3+
namespace HomeSpeaker.Server2;
4+
5+
public class DailyAnchorWorker : BackgroundService
6+
{
7+
private readonly IServiceProvider serviceProvider;
8+
private readonly ILogger<DailyAnchorWorker> logger;
9+
10+
public DailyAnchorWorker(IServiceProvider serviceProvider, ILogger<DailyAnchorWorker> logger)
11+
{
12+
this.serviceProvider = serviceProvider;
13+
this.logger = logger;
14+
}
15+
16+
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
17+
{
18+
logger.LogInformation("Daily Anchor Worker started");
19+
20+
while (!stoppingToken.IsCancellationRequested)
21+
{
22+
try
23+
{
24+
using (var scope = serviceProvider.CreateScope())
25+
{
26+
var anchorService = scope.ServiceProvider.GetRequiredService<AnchorService>();
27+
await anchorService.EnsureTodayAnchorsForAllUsersAsync();
28+
logger.LogInformation("Daily anchors ensured for all users");
29+
}
30+
}
31+
catch (Exception ex)
32+
{
33+
logger.LogError(ex, "Error ensuring daily anchors");
34+
}
35+
36+
// Wait until the next day at midnight
37+
var now = DateTime.Now;
38+
var tomorrow = now.Date.AddDays(1);
39+
var delay = tomorrow - now;
40+
41+
// If delay is less than 1 minute, add a day (to handle edge cases)
42+
if (delay.TotalMinutes < 1)
43+
{
44+
delay = delay.Add(TimeSpan.FromDays(1));
45+
}
46+
47+
logger.LogInformation("Next daily anchor creation scheduled for {time} (in {hours} hours)",
48+
now.Add(delay), delay.TotalHours);
49+
50+
try
51+
{
52+
await Task.Delay(delay, stoppingToken);
53+
}
54+
catch (OperationCanceledException)
55+
{
56+
// Service is being stopped
57+
break;
58+
}
59+
}
60+
61+
logger.LogInformation("Daily Anchor Worker stopped");
62+
}
63+
}

HomeSpeaker.Server2/Data/MusicContext.cs

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,40 +7,83 @@ public class MusicContext : DbContext
77
public MusicContext(DbContextOptions<MusicContext> options) : base(options)
88
{
99

10-
}
11-
public DbSet<Thumbnail> Thumbnails { get; set; }
10+
} public DbSet<Thumbnail> Thumbnails { get; set; }
1211
public DbSet<Playlist> Playlists { get; set; }
1312
public DbSet<PlaylistItem> PlaylistItems { get; set; }
1413
public DbSet<Impression> Impressions { get; set; }
14+
public DbSet<AnchorDefinitionEntity> AnchorDefinitions { get; set; }
15+
public DbSet<UserAnchorEntity> UserAnchors { get; set; }
16+
public DbSet<DailyAnchorEntity> DailyAnchors { get; set; }
1517
}
1618

1719
public class Thumbnail
1820
{
1921
public int Id { get; set; }
20-
public string Artist { get; set; }
21-
public string Album { get; set; }
22-
public string ThumbnailUrl { get; set; }
22+
public string Artist { get; set; } = string.Empty;
23+
public string Album { get; set; } = string.Empty;
24+
public string ThumbnailUrl { get; set; } = string.Empty;
2325
}
2426

2527
public class Playlist
2628
{
2729
public int Id { get; set; }
28-
public string Name { get; set; }
30+
public string Name { get; set; } = string.Empty;
2931
public List<PlaylistItem> Songs { get; set; } = new();
3032
}
3133

3234
public class PlaylistItem
3335
{
3436
public int Id { get; set; }
3537
public int PlaylistId { get; set; }
36-
public string SongPath { get; set; }
38+
public string SongPath { get; set; } = string.Empty;
3739
public int Order { get; set; }
3840
}
3941

4042
public class Impression
4143
{
4244
public int Id { get; set; }
43-
public string SongPath { get; set; }
45+
public string SongPath { get; set; } = string.Empty;
4446
public DateTime Timestamp { get; set; }
45-
public string PlayedBy { get; set; }
47+
public string PlayedBy { get; set; } = string.Empty;
48+
}
49+
50+
/// <summary>
51+
/// Entity for anchor definitions (the template)
52+
/// </summary>
53+
public class AnchorDefinitionEntity
54+
{
55+
public int Id { get; set; }
56+
public string Name { get; set; } = string.Empty;
57+
public string Description { get; set; } = string.Empty;
58+
public bool IsActive { get; set; } = true;
59+
public DateTime CreatedAt { get; set; }
60+
public DateTime? DeactivatedAt { get; set; }
61+
}
62+
63+
/// <summary>
64+
/// Entity for user's current anchors (current active assignments)
65+
/// </summary>
66+
public class UserAnchorEntity
67+
{
68+
public int Id { get; set; }
69+
public string UserId { get; set; } = string.Empty;
70+
public int AnchorDefinitionId { get; set; }
71+
public DateTime CreatedAt { get; set; }
72+
public AnchorDefinitionEntity? AnchorDefinition { get; set; }
73+
}
74+
75+
/// <summary>
76+
/// Entity for daily anchor snapshots (temporal records)
77+
/// </summary>
78+
public class DailyAnchorEntity
79+
{
80+
public int Id { get; set; }
81+
public string UserId { get; set; } = string.Empty;
82+
public int AnchorDefinitionId { get; set; }
83+
public DateOnly Date { get; set; }
84+
public bool IsCompleted { get; set; }
85+
public DateTime? CompletedAt { get; set; }
86+
public string AnchorName { get; set; } = string.Empty; // Snapshot of name at time of creation
87+
public string AnchorDescription { get; set; } = string.Empty; // Snapshot of description at time of creation
88+
public DateTime CreatedAt { get; set; }
4689
}

HomeSpeaker.Server2/Migrations/20250623000440_AddAnchorTables.Designer.cs

Lines changed: 222 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)