diff --git a/src/app.module.ts b/src/app.module.ts
index dbb03cf7baa35d2d4deafdbff6ba67bd64381c92..f2c7b7765304436488bbadb3fdfce4fbdc1fbd9a 100644
--- a/src/app.module.ts
+++ b/src/app.module.ts
@@ -2,19 +2,23 @@ import { Module } from '@nestjs/common';
 import { APP_FILTER, APP_INTERCEPTOR, APP_GUARD } from '@nestjs/core';
 import { TypeOrmModule } from '@nestjs/typeorm';
 import { Connection } from 'typeorm';
+
 import { AppController } from './app.controller';
 import { AppService } from './app.service';
-import { UserModule } from './user/user.module';
-import { HttpErrorFilter } from './shared/http-error.filter';
+
+import { RolesGuard } from './shared/roles.guard';
 import { LoggingInterceptor } from './shared/logging.interceptor';
+import { StatesGuard } from './shared/states.guard';
+import { HttpErrorFilter } from './shared/http-error.filter';
+
 import { NotificationModule } from './notifications/notifications.module';
-import { GameModule } from './game/game.module';
-import { RolesGuard } from './shared/roles.guard';
 import { TaskModule } from './task/task.module';
+import { TrackingModule } from './tracking/tracking.module';
+import { UserModule } from './user/user.module';
 import { DrawModule } from './draw/draw.module';
 import { FactionModule } from './faction/faction.module';
