Skip to content
Snippets Groups Projects
game.service.ts 8.23 KiB
Newer Older
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Not } from 'typeorm';
L4168's avatar
L4168 committed
import {
  GameEntity,
  Game_PersonEntity,
  ObjectivePointEntity,
  ObjectivePoint_HistoryEntity,
} from './game.entity';
import { GameDTO, FlagboxEventDTO } from './game.dto';
L4168's avatar
L4168 committed
import { PersonEntity } from '../user/user.entity';
import { GameGroupEntity } from './group.entity';
import { FactionEntity } from './faction.entity';
L4168's avatar
L4168 committed
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>,
L4168's avatar
L4168 committed
    @InjectRepository(Game_PersonEntity)
    private game_PersonRepository: Repository<Game_PersonEntity>,
    @InjectRepository(GameGroupEntity)
    private game_GroupRepository: Repository<GameGroupEntity>,
L4168's avatar
L4168 committed
    @InjectRepository(ObjectivePointEntity)
    private objectivePointRepository: Repository<ObjectivePointEntity>,
    @InjectRepository(ObjectivePoint_HistoryEntity)
    private objectivePoint_HistoryRepository: Repository<
      ObjectivePoint_HistoryEntity
    >,
    private notificationGateway: NotificationGateway,
  ) {}

  // create a new game
Samuli Virtapohja's avatar
Samuli Virtapohja committed
  async createNewGame(personId: PersonEntity, gameData: GameDTO) {
    try {
      // 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,
Samuli Virtapohja's avatar
Samuli Virtapohja committed
        factions: gameData.factions,
Samuli Virtapohja's avatar
Samuli Virtapohja committed
      });
      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',
      };
    } catch (error) {
      return error.message;
  }

  // edit already created game
Samuli Virtapohja's avatar
Samuli Virtapohja committed
  async editGame(id: string, gameData: GameDTO) {
Samuli Virtapohja's avatar
Samuli Virtapohja committed
    try {
      // 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,
Samuli Virtapohja's avatar
Samuli Virtapohja committed
        factions: null,
L4168's avatar
L4168 committed
        objective_points: null,
Samuli Virtapohja's avatar
Samuli Virtapohja committed
      });
      updatedGame['id'] = id;
      const gameId = await this.gameRepository.save(updatedGame);
Samuli Virtapohja's avatar
Samuli Virtapohja committed

L4168's avatar
L4168 committed
      // get all the factions that are associated with the game to deny duplicate entries
Samuli Virtapohja's avatar
Samuli Virtapohja committed
      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,
L4072's avatar
L4072 committed
              gameId: gameId,
Samuli Virtapohja's avatar
Samuli Virtapohja committed
            });
            await this.factionRepository.insert(name);
          }
        });
      }
L4168's avatar
L4168 committed
      // 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

Samuli Virtapohja's avatar
Samuli Virtapohja committed
      return {
        message: 'Game updated',
      };
    } catch (error) {
      return error;
Samuli Virtapohja's avatar
Samuli Virtapohja committed
    }
L4168's avatar
L4168 committed
  }
L4072's avatar
L4072 committed
  async deleteGame(id) {
    // TODO: Delete factions from Faction table associated with the deleted game
L4072's avatar
L4072 committed
    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) {
    try {
      // 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,
        );
      }
L4168's avatar
L4168 committed

      // 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);
        message: 'created new group',
      };
    } catch (e) {
      return e;
    }
  }

  async showGroups() {
    try {
      return await this.game_GroupRepository.find({
        relations: ['leader', 'players', 'game'],
      });
    } catch (e) {
      return e;
    }
  }

  async joinGroup(person, groupId) {
    try {
      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',
      };
    } catch (e) {
      return e;
    }
L4168's avatar
L4168 committed
  // returns name and id of each game
  async listGames() {
Samuli Virtapohja's avatar
Samuli Virtapohja committed
    try {
      const games = await this.gameRepository.find();
      return games.map(game => {
        return game.gameObject();
      });
    } catch (error) {
      return error;
    }
L4168's avatar
L4168 committed

  // returns information about a game identified by id
  async returnGameInfo(id: string) {
    const game = await this.gameRepository.findOne({
      where: { id: id },
L4168's avatar
L4168 committed
      relations: ['factions', 'objective_points'],
L4168's avatar
L4168 committed
    return game;
  }
L4168's avatar
L4168 committed

  // 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
Samuli Virtapohja's avatar
Samuli Virtapohja committed
    const factionRef = await this.factionRepository.find({ gameId: gameId });
L4168's avatar
L4168 committed
    // 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');
  }