2
0
mirror of https://github.com/9ParsonsB/Pulsar.git synced 2025-07-01 16:33:43 -04:00

Implement Other state events

now emitted to websocket connections on connect
This commit is contained in:
2024-05-25 22:49:08 +10:00
parent 68eff73dbd
commit 7eae5e5ee6
68 changed files with 222 additions and 182 deletions

View File

@ -1,9 +1,8 @@
using Microsoft.EntityFrameworkCore;
namespace Pulsar.Context.Configuration;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Observatory.Framework.Files.Journal.Startup;
namespace Pulsar.Context.Configuration;
public class CargoConfiguration : IEntityTypeConfiguration<Cargo>
{
public void Configure(EntityTypeBuilder<Cargo> builder)

View File

@ -1,9 +1,8 @@
using Microsoft.EntityFrameworkCore;
namespace Pulsar.Context.Configuration;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Observatory.Framework.Files.Journal.Odyssey;
namespace Pulsar.Context.Configuration;
public class ShipLockerConfiguration : IEntityTypeConfiguration<ShipLockerMaterials>
{
public void Configure(EntityTypeBuilder<ShipLockerMaterials> builder)

View File

@ -1,12 +1,11 @@
namespace Pulsar.Context;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Observatory.Framework.Files.Journal;
using Observatory.Framework.Files.Journal.Odyssey;
using Observatory.Framework.Files.Journal.Startup;
using Observatory.Framework.Files.Journal.StationServices;
using Observatory.Framework.Files.Journal.Travel;
using Pulsar.Features.ShipLocker;
/// <summary>
/// An in-memory database context for Pulsar.
@ -14,7 +13,6 @@ using Pulsar.Features.ShipLocker;
public class PulsarContext : DbContext
{
public SqliteConnection Connection { get; private set; }
public DbSet<Commander> Commander { get; set; }
public DbSet<Materials> Materials { get; set; }

View File

@ -1,17 +1,20 @@
using Pulsar.Features.Journal;
namespace Pulsar.Features;
using Observatory.Framework.Files;
using Observatory.Framework.Files.Journal;
using Observatory.Framework.Files.Journal.Odyssey;
public class EventsHub(IJournalService journalService) : Hub<IEventsHub>
{
public override async Task OnConnectedAsync()
{
await base.OnConnectedAsync();
await Clients.Caller.JournalUpdated(await journalService.GetLastStartupEvents());
var state = await journalService.GetLatestState();
if (state.Any())
{
await Clients.Caller.JournalUpdated(state);
}
}
public async Task Status([FromServices] IStatusService statusService)
@ -30,7 +33,7 @@ public class EventsHub(IJournalService journalService) : Hub<IEventsHub>
public async Task MarketUpdated(MarketFile market) => await Clients.All.MarketUpdated(market);
public async Task JournalUpdated(IReadOnlyCollection<JournalBase> journals) => await Clients.All.JournalUpdated(journals);
public async Task JournalUpdated(List<JournalBase> journals) => await Clients.All.JournalUpdated(journals);
public async Task ModuleInfoUpdated(ModuleInfoFile moduleInfo) => await Clients.All.ModuleInfoUpdated(moduleInfo);
@ -55,7 +58,7 @@ public interface IEventsHub
Task MarketUpdated(MarketFile market);
Task JournalUpdated(IReadOnlyCollection<JournalBase> journals);
Task JournalUpdated(List<JournalBase> journals);
Task ModuleInfoUpdated(ModuleInfoFile moduleInfo);

View File

@ -1,8 +1,8 @@
using System.Collections.Concurrent;
namespace Pulsar.Features;
using Observatory.Framework.Files;
using Observatory.Framework.Files.Journal;
using Observatory.Framework.Files.Journal.Odyssey;
namespace Pulsar.Features;
public interface IFileHandler
{

View File

@ -1,10 +1,9 @@
using Observatory.Framework.Files.Journal.StationServices;
namespace Pulsar.Features.Journal;
using Observatory.Framework;
using Observatory.Framework.Files.Journal;
using Observatory.Framework.Files.Journal.Startup;
using Observatory.Framework.Files.Journal.StationServices;
public class JournalProcessor(
ILogger<JournalProcessor> logger,

View File

@ -1,14 +1,36 @@
using Microsoft.EntityFrameworkCore;
using Observatory.Framework.Files.Journal.Startup;
using Observatory.Framework.Files.Journal.StationServices;
namespace Pulsar.Features.Journal;
using Observatory.Framework.Files.Journal;
public interface IJournalService : IJournalHandler<List<JournalBase>>
{
/// <summary>
/// Gets the Latest of the following (start of game) events:
/// Commander
/// Materials
/// Rank
/// Progress
/// Reputation
/// EngineerProgress
/// LoadGame
/// Statistics
/// </summary>
/// <returns></returns>
Task<List<JournalBase>> GetLastStartupEvents();
/// <summary>
/// Get the Latest of the following events:
/// <p>
/// Location<br/>
/// Powerplay<br/>
/// Music<br/>
/// ShipLocker<br/>
/// Missions<br/>
/// Loadout</p>
/// <p>When there are none of an event since the last game start, no event will be given.</p>
/// </summary>
/// <returns></returns>
Task<List<JournalBase>> GetLatestState();
}
public class JournalService(
@ -29,10 +51,8 @@ public class JournalService(
store.EnqueueFile(filePath);
return Task.CompletedTask;
}
// Start of game events/order:
/** Commander
* Materials
@ -51,7 +71,7 @@ public class JournalService(
Loadout
Cargo
*/
// StartupEvents:
// Commander
// Materials
@ -60,45 +80,19 @@ public class JournalService(
// Reputation
// EngineerProgress
// LoadGame
// StateEvents:
// Location
// Powerplay
// Music
// ShipLocker
// Missions
// Loadout
// Cargo
// -- ...
// Statistics
public async Task<List<JournalBase>> GetLastStartupEvents()
{
//TODO: add other state events
var commanderTask = context.Commander.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var materialsTask = context.Materials.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var rankTask = context.Rank.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var progressTask = context.Progress.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var reputationTask = context.Reputation.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var engineerProgressTask = context.EngineerProgress.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var loadGameTask = context.LoadGames.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var statisticsTask = context.Statistics.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var commander = await context.Commander.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var materials = await context.Materials.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var rank = await context.Rank.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var progress = await context.Progress.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var reputation = await context.Reputation.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var engineerProgress = await context.EngineerProgress.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var loadGame = await context.LoadGames.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var statistics = await context.Statistics.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
await Task.WhenAll(
commanderTask,
materialsTask,
rankTask,
progressTask,
reputationTask,
engineerProgressTask,
loadGameTask,
statisticsTask);
var commander = await commanderTask;
var materials = await materialsTask;
var rank = await rankTask;
var progress = await progressTask;
var reputation = await reputationTask;
var engineerProgress = await engineerProgressTask;
var loadGame = await loadGameTask;
var statistics = await statisticsTask;
// if any null, return empty list
if (materials == null || rank == null || progress == null || reputation == null || engineerProgress == null ||
@ -108,20 +102,62 @@ public class JournalService(
}
// dont check the time of statistics as it may occur a few moments after
if (commander.Timestamp != materials.Timestamp ||
materials.Timestamp != rank.Timestamp ||
rank.Timestamp != progress.Timestamp ||
progress.Timestamp != reputation.Timestamp ||
reputation.Timestamp != engineerProgress.Timestamp ||
engineerProgress.Timestamp != loadGame.Timestamp ||
statistics.Timestamp < materials.Timestamp)
if (commander.Timestamp > materials.Timestamp ||
commander.Timestamp > materials.Timestamp ||
commander.Timestamp > rank.Timestamp ||
commander.Timestamp > progress.Timestamp ||
commander.Timestamp > reputation.Timestamp ||
commander.Timestamp > engineerProgress.Timestamp ||
commander.Timestamp > loadGame.Timestamp ||
commander.Timestamp > statistics.Timestamp)
{
throw new InvalidOperationException("Timestamps do not match");
throw new InvalidOperationException("Timestamps are invalid");
}
return [commander, materials, rank, progress, reputation, engineerProgress, loadGame, statistics];
}
/// <summary>
/// StateEvents:
/// Location
/// Powerplay
/// Music
/// ShipLocker
/// Missions
/// Loadout
/// Cargo
/// </summary>
/// <returns></returns>
public async Task<List<JournalBase>> GetLatestState()
{
// dont get anything before the last command timestamp
var commander = await context.Commander.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
if (commander == null) return [];
var location = await context.Locations
.Where(x => x.Timestamp > commander.Timestamp)
.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var powerplay = await context.PowerPlay
.Where(x => x.Timestamp > commander.Timestamp)
.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var shiplocker = await context.ShipLocker
.Where(x => x.Timestamp > commander.Timestamp)
.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var missions = await context.Missions
.Where(x => x.Timestamp > commander.Timestamp)
.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var loadout = await context.Loadout
.Where(x => x.Timestamp > commander.Timestamp)
.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
var cargo = await context.Cargo
.Where(x => x.Timestamp > commander.Timestamp)
.OrderByDescending(x => x.Timestamp).FirstOrDefaultAsync();
return new List<JournalBase?> { location, powerplay, shiplocker, missions, loadout, cargo }
.Where(x => x != null).Cast<JournalBase>().ToList();
}
public async Task<List<JournalBase>> Get()
{
return [];

View File

@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using Observatory.Framework.Files.Journal.Startup;
using Pulsar.Context;
namespace Pulsar.Features.Status;

View File

@ -1,6 +1,9 @@
global using Pulsar;
global using Pulsar.Utils;
global using Pulsar.Context;
global using Pulsar.Features;
global using Pulsar.Features.Status;
global using Pulsar.Features.Journal;
global using System.Text;
global using System.Text.Json;
global using System.Text.Json.Nodes;
@ -8,4 +11,5 @@ global using System.Text.Json.Serialization;
global using Microsoft.AspNetCore.Mvc;
global using Microsoft.AspNetCore.SignalR;
global using Microsoft.Extensions.Options;
global using Microsoft.EntityFrameworkCore;
global using IEventHubContext = Microsoft.AspNetCore.SignalR.IHubContext<Pulsar.Features.EventsHub, Pulsar.Features.IEventsHub>;

View File

@ -1,15 +1,16 @@
using Lamar.Microsoft.DependencyInjection;
using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using Pulsar.Features;
using Pulsar.Features.Journal;
Console.WriteLine((string?)null!);
var builder = WebApplication.CreateBuilder(new WebApplicationOptions()
{
Args = args, WebRootPath = "static", ContentRootPath = "WebApp", ApplicationName = "Pulsar", EnvironmentName =
Args = args,
WebRootPath = "static",
ContentRootPath = "WebApp",
ApplicationName = "Pulsar",
EnvironmentName =
#if DEBUG
"Development"
#else