Skip to content
Snippets Groups Projects
game.service.ts 9.2 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,
  JoinFactionDTO,
  GameGroupDTO,
} 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) {
L4168's avatar
L4168 committed
    // checks if a game with the same name exists already
    if (await this.gameRepository.findOne({ name: gameData.name })) {
L4168's avatar
L4168 committed
      throw new HttpException('Game already exists', HttpStatus.BAD_REQUEST);
L4168's avatar
L4168 committed
    // else add the game to the database
    const game = await this.gameRepository.create(gameData);
L4168's avatar
L4168 committed
    await this.gameRepository.insert(game);
    // add gamePerson with role admin to the game
L4168's avatar
L4168 committed
    const gamePerson = await this.game_PersonRepository.create({
      game: game,
      person: personId,
      role: 'admin',
L4168's avatar
L4168 committed
    });
    await this.game_PersonRepository.insert(gamePerson);
    return {
      message: 'New game added',
    };
  }

  // edit already created game
Samuli Virtapohja's avatar
Samuli Virtapohja committed
  async editGame(id: string, gameData: GameDTO) {
L4168's avatar
L4168 committed
    // checks if a game with the same name exists already
    if (
      await this.gameRepository.findOne({ name: gameData.name, id: Not(id) })
    ) {
L4168's avatar
L4168 committed
      throw new HttpException('Game already exists', HttpStatus.BAD_REQUEST);
    }
    // update game entry in db
    const updatedGame = await this.gameRepository.create(gameData);
L4168's avatar
L4168 committed
    updatedGame['id'] = id;
    const gameId = await this.gameRepository.save(updatedGame);

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

    // TO DO: ADD FLAGBOX LOCATION TO MAPDRAWING ENTITY

    return {
      message: 'Game updated',
    };
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: GameGroupDTO) {
L4168's avatar
L4168 committed
    // 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);

    return {
      message: 'created new group',
    };
  }

  async showGroups() {
L4168's avatar
L4168 committed
    return await this.game_GroupRepository.find({
      relations: ['leader', 'players', 'game'],
    });
  }

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

Samuli Virtapohja's avatar
Samuli Virtapohja committed
  async listFactionMembers(faction) {
    return await this.game_PersonRepository.find({
      where: { faction },
      relations: ['person'],
      order: { person: 'DESC' },
    });
  }

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

  async promotePlayer(body) {
    const gamepersonId = body.player;
    // get playerdata
    const gameperson = await this.game_PersonRepository.findOne({
      where: { gamepersonId },
    });
    if (gameperson) {
      const factionleader = await this.game_PersonRepository.create(gameperson);
      factionleader.role = body.role;
      return await this.game_PersonRepository.save(factionleader);
    }
    throw new HttpException('player does not exist', HttpStatus.BAD_REQUEST);
  }

Samuli Virtapohja's avatar
Samuli Virtapohja committed
  async joinFaction(person, faction: JoinFactionDTO) {
L4168's avatar
L4168 committed
    // get faction
    const factionInDb = await this.factionRepository.findOne({
Samuli Virtapohja's avatar
Samuli Virtapohja committed
      factionId: faction.factionId,
L4168's avatar
L4168 committed
    });
Samuli Virtapohja's avatar
Samuli Virtapohja committed

L4168's avatar
L4168 committed
    if (!factionInDb) {
      throw new HttpException('No factions exist!', HttpStatus.BAD_REQUEST);
    }
    //check if password is correct
    if (factionInDb.passwordCheck(faction.factionPassword)) {
      const gameperson = await this.game_PersonRepository.create({
Samuli Virtapohja's avatar
Samuli Virtapohja committed
        faction: factionInDb,
L4168's avatar
L4168 committed
        game: faction.game,
        role: 'soldier',
        person: person,
      });
      //check if user is already in a faction
      if (await this.game_PersonRepository.findOne(gameperson)) {
        throw new HttpException(
          'You have already joined faction!',
          HttpStatus.BAD_REQUEST,
        );
      }
      // insert to database
      return await this.game_PersonRepository.save(gameperson);
    } else {
      throw new HttpException('Invalid password!', HttpStatus.UNAUTHORIZED);
    }
  }