-import { TrackingModule } from './tracking/tracking.module';
-
+import { GameModule } from './game/game.module';
+import { ScoreModule } from './score/score.module';
 
 @Module({
   imports: [
@@ -26,6 +30,7 @@ import { TrackingModule } from './tracking/tracking.module';
     DrawModule,
     FactionModule,
     TrackingModule,
+    ScoreModule,
   ],
   controllers: [AppController],
   providers: [
@@ -42,6 +47,10 @@ import { TrackingModule } from './tracking/tracking.module';
       provide: APP_GUARD,
       useClass: RolesGuard,
     },
+    {
+      provide: APP_GUARD,
+      useClass: StatesGuard,
+    },
   ],
 })
 export class AppModule {
diff --git a/src/draw/coordinate.entity.ts b/src/draw/coordinate.entity.ts
index 9cee16c6a496d5e9c68a33eabf57514e88cdf7c1..ef5447f61cfd1dd07d1f81a8ee1fce8e8256da2a 100644
--- a/src/draw/coordinate.entity.ts
+++ b/src/draw/coordinate.entity.ts
@@ -17,9 +17,13 @@ export class MapDrawingEntity {
 
   @Column({ type: 'json', nullable: true }) data: JSON;
 
-  @ManyToOne(type => FactionEntity, faction => faction.mapDrawings)
+  @ManyToOne(type => FactionEntity, faction => faction.mapDrawings, {
+    onDelete: 'CASCADE',
+  })
   faction: FactionEntity;
-  @ManyToOne(type => GameEntity, gameEntity => gameEntity.id)
+  @ManyToOne(type => GameEntity, gameEntity => gameEntity.id, {
+    onDelete: 'CASCADE',
+  })
   gameId: GameEntity;
 }
 
@@ -28,8 +32,20 @@ export class Game_Person_MapDrawingEntity {
   @PrimaryGeneratedColumn('uuid') GPmapDrawingId: string;
   @Column({ type: 'timestamp' }) GPCTimeStamp: Timestamp;
 
-  @ManyToOne(type => Game_PersonEntity, game_person => game_person.gamepersonId)
+  @ManyToOne(
+    type => Game_PersonEntity,
+    game_person => game_person.gamepersonId,
+    {
+      onDelete: 'CASCADE',
+    },
+  )
   game_person: Game_PersonEntity;
-  @ManyToOne(type => MapDrawingEntity, map_drawing => map_drawing.mapDrawingId)
+  @ManyToOne(
+    type => MapDrawingEntity,
+    map_drawing => map_drawing.mapDrawingId,
+    {
+      onDelete: 'CASCADE',
+    },
+  )
   map_drawing: MapDrawingEntity;
 }
diff --git a/src/draw/draw.controller.ts b/src/draw/draw.controller.ts
index 21306d7ae91e565a5459138229a384e21fd68abd..26f6cf8c56142ef190ad3bcbfd7ce9d32caa371e 100644
--- a/src/draw/draw.controller.ts
+++ b/src/draw/draw.controller.ts
@@ -11,7 +11,8 @@ import {
 
 import { AuthGuard } from '../shared/auth.guard';
 import { DrawService } from './draw.service';
-import { Roles } from '../shared/roles.decorator';
+import { Roles, GameStates } from '../shared/guard.decorator';
+import { MapDrawingDTO, ReturnDrawingsDTO } from './mapdrawing.dto';
 
 /*
       DrawController
@@ -25,16 +26,17 @@ export class DrawController {
   constructor(private drawService: DrawService) {}
 
   @Put('mapdrawing/:id')
-  @UsePipes(new ValidationPipe())
   @Roles('admin', 'factionleader')
-  async draw(@Param('id') gameId, @Body() data) {
+  @GameStates('CREATED', 'STARTED')
+  @UsePipes(new ValidationPipe())
+  async draw(@Param('id') gameId, @Body() data: MapDrawingDTO) {
     return this.drawService.draw(gameId, data);
   }
 
   @Get('map/:id')
   @UseGuards(new AuthGuard())
   @UsePipes(new ValidationPipe())
-  async drawMap(@Param('id') id, @Body() data) {
+  async drawMap(@Param('id') id, @Body() data: ReturnDrawingsDTO) {
     return this.drawService.drawMap(id, data);
   }
 }
diff --git a/src/draw/draw.service.ts b/src/draw/draw.service.ts
index e3b62b5132223f466fa94661d4748b3f7cd497f5..d5ddf23e9574771bc769e2b6d58b59a4e95ad10d 100644
--- a/src/draw/draw.service.ts
+++ b/src/draw/draw.service.ts
@@ -3,6 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm';
 import { Repository } from 'typeorm';
 
 import { MapDrawingEntity } from '../draw/coordinate.entity';
+import { MapDrawingDTO, ReturnDrawingsDTO } from './mapdrawing.dto';
 
 @Injectable()
 export class DrawService {
@@ -11,15 +12,13 @@ export class DrawService {
     private mapDrawingRepository: Repository<MapDrawingEntity>,
   ) {}
 
-  async draw(gameId, data: MapDrawingEntity) {
+  async draw(gameId, data: MapDrawingDTO) {
     data['gameId'] = gameId;
-
     const drawing = await this.mapDrawingRepository.create(data);
-
     if (data.mapDrawingId == null || data.mapDrawingId == '') {
       // luo uuden instanssin.
-      const mapdrawing = await this.mapDrawingRepository.insert(drawing);
-      return mapdrawing.identifiers;
+      const mapDrawing = await this.mapDrawingRepository.insert(drawing);
+      return mapDrawing.identifiers;
     } else {
       //päivittää mapDrawingin
       return await this.mapDrawingRepository.save(drawing);
@@ -27,13 +26,21 @@ export class DrawService {
   }
 
   // draw map based on game and
-  async drawMap(id, data: MapDrawingEntity) {
-    data['gameId'] = id;
-    data['drawingIsActive'] = true;
-    // get faction
-    const mapDrawings = await this.mapDrawingRepository.create(data);
-
+  async drawMap(id, data: ReturnDrawingsDTO) {
     // return mapdrawings with given faction and gameid
-    return await this.mapDrawingRepository.find(mapDrawings);
+    return await this.mapDrawingRepository.find({
+      where: [
+        {
+          gameId: id,
+          faction: data.factionId,
+          drawingIsActive: true,
+        },
+        {
+          gameId: id,
+          faction: null,
+          drawingIsActive: true,
+        },
+      ],
+    });
   }
 }
diff --git a/src/draw/mapdrawing.dto.ts b/src/draw/mapdrawing.dto.ts
index 03eca2d1057490558e271252d12a2cc1ef883273..f7e7c781a0cbd308edf5f8c14f068b449f43a05e 100644
--- a/src/draw/mapdrawing.dto.ts
+++ b/src/draw/mapdrawing.dto.ts
@@ -1,26 +1,27 @@
-import { IsUUID } from 'class-validator';
+import { IsUUID, IsOptional, IsBoolean, Allow } from 'class-validator';
 
-import { GameDTO } from '../game/game.dto';
-import { GameEntity, Game_PersonEntity } from '../game/game.entity';
 import { FactionEntity } from '../faction/faction.entity';
-import { FactionDTO } from '../faction/faction.dto';
-import { MapDrawingEntity } from '../draw/coordinate.entity';
+import { GameEntity } from '../game/game.entity';
 
 export class MapDrawingDTO {
+  @IsOptional()
+  @IsUUID('4')
+  mapDrawingId: string;
+  @Allow()
   data: JSON;
-  gameId: GameDTO;
-  faction?: FactionDTO;
-  isActive?: boolean;
-  validUntil?: string;
+  @IsOptional()
+  @IsUUID('4')
+  gameId: GameEntity;
+  @IsOptional()
+  @IsUUID('4')
+  faction?: FactionEntity;
+  @IsBoolean()
+  drawingIsActive?: boolean;
+  drawingValidTill?: string;
 }
 
-export class DrawMapDTO {
+export class ReturnDrawingsDTO {
+  @IsOptional()
   @IsUUID('4')
-  mapDrawingId: MapDrawingEntity;
-
-  gameId: GameEntity;
   factionId: FactionEntity;
-
-  gamepersonId: Game_PersonEntity;
-  data: JSON;
 }
diff --git a/src/faction/faction.controller.ts b/src/faction/faction.controller.ts
index dec9308d456e93f4c6f26fee5f5f802af4e5857e..da7e5950626bbcd5385d80755d208e59be589b48 100644
--- a/src/faction/faction.controller.ts
+++ b/src/faction/faction.controller.ts
@@ -21,7 +21,7 @@ import {
   JoinGameGroupDTO,
 } from './faction.dto';
 import { FactionService } from './faction.service';
-import { Roles } from '../shared/roles.decorator';
+import { Roles, GameStates } from '../shared/guard.decorator';
 
 @Controller('faction')
 export class FactionController {
@@ -30,6 +30,7 @@ export class FactionController {
   // takes gameId from the url to verify user role
   @Post('create-group/:id')
   @Roles('soldier')
+  @GameStates('CREATED')
   @UsePipes(new ValidationPipe())
   async createGroup(
     @User('id') person,
@@ -50,6 +51,7 @@ export class FactionController {
   // takes gameId from the url to verify user role
   @Put('join-group/:id')
   @Roles('soldier')
+  @GameStates('CREATED')
   async joinGroup(
     @User('id') person,
     @Param('id') id,
@@ -66,17 +68,31 @@ export class FactionController {
 
   // param game ID is passed to @Roles
   @Put('promote/:id')
-  @UseGuards(new AuthGuard())
-  @UsePipes(new ValidationPipe())
   @Roles('admin')
+  @GameStates('CREATED')
+  @UsePipes(new ValidationPipe())
   promotePlayer(@Param('id') game, @Body() body: PromotePlayerDTO) {
     return this.factionservice.promotePlayer(body);
   }
 
-  @Put('join-faction')
+  // used to join a faction
+  // :id is the id of the game, and is needed for GameStates to check the state of the game
+  @Put('join-faction/:id')
   @UseGuards(new AuthGuard())
+  @GameStates('CREATED', 'STARTED')
   @UsePipes(new ValidationPipe())
-  joinFaction(@User('id') person, @Body() data: JoinFactionDTO) {
+  joinFaction(
+    @User('id') person,
+    @Param('id') game,
+    @Body() data: JoinFactionDTO,
+  ) {
     return this.factionservice.joinFaction(person, data);
   }
+
+  // check if person belongs to a faction in a game
+  @Get('check-faction/:id')
+  @UseGuards(new AuthGuard())
+  checkFaction(@User('id') userId, @Param('id') gameId) {
+    return this.factionservice.verifyUser(userId, gameId);
+  }
 }
diff --git a/src/faction/faction.dto.ts b/src/faction/faction.dto.ts
index a5b9f044bdf74edefa37ac077e09a3e384e5e5c3..0b65c47007d6424584d8fdb35ac9d9ee53eaa924 100644
--- a/src/faction/faction.dto.ts
+++ b/src/faction/faction.dto.ts
@@ -7,14 +7,18 @@ import {
   IsNumber,
   Min,
   Max,
+  IsOptional,
 } from 'class-validator';
 
 import { GameEntity } from '../game/game.entity';
-import { RoleValidation } from '../shared/custom-validation';
+import { RoleValidation, Uuid } from '../shared/custom-validation';
 import { GameDTO } from '../game/game.dto';
 import { FactionEntity, GameGroupEntity } from './faction.entity';
 
 export class FactionDTO {
+  @IsOptional()
+  @IsUUID('4')
+  factionId?: string;
   @IsString()
   @IsNotEmpty()
   @Length(2, 31)
diff --git a/src/faction/faction.entity.ts b/src/faction/faction.entity.ts
index 42f3aca413b36455786494818f2ca06f50f50f2e..3aa74cf615d77deb1421d52d46d4159bf7e0d241 100644
--- a/src/faction/faction.entity.ts
+++ b/src/faction/faction.entity.ts
@@ -28,7 +28,9 @@ export class FactionEntity {
 
   @OneToMany(type => Game_PersonEntity, game_persons => game_persons.faction)
   game_persons: Game_PersonEntity[];
-  @ManyToOne(type => GameEntity, game => game.factions)
+  @ManyToOne(type => GameEntity, game => game.factions, {
+    onDelete: 'CASCADE',
+  })
   game: GameEntity;
   @OneToMany(type => MapDrawingEntity, mapDrawings => mapDrawings.faction)
   mapDrawings: MapDrawingEntity[];
@@ -43,7 +45,7 @@ export class FactionEntity {
   }
 }
 
-@Entity('PowerUp')
+/* @Entity('PowerUp')
 export class PowerUpEntity {
   @PrimaryGeneratedColumn('uuid') powerUpId: string;
   @Column({ type: 'text' }) powerUpName: string;
@@ -51,7 +53,9 @@ export class PowerUpEntity {
   @Column({ type: 'int' }) amount: number;
   @Column({ type: 'time' }) cooldown: string;
 
-  @OneToMany(type => FactionEntity, factions => factions.factionId)
+  @OneToMany(type => FactionEntity, factions => factions.factionId, {
+    onDelete: 'CASCADE',
+  })
   factions: Faction_PowerUpEntity[];
 }
 
@@ -77,17 +81,7 @@ export class FP_HistoryEntity {
     faction_PowerUp => faction_PowerUp.histories,
   )
   faction_PowerUp: Faction_PowerUpEntity;
-}
-
-@Entity('Score')
-export class ScoreEntity {
-  @PrimaryGeneratedColumn('uuid') scoreId: string;
-  @Column({ type: 'float' }) score: number;
-  @Column({ type: 'timestamp' }) scoreTimeStamp: Timestamp;
-
-  @ManyToOne(type => FactionEntity, factionName => factionName.factionId)
-  faction: FactionEntity;
-}
+} */
 
 @Entity('GameGroup')
 export class GameGroupEntity {
@@ -102,6 +96,8 @@ export class GameGroupEntity {
     onDelete: 'CASCADE',
   })
   players: Game_PersonEntity[];
-  @ManyToOne(type => FactionEntity, faction => faction.factionId)
+  @ManyToOne(type => FactionEntity, faction => faction.factionId, {
+    onDelete: 'CASCADE',
+  })
   faction: FactionEntity;
 }
diff --git a/src/faction/faction.service.ts b/src/faction/faction.service.ts
index 76242dfe1bceda0776435b43c4fdc4cb60fe272c..67edef1db5d071e1936aba03ded5c5051c1ae713 100644
--- a/src/faction/faction.service.ts
+++ b/src/faction/faction.service.ts
@@ -35,7 +35,12 @@ export class FactionService {
         person: person,
       });
       //check if user is already in a faction
