Skip to content

Commit

Permalink
Merge pull request #131 from game-node-app/dev
Browse files Browse the repository at this point in the history
Deprecated game filter's exclusion system
  • Loading branch information
Lamarcke authored Dec 10, 2024
2 parents fe982bb + 709b866 commit 4d2da42
Show file tree
Hide file tree
Showing 14 changed files with 47 additions and 262 deletions.
Binary file added public/icons/a-survivor-is-born.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/delivery-system.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion server_swagger.json

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions src/achievements/achievements.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ export enum AchievementCategory {
COLLECTIONS,
FOLLOWERS,
REVIEWS,
REVIEW_COMMENTS,
COMMENTS,
MISC,
}

export const ACHIEVEMENTS_GAME_IDS = {
JUST_DANCE_IDS: [],
};
TOMB_RAIDER_2013: 1164,
DEATH_STRANDING_IDS: [19564, 152063, 228530],
} as const;

export const ACHIEVEMENTS_GAME_THEMES_IDS = {
HORROR_ID: 19,
};
} as const;
20 changes: 19 additions & 1 deletion src/achievements/data/achievements-collections.data.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Achievement } from "../models/achievement.model";
import {
AchievementCategory,
ACHIEVEMENTS_GAME_IDS,
ACHIEVEMENTS_GAME_THEMES_IDS,
} from "../achievements.constants";
import { Review } from "../../reviews/entities/review.entity";
import { Collection } from "../../collections/entities/collection.entity";
import { CollectionEntry } from "../../collections/collections-entries/entities/collection-entry.entity";

Expand Down Expand Up @@ -97,4 +97,22 @@ export const achievementsCollectionsData: Achievement[] = [
return collectionMeetsCriteria;
},
},
{
id: "a-survivor-is-born",
name: "A Survivor is Born",
category: AchievementCategory.COLLECTIONS,
expGainAmount: 50,
description: "Have Tomb Raider 2013 in your library",
checkEligibility: async (dataSource, targetUserId) => {
const collectionEntryRepository =
dataSource.getRepository(CollectionEntry);

return await collectionEntryRepository.existsBy({
gameId: ACHIEVEMENTS_GAME_IDS.TOMB_RAIDER_2013,
collections: {
libraryUserId: targetUserId,
},
});
},
},
];
22 changes: 19 additions & 3 deletions src/achievements/data/achievements-reviews.data.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Achievement } from "../models/achievement.model";
import {
AchievementCategory,
ACHIEVEMENTS_GAME_IDS,
ACHIEVEMENTS_GAME_THEMES_IDS,
} from "../achievements.constants";
import { Review } from "../../reviews/entities/review.entity";
import { In } from "typeorm";

