109 lines
3.2 KiB
Scala
109 lines
3.2 KiB
Scala
package industries.sunshine.planningpoker.common
|
|
|
|
import java.util.UUID
|
|
import io.circe._
|
|
import scala.util.Random
|
|
|
|
object Models {
|
|
|
|
/** view of the single planning poker round
|
|
* @param players
|
|
* \- people who are currently playing
|
|
* @param allowedCards-
|
|
* the cards values that can be used by players
|
|
* @param round
|
|
* \- state of the selected cards of the players
|
|
* @param canCloseRound
|
|
* \- whether current player has access to button to finish the round
|
|
*/
|
|
final case class RoomStateView(
|
|
roomName: String,
|
|
players: List[Player],
|
|
me: PlayerID,
|
|
allowedCards: List[String],
|
|
round: RoundStateView,
|
|
canCloseRound: Boolean = false
|
|
) derives Codec.AsObject
|
|
|
|
object RoomStateView {
|
|
val empty = RoomStateView(
|
|
"",
|
|
List.empty,
|
|
PlayerID(0),
|
|
List.empty,
|
|
RoundStateView.Voting(None, List.empty),
|
|
false
|
|
)
|
|
}
|
|
|
|
enum RoundStateView derives Codec.AsObject:
|
|
/** view state for round before votes are open player can know their vote and who of the other
|
|
* players have voted
|
|
*/
|
|
case Voting(
|
|
myCard: Option[String],
|
|
alreadyVoted: List[PlayerID]
|
|
)
|
|
|
|
/** view state for round after opening the votes
|
|
*/
|
|
case Viewing(
|
|
votes: List[(PlayerID, String)]
|
|
)
|
|
|
|
final case class PlayerID(id: Long) derives Codec.AsObject
|
|
final case class Player(name: String, id: PlayerID) derives Codec.AsObject
|
|
object Player {
|
|
def create(name: String) = Player(name, PlayerID(Random.nextLong))
|
|
}
|
|
|
|
final case class RoomID(name: String) derives Codec.AsObject
|
|
final case class Room(
|
|
id: RoomID,
|
|
players: List[Player],
|
|
owner: String, // TODO switch to nickname
|
|
password: String,
|
|
allowedCards: List[String],
|
|
round: RoundState,
|
|
playersPasswords: Map[String, String] = Map.empty, // nickname into password
|
|
) {
|
|
def getViewFor(playerId: PlayerID): RoomStateView = {
|
|
players
|
|
.find(_.id == playerId)
|
|
.fold(ifEmpty = RoomStateView.empty)((me: Player) =>
|
|
RoomStateView(
|
|
id.name,
|
|
players,
|
|
me.id,
|
|
allowedCards,
|
|
round.toViewFor(playerId),
|
|
me.name == owner
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
// no need to send to the front end, no deed to derive codec, cool
|
|
sealed trait RoundState {
|
|
def toViewFor(player: PlayerID): RoundStateView
|
|
def removePlayer(id: PlayerID): RoundState
|
|
}
|
|
object RoundState {
|
|
final case class Voting(votes: Map[PlayerID, String]) extends RoundState {
|
|
override def toViewFor(playerId: PlayerID): RoundStateView.Voting = RoundStateView.Voting(
|
|
myCard = votes.get(playerId),
|
|
alreadyVoted = votes.filterKeys(id => id != playerId).keys.toList
|
|
)
|
|
override def removePlayer(id: PlayerID): RoundState.Voting =
|
|
RoundState.Voting(votes.filterKeys(_ != id).toMap)
|
|
}
|
|
|
|
final case class Viewing(votes: Map[PlayerID, String]) extends RoundState {
|
|
override def toViewFor(player: PlayerID): RoundStateView.Viewing =
|
|
RoundStateView.Viewing(votes.toList)
|
|
override def removePlayer(id: PlayerID): RoundState.Viewing =
|
|
RoundState.Viewing(votes.filterKeys(_ != id).toMap)
|
|
}
|
|
}
|
|
}
|