-      if (await this.game_PersonRepository.findOne(gameperson)) {
+      if (
+        await this.game_PersonRepository.findOne({
+          person: person,
+          game: faction.game,
+        })
+      ) {
         throw new HttpException(
           'You have already joined faction!',
           HttpStatus.BAD_REQUEST,
@@ -94,7 +99,6 @@ export class FactionService {
     await this.game_PersonRepository.save(gamePerson);
 
     return {
-      code: 201,
       message: 'created new group',
     };
   }
@@ -114,7 +118,6 @@ export class FactionService {
     gamePerson.group = data.groupId;
     await this.game_PersonRepository.save(gamePerson);
     return {
-      code: 200,
       message: 'Joined group',
     };
   }
@@ -129,4 +132,18 @@ export class FactionService {
     });
     return members;
   }
+
+  async verifyUser(person, game) {
+    const gameperson = await this.game_PersonRepository.findOne({
+      where: { person, game },
+      relations: ['faction'],
+    });
+    if (gameperson) {
+      return {
+        message: gameperson,
+      };
+    } else {
+      throw new HttpException('No faction was found', HttpStatus.BAD_REQUEST);
+    }
+  }
 }
diff --git a/src/game/game.controller.ts b/src/game/game.controller.ts
index 015baf9673563cd8732ce15493e80e23c19e0e6b..8d7494ba4dfa4a77e22963600e45a7579fca5d5d 100644
--- a/src/game/game.controller.ts
+++ b/src/game/game.controller.ts
@@ -9,14 +9,15 @@ import {
   Put,
   UseInterceptors,
   ClassSerializerInterceptor,
+  Delete,
 } from '@nestjs/common';
 
 import { GameService } from './game.service';
 import { AuthGuard } from '../shared/auth.guard';
 import { User } from '../user/user.decorator';
-import { GameDTO, FlagboxEventDTO } from './game.dto';
+import { GameDTO, FlagboxEventDTO, GameStateDTO } from './game.dto';
 import { ValidationPipe } from '../shared/validation.pipe';
-import { Roles } from '../shared/roles.decorator';
+import { Roles, GameStates } from '../shared/guard.decorator';
 import { GameEntity } from './game.entity';
 
 @Controller('game')