export const achievementsReviewsData: Achievement[] = [
{
Expand All @@ -16,9 +18,7 @@ export const achievementsReviewsData: Achievement[] = [
const reviewsRepository = dataSource.getRepository(Review);
return await reviewsRepository.exists({
where: {
profile: {
userId: targetUserId,
},
profileUserId: targetUserId,
game: {
themes: {
// Horror game ID in the game_theme table.
Expand All @@ -29,4 +29,20 @@ export const achievementsReviewsData: Achievement[] = [
});
},
},
{
id: "delivery-system",
name: "Delivery System",
description: "Review Death Stranding",
category: AchievementCategory.REVIEWS,
expGainAmount: 100,
checkEligibility: async (dataSource, targetUserId) => {
const reviewsRepository = dataSource.getRepository(Review);
return await reviewsRepository.exists({
where: {
profileUserId: targetUserId,
gameId: In(ACHIEVEMENTS_GAME_IDS.DEATH_STRANDING_IDS),
},
});
},
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,6 @@ export class ActivitiesRepositoryService {
return;
}

const isGameExcluded =
await this.gameFilterService.isExcluded(targetGameId);
if (isGameExcluded) {
throw new UnrecoverableError(
"Target game is excluded from front-facing content",
);
}

const isGameMature =
await this.gameFilterService.isMature(targetGameId);
if (isGameMature) {
Expand Down
3 changes: 0 additions & 3 deletions src/game/game-filter/dto/change-exclusion-status.dto.ts

This file was deleted.

17 changes: 0 additions & 17 deletions src/game/game-filter/dto/find-all-excluded-games.dto.ts

This file was deleted.

42 changes: 0 additions & 42 deletions src/game/game-filter/entity/game-exclusion.entity.ts

This file was deleted.

62 changes: 0 additions & 62 deletions src/game/game-filter/game-filter.controller.ts

This file was deleted.

6 changes: 1 addition & 5 deletions src/game/game-filter/game-filter.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { Module } from "@nestjs/common";
import { GameFilterService } from "./game-filter.service";
import { TypeOrmModule } from "@nestjs/typeorm";
import { GameExclusion } from "./entity/game-exclusion.entity";
import { GameRepositoryModule } from "../game-repository/game-repository.module";
import { GameFilterController } from './game-filter.controller';

/**
* The game filter module is responsible for issuing 'exclusions' for certain games.
Expand All @@ -13,9 +10,8 @@ import { GameFilterController } from './game-filter.controller';
* info page (hopefully only there).
*/
@Module({
imports: [TypeOrmModule.forFeature([GameExclusion]), GameRepositoryModule],
imports: [GameRepositoryModule],
providers: [GameFilterService],
exports: [GameFilterService],
controllers: [GameFilterController],
})
export class GameFilterModule {}
113 changes: 1 addition & 112 deletions src/game/game-filter/game-filter.service.ts
Original file line number Diff line number Diff line change
@@ -1,88 +1,14 @@
import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { GameExclusion } from "./entity/game-exclusion.entity";
import { DataSource, In, Repository } from "typeorm";
import { Injectable } from "@nestjs/common";
import { GameRepositoryService } from "../game-repository/game-repository.service";
import { FindAllExcludedGamesRequestDto } from "./dto/find-all-excluded-games.dto";
import { buildBaseFindOptions } from "../../utils/buildBaseFindOptions";
import { TPaginationData } from "../../utils/pagination/pagination-response.dto";
import { ChangeExclusionStatusDto } from "./dto/change-exclusion-status.dto";

import { MATURE_THEME_ID } from "./game-filter.constants";

@Injectable()
export class GameFilterService {
constructor(
@InjectRepository(GameExclusion)
private readonly gameExclusionRepository: Repository<GameExclusion>,
private readonly gameRepositoryService: GameRepositoryService,
private readonly dataSource: DataSource,
) {}

public async findAll(
dto: FindAllExcludedGamesRequestDto,
): Promise<TPaginationData<GameExclusion>> {
const options = buildBaseFindOptions(dto);
return this.gameExclusionRepository.findAndCount(options);
}

public async register(issuerUserId: string, targetGameId: number) {
// Errors out if game doesn't exist
await this.gameRepositoryService.findOneById(targetGameId);

const existingExclusion = await this.gameExclusionRepository.findOne({
where: {
targetGameId: targetGameId,
isActive: true,
},
});

if (existingExclusion) {
throw new HttpException(
"A exclusion for this game is already in place.",
HttpStatus.BAD_REQUEST,
);
}

await this.gameExclusionRepository.insert({
targetGameId: targetGameId,
isActive: true,
issuerUserId: issuerUserId,
});
}

public async changeStatus(
targetGameId: number,
dto: ChangeExclusionStatusDto,
) {
await this.gameRepositoryService.findOneById(targetGameId);
const exclusion = await this.gameExclusionRepository.findOneByOrFail({
targetGameId: targetGameId,
});

await this.gameExclusionRepository.update(exclusion.id, {
isActive: dto.isActive,
});
}

public async delete(targetGameId: number) {
// Errors out if game doesn't exist
await this.gameRepositoryService.findOneById(targetGameId);

await this.gameExclusionRepository.delete({
targetGameId: targetGameId,
});
}

public async isExcluded(targetGameId: number) {
return await this.gameExclusionRepository.exists({
where: {
targetGameId: targetGameId,
isActive: true,
},
});
}

public async isMature(targetGameId: number) {
const game = await this.gameRepositoryService.findOneById(
targetGameId,
Expand Down Expand Up @@ -120,41 +46,4 @@ export class GameFilterService {
// Done this way to preserve ordering
return gameIds.filter((id) => !matureGameIds.includes(id));
}

/**
* Returns a list of gameIds with excluded ones removed.
* @param gameIds
*/
public async removeExcluded(gameIds: number[]) {
const excludedIds = await this.gameExclusionRepository.findBy({
targetGameId: In(gameIds),
isActive: true,
});

// Done this way to preserve ordering
return gameIds.filter((gameId) => {
return !excludedIds.some(
(excluded) => excluded.targetGameId === gameId,
);
});
}

/**
* Returns a subquery to be used with QueryBuilders that automatically removes excluded
* games. <br>
* This subquery should run with a 'NOT EXISTS' statement.
* @param targetGameIdRelation - Target entity alias followed by target game id property
* e.g. 'ge.gameId'
* @see https://www.w3schools.com/mysql/mysql_exists.asp
*/
public buildQueryBuilderSubQuery(targetGameIdRelation: string) {
return this.dataSource
.createQueryBuilder()
.subQuery()
.from(GameExclusion, "ge")
.select("1")
.where(`ge.targetGameId = ${targetGameIdRelation}`)
.andWhere(`ge.isActive = true`)
.getQuery();
}
}
Loading

0 comments on commit 4d2da42

Please sign in to comment.