Skip to content

Commit 246ed80

Browse files
committed
Refactoring
1 parent c72ad2b commit 246ed80

10 files changed

+79
-86
lines changed

src/app.module.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,17 @@ import { PlayerController } from 'rest/player.controller';
1313
import { InfoController } from 'rest/info.controller';
1414
import { PlayerService } from 'rest/service/player.service';
1515
import { ScheduleModule } from '@nestjs/schedule';
16-
import { MetaController } from 'rest/meta.controller';
17-
import { MetaService } from 'rest/service/meta.service';
16+
import { MetaController } from 'rest/meta/meta.controller';
17+
import { MetaService } from 'rest/meta/meta.service';
1818
import { GetUserInfoQuery } from 'gateway/queries/GetUserInfo/get-user-info.query';
1919
import { outerQuery } from 'gateway/util/outerQuery';
2020
import { QueryCache } from 'rcache';
2121
import { CacheModule } from '@nestjs/cache-manager';
22-
import { MatchService } from 'rest/service/match.service';
22+
import { MatchService } from 'rest/match/match.service';
2323
import { CrimeController } from 'rest/crime.controller';
2424
import { MatchMapper } from 'rest/match/match.mapper';
2525
import { MatchController } from 'rest/match/match.controller';
26+
import { MetaMapper } from 'rest/meta/meta.mapper';
2627

2728

