All files PlayerState.ts

45.9% Statements 28/61
25% Branches 5/20
58.33% Functions 7/12
47.45% Lines 28/59

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161      1x 1x           1x                       96780x 96780x 96780x 96780x             22332x                                         74387x                 141x 141x 141x 141x 141x                                                     141x 141x     141x             141x 141x 705x   141x                                                                   22212x 22212x 5x   22212x 22212x 111055x   22212x                    
/**
 * @author Timo Lehnertz
 */
import { BoardPosition } from "./BoardPosition";
import { Treasure } from "./Treasure";
 
/**
 * Immutable Playerstate class containing all information about a player.
 * Only publicly exposes the information that other players and the player itself can legaly know
 */
export class PlayerState {
  private readonly foundTreasures: Treasure[];
  private readonly remainingTreasures: Treasure[];
  public readonly currentTreasure: Treasure | null;
  public readonly position: BoardPosition;
 
  public constructor(
    foundTreasures: Treasure[],
    remainingTreasures: Treasure[],
    currentTreasure: Treasure | null,
    position: BoardPosition
  ) {
    this.foundTreasures = foundTreasures;
    this.remainingTreasures = remainingTreasures;
    this.currentTreasure = currentTreasure;
    this.position = position;
  }
 
  /**
   * Returns the number of remaining treasures to be found including the currently open treasure
   */
  public get remainingTreasureCount(): number {
    return (
      this.remainingTreasures.length + (this.currentTreasure !== null ? 1 : 0)
    );
  }
 
  public get lastFoundTreasure(): Treasure | null {
    Iif (this.foundTreasures.length === 0) {
      return null;
    }
    return this.foundTreasures[this.foundTreasures.length - 1];
  }
 
  public get foundTreasureCount(): number {
    return this.foundTreasures.length;
  }
 
  public getFoundTreasure(index: number): Treasure {
    return this.foundTreasures[index];
  }
 
  public setPosition(newPosition: BoardPosition): PlayerState {
    return new PlayerState(
      this.foundTreasures,
      this.remainingTreasures,
      this.currentTreasure,
      newPosition
    );
  }
 
  public collectTreasure(treasure: Treasure): PlayerState {
    const newFoundTreasures = this.copyFoundTreasures();
    const newRemainingTreasures = this.copyRemainingTreasures();
    const newCurrentTreasure = newRemainingTreasures.pop() ?? null;
    newFoundTreasures.push(treasure);
    return new PlayerState(
      newFoundTreasures,
      newRemainingTreasures,
      newCurrentTreasure,
      this.position
    );
  }
 
  public removeLastTreasure(): PlayerState {
    const newFoundTreasures = this.copyFoundTreasures();
    const newRemainingTreasures = this.copyRemainingTreasures();
    Iif (this.currentTreasure !== null) {
      newRemainingTreasures.push(this.currentTreasure);
    }
    const newCurrentTreasure = newFoundTreasures.pop() ?? null;
    return new PlayerState(
      newFoundTreasures,
      newRemainingTreasures,
      newCurrentTreasure,
      this.position
    );
  }
 
  /**
   * Treasures are immutable so we dont need to make a deep copy here
   */
  private copyFoundTreasures(): Treasure[] {
    const newFoundTreasures: Treasure[] = [];
    for (const foundTreasure of this.foundTreasures) {
      newFoundTreasures.push(foundTreasure);
    }
    return newFoundTreasures;
  }
 
  /**
   * Treasures are immutable so we dont need to make a deep copy here
   */
  private copyRemainingTreasures(): Treasure[] {
    const newRemainingTreasures: Treasure[] = [];
    for (const remainingTreasure of this.remainingTreasures) {
      newRemainingTreasures.push(remainingTreasure);
    }
    return newRemainingTreasures;
  }
 
  public equals(other: PlayerState): boolean {
    Iif (!this.position.equals(other.position)) {
      return false;
    }
    Iif (!Treasure.compare(this.currentTreasure, other.currentTreasure)) {
      return false;
    }
    Iif (this.foundTreasures.length !== other.foundTreasures.length) {
      return false;
    }
    for (let i = 0; i < this.foundTreasures.length; i++) {
      const a = this.foundTreasures[i];
      const b = other.foundTreasures[i];
      Iif (!a.equals(b)) {
        return false;
      }
    }
    Iif (this.remainingTreasures.length !== other.remainingTreasures.length) {
      return false;
    }
    for (let i = 0; i < this.remainingTreasures.length; i++) {
      const a = this.remainingTreasures[i];
      const b = other.remainingTreasures[i];
      Iif (!a.equals(b)) {
        return false;
      }
    }
    return true;
  }
 
  public static create(instance: PlayerState): PlayerState {
    const foundTreasures: Treasure[] = [];
    for (const foundTreasure of instance.foundTreasures) {
      foundTreasures.push(Treasure.create(foundTreasure));
    }
    const remainingTreasures: Treasure[] = [];
    for (const remainingTreasure of instance.remainingTreasures) {
      remainingTreasures.push(Treasure.create(remainingTreasure));
    }
    return new PlayerState(
      foundTreasures,
      remainingTreasures,
      instance.currentTreasure !== null
        ? Treasure.create(instance.currentTreasure)
        : null,
      BoardPosition.create(instance.position)
    );
  }
}