@@ -32,11 +33,27 @@ export class GameController {
 
   @Put('edit/:id')
   @Roles('admin')
+  @GameStates('CREATED')
   @UsePipes(new ValidationPipe())
   async editGame(@Param('id') id: string, @Body() body: GameDTO) {
+    body.id = id;
     return this.gameservice.editGame(id, body);
   }
 
+  @Delete('delete/:id')
+  @Roles('admin')
+  @GameStates('CREATED')
+  async deleteGame(@Param('id') id: string) {
+    return this.gameservice.deleteGame(id);
+  }
+
+  @Put('edit-state/:id')
+  @Roles('admin')
+  @UsePipes(new ValidationPipe())
+  async updateGameState(@Param('id') id: string, @Body() body: GameStateDTO) {
+    return this.gameservice.updateGameStatus(body);
+  }
+
   @Get('listgames')
   async listGames() {
     return this.gameservice.listGames();
@@ -61,6 +78,7 @@ export class GameController {
   }
 
   @Post('flag/:id')
+  @GameStates('STARTED')
   async flagboxEvent(@Param('id') id: string, @Body() data: FlagboxEventDTO) {
     return this.gameservice.flagboxEvent(id, data);
   }
diff --git a/src/game/game.dto.ts b/src/game/game.dto.ts
index 913b6c0f76637ecc94c82c8853cb5428e411f06d..266a8b1564e5b11fb42da755359c79d37f4b170b 100644
--- a/src/game/game.dto.ts
+++ b/src/game/game.dto.ts
@@ -9,6 +9,9 @@ import {
   Max,
   ValidateNested,
   Allow,
+  IsUUID,
+  IsIn,
+  IsOptional,
 } from 'class-validator';
 
 import { ObjectivePointEntity } from './game.entity';
@@ -18,6 +21,8 @@ import { CenterDTO, NodeSettingsDTO } from './game.json.dto';
 import { Type } from 'class-transformer';
 
 export class GameDTO {
+  @IsOptional()
+  id: string;
   @IsString()
   @IsNotEmpty()
   @Length(3, 30)
@@ -68,7 +73,17 @@ export class newGameDTO {
   enddate: string;
 }
 
+export class GameStateDTO {
+  @IsUUID('4')
+  id: string;
+  @IsIn(['CREATED', 'STARTED', 'PAUSED', 'ENDED'])
+  state: string;
+}
+
 export class FlagboxDTO {
+  @IsOptional()
+  @IsUUID('4')
+  objectivePointId: string;
   @IsString()
   @IsNotEmpty()
   @Length(7)
@@ -85,7 +100,7 @@ export class FlagboxEventDTO {
   @IsNumber()
   @Min(0)
   @Max(3)
-  owner: number; // owner = 0, => first entry in faction db, owner = 1, => second entry etc
+  owner: number; // owner = 0, => no owner, owner = 1, => first entry in faction db
   @IsNumber()
   @Min(0)
   @Max(3)
diff --git a/src/game/game.entity.ts b/src/game/game.entity.ts
index 5f019e83c0b3af08bd423809b79ec5039850bbd2..7ae6e29955d02a2c1368b5f720200f009bd92ee1 100644
--- a/src/game/game.entity.ts
+++ b/src/game/game.entity.ts
@@ -25,6 +25,7 @@ export class GameEntity {
   @Column('json') center: CenterDTO;
   @Column({ type: 'json', nullable: true }) map: JSON;
   @Column({ type: 'json', nullable: true }) nodesettings?: NodeSettingsDTO;
+  @Column('text') state: string;
   @Column('timestamp') startdate: Timestamp;
   @Column('timestamp') enddate: Timestamp;
 
@@ -55,18 +56,20 @@ export class GameEntity {
 export class Game_PersonEntity {
   @PrimaryGeneratedColumn('uuid') gamepersonId: string;
   @Column({ type: 'text', nullable: true }) role: string;
-  @ManyToOne(type => FactionEntity, faction => faction.game_persons)
+  @ManyToOne(type => FactionEntity, faction => faction.game_persons, {
+    onDelete: 'CASCADE',
+  })
   faction: FactionEntity;
-  @ManyToOne(type => GameEntity, game => game.id)
+  @ManyToOne(type => GameEntity, game => game.id, {
+    onDelete: 'CASCADE',
+  })
   game: GameEntity;
   @ManyToOne(type => PersonEntity, person => person.id)
   person: PersonEntity;
-  @OneToOne(type => GameGroupEntity, group => group.leader, {
-    onDelete: 'CASCADE',
-  })
+  @OneToOne(type => GameGroupEntity, group => group.leader)
   leaderGroup: GameGroupEntity;
   @ManyToOne(type => GameGroupEntity, group => group.players, {
-    onDelete: 'CASCADE',
+    onDelete: 'NO ACTION',
   })
   @JoinColumn({ name: 'group' })
   group: GameGroupEntity;
@@ -78,9 +81,13 @@ export class ObjectivePointEntity {
   @Column({ type: 'text' }) objectivePointDescription: string;
   @Column({ type: 'float' }) objectivePointMultiplier: number;
 
-  @ManyToOne(type => MapDrawingEntity, coordinate => coordinate.data)
+  @ManyToOne(type => MapDrawingEntity, coordinate => coordinate.data, {
+    onDelete: 'CASCADE',
+  })
   coordinate: MapDrawingEntity;
-  @ManyToOne(type => GameEntity, game => game.objective_points)
+  @ManyToOne(type => GameEntity, game => game.objective_points, {
+    onDelete: 'CASCADE',
+  })
   game: GameEntity;
 }
 
@@ -89,13 +96,20 @@ export class ObjectivePoint_HistoryEntity {
   @PrimaryGeneratedColumn('uuid') oP_HistoryId: string;
   @Column({ type: 'timestamp' }) oP_HistoryTimestamp: Timestamp;
   @Column('float') action: number;
-  @ManyToOne(type => FactionEntity, factionEntity => factionEntity.factionId)
+  @ManyToOne(type => FactionEntity, factionEntity => factionEntity.factionId, {
+    onDelete: 'CASCADE',
+  })
   capture: FactionEntity;
-  @ManyToOne(type => FactionEntity, factionentity => factionentity.factionId)
+  @ManyToOne(type => FactionEntity, factionentity => factionentity.factionId, {
+    onDelete: 'CASCADE',
+  })
   owner: FactionEntity;
   @ManyToOne(
     type => ObjectivePointEntity,
     objective_point => objective_point.objectivePointId,
+    {
+      onDelete: 'CASCADE',
+    },
   )
-  objective_point: ObjectivePointEntity;
+  objective_point: string;
 }
diff --git a/src/game/game.service.ts b/src/game/game.service.ts
index 573bb2255ba2d65f828ad3900ff064e1fc471d13..3f6506b649f7dbe09936e283b4658f9765be8ec4 100644
--- a/src/game/game.service.ts
+++ b/src/game/game.service.ts
@@ -8,7 +8,7 @@ import {
   ObjectivePointEntity,
   ObjectivePoint_HistoryEntity,
 } from './game.entity';
-import { GameDTO, FlagboxEventDTO } from './game.dto';
+import { GameDTO, FlagboxEventDTO, GameStateDTO } from './game.dto';
 import { PersonEntity } from '../user/user.entity';
 import { FactionEntity } from '../faction/faction.entity';
 import { NotificationGateway } from '../notifications/notifications.gateway';
@@ -39,6 +39,7 @@ export class GameService {
     }
     // else add the game to the database
     const game = await this.gameRepository.create(gameData);
+    game.state = 'CREATED';
     await this.gameRepository.insert(game);
     // add gamePerson with role admin to the game
     const gamePerson = await this.game_PersonRepository.create({
@@ -48,70 +49,114 @@ export class GameService {
     });
     await this.game_PersonRepository.insert(gamePerson);
     return {
-      code: 201,
       message: 'New game added',
     };
   }
 
   // edit already created game
-  async editGame(id: string, gameData: GameDTO) {
+  async editGame(id, gameData: GameDTO) {
     // checks if a game with the same name exists already
     if (
       await this.gameRepository.findOne({ name: gameData.name, id: Not(id) })
     ) {
-      throw new HttpException('Game already exists', HttpStatus.BAD_REQUEST);
+      throw new HttpException(
+        'Game with the same name already exists',
+        HttpStatus.BAD_REQUEST,
+      );
+    }
+
+    // check for duplicate names in gameData
+    const factionNames = gameData.factions.map(
+      ({ factionName }) => factionName,
+    );
+    const flagboxNodeIds = gameData.objective_points.map(
+      ({ objectivePointDescription }) => objectivePointDescription,
+    );
+    if (
+      new Set(factionNames).size !== factionNames.length ||
+      new Set(flagboxNodeIds).size !== flagboxNodeIds.length
+    ) {
+      throw new HttpException(
+        'No duplicate names allowed!',
+        HttpStatus.BAD_REQUEST,
+      );
     }
+
+    // get factions that have been added previously
+    let factions = await this.factionRepository.find({ game: id });
+    // get flagboxes that have been added previously
+    let flagboxes = await this.objectivePointRepository.find({
+      game: id,
+    });
     // update game entry in db
     const updatedGame = await this.gameRepository.create(gameData);
-    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({ game: gameId });
-    const factionNames = factions.map(({ factionName }) => factionName);
-    // add the factions to db
+    // iterate factions if any were added
     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);
+      const factionIds = gameData.factions.map(({ factionId }) => factionId);
+      // delete all existing factions that are not in submitted data
+      factions.map(async faction => {
+        if (!factionIds.includes(faction.factionId)) {
+          await this.factionRepository.delete(faction);
         }
       });
+      // create / update factions present in the submitted data
+      gameData.factions.map(async faction => {
+        let name = await this.factionRepository.create({
+          ...faction,
+          game: gameId,
+        });
+        await this.factionRepository.save(name);
+      });
+    } else {
+      // if no factions are present in data, delete all factions associated with the game
+      await this.factionRepository.delete({ game: id });
     }
 
-    // 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);
+      const flagboxIds = gameData.objective_points.map(
+        ({ objectivePointId }) => objectivePointId,
+      );
+      flagboxes.map(async flagbox => {
+        if (!flagboxIds.includes(flagbox.objectivePointDescription)) {
+          await this.objectivePointRepository.delete(flagbox);
         }
       });
+      gameData.objective_points.map(async flagbox => {
+        let newFlagbox = await this.objectivePointRepository.create({
+          ...flagbox,
+          game: gameId,
+        });
+        await this.objectivePointRepository.save(newFlagbox);
+      });
+    } else {
+      await this.objectivePointRepository.delete({ game: id });
     }
 
     // TO DO: ADD FLAGBOX LOCATION TO MAPDRAWING ENTITY
 
     return {
-      code: 200,
       message: 'Game updated',
     };
   }
 
+  async updateGameStatus(game: GameStateDTO) {
+    const updatedGame = await this.gameRepository.findOne({ id: game.id });
+    if (updatedGame) {
+      updatedGame.state = game.state;
+      await this.gameRepository.save(updatedGame);
+      // notify players about game state change
+      this.notificationGateway.server.emit(game.id, {
+        type: 'gamestate-update',
+      });
+      return {
+        message: 'State was updated',
+      };
+    }
+    throw new HttpException("Game doesn't exist", HttpStatus.BAD_REQUEST);
+  }
+
   async listFactions(game: GameEntity) {
     return this.factionRepository.find({ game });
   }
@@ -120,7 +165,6 @@ export class GameService {
     // TODO: Delete factions from Faction table associated with the deleted game
     await this.gameRepository.delete({ id });
     return {
-      code: 200,
       message: 'Game deleted',
     };
   }
@@ -164,15 +208,15 @@ export class GameService {
     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,
+      // -1 as 0 means null
+      capture: data.capture !== 0 ? factionRef[data.capture - 1] : null,
+      owner: data.owner !== 0 ? factionRef[data.owner - 1] : null,
+      objective_point: objectiveRef.objectivePointId,
     });
     await this.objectivePoint_HistoryRepository.insert(eventUpdate);
     // send flagbox event to flagbox subscribers
-    this.notificationGateway.server.emit('flagbox', 'event update');
+    this.notificationGateway.server.emit(gameId, { type: 'flagbox-event' });
     return {
-      code: 201,
       message: 'OK',
     };
   }
diff --git a/src/notifications/notification.dto.ts b/src/notifications/notification.dto.ts
new file mode 100644
index 0000000000000000000000000000000000000000..807af14058161062d61c9b88a1d8e56637004acc
--- /dev/null
+++ b/src/notifications/notification.dto.ts
@@ -0,0 +1,12 @@
+import { IsString, Length, IsUUID, IsIn } from 'class-validator';
+
+export class NotificationdDTO {
+  // alert is for serious messages, note is for smaller updates on a situation
+  @IsIn(['alert', 'note'])
+  type: string;
+  @IsString()
+  @Length(0, 63)
+  message: string;
+  @IsUUID('4')
+  game: string;
+}
diff --git a/src/notifications/notification.entity.ts b/src/notifications/notification.entity.ts
index 3f8781633ec42bc3132c5df92f4f74045721506b..f9d5dca9290c30da406a63adf56ee06fe716a7b5 100644
--- a/src/notifications/notification.entity.ts
+++ b/src/notifications/notification.entity.ts
@@ -1,11 +1,23 @@
-import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn } from "typeorm";
+import {
+  Entity,
+  PrimaryGeneratedColumn,
+  Column,
+  CreateDateColumn,
+  ManyToOne,
+} from 'typeorm';
+
+import { GameEntity } from '../game/game.entity';
 
 // temporary table for warning notifications
 @Entity('Notifications')
 export class NotificationEntity {
-    @PrimaryGeneratedColumn('uuid') id: string;
-    @Column({type: 'text'}) message: string;
-    @CreateDateColumn() issued: Date;
-    // TODO:
-    // when game creation has been implemented, add logic so that the notifications are tied to games
-}
\ No newline at end of file
+  @PrimaryGeneratedColumn('uuid') id: string;
+  @Column('text') type: string;
+  @Column({ type: 'text' }) message: string;
+  @CreateDateColumn() issued: Date;
+
+  @ManyToOne(type => GameEntity, game => game.id, {
+    onDelete: 'CASCADE',
+  })
+  game: string;
+}
diff --git a/src/notifications/notifications.gateway.ts b/src/notifications/notifications.gateway.ts
index c30114895ffa8d4b40c3cedeaf827c5b3401cb25..5e952d6c78c6f35977f362a7459c0ebf65d1ab5e 100644
--- a/src/notifications/notifications.gateway.ts
+++ b/src/notifications/notifications.gateway.ts
@@ -6,12 +6,15 @@ import {
   OnGatewayConnection,
   OnGatewayDisconnect,
 } from '@nestjs/websockets';
-import { Logger } from '@nestjs/common';
+import { Logger, UsePipes } from '@nestjs/common';
 import { InjectRepository } from '@nestjs/typeorm';
 import { Server, Socket } from 'socket.io';
 import { Repository } from 'typeorm';
 
 import { NotificationEntity } from './notification.entity';
+import { GameEntity } from '../game/game.entity';
+import { NotificationdDTO } from './notification.dto';
+import { ValidationPipe } from '../shared/validation.pipe';
 
 @WebSocketGateway()
 export class NotificationGateway
@@ -20,6 +23,8 @@ export class NotificationGateway
     //create references to tables as repositories
     @InjectRepository(NotificationEntity)
     private notificationRepository: Repository<NotificationEntity>,
+    @InjectRepository(GameEntity)
+    private gameRepository: Repository<GameEntity>,
   ) {}
   @WebSocketServer()
   server: Server;
@@ -40,14 +45,17 @@ export class NotificationGateway
   }
 
   // notifications for when game needs to be paused / stopped