2829
export function qCache<T, B>() {
@@ -71,6 +72,7 @@ export function qCache<T, B>() {
7172
MatchService,
7273
PlayerService,
7374
MatchMapper,
75+
MetaMapper,
7476
Mapper,
7577
...GameServerDomain,
7678
outerQuery(GetUserInfoQuery, 'QueryCore', qCache())

src/gameserver/model/player-crime-log.entity.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@ export class PlayerCrimeLogEntity {
1212
@Column()
1313
crime: BanReason;
1414

15-
@Column({ default: true })
16-
handled: boolean
15+
@Column({ default: false })
16+
handled: boolean;
1717

1818
@Column({ default: 0 })
1919
banTime: number;
2020

21-
@CreateDateColumn()
21+
@CreateDateColumn({ type: "timestamptz" })
2222
created_at: Date;
23-
2423
}

src/rest/match/match-controller.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import FinishedMatchEntity from 'gameserver/model/finished-match.entity';
66
import PlayerInMatchEntity from 'gameserver/model/player-in-match.entity';
77
import { MatchController } from './match.controller';
88
import { createFakeMatch, fillMatch } from '@test/create-fake-match';
9-
import { MatchService } from 'rest/service/match.service';
109
import { MmrChangeLogEntity } from 'gameserver/model/mmr-change-log.entity';
1110
import { MatchMapper } from 'rest/match/match.mapper';
1211
import { MatchEntity } from 'gameserver/model/match.entity';
1312
import { NestApplication } from '@nestjs/core';
1413
import * as request from 'supertest';
1514
import { makePage } from 'gateway/util/make-page';
15+
import { MatchService } from 'rest/match/match.service';
1616

1717
describe("MatchController", () => {
1818
jest.setTimeout(60000);

src/rest/match/match.controller.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { MatchmakingMode } from 'gateway/shared-types/matchmaking-mode';
77
import { NullableIntPipe } from 'util/pipes';
88
import FinishedMatchEntity from 'gameserver/model/finished-match.entity';
99
import PlayerInMatchEntity from 'gameserver/model/player-in-match.entity';
10-
import { MatchService } from 'rest/service/match.service';
10+
import { MatchService } from './match.service';
1111
import { MmrChangeLogEntity } from 'gameserver/model/mmr-change-log.entity';
1212
import { makePage } from 'gateway/util/make-page';
1313
import { MatchMapper } from 'rest/match/match.mapper';
File renamed without changes.

src/rest/meta.controller.ts

-34
This file was deleted.

src/rest/meta/meta.controller.ts

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Controller, Get, Param } from '@nestjs/common';
2+
import { ApiTags } from '@nestjs/swagger';
3+
import { MetaService } from './meta.service';
4+
import { NullableIntPipe } from 'util/pipes';
5+
import { HeroItemDto, HeroSummaryDto, ItemDto, ItemHeroDto } from 'rest/dto/meta.dto';
6+
import { MetaMapper } from 'rest/meta/meta.mapper';
7+
8+
@Controller("meta")
9+
@ApiTags("meta")
10+
export class MetaController {
11+
constructor(
12+
private readonly metaService: MetaService,
13+
private readonly mapper: MetaMapper,
14+
) {}
15+
16+
@Get("heroes")
17+
public async heroes(): Promise<HeroSummaryDto[]> {
18+
return this.metaService.heroesSummary();
19+
}
20+
21+
@Get("heroes/:hero")
22+
public async heroData(@Param("hero") hero: string): Promise<HeroItemDto[]> {
23+
return this.metaService.heroMeta(hero);
24+
}
25+
26+
@Get("items")
27+
public async items(): Promise<ItemDto[]> {
28+
return (await this.metaService.items()).map(this.mapper.mapItem);
29+
}
30+
31+
@Get("items/:item")
32+
public async itemData(
33+
@Param("item", NullableIntPipe) item: number,
34+
): Promise<ItemHeroDto[]> {
35+
return (await this.metaService.itemHeroes(item)).map((it) => ({
36+
item: it.item_id,
37+
hero: it.hero,
38+
wins: it.wins,
39+
played: it.played,
40+
}));
41+
}
42+
}

src/rest/meta/meta.mapper.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Injectable } from '@nestjs/common';
2+
import { ItemHeroView } from 'gameserver/model/item-hero.view';
3+
import { ItemDto, ItemHeroDto } from 'rest/dto/meta.dto';
4+
import { ItemView } from 'gameserver/model/item.view';
5+
6+
@Injectable()
7+
export class MetaMapper {
8+
public mapItemHero = (it: ItemHeroView): ItemHeroDto => ({
9+
item: it.item_id,
10+
hero: it.hero,
11+
wins: it.wins,
12+
played: it.played,
13+
});
14+
15+
public mapItem = (it: ItemView): ItemDto => ({
16+
item: it.item_id,
17+
popularity: it.popularity,
18+
games: it.games_played,
19+
wins: it.wins,
20+
});
21+
}

src/rest/service/meta.service.ts src/rest/meta/meta.service.ts

+5-42
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import { Injectable } from '@nestjs/common';
22
import { InjectRepository } from '@nestjs/typeorm';
3-
import { Connection, In, Repository } from 'typeorm';
3+
import { Repository } from 'typeorm';
44
import { HeroItemDto, HeroSummaryDto } from 'rest/dto/meta.dto';
55
import { MatchmakingMode } from 'gateway/shared-types/matchmaking-mode';
6-
import { Page } from 'rest/dto/page';
7-
import { cached } from 'util/method-cache';
86
import FinishedMatchEntity from 'gameserver/model/finished-match.entity';
97
import PlayerInMatchEntity from 'gameserver/model/player-in-match.entity';
108
import { ItemHeroView } from 'gameserver/model/item-hero.view';
@@ -17,50 +15,14 @@ export class MetaService {
1715
private readonly playerInMatchRepository: Repository<PlayerInMatchEntity>,
1816
@InjectRepository(FinishedMatchEntity)
1917
private readonly matchRepository: Repository<FinishedMatchEntity>,
20-
private readonly connection: Connection,
2118
@InjectRepository(ItemHeroView)
2219
private readonly itemHeroViewRepository: Repository<ItemHeroView>,
2320
@InjectRepository(ItemView)
2421
private readonly itemViewRepository: Repository<ItemView>,
2522
) {}
2623

27-
@cached(60 * 24, 'meta_heroMatches')
28-
public async heroMatches(
29-
page: number,
30-
perPage: number,
31-
hero: string,
32-
): Promise<Page<FinishedMatchEntity>> {
33-
const [ids, count] = await this.matchRepository
34-
.createQueryBuilder('m')
35-
.select(['m.id', 'm.timestamp'])
36-
.addOrderBy('m.timestamp', 'DESC')
37-
.leftJoin('m.players', 'pims')
38-
.where('pims.hero = :hero', { hero })
39-
.andWhere('m.matchmaking_mode in (:...modes)', {
40-
modes: [MatchmakingMode.RANKED, MatchmakingMode.UNRANKED],
41-
})
42-
.take(perPage)
43-
.skip(perPage * page)
44-
.getManyAndCount();
45-
46-
const mapped = await this.matchRepository.find({
47-
where: {
48-
id: In(ids.map(t => t.id)),
49-
},
50-
});
51-
52-
return {
53-
data: mapped,
54-
page,
55-
perPage: perPage,
56-
pages: Math.ceil(count / perPage),
57-
};
58-
}
59-
60-
// 24 hours
61-
@cached(60 * 24, 'meta_heroesSummary')
6224
public async heroesSummary(): Promise<HeroSummaryDto[]> {
63-
return this.connection.query(
25+
return this.playerInMatchRepository.query(
6426
`with picks as (select count(*) as cnt from player_in_match p)
6527
SELECT "pim"."hero" AS "hero",
6628
(count(pim.hero)::float / greatest(1, s.cnt))::float as pickrate,
@@ -87,7 +49,8 @@ GROUP BY "pim"."hero", s.cnt`,
8749
* This is a heavy method that should be cached
8850
* @param hero
8951
*/
90-
public async heroMeta(hero: string) {
52+
53+
public async heroMeta(hero: string): Promise<HeroItemDto[]> {
9154
// This query finds all unique items bought on hero, games that played on this hero, and then counts winrates
9255
const query = `with games as (select pim.item0,
9356
pim.item1,
@@ -107,7 +70,7 @@ GROUP BY "pim"."hero", s.cnt`,
10770
group by i.item_id) select w.item, w.wins::int, w.game_count::int, w.winrate::float from winrates w where w.game_count > 10 and w.item != 0
10871
order by w.game_count desc`;
10972

110-
return this.connection.query<HeroItemDto[]>(query, [hero]);
73+
return this.playerInMatchRepository.query(query, [hero]);
11174
}
11275

11376
public async itemHeroes(item: number): Promise<ItemHeroView[]> {

src/util/typeorm-config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export const prodDbConfig: TypeOrmModuleOptions = {
7979
dropSchema: false,
8080
poolSize: 50,
8181

82-
// maxQueryExecutionTime: 10,
82+
// maxQueryExecutionTime: 100,
8383

8484
ssl: false,
8585
};

0 commit comments

Comments
 (0)