Skip to content

Commit b3b620e

Browse files
committed
Create effects concept
1 parent 32020c7 commit b3b620e

File tree

10 files changed

+525
-68
lines changed

10 files changed

+525
-68
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROP TABLE `user_effect`;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CREATE TABLE `user_effect` (
2+
`Id` varchar(255) NOT NULL,
3+
`WhenCreated` datetime NOT NULL,
4+
`WhenUpdated` datetime NOT NULL,
5+
`Name` varchar(255) NOT NULL,
6+
`UserId` varchar(255) NOT NULL,
7+
`Unused` int NOT NULL DEFAULT 0,
8+
`WhenExpires` datetime NULL,
9+
PRIMARY KEY (`Id`)
10+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

jest.setup.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
jest.setTimeout(1 * 1000); // 1 second
22
jest.resetModules();
3-
jest.resetAllMocks();
3+
jest.resetAllMocks();
4+
jest.useFakeTimers();

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"clean": "rm -rf node_modules/ dist/",
88
"build": "tsc",
99
"start": "node ./dist/bot.js",
10-
"test": "echo true",
10+
"test": "jest",
1111
"lint": "eslint .",
1212
"lint:fix": "eslint . --fix",
1313
"db:up": "typeorm migration:run -d dist/database/dataSources/appDataSource.js",
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import {Column, Entity} from "typeorm";
2+
import AppBaseEntity from "../../../contracts/AppBaseEntity";
3+
import AppDataSource from "../../dataSources/appDataSource";
4+
5+
@Entity()
6+
export default class UserEffect extends AppBaseEntity {
7+
constructor(name: string, userId: string, unused: number, WhenExpires?: Date) {
8+
super();
9+
10+
this.Name = name;
11+
this.UserId = userId;
12+
this.Unused = unused;
13+
this.WhenExpires = WhenExpires;
14+
}
15+
16+
@Column()
17+
Name: string;
18+
19+
@Column()
20+
UserId: string;
21+
22+
@Column()
23+
Unused: number;
24+
25+
@Column({ nullable: true })
26+
WhenExpires?: Date;
27+
28+
public AddUnused(amount: number) {
29+
this.Unused += amount;
30+
}
31+
32+
public UseEffect(whenExpires: Date): boolean {
33+
if (this.Unused == 0) {
34+
return false;
35+
}
36+
37+
this.Unused -= 1;
38+
this.WhenExpires = whenExpires;
39+
40+
return true;
41+
}
42+
43+
public IsEffectActive(): boolean {
44+
const now = new Date();
45+
46+
if (this.WhenExpires && now < this.WhenExpires) {
47+
return true;
48+
}
49+
50+
return false;
51+
}
52+
53+
public static async FetchOneByUserIdAndName(userId: string, name: string): Promise<UserEffect | null> {
54+
const repository = AppDataSource.getRepository(UserEffect);
55+
56+
const single = await repository.findOne({ where: { UserId: userId, Name: name } });
57+
58+
return single;
59+
}
60+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { MigrationInterface, QueryRunner } from "typeorm";
2+
import MigrationHelper from "../../../../helpers/MigrationHelper";
3+
4+
export class CreateUserEffect1729962056556 implements MigrationInterface {
5+
6+
public async up(queryRunner: QueryRunner): Promise<void> {
7+
MigrationHelper.Up("1729962056556-createUserEffect", "0.9", [
8+
"01-table-userEffect",
9+
], queryRunner);
10+
}
11+
12+
public async down(queryRunner: QueryRunner): Promise<void> {
13+
MigrationHelper.Down("1729962056556-createUserEffect", "0.9", [
14+
"01-table-userEffect",
15+
], queryRunner);
16+
}
17+
18+
}

src/helpers/EffectHelper.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import UserEffect from "../database/entities/app/UserEffect";
2+
3+
export default class EffectHelper {
4+
public static async AddEffectToUserInventory(userId: string, name: string, quantity: number = 1) {
5+
let effect = await UserEffect.FetchOneByUserIdAndName(userId, name);
6+
7+
if (!effect) {
8+
effect = new UserEffect(name, userId, quantity);
9+
} else {
10+
effect.AddUnused(quantity);
11+
}
12+
13+
await effect.Save(UserEffect, effect);
14+
}
15+
16+
public static async UseEffect(userId: string, name: string, whenExpires: Date): Promise<boolean> {
17+
const effect = await UserEffect.FetchOneByUserIdAndName(userId, name);
18+
const now = new Date();
19+
20+
if (!effect || effect.Unused == 0) {
21+
return false;
22+
}
23+
24+
if (effect.WhenExpires && now < effect.WhenExpires) {
25+
return false;
26+
}
27+
28+
effect.UseEffect(whenExpires);
29+
30+
await effect.Save(UserEffect, effect);
31+
32+
return true;
33+
}
34+
35+
public static async HasEffect(userId: string, name: string): Promise<boolean> {
36+
const effect = await UserEffect.FetchOneByUserIdAndName(userId, name);
37+
const now = new Date();
38+
39+
if (!effect || !effect.WhenExpires) {
40+
return false;
41+
}
42+
43+
if (now > effect.WhenExpires) {
44+
return false;
45+
}
46+
47+
return true;
48+
}
49+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import UserEffect from "../../../../src/database/entities/app/UserEffect";
2+
3+
let userEffect: UserEffect;
4+
const now = new Date();
5+
6+
beforeEach(() => {
7+
userEffect = new UserEffect("name", "userId", 1);
8+
});
9+
10+
describe("AddUnused", () => {
11+
beforeEach(() => {
12+
userEffect.AddUnused(1);
13+
});
14+
15+
test("EXPECT unused to be the amount more", () => {
16+
expect(userEffect.Unused).toBe(2);
17+
});
18+
});
19+
20+
describe("UseEffect", () => {
21+
describe("GIVEN Unused is 0", () => {
22+
let result: boolean;
23+
24+
beforeEach(() => {
25+
userEffect.Unused = 0;
26+
27+
result = userEffect.UseEffect(now);
28+
});
29+
30+
test("EXPECT false returned", () => {
31+
expect(result).toBe(false);
32+
});
33+
34+
test("EXPECT details not to be changed", () => {
35+
expect(userEffect.Unused).toBe(0);
36+
expect(userEffect.WhenExpires).toBeUndefined();
37+
});
38+
});
39+
40+
describe("GIVEN Unused is greater than 0", () => {
41+
let result: boolean;
42+
43+
beforeEach(() => {
44+
result = userEffect.UseEffect(now);
45+
});
46+
47+
test("EXPECT true returned", () => {
48+
expect(result).toBe(true);
49+
});
50+
51+
test("EXPECT Unused to be subtracted by 1", () => {
52+
expect(userEffect.Unused).toBe(0);
53+
});
54+
55+
test("EXPECT WhenExpires to be set", () => {
56+
expect(userEffect.WhenExpires).toBe(now);
57+
});
58+
});
59+
});
60+
61+
describe("IsEffectActive", () => {
62+
describe("GIVEN WhenExpires is null", () => {
63+
let result: boolean;
64+
65+
beforeEach(() => {
66+
result = userEffect.IsEffectActive();
67+
});
68+
69+
test("EXPECT false returned", () => {
70+
expect(result).toBe(false);
71+
});
72+
});
73+
74+
describe("GIVEN WhenExpires is defined", () => {
75+
describe("AND WhenExpires is in the past", () => {
76+
let result: boolean;
77+
78+
beforeEach(() => {
79+
userEffect.WhenExpires = new Date(now.getTime() - 100);
80+
81+
result = userEffect.IsEffectActive();
82+
});
83+
84+
test("EXPECT false returned", () => {
85+
expect(result).toBe(false);
86+
});
87+
});
88+
89+
describe("AND WhenExpires is in the future", () => {
90+
let result: boolean;
91+
92+
beforeEach(() => {
93+
userEffect.WhenExpires = new Date(now.getTime() + 100);
94+
95+
result = userEffect.IsEffectActive();
96+
});
97+
98+
test("EXPECT true returned", () => {
99+
expect(result).toBe(true);
100+
});
101+
});
102+
});
103+
});

0 commit comments

Comments
 (0)