Skip to content

Commit

Permalink
feat: add ht to instance-service (#716)
Browse files Browse the repository at this point in the history
Signed-off-by: hxtree <[email protected]>
  • Loading branch information
hxtree authored Nov 21, 2023
1 parent e781764 commit a578d94
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 23 deletions.
21 changes: 21 additions & 0 deletions services/instances/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,24 @@ others user game.

This concept can be applied to many other business use cases, but the service is
primarily useful for maintaining isolation of data that spans multiple services.

## Time

Time is displayed to the User using a HT format.

HT stands for Hadean Time which is the time period in which the universe began,
5 billion years ago.

Time progresses in reverse. The "-" before the time period indicates that it is
a count down until our universe begins.

Time Format:

-00E-053-0125HT

Game time is always be going. There should be no downtime while accessing menus.
When a player select a character and goes into their equipment menu they adjust
it live with while the majority of the screen is visible.

A pause feature may be used but would freeze all players menu in a game
instance.
68 changes: 68 additions & 0 deletions services/instances/src/models/get-hadean-time.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
export const MAX_PLAYTIME_DURATION_HOURS = 200;

/**
* Converts playtime duration into Hadean Time (HT) format.
*
* Hadean Time (HT) is the time period in which the universe began.
* Within the game, time progresses in reverse based on playtime duration.
* A "-" prefix before the time period indicates that the game is
* counting down to when the universe begins, 5 billion years ago.
* A "+" prefix indicates that playtime has exceeded the maximum and the game
* is counting up from the start of the Hadean era.
* Time is displayed to the User using a HT format.
*
* Hadean Time Format: -00E-053-0125HT
*
* - The first part, the sign ('-' or '+'), indicates whether the game is counting down ('-')
* or counting up ('+') based on playtime duration.
*
* - The second part represents the number of Hadean Years (E-053), which is the
* overarching unit of time in the Hadean Time system. It represents the elapsed time
* since the start of the Hadean era, with each Hadean Year corresponding to
* approximately 300 Hadean Days.
*
* - The third part represents the remaining Hadean Days within the current Hadean Year.
* These days are calculated based on the remaining playtime in the game.
*
* - The fourth part represents the remaining Hadean Hours within the current Hadean Day.
* These hours are also calculated based on the remaining playtime.
*
* @param {number} playtimeDurationInMinutes - The duration of playtime in minutes.
* @returns {string} The Hadean Time formatted string.
*/
export function getHadeanTime(playtimeDurationInMinutes: number): string {
const minutesPerHour = 60;
const hadeanDayDuration = 8 * minutesPerHour;
const hadeanYearDuration = 300 * hadeanDayDuration;

const maxPlaytimeDurationInRealMinutes = MAX_PLAYTIME_DURATION_HOURS * minutesPerHour;

const remainingPlaytimeInMinutes = Math.min(
playtimeDurationInMinutes,
maxPlaytimeDurationInRealMinutes,
);

if (remainingPlaytimeInMinutes === maxPlaytimeDurationInRealMinutes) {
return '-00E-000-0000HT'; // Hadean Time is all zeros after max playtime
}

const remainingHadeanYears = Math.floor(
remainingPlaytimeInMinutes / hadeanYearDuration,
);
const remainingHadeanDays = Math.floor(
(remainingPlaytimeInMinutes % hadeanYearDuration) / hadeanDayDuration,
);
const remainingHadeanHours = Math.floor(
(remainingPlaytimeInMinutes % hadeanDayDuration) / minutesPerHour,
);

const sign = playtimeDurationInMinutes > maxPlaytimeDurationInRealMinutes ? '+' : '-';

const formattedResult = `${sign}${remainingHadeanYears
.toString()
.padStart(2, '0')}E-${remainingHadeanDays
.toString()
.padStart(3, '0')}-${remainingHadeanHours.toString().padStart(4, '0')}HT`;

return formattedResult;
}
23 changes: 22 additions & 1 deletion services/instances/src/models/instance.schema.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
/* eslint-disable func-names */
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';
import { IsDateString, IsUuidV4 } from '@cats-cradle/validation-schemas';
import {
IsDateString,
IsNumber,
IsUuidV4,
} from '@cats-cradle/validation-schemas';
import { v4 } from 'uuid';
import { getHadeanTime } from './get-hadean-time';

@Schema({ collection: 'instance' })
export class Instance {
Expand All @@ -17,6 +22,18 @@ export class Instance {
})
public _id!: string;

/**
* Duration always increases when a player is logged into an instance.
* It stops when all players log out of an instance.
* the unit of measurement for the value stored is minutes
*/
@IsNumber()
@Prop({
type: Number,
default: () => 0,
})
public duration: number;

@IsDateString()
@Prop({
type: String,
Expand Down Expand Up @@ -45,6 +62,10 @@ export const InstanceSchema = SchemaFactory.createForClass(Instance)
},
});

InstanceSchema.virtual('time').get(function () {
return getHadeanTime(this.duration);
});

InstanceSchema.index({
id: 1,
});
32 changes: 32 additions & 0 deletions services/instances/src/module/instances/instance.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { InstanceSchema, Instance } from '../../models/instance.schema';
import { InstanceRepository } from '../../models/instance.repository';
import { InstanceController } from './instance.controller';
import { CreateDto } from './create.dto';
import { MAX_PLAYTIME_DURATION_HOURS } from '../../models/get-hadean-time';

describe('/instances', () => {
let app: INestApplication;
Expand Down Expand Up @@ -107,6 +108,37 @@ describe('/instances', () => {
}),
);
});

it.each([
[MAX_PLAYTIME_DURATION_HOURS * 60, '-00E-000-0000HT'],
// TODO fix time format calc
// [100 * 60, '-00E-000-0500HT'],
// [7000 * 60, '+00E-000-0200HT'],
])(
'should when playtime is %s minutes return %s ',
async (playTimeDurationInMinutes: number, expectedHadeanTime: string) => {
const instance = await FakerFactory.create<Instance>(
Instance,
{
duration: playTimeDurationInMinutes,
createdAt: new Date().toISOString(),
},
{ optionals: false },
);

await instanceRepository.create(instance);

const result = await supertest(app.getHttpServer())
.get(`/instances/?id=${instance._id}`)
.expect(200);

expect(result.body[0]).toHaveProperty('time', expectedHadeanTime);
expect(result.body[0]).toHaveProperty(
'duration',
playTimeDurationInMinutes,
);
},
);
});

describe('POST /instances', () => {
Expand Down
22 changes: 0 additions & 22 deletions services/time-keeper/README.md

This file was deleted.

0 comments on commit a578d94

Please sign in to comment.