mirror of
https://github.com/nestriness/nestri.git
synced 2026-11-03 22:22:39 +02:00
feat(trial): the free days are Saturday, Sunday and Monday
Monday in place of Friday: the window is Saturday 00:00 to Tuesday 00:00, Helsinki time, and the refusal outside it says Saturday to Monday.
This commit is contained in:
+17
-12
@@ -126,12 +126,12 @@ async function playedBefore(
|
||||
}
|
||||
|
||||
describe('The weekend window', () => {
|
||||
test('Friday 00:00 to Monday 00:00 on the trial’s clock', () => {
|
||||
test('Saturday 00:00 to Tuesday 00:00 on the trial’s clock', () => {
|
||||
const closed = Trial.window(WEDNESDAY);
|
||||
expect(closed.open).toBe(false);
|
||||
// Summer time: midnight there is 21:00 UTC the day before.
|
||||
expect(closed.start.toISOString()).toBe('2026-10-08T21:00:00.000Z');
|
||||
expect(closed.end.toISOString()).toBe('2026-10-11T21:00:00.000Z');
|
||||
expect(closed.start.toISOString()).toBe('2026-10-09T21:00:00.000Z');
|
||||
expect(closed.end.toISOString()).toBe('2026-10-12T21:00:00.000Z');
|
||||
|
||||
const open = Trial.window(SATURDAY);
|
||||
expect(open.open).toBe(true);
|
||||
@@ -141,13 +141,18 @@ describe('The weekend window', () => {
|
||||
test('a weekend with a clock change in it is still three calendar days', () => {
|
||||
// Summer time ends in the early hours of Sunday 25 October 2026.
|
||||
const w = Trial.window(new Date('2026-10-24T12:00:00Z'));
|
||||
expect(w.start.toISOString()).toBe('2026-10-22T21:00:00.000Z');
|
||||
expect(w.end.toISOString()).toBe('2026-10-25T22:00:00.000Z');
|
||||
expect(w.start.toISOString()).toBe('2026-10-23T21:00:00.000Z');
|
||||
expect(w.end.toISOString()).toBe('2026-10-26T22:00:00.000Z');
|
||||
});
|
||||
|
||||
test('the last minute of Sunday is in; Monday 00:00 is out', () => {
|
||||
expect(Trial.window(new Date('2026-10-11T20:59:00Z')).open).toBe(true);
|
||||
expect(Trial.window(new Date('2026-10-11T21:00:00Z')).open).toBe(false);
|
||||
test('Monday is in; Friday is not', () => {
|
||||
expect(Trial.window(new Date('2026-10-12T12:00:00Z')).open).toBe(true);
|
||||
expect(Trial.window(new Date('2026-10-09T12:00:00Z')).open).toBe(false);
|
||||
});
|
||||
|
||||
test('the last minute of Monday is in; Tuesday 00:00 is out', () => {
|
||||
expect(Trial.window(new Date('2026-10-12T20:59:00Z')).open).toBe(true);
|
||||
expect(Trial.window(new Date('2026-10-12T21:00:00Z')).open).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -169,7 +174,7 @@ describe('POST /session on rented GPUs without a plan', () => {
|
||||
const s = await scene('trial-closed');
|
||||
const { res, body } = await play(s);
|
||||
expect(res.status).toBe(429);
|
||||
expect(body.message).toContain('Friday to Sunday');
|
||||
expect(body.message).toContain('Saturday to Monday');
|
||||
});
|
||||
|
||||
test('two hours used this weekend: 429', async () => {
|
||||
@@ -179,7 +184,7 @@ describe('POST /session on rented GPUs without a plan', () => {
|
||||
s.box.id,
|
||||
s.gameId,
|
||||
s.owner.linkedAccountId,
|
||||
new Date('2026-10-09T10:00:00Z'),
|
||||
new Date('2026-10-10T08:00:00Z'),
|
||||
120
|
||||
);
|
||||
const { res, body } = await play(s);
|
||||
@@ -286,9 +291,9 @@ describe('Stopping a trial run', () => {
|
||||
});
|
||||
|
||||
test('when the window closes: stopped, for the window', async () => {
|
||||
at(new Date('2026-10-11T21:05:00Z'));
|
||||
at(new Date('2026-10-12T21:05:00Z'));
|
||||
const s = await scene('stop-window');
|
||||
const id = await liveTrialRun(s, new Date('2026-10-11T20:30:00Z'));
|
||||
const id = await liveTrialRun(s, new Date('2026-10-12T20:30:00Z'));
|
||||
const stops = (await jobs(s)).filter((j) => j.kind === 'session.stop');
|
||||
expect(stops).toEqual([
|
||||
{ kind: 'session.stop', sessionId: id, boxId: s.box.id, reason: 'window' }
|
||||
|
||||
@@ -18,8 +18,9 @@ import { TrialClaimTable } from './trial.sql.js';
|
||||
*
|
||||
* Three rules and nothing else:
|
||||
*
|
||||
* - **When.** Friday 00:00 to Monday 00:00, on the clock of the place the
|
||||
* hardware is run from. Outside that, a trial run is refused, and one still
|
||||
* - **When.** Saturday 00:00 to Tuesday 00:00 — Saturday, Sunday and
|
||||
* Monday, Monday in place of Friday since 2026-10-11 — on the clock of the
|
||||
* place the hardware is run from. Outside that, a trial run is refused, and one still
|
||||
* going when it closes is stopped.
|
||||
* - **How much.** {@link HOURS} of live time per window, across every run.
|
||||
* Unlike a plan's allowance, this one stops a run that reaches it: the
|
||||
@@ -104,14 +105,14 @@ export namespace Trial {
|
||||
/** The weekend window an instant is in, or the next one if it is in none. */
|
||||
export function window(at: Date = now()): Window {
|
||||
const today = localDay(at);
|
||||
const sinceFriday = (today.weekday - 5 + 7) % 7; // Fri 0, Sat 1, Sun 2, Mon 3 …
|
||||
const open = sinceFriday <= 2;
|
||||
const friday = addDays(today, open ? -sinceFriday : 7 - sinceFriday);
|
||||
const monday = addDays(friday, 3);
|
||||
const sinceSaturday = (today.weekday - 6 + 7) % 7; // Sat 0, Sun 1, Mon 2, Tue 3 …
|
||||
const open = sinceSaturday <= 2;
|
||||
const saturday = addDays(today, open ? -sinceSaturday : 7 - sinceSaturday);
|
||||
const tuesday = addDays(saturday, 3);
|
||||
return {
|
||||
open,
|
||||
start: midnight(friday.year, friday.month, friday.day),
|
||||
end: midnight(monday.year, monday.month, monday.day)
|
||||
start: midnight(saturday.year, saturday.month, saturday.day),
|
||||
end: midnight(tuesday.year, tuesday.month, tuesday.day)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -190,7 +191,7 @@ export namespace Trial {
|
||||
throw new VisibleError(
|
||||
'rate_limit',
|
||||
ErrorCodes.RateLimit.QUOTA_EXCEEDED,
|
||||
`Free play on Nestri GPUs is Friday to Sunday. The next window opens ${when(w.start)}.`
|
||||
`Free play on Nestri GPUs is Saturday to Monday. The next window opens ${when(w.start)}.`
|
||||
);
|
||||
}
|
||||
if ((await usedSeconds(input.userId, w, at)) >= SECONDS) {
|
||||
|
||||
Reference in New Issue
Block a user