-  @SubscribeMessage('shutItDown')
-  async handleMessage(client: Socket, text: string) {
-    this.logger.log(text);
-    // send the message to all clients listening to warningToPlayers branch
-    this.server.emit('warningToPlayers', text);
-    // create entity properties
-    const message = await this.notificationRepository.create({ message: text });
-    // insert created entity NOTE: insert method doesn't check for duplicates.
-    await this.notificationRepository.insert(message);
+  @SubscribeMessage('game-info')
+  @UsePipes(new ValidationPipe())
+  async handleMessage(client: Socket, data: NotificationdDTO) {
+    // check if the game exists and is either started or paused
+    const game = await this.gameRepository.findOne({ id: data.game });
+    if (game && ['STARTED', 'PAUSED'].includes(game.state)) {
+      // send the message to all clients listening to gameId branch
+      this.server.emit(data.game, data);
+      // create entry for notification in db
+      const message = await this.notificationRepository.create(data);
+      await this.notificationRepository.insert(message);
+    }
   }
 }
diff --git a/src/notifications/notifications.module.ts b/src/notifications/notifications.module.ts
index 194c5c38155d0f976d286456a53814a08f517050..41e2fcaa36d1928dff9a60bd2c6853e240baf16f 100644
--- a/src/notifications/notifications.module.ts
+++ b/src/notifications/notifications.module.ts
@@ -3,9 +3,10 @@ import { TypeOrmModule } from '@nestjs/typeorm';
 
 import { NotificationGateway } from './notifications.gateway';
 import { NotificationEntity } from './notification.entity';
+import { GameEntity } from '../game/game.entity';
 
 @Module({
-  imports: [TypeOrmModule.forFeature([NotificationEntity])],
+  imports: [TypeOrmModule.forFeature([NotificationEntity, GameEntity])],
   providers: [NotificationGateway],
   exports: [NotificationGateway],
 })
