import { Injectable, HttpException, HttpStatus } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository, Not } from 'typeorm'; import { GameEntity, Game_PersonEntity, ObjectivePointEntity, ObjectivePoint_HistoryEntity, } from './game.entity'; import { GameDTO, FlagboxEventDTO } from './game.dto'; import { PersonEntity } from '../user/user.entity'; import { GameGroupEntity } from './group.entity'; import { FactionEntity } from './faction.entity'; import { NotificationGateway } from 'src/notifications/notifications.gateway'; @Injectable() export class GameService { constructor( @InjectRepository(GameEntity) private gameRepository: Repository<GameEntity>, @InjectRepository(FactionEntity) private factionRepository: Repository<FactionEntity>, @InjectRepository(PersonEntity) private personRepository: Repository<PersonEntity>, @InjectRepository(Game_PersonEntity) private game_PersonRepository: Repository<Game_PersonEntity>, @InjectRepository(GameGroupEntity) private game_GroupRepository: Repository<GameGroupEntity>, @InjectRepository(ObjectivePointEntity) private objectivePointRepository: Repository<ObjectivePointEntity>, @InjectRepository(ObjectivePoint_HistoryEntity) private objectivePoint_HistoryRepository: Repository< ObjectivePoint_HistoryEntity >, private notificationGateway: NotificationGateway, ) {} // create a new game async createNewGame(personId: PersonEntity, gameData: GameDTO) { // checks if a game with the same name exists already const { name } = gameData; if (await this.gameRepository.findOne({ where: { name } })) { throw new HttpException('Game already exists', HttpStatus.BAD_REQUEST); } // else add the game to the database const game = await this.gameRepository.create({ ...gameData, factions: gameData.factions, }); await this.gameRepository.insert(game); const gamePerson = await this.game_PersonRepository.create({ faction: null, game: game, person: personId, }); gamePerson['role'] = 'admin'; await this.game_PersonRepository.insert(gamePerson); return { message: 'New game added', }; } // edit already created game async editGame(id: string, gameData: GameDTO) { // checks if a game with the same name exists already const { name } = gameData; if (await this.gameRepository.findOne({ name: name, id: Not(id) })) { throw new HttpException('Game already exists', HttpStatus.BAD_REQUEST); } // update game entry in db const updatedGame = await this.gameRepository.create({ ...gameData, factions: null, objective_points: null, }); updatedGame['id'] = id; const gameId = await this.gameRepository.save(updatedGame); // get all the factions that are associated with the game to deny duplicate entries const factions = await this.factionRepository.find(gameId); const factionNames = factions.map(({ factionName }) => factionName); // add the factions to db if (gameData.factions) { gameData.factions.map(async faction => { if (!Object.values(factionNames).includes(faction.factionName)) { let name = await this.factionRepository.create({ ...faction, game: gameId, }); await this.factionRepository.insert(name); } }); } // get old flagboxes to deny duplicate entries const flagboxes = await this.objectivePointRepository.find({ game: gameId, }); const flagboxIds = flagboxes.map( ({ objectivePointDescription }) => objectivePointDescription, ); // insert the flagboxes to db if (gameData.objective_points) { gameData.objective_points.map(async flagbox => { if ( !Object.values(flagboxIds).includes(flagbox.objectivePointDescription) ) { let newFlagbox = await this.objectivePointRepository.create({ ...flagbox, game: gameId, }); await this.objectivePointRepository.insert(newFlagbox); } }); } // TO DO: ADD FLAGBOX LOCATION TO MAPDRAWING ENTITY return { message: 'Game updated', }; } async deleteGame(id) { // TODO: Delete factions from Faction table associated with the deleted game await this.gameRepository.delete({ id }); return { message: 'Game deleted', }; } // checks the password, creates an entry in GamePerson table with associated role&faction async createGroup(person, gameId, groupData) { // check if the person already is in a group in this game const checkDuplicate = await this.game_PersonRepository.findOne({ person: person, }); if (checkDuplicate) { throw new HttpException( 'You already belong to a group!', HttpStatus.BAD_REQUEST, ); } // create a group entry and insert it to db const group = await this.game_GroupRepository.create({ ...groupData, game: gameId, }); const gameGroup = await this.game_GroupRepository.insert(group); // create game_Person entry and insert it to db const gamePerson = await this.game_PersonRepository.create({ role: 'soldier', faction: null, game: gameId, person: person, leaderGroup: gameGroup.identifiers[0]['id'], group: gameGroup.identifiers[0]['id'], }); await this.game_PersonRepository.insert(gamePerson); return { message: 'created new group', }; } async showGroups() { return await this.game_GroupRepository.find({ relations: ['leader', 'players', 'game'], }); } async joinGroup(person, groupId) { const gameData = await this.game_GroupRepository.findOne({ where: { id: groupId }, relations: ['players', 'game'], }); const gamePerson = await this.game_PersonRepository.create({ role: 'soldier', faction: null, game: gameData.game, person: person, leaderGroup: null, group: groupId, }); await this.game_PersonRepository.insert(gamePerson); return { message: 'Joined group', }; } // returns name and id of each game async listGames() { const games = await this.gameRepository.find(); return games.map(game => { return game.gameObject(); }); } // returns information about a game identified by id async returnGameInfo(id: string) { const game = await this.gameRepository.findOne({ where: { id: id }, relations: ['factions', 'objective_points'], }); return game; } // returns flagbox settings async flagboxQuery(gameId) { const game = await this.gameRepository.findOne({ id: gameId }); return game.nodesettings; } // add events to history and send updates with socket async flagboxEvent(gameId, data: FlagboxEventDTO) { // get all the factions associated with the game const factionRef = await this.factionRepository.find({ game: gameId }); // get reference to the objective const objectiveRef = await this.objectivePointRepository.findOne({ where: { objectivePointDescription: data.node_id, game: gameId }, }); data.oP_HistoryTimestamp = new Date(Date.now()).toLocaleString(); const eventUpdate = await this.objectivePoint_HistoryRepository.create({ oP_HistoryTimestamp: data.oP_HistoryTimestamp, action: data.action, capture: factionRef[data.capture], owner: factionRef[data.owner], objective_point: objectiveRef, }); await this.objectivePoint_HistoryRepository.insert(eventUpdate); // send flagbox event to flagbox subscribers this.notificationGateway.server.emit('flagbox', 'event update'); } }