Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions docs/db_structure/database_schema_documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ Generated from DBML structure.
- [season_tier_claims](#season-tier-claims)
- [season_tiers](#season-tiers)
- [seasons](#seasons)
- [serverwideepbonus](#serverwideepbonus)
- [serverinfo](#serverinfo)
- [settings](#settings)
- [siegeitems](#siegeitems)
Expand Down Expand Up @@ -6344,6 +6345,27 @@ Rows older than 90 days are pruned by `recalculate_raw_material_prices`.

---

## serverwideepbonus

**Schema:** `dbo`

Singleton persistence for the currently active aggregate server-wide EP bonus. Timestamps are real UTC instants; this is unrelated to the three-hour in-game day/night presentation.

### Columns

| Column | Definition |
|---|---|
| `id` | `tinyint [not null, pk, check: 1]` |
| `bonus` | `int [not null, check: 0..25]` |
| `expiresatutc` | `datetime2(3) [null]` |
| `updatedatutc` | `datetime2(3) [not null]` |

### Constraints

- `bonus = 0` requires `expiresatutc` to be `NULL`; an active bonus requires a UTC expiry.

---

## serverinfo

**Schema:** `dbo`
Expand Down
3 changes: 2 additions & 1 deletion src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ private void InitRelayManager()
_ = _builder.RegisterType<GoodiePackHandler>();

// OPP: EPBonusEventService singleton
_ = _builder.RegisterType<ServerWideEpBonusRepository>().As<IServerWideEpBonusRepository>().SingleInstance();
_ = _builder.RegisterType<EPBonusEventService>().SingleInstance().OnActivated(e =>
{
e.Context.Resolve<IProcessManager>().AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromMinutes(1)));
Expand Down Expand Up @@ -717,4 +718,4 @@ private IRegistrationBuilder<T, ConcreteReflectionActivatorData, SingleRegistrat
});
}
}
}
}
19 changes: 3 additions & 16 deletions src/Perpetuum.RequestHandlers/EPBonusEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ namespace Perpetuum.RequestHandlers
public class EPBonusEvent : IRequestHandler
{
private readonly EPBonusEventService _eventService;
private readonly TimeSpan MAX_DURATION = TimeSpan.FromDays(14);
private const int MIN_BONUS = 0;
private const int MAX_BONUS = 25;

public EPBonusEvent(EPBonusEventService eventService)
{
_eventService = eventService;
Expand All @@ -19,21 +15,12 @@ public EPBonusEvent(EPBonusEventService eventService)
public void HandleRequest(IRequest request)
{
using System.Transactions.TransactionScope scope = Db.CreateTransaction();
int existingBonus = _eventService.GetBonus();
int bonusAmount = request.Data.GetOrDefault<int>(k.bonus);
int resultingBonus = existingBonus + bonusAmount;

double timeRemained = _eventService.GetTimeRemained().TotalHours;
double durationHours = request.Data.GetOrDefault<int>(k.duration);
double resultingTime = timeRemained + durationHours;

bool checkArgs = resultingBonus is >= MIN_BONUS and <= MAX_BONUS;
checkArgs = checkArgs && resultingTime <= MAX_DURATION.TotalHours;
checkArgs.ThrowIfFalse(ErrorCodes.InputTooHigh);
int durationHours = request.Data.GetOrDefault<int>(k.duration);

_eventService.SetEvent(resultingBonus, TimeSpan.FromHours(resultingTime));
_eventService.Activate(bonusAmount, TimeSpan.FromHours(durationHours));

scope.Complete();
}
}
}
}
13 changes: 12 additions & 1 deletion src/Perpetuum.RequestHandlers/UseLotteryItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -373,10 +373,21 @@ private void HandleServerWideEpBooster(IRequest request, long itemEid)
Transaction.Current.OnCommited(() =>
{
accountRepository.Update(account);
Message.Builder
.SetCommand(Commands.ServerMessage)
.WithData(new Dictionary<string, object>
{
{ k.message, MessageConstants.ServerWideEpBonusActivated },
{ k.type, 0 },
{ k.recipients, 0 },
{ k.translate, 1 },
})
.ToAll()
.Send();
});

scope.Complete();
}
}
}
}
}
62 changes: 62 additions & 0 deletions src/Perpetuum.Tests/Unit/ServerWideEpBonusStateTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using Perpetuum.Services.EventServices;
using Xunit;

namespace Perpetuum.Tests.Unit
{
public class ServerWideEpBonusStateTests
{
private static readonly DateTime Now = new(2049, 1, 2, 3, 4, 5, DateTimeKind.Utc);

[Fact]
public void Five_plus_five_activations_stack_to_plus_twenty_five_for_one_hundred_twenty_hours()
{
var state = ServerWideEpBonusState.None;

for (var i = 0; i < 5; i++)
{
state = EPBonusEventService.CalculateNextState(state, 5, TimeSpan.FromHours(24), Now);
}

Assert.Equal(25, state.Bonus);
Assert.Equal(Now.AddHours(120), state.ExpiresAtUtc);
}

[Fact]
public void Activation_adds_duration_to_remaining_time()
{
var existing = new ServerWideEpBonusState(20, Now.AddHours(90));

var state = EPBonusEventService.CalculateNextState(existing, 5, TimeSpan.FromHours(24), Now);

Assert.Equal(25, state.Bonus);
Assert.Equal(Now.AddHours(114), state.ExpiresAtUtc);
}

[Fact]
public void Expired_state_is_not_reactivated_or_extended()
{
var expired = new ServerWideEpBonusState(25, Now.AddTicks(-1));

var state = EPBonusEventService.CalculateNextState(expired, 5, TimeSpan.FromHours(24), Now);

Assert.Equal(5, state.Bonus);
Assert.Equal(Now.AddHours(24), state.ExpiresAtUtc);
}

[Fact]
public void Bonus_above_twenty_five_is_rejected()
{
var existing = new ServerWideEpBonusState(25, Now.AddHours(24));

Assert.Throws<PerpetuumException>(() => EPBonusEventService.CalculateNextState(existing, 5, TimeSpan.FromHours(24), Now));
}

[Fact]
public void Duration_above_fourteen_days_is_rejected()
{
var existing = new ServerWideEpBonusState(5, Now.AddHours(336));

Assert.Throws<PerpetuumException>(() => EPBonusEventService.CalculateNextState(existing, 5, TimeSpan.FromHours(1), Now));
}
}
}
14 changes: 0 additions & 14 deletions src/Perpetuum/Items/ServerWideEpBooster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,6 @@ public void Activate(ISession session)

session.HandleLocalRequest(epBoost);

Request message = new Request
{
Command = Commands.ServerMessage,
Session = session,
Data = new Dictionary<string, object>
{
{ k.message, MessageConstants.ServerWideEpBonusActivated },
{ k.type, 0 },
{ k.recipients, 0 },
{ k.translate, 1 },
},
};

session.HandleLocalRequest(message);
}
}
}
Loading