diff --git a/src/score/score.controller.ts b/src/score/score.controller.ts
new file mode 100644
index 0000000000000000000000000000000000000000..73fda22e699f5702b1616360bd7e95f0ac8aeb10
--- /dev/null
+++ b/src/score/score.controller.ts
@@ -0,0 +1,36 @@
+import { Controller, Post, UsePipes, Body, Param, Get } from '@nestjs/common';
+
+import { ValidationPipe } from '../shared/validation.pipe';
+import { ScoreService } from './score.service';
+import { ScoreDTO } from './score.dto';
+import { GameEntity } from '../game/game.entity';
+import { Roles, GameStates } from '../shared/guard.decorator';
+
+@Controller('score')
+export class ScoreController {
+  constructor(private scoreService: ScoreService) {}
+
+  // adds score manually to Faction
+  // :id is gameId
+  @Post('add-score/:id')
+  @Roles('admin')
+  @GameStates('STARTED')
+  @UsePipes(new ValidationPipe())
+  async addingScore(@Body() data: ScoreDTO, @Param('id') gameId: GameEntity) {
+    return this.scoreService.addScore(data, gameId);
+  }
+
+  // temporary scoreTick path, :id is gameId
+  @Get('tick-score/:id')
+  @GameStates('STARTED')
+  async scoreTick(@Param('id') gameId: GameEntity) {
+    return this.scoreService.scoreTick(gameId);
+  }
+
+  // shows scores, :id is gameId 
+  @Get('get-score/:id')
+  @GameStates('STARTED')
+  async getScores(@Param('id') gameId: GameEntity) {
+    return this.scoreService.getScores(gameId);
+  }
+}
diff --git a/src/score/score.dto.ts b/src/score/score.dto.ts
new file mode 100644
index 0000000000000000000000000000000000000000..99955f56eff34a41ce46111d7fd0cb9cd597386f
--- /dev/null
+++ b/src/score/score.dto.ts
@@ -0,0 +1,10 @@
+import { IsNumber, Min, Max, IsUUID } from 'class-validator';
+
+export class ScoreDTO {
+  @IsNumber()
+  @Min(1)
+  @Max(99)
+  score: number;
+  @IsUUID('4')
+  faction: string;
+}
diff --git a/src/score/score.entity.ts b/src/score/score.entity.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6ca9ab77b968060a6dc88c860425119914cec030
--- /dev/null
+++ b/src/score/score.entity.ts
@@ -0,0 +1,21 @@
+import {
+  Entity,
+  PrimaryGeneratedColumn,
+  Column,
+  ManyToOne,
+  Timestamp,
+  CreateDateColumn,
+} from 'typeorm';
+import { FactionEntity } from '../faction/faction.entity';
+
+@Entity('Score')
+export class ScoreEntity {
+  @PrimaryGeneratedColumn('uuid') scoreId: string;
+  @Column({ type: 'float' }) score: number;
+  @CreateDateColumn({ type: 'timestamp' }) scoreTimeStamp: Timestamp;
+
+  @ManyToOne(type => FactionEntity, factionName => factionName.factionId, {
+    onDelete: 'CASCADE',
+  })
+  faction: string;
+}
diff --git a/src/score/score.module.ts b/src/score/score.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c04486fc676fca0d7c6a38c74374e03e23a1008c
--- /dev/null
+++ b/src/score/score.module.ts
@@ -0,0 +1,27 @@
+import { Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
+
+import { ScoreController } from './score.controller';
+import { ScoreService } from './score.service';
+import { FactionEntity } from '../faction/faction.entity';
+import {
+  ObjectivePointEntity,
+  ObjectivePoint_HistoryEntity,
+} from '../game/game.entity';
+import { ScoreEntity } from './score.entity';
+import { NotificationModule } from '../notifications/notifications.module';
+
+@Module({
+  imports: [
+    TypeOrmModule.forFeature([
+      ScoreEntity,
+      ObjectivePointEntity,
+      ObjectivePoint_HistoryEntity,
+      FactionEntity,
+    ]),
+    NotificationModule,
+  ],
+  controllers: [ScoreController],
+  providers: [ScoreService],
+})
+export class ScoreModule {}
diff --git a/src/score/score.service.ts b/src/score/score.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dba8e6e79206322a4dffae937b5af6b2bdd89041
--- /dev/null
+++ b/src/score/score.service.ts
@@ -0,0 +1,119 @@
+import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
+import { InjectRepository } from '@nestjs/typeorm';
+import { Repository } from 'typeorm';
+
+import { FactionEntity } from '../faction/faction.entity';
+import { ScoreDTO } from './score.dto';
+import {
+  ObjectivePoint_HistoryEntity,
+  ObjectivePointEntity,
+  GameEntity,
+} from '../game/game.entity';
+import { ScoreEntity } from './score.entity';
+import { NotificationGateway } from '../notifications/notifications.gateway';
+
+@Injectable()
+export class ScoreService {
+  constructor(
+    @InjectRepository(ScoreEntity)
+    private scoreRepository: Repository<ScoreEntity>,
+    @InjectRepository(ObjectivePointEntity)
+    private flagRepository: Repository<ObjectivePointEntity>,
+    @InjectRepository(ObjectivePoint_HistoryEntity)
+    private flagHistoryRepository: Repository<ObjectivePoint_HistoryEntity>,
+    @InjectRepository(FactionEntity)
+    private factionRepository: Repository<FactionEntity>,
+    private notificationGateway: NotificationGateway,
+  ) {}
+
+  async addScore(scoreData: ScoreDTO, gameId: GameEntity) {
+    // check if faction exists
+    const faction = await this.factionRepository.findOne({
+      factionId: scoreData.faction,
+    });
+    if (!faction) {
+      throw new HttpException('Faction was not found', HttpStatus.BAD_REQUEST);
+    }
+    // get the previous score and add it, if it exists
+    let lastScore = await this.scoreRepository.findOne({
+      where: { faction: scoreData.faction },
+      order: { scoreTimeStamp: 'DESC' },
+    });
+    if (lastScore) {
+      scoreData.score += lastScore.score;
+    }
+    // add the score for Faction
+    const newScore = await this.scoreRepository.create(scoreData);
+    await this.scoreRepository.insert(newScore);
+    return {
+      message: 'Score updated!',
+    };
+  }
+
+  async scoreTick(gameId) {
+    // get game's flagboxes
+    const flagboxes = await this.flagRepository.find({ game: gameId });
+    // create an array of DTOs for adding score
+    let scoreData = [];
+    await Promise.all(
+      flagboxes.map(async box => {
+        // get the newest entry in history
+        let current = await this.flagHistoryRepository.findOne({
+          where: { objective_point: box.objectivePointId },
+          relations: ['owner'],
+          order: { oP_HistoryTimestamp: 'DESC' },
+        });
+        // if result was found, add score to the owner
+        if (current.owner) {
+          let index = await scoreData.findIndex(
+            i => i.faction === current.owner.factionId,
+          );
+          index !== -1
+            ? await (scoreData[index]['score'] += box.objectivePointMultiplier)
+            : await scoreData.push({
+                score: box.objectivePointMultiplier,
+                faction: current.owner.factionId,
+              });
+        }
+      }),
+    );
+    scoreData.map(async data => {
+      await this.addScore(data, gameId);
+    });
+    this.notificationGateway.server.emit(gameId, { type: 'score-update' });
+    return {
+      message: 'Scores added',
+    };
+  }
+
+  async getScores(gameId: GameEntity) {
+    // find games factions
+    const factions = await this.factionRepository.find({
+      where: {game: gameId,},
+      relations: ['game'],
+    });
+    let scores = [];
+    await Promise.all(
+      factions.map(async factionNow => {
+        let score = await this.scoreRepository.findOne({
+          where: {faction: factionNow},
+          relations: ['faction'],
+          order: {scoreTimeStamp: 'DESC'},
+        });
+        //if score was found, put info to scores array
+        if (score.faction) {
+            let index = await scores.findIndex(
+              i => i.faction === score.faction,
+            );
+          scores.push(score);
+        }
+      }))
+      return scores;
+  }
+} //
+
+// Hae kaikki Objective pointit
+// aja map funktio pelin objective pointteihin
+// jokaisella objective point ID:llä hae historystä
+// relaatio, missä uusin timestamp
+// katso uusimmista history entrystä omistaja
diff --git a/src/shared/roles.decorator.ts b/src/shared/guard.decorator.ts
similarity index 53%
rename from src/shared/roles.decorator.ts
rename to src/shared/guard.decorator.ts
index 0d14223c3ce5ee1002cf245fa16fd1b57749bae1..b299d6de913f54dd496c344f6dcdafd2942b2c9c 100644
--- a/src/shared/roles.decorator.ts
+++ b/src/shared/guard.decorator.ts
@@ -1,3 +1,6 @@
 import { SetMetadata } from '@nestjs/common';
 
-export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
\ No newline at end of file
+export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
+
+export const GameStates = (...states: string[]) =>
+  SetMetadata('states', states);
diff --git a/src/shared/states.guard.ts b/src/shared/states.guard.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9e85e94e40f92ed6b016e451c592a3025a684cad
--- /dev/null
+++ b/src/shared/states.guard.ts
@@ -0,0 +1,47 @@
+import {
+  Injectable,
+  CanActivate,
+  ExecutionContext,
+  HttpException,
+  HttpStatus,
+} from '@nestjs/common';
+import { Reflector } from '@nestjs/core';
+import { InjectRepository } from '@nestjs/typeorm';
+import { Repository } from 'typeorm';
+
+import { GameEntity } from '../game/game.entity';
+
+@Injectable()
+export class StatesGuard implements CanActivate {
+  constructor(
+    private readonly reflector: Reflector,
+    @InjectRepository(GameEntity)
+    private gameRepository: Repository<GameEntity>,
+  ) {}
+
+  // Checks the state for gameId and grants access if it matches the criteria
+  // allowed states are CREATED, STARTED, PAUSED, ENDED
+  async canActivate(context: ExecutionContext): Promise<boolean> {
+    // get game states that are allowed access, identified by @GameStates('state') decorators in controllers
+    const states = this.reflector.get<string[]>('states', context.getHandler());
+    if (!states) {
+      return true;
+    }
+    const request = context.switchToHttp().getRequest();
+    const gameId = request.params.id;
+    const gameRef = await this.gameRepository.findOne({
+      id: gameId,
+    });
+    // check that the gameState matches the criteria
+    if (gameRef && states.includes(gameRef.state)) {
+      return true;
+    } else {
+      throw new HttpException(
+        `Game is set to ${
+          gameRef.state
+        }, operation only valid in states ${states.join(', ')}`,
+        HttpStatus.BAD_REQUEST,
+      );
+    }
+  }
+}
diff --git a/src/task/task.controller.ts b/src/task/task.controller.ts
index 2cb030ff4332cc890e212f9749f1c84f0aa81248..8283ba5bd2c4d7da4eb668ac6268d5165930e3f4 100644
--- a/src/task/task.controller.ts
+++ b/src/task/task.controller.ts
@@ -1,8 +1,16 @@
-import { Controller, Post, Body, UsePipes, Get, Param } from '@nestjs/common';
+import {
+  Controller,
+  Post,
+  Body,
+  UsePipes,
+  Get,
+  Param,
+  Delete,
+} from '@nestjs/common';
 
 import { TaskService } from './task.service';
-import { CreateTaskDTO, EditTaskDTO } from './task.dto';
-import { Roles } from '../shared/roles.decorator';
+import { CreateTaskDTO, EditTaskDTO, DeleteTaskDTO } from './task.dto';
+import { Roles } from '../shared/guard.decorator';
 import { ValidationPipe } from '../shared/validation.pipe';
 import { User } from '../user/user.decorator';
 
@@ -28,7 +36,16 @@ export class TaskController {
     return this.taskService.editTask(data);
   }
 
-  // lists all the tasks for the game if user has game_person entry
+  // deletes a created task if the user has admin role in the game
+  // :id is the id of the game
+  @Delete('delete-task/:id')
+  @Roles('admin')
+  @UsePipes(new ValidationPipe())
+  async deleteTask(@Param('id') id: string, @Body() data: DeleteTaskDTO) {
+    return this.taskService.deleteTask(data);
+  }
+
+  // lists all the tasks for the game if the user has game_person entry
   // :id is the id of the game
   @Get('get-tasks/:id')
   @Roles('soldier', 'factionleader', 'admin')
diff --git a/src/task/task.dto.ts b/src/task/task.dto.ts
index a8830d7a770f8337c81b1922dcf02751eaf4e6ad..a1576e7d12c9d9a6263b445fdba293fe94e8964a 100644
--- a/src/task/task.dto.ts
+++ b/src/task/task.dto.ts
@@ -36,3 +36,8 @@ export class EditTaskDTO {
   @IsUUID('4')
   taskGame: GameEntity;
 }
+
+export class DeleteTaskDTO {
+  @IsUUID('4')
+  taskId: string;
+}
diff --git a/src/task/task.entity.ts b/src/task/task.entity.ts
index 85ee3c26d3830bdb81ebe89bccac93051e0562c7..f1c1cf103fa4338a7f10d0305888d13c097d7a09 100644
--- a/src/task/task.entity.ts
+++ b/src/task/task.entity.ts
@@ -16,11 +16,17 @@ export class TaskEntity {
   @Column({ type: 'text' }) taskDescription: string;
   @Column({ type: 'bool' }) taskIsActive: boolean;
 
-  @ManyToOne(type => FactionEntity, faction => faction.factionId)
+  @ManyToOne(type => FactionEntity, faction => faction.factionId, {
+    onDelete: 'CASCADE',
+  })
   faction: FactionEntity;
-  @ManyToOne(type => FactionEntity, faction => faction.factionId)
+  @ManyToOne(type => FactionEntity, faction => faction.factionId, {
+    onDelete: 'CASCADE',
+  })
   taskWinner: FactionEntity;
-  @ManyToOne(type => GameEntity, game => game.id)
+  @ManyToOne(type => GameEntity, game => game.id, {
+    onDelete: 'CASCADE',
+  })
   @JoinColumn({ name: 'taskGame' })
   taskGame: GameEntity;
 }
diff --git a/src/task/task.service.ts b/src/task/task.service.ts
index abada374a0c79ae4627c0968b80ce8798fadab04..d79338e0d21e9ce741c67d4bf94b89ba64e4c9c9 100644
--- a/src/task/task.service.ts
+++ b/src/task/task.service.ts
@@ -3,7 +3,7 @@ import { Repository } from 'typeorm';
 import { InjectRepository } from '@nestjs/typeorm';
 
 import { TaskEntity } from './task.entity';
-import { CreateTaskDTO, EditTaskDTO } from './task.dto';
+import { CreateTaskDTO, EditTaskDTO, DeleteTaskDTO } from './task.dto';
 import { FactionEntity } from '../faction/faction.entity';
 import { Game_PersonEntity } from '../game/game.entity';
 import { NotificationGateway } from '../notifications/notifications.gateway';
@@ -36,8 +36,8 @@ export class TaskService {
     // notify subscribers about a new task
     // if faction was set it notifies only faction members, else everyone
     this.notificationGateway.server.emit(
-      task.faction != null ? task.faction.toString() : 'global',
-      'new task',
+      task.faction != null ? task.faction.toString() : task.taskGame.toString(),
+      { type: 'task-update' },
     );
     return {
       message: 'Task added',
@@ -67,6 +67,17 @@ export class TaskService {
     };
   }
 
+  async deleteTask(data: DeleteTaskDTO) {
+    const task = await this.taskRepository.findOne({ taskId: data.taskId });
+    if (task) {
+      await this.taskRepository.delete({ taskId: task.taskId });
+      return {
+        message: 'Task deleted',
+      };
+    }
+    throw new HttpException('Task not found', HttpStatus.BAD_REQUEST);
+  }
+
   async fetchTasks(user, taskGame) {
     const gamePerson = await this.gamePersonRepository.findOne({
       where: {
@@ -78,23 +89,22 @@ export class TaskService {
     if (gamePerson.role == 'admin') {
       return await this.taskRepository.find({
         where: { taskGame: taskGame },
-        relations: ['faction'],
+        relations: ['faction', 'taskWinner'],
       });
     } else {
       return await this.taskRepository.find({
-        relations: ['faction'],
+        relations: ['faction', 'taskWinner'],
         where: [
           {
             taskGame: taskGame,
             faction: gamePerson.faction.factionId,
-            taskIsActive: true,
           },
           {
             taskGame: taskGame,
             faction: null,
-            taskIsActive: true,
           },
         ],
+        order: { taskIsActive: 'DESC' },
       });
     }
   }
diff --git a/src/tracking/geo.dto.ts b/src/tracking/geo.dto.ts
new file mode 100644
index 0000000000000000000000000000000000000000..352faf704db72912a548734185d277253d67c789
--- /dev/null
+++ b/src/tracking/geo.dto.ts
@@ -0,0 +1,14 @@
+import { IsNumber, Min, Max, Allow } from 'class-validator';
+
+export class GeoDTO {
+  @IsNumber()
+  @Min(-90)
+  @Max(90)
+  lat: number;
+  @IsNumber()
+  @Min(-180)
+  @Max(180)
+  lng: number;
+  @Allow()
+  time: number;
+}
diff --git a/src/tracking/tracking.controller.ts b/src/tracking/tracking.controller.ts
index 140b51e0ce816c2ac5c8b2b11ced8eee2b7d869f..ca0e79ee5195503f61d827dbc170474e66fd1bad 100644
--- a/src/tracking/tracking.controller.ts
+++ b/src/tracking/tracking.controller.ts
@@ -1,32 +1,42 @@
 import {
   Controller,
-  Get,
   Post,
   Param,
   UseGuards,
   UsePipes,
   Body,
+  Get,
 } from '@nestjs/common';
+
 import { TrackingService } from './tracking.service';
-import { Roles } from '../shared/roles.decorator';
-import { AuthGuard } from '../shared/auth.guard';
-import { ValidationPipe } from '../shared/validation.pipe';
 import { TrackingDTO } from './tracking.dto';
-import { User } from 'src/user/user.decorator';
+import { User } from '../user/user.decorator';
+import { Roles, GameStates } from '../shared/guard.decorator';
+import { ValidationPipe } from '../shared/validation.pipe';
+import { GeoDTO } from './geo.dto';
 
 @Controller('tracking')
 export class TrackingController {
   constructor(private trackingservice: TrackingService) {}
 
+  // inserts tracking data to the database
+  // :id is the id of the game
   @Post('location/:id')
-  @UseGuards(new AuthGuard())
-  @UsePipes(new ValidationPipe())
   @Roles('soldier')
+  @GameStates('STARTED')
+  @UsePipes(new ValidationPipe())
   async trackLocation(
     @User('id') userId,
     @Param('id') id,
-    @Body() trackdata: TrackingDTO,
+    @Body() trackdata: GeoDTO,
   ) {
     return this.trackingservice.trackLocation(userId, id, trackdata);
   }
+
+  @Get('players/:id')
+  @Roles('admin', 'factionleader')
+  @GameStates('STARTED', 'PAUSED')
+  async getPlayerLocations(@User('id') userId, @Param('id') gameId) {
+    return this.trackingservice.getPlayers(userId, gameId);
+  }
 }
diff --git a/src/tracking/tracking.dto.ts b/src/tracking/tracking.dto.ts
index 8dc949c954931fb730a455ba2096f89fe9bb5fec..81cc71597fa93910cb195b1fd4e30f38c62c1f05 100644
--- a/src/tracking/tracking.dto.ts
+++ b/src/tracking/tracking.dto.ts
@@ -1,8 +1,10 @@
 import { Game_PersonEntity } from '../game/game.entity';
-import { Allow } from 'class-validator';
+import { Allow, ValidateNested } from 'class-validator';
+import { GeoDTO } from './geo.dto';
+import { Type } from 'class-transformer';
 
 export class TrackingDTO {
-  @Allow()
-  data: JSON;
-  gamepersonId: Game_PersonEntity;
+  @ValidateNested()
+  @Type(() => GeoDTO)
+  data: GeoDTO;
 }
diff --git a/src/tracking/tracking.entity.ts b/src/tracking/tracking.entity.ts
index c64f64f1bb90a8f7cbcb662956f883f895f17221..c2699a09388ce8ad47c7119b46f4614fa52b34ec 100644
--- a/src/tracking/tracking.entity.ts
+++ b/src/tracking/tracking.entity.ts
@@ -1,17 +1,19 @@
-import {
-  Entity,
-  PrimaryGeneratedColumn,
-  Column,
-  ManyToOne,
-  OneToOne,
-  JoinColumn,
-} from 'typeorm';
+import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
 import { Game_PersonEntity, GameEntity } from '../game/game.entity';
+import { FactionEntity } from 'src/faction/faction.entity';
+import { GeoDTO } from './geo.dto';
 
 @Entity('Tracking')
 export class TrackingEntity {
   @PrimaryGeneratedColumn('uuid') id: string;
-  @Column({ type: 'json', nullable: true }) data: JSON;
-  @ManyToOne(type => Game_PersonEntity, person => person.gamepersonId)
+  @Column({ type: 'json', nullable: true }) data: GeoDTO[];
+
+  @ManyToOne(type => Game_PersonEntity, person => person.gamepersonId, {
+    onDelete: 'CASCADE',
+  })
   gamepersonId: Game_PersonEntity;
+  @ManyToOne(type => FactionEntity, faction => faction.factionId)
+  faction: FactionEntity;
+  @ManyToOne(type => GameEntity, game => game.id)
+  game: GameEntity;
 }
diff --git a/src/tracking/tracking.module.ts b/src/tracking/tracking.module.ts
index a6f3ff1734adba3435360213c13cf024fe3cb288..45b167fc526ab41addbb87575518c9acae884482 100644
--- a/src/tracking/tracking.module.ts
+++ b/src/tracking/tracking.module.ts
@@ -1,9 +1,10 @@
 import { Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
+
 import { TrackingController } from './tracking.controller';
 import { TrackingService } from './tracking.service';
-import { TypeOrmModule } from '@nestjs/typeorm';
-import { Game_PersonEntity } from 'src/game/game.entity';
 import { TrackingEntity } from './tracking.entity';
+import { Game_PersonEntity } from '../game/game.entity';
 
 @Module({
   imports: [TypeOrmModule.forFeature([TrackingEntity, Game_PersonEntity])],
diff --git a/src/tracking/tracking.service.ts b/src/tracking/tracking.service.ts
index 06f665c4f8471c0863ab8c22da34c0fa9fb9d36b..9941256dde52240d7c90b45d61b7b32ef4e1c242 100644
--- a/src/tracking/tracking.service.ts
+++ b/src/tracking/tracking.service.ts
@@ -1,9 +1,13 @@
 import { Injectable, HttpStatus, HttpException } from '@nestjs/common';
+import { InjectRepository } from '@nestjs/typeorm';
 import { Repository } from 'typeorm';
+
 import { Game_PersonEntity } from '../game/game.entity';
-import { InjectRepository } from '@nestjs/typeorm';
 import { TrackingEntity } from './tracking.entity';
 import { TrackingDTO } from './tracking.dto';
+import { FactionEntity } from '../faction/faction.entity';
+import { NotificationGateway } from 'src/notifications/notifications.gateway';
+import { GeoDTO } from './geo.dto';
 
 @Injectable()
 export class TrackingService {
@@ -14,11 +18,11 @@ export class TrackingService {
     private gamepersonrepository: Repository<Game_PersonEntity>,
   ) {}
 
-  async trackLocation(personId, gameId, trackdata: TrackingDTO) {
+  async trackLocation(personId, gameId, trackdata: GeoDTO) {
     // find player
     let gameperson = await this.gamepersonrepository.findOne({
-      game: gameId,
-      person: personId,
+      where: { game: gameId, person: personId },
+      relations: ['faction'],
     });
     if (!gameperson) {
       throw new HttpException(
@@ -32,28 +36,64 @@ export class TrackingService {
 
     // if player has pushed tracking data, update entry
     if (trackedperson) {
+      trackdata['time'] = Date.now();
       //add coordinates
-      trackedperson.data['geometry']['coordinates'].push(
-        await this.mapFunction(trackdata.data['geometry']['coordinates']),
-      );
+      trackedperson.data.push(trackdata);
       //add timestamp
-      trackedperson.data['geometry']['properties']['time'].push(
-        new Date(Date.now()),
-      );
-
-      return await this.trackingrepository.save(trackedperson);
+      await this.trackingrepository.save(trackedperson);
+      return { code: 201, message: 'Location updated!' };
     } else {
       // first entry will be empty
-      // initialize coordinates
-      trackdata.data['geometry']['coordinates'] = [];
-      // initialize timestamp
-      trackdata.data['geometry']['properties']['time'] = [];
-      trackedperson = await this.trackingrepository.create(trackdata);
+      trackdata['time'] = Date.now();
+      // initialize data
+      trackedperson = await this.trackingrepository.create(trackedperson);
+      trackedperson.data = [trackdata];
+      trackedperson.faction = gameperson.faction;
+      trackedperson.game = gameId;
       trackedperson.gamepersonId = gameperson;
-      return await this.trackingrepository.save(trackedperson);
+      await this.trackingrepository.save(trackedperson);
+
+      return { code: 201, message: 'Entry Created!' };
     }
   }
 
+  // get player data while game is running
+  async getPlayers(userId, gameId) {
+    // get gameperson
+    const gameperson = await this.gamepersonrepository.findOne({
+      where: { person: userId, game: gameId },
+      relations: ['faction'],
+    });
+
+    let playerdata;
+    // get playerdata
+    if (gameperson.faction) {
+      playerdata = await this.trackingrepository.find({
+        where: { faction: gameperson.faction },
+        relations: ['faction', 'gamepersonId'],
+      });
+    } else {
+      playerdata = await this.trackingrepository.find({
+        where: { game: gameId },
+        relations: ['faction', 'gamepersonId'],
+      });
+    }
+
+    // parse data
+    const currentdata = await Promise.all(
+      playerdata.map(async player => {
+        return {
+          gamepersonId: player['gamepersonId']['gamepersonId'],
+          gamepersonRole: player['gamepersonId']['role'],
+          factionId: player['faction']['factionId'],
+          coordinates: player['data'].pop(),
+        };
+      }),
+    );
+
+    return currentdata;
+  }
+
   private async mapFunction(data): Promise<Number> {
     return await data.map(type => {
       return type;