import GameState from "../../../GameState" ; import House from "../../game-data-structure/House" ; import { ClientMessage } from "../../../../messages/ClientMessage" ; import Player from "../../Player" ; import { ServerMessage } from "../../../../messages/ServerMessage" ; import Game from "../../game-data-structure/Game" ; import * as _ from "lodash" ; import { observable } from "mobx" ; import BetterMap from "../../../../utils/BetterMap" ; import User from "../../../../server/User" ; import IngameGameState from "../../IngameGameState" ; import { PlayerActionType } from "../../game-data-structure/GameLog" ; export interface BiddingGameStateParent extends GameState < any , any > { game : Game ; ingame : IngameGameState ; onBiddingGameStateEnd : ( results : [ number , House [ ] ] [ ] ) => void ; } export default class BiddingGameState < ParentGameState extends BiddingGameStateParent > extends GameState < ParentGameState > { participatingHouses : House [ ] ; @ observable bids : BetterMap < House , number > = new BetterMap < House , number > ( ) ; @ observable powerTokensToBid = 0 ; get game ( ) : Game { return this . parentGameState . game ; } get ingame ( ) : IngameGameState { return this . parentGameState . ingame ; } onPlayerMessage ( player , message ) { if ( message . type == "bid" ) { const bid = message . powerTokens ; if ( ! this . participatingHouses . includes ( player . house ) || bid < 0 || bid > player . house . powerTokens ) { return ; } this . bids . set ( player . house , bid ) ; this . entireGame . sendMessageToClients ( _ . without ( this . entireGame . users . values , player . user ) , { type : "bid-done" , houseId : player . house . id , value : - 1 } ) ; this . entireGame . sendMessageToClients ( [ player . user ] , { type : "bid-done" , houseId : player . house . id , value : bid } ) ; this . ingame . log ( { type : "player-action" , house : player . house . id , action : PlayerActionType . BID_MADE } ) ; this . checkAndProceedEndOfBidding ( ) ; } } checkAndProceedEndOfBidding ( ) { if ( this . getHousesLeftToBid ( ) . length > 0 ) { return false ; } this . bids . entries . forEach ( ( [ house , bid ] ) => { house . powerTokens -= bid ; this . entireGame . broadcastToClients ( { type : "change-power-token" , houseId : house . id , powerTokenCount : house . powerTokens } ) ; } ) ; const housesPerBid = new BetterMap < number , House [ ] > ( ) ; this . bids . forEach ( ( bid , house ) => { if ( housesPerBid . has ( bid ) ) { housesPerBid . get ( bid ) . push ( house ) ; } else { housesPerBid . set ( bid , [ house ] ) ; } } ) ; const results = _ . sortBy ( housesPerBid . entries , ( [ bid , _ ] ) => - bid ) ; this . parentGameState . onBiddingGameStateEnd ( results ) ; return true ; } onServerMessage ( message ) { if ( message . type == "bid-done" ) { const house = this . game . houses . get ( message . houseId ) ; this . bids . set ( house , message . value ) ; } else if ( message . type == "bidding-begin" ) { this . bids = new BetterMap ( ) ; this . powerTokensToBid = 0 ; } } bid ( powerTokens ) { this . entireGame . sendMessageToServer ( { type : "bid" , powerTokens : powerTokens } ) ; } hasBid ( house ) { return this . bids . has ( house ) ; } getWaitedUsers ( ) { return this . getHousesLeftToBid ( ) . map ( h => this . parentGameState . ingame . getControllerOfHouse ( h ) . user ) ; } getHousesLeftToBid ( ) { return _ . difference ( this . participatingHouses , this . bids . keys ) ; } firstStart ( participatingHouses = [ ] ) { this . participatingHouses = participatingHouses ; this . participatingHouses . forEach ( h => { if ( h . powerTokens == 0 || this . ingame . isVassalHouse ( h ) ) { this . bids . set ( h , 0 ) ; if ( ! this . ingame . isVassalHouse ( h ) ) { this . ingame . log ( { type : "player-action" , house : h . id , action : PlayerActionType . BID_MADE } , true ) ; } } } ) ; if ( ! this . checkAndProceedEndOfBidding ( ) ) { this . entireGame . broadcastToClients ( { type : "bidding-begin" } ) ; } } serializeToClient ( admin , player ) { return { type : "bidding" , participatingHouses : this . participatingHouses . map ( h => h . id ) , bids : this . bids . entries . map ( ( [ house , bid ] ) => { if ( admin || ( player && house == player . house ) ) { return [ house . id , bid ] ; } else { return [ house . id , - 1 ] ; } } ) } ; } static deserializeFromServer < ParentGameState extends BiddingGameStateParent > ( parent , data ) { const biddingGameState = new BiddingGameState ( parent ) ; biddingGameState . participatingHouses = data . participatingHouses . map ( hid => parent . game . houses . get ( hid ) ) ; biddingGameState . bids = new BetterMap ( data . bids . map ( ( [ houseId , bid ] ) => [ parent . game . houses . get ( houseId ) , bid ] ) ) ; return biddingGameState ; } actionAfterVassalReplacement ( newVassal ) { if ( this . participatingHouses . includes ( newVassal ) ) { this . bids . set ( newVassal , 0 ) ; this . ingame . entireGame . broadcastToClients ( { type : "bid-done" , houseId : newVassal . id , value : 0 } ) ; this . checkAndProceedEndOfBidding ( ) ; } } } export interface SerializedBiddingGameState { type : "bidding" ; participatingHouses : string [ ] ; bids : [ string , number ] [ ] ; }