Compare commits

..

3 Commits

Author SHA1 Message Date
efim a87f4f99c0 add display of the name on the open card
to make disambiguation on the viewing round simpler
will style this later
2023-04-28 11:58:48 +04:00
efim d7d4e2be9d bugfix: need to recognize owner after relogin
playerid is not stable right now, need to use nickname
2023-04-28 11:54:51 +04:00
efim 3158a75f5d bugfix: leaving room needs to clear votes 2023-04-28 11:43:59 +04:00
5 changed files with 56 additions and 37 deletions

View File

@ -82,6 +82,6 @@ object Auth {
def make[F[_]: Sync](): F[Auth[F]] = def make[F[_]: Sync](): F[Auth[F]] =
for { for {
sessionsMap <- Ref.of[F, SessionsMap](TestModels.testSessions) sessionsMap <- Ref.of[F, SessionsMap](Map.empty)
} yield new SimpleAuth(sessionsMap) } yield new SimpleAuth(sessionsMap)
} }

View File

@ -59,7 +59,7 @@ class InMemoryRoomService[F[_]: Concurrent](stateRef: Ref[F, Map[RoomID, (Room,
val newRoom = Room( val newRoom = Room(
roomId, roomId,
players = List(ownerPlayer), players = List(ownerPlayer),
owner = ownerPlayer.id, owner = ownerPlayer.name,
password = roomPassword, password = roomPassword,
allowedCards = List("XS", "S", "M", "L", "XL"), // TODO accept from front allowedCards = List("XS", "S", "M", "L", "XL"), // TODO accept from front
round = RoundState.Voting(Map.empty), round = RoundState.Voting(Map.empty),
@ -122,7 +122,11 @@ class InMemoryRoomService[F[_]: Concurrent](stateRef: Ref[F, Map[RoomID, (Room,
*/ */
override def leaveRoom(roomID: RoomID, playerID: PlayerID): F[Unit] = updateRoom( override def leaveRoom(roomID: RoomID, playerID: PlayerID): F[Unit] = updateRoom(
roomID, roomID,
room => room.copy(players = room.players.filterNot(_.id == playerID)) room =>
room.copy(
players = room.players.filterNot(_.id == playerID),
round = room.round.removePlayer(playerID)
)
) )
override def deleteRoom(roomID: RoomID): F[Unit] = { override def deleteRoom(roomID: RoomID): F[Unit] = {
@ -159,7 +163,7 @@ class InMemoryRoomService[F[_]: Concurrent](stateRef: Ref[F, Map[RoomID, (Room,
room.players.find(_.name == nickName) match { room.players.find(_.name == nickName) match {
case Some(player) => player.id -> room case Some(player) => player.id -> room
case None => // player is not present, but potentially was previously case None => // player is not present, but potentially was previously
val addingPlayer = Player.create(nickPassword) val addingPlayer = Player.create(nickName)
val roomWithPlayer = room.copy(players = addingPlayer :: room.players) val roomWithPlayer = room.copy(players = addingPlayer :: room.players)
room.playersPasswords.get(nickName) match { room.playersPasswords.get(nickName) match {
case Some(_) => addingPlayer.id -> roomWithPlayer case Some(_) => addingPlayer.id -> roomWithPlayer

View File

@ -59,7 +59,7 @@ object Models {
final case class Room( final case class Room(
id: RoomID, id: RoomID,
players: List[Player], players: List[Player],
owner: PlayerID, // TODO switch to nickname owner: String, // TODO switch to nickname
password: String, password: String,
allowedCards: List[String], allowedCards: List[String],
round: RoundState, round: RoundState,
@ -74,7 +74,7 @@ object Models {
me.id, me.id,
allowedCards, allowedCards,
round.toViewFor(playerId), round.toViewFor(playerId),
playerId == owner me.name == owner
) )
) )
} }
@ -83,18 +83,23 @@ object Models {
// no need to send to the front end, no deed to derive codec, cool // no need to send to the front end, no deed to derive codec, cool
sealed trait RoundState { sealed trait RoundState {
def toViewFor(player: PlayerID): RoundStateView def toViewFor(player: PlayerID): RoundStateView
def removePlayer(id: PlayerID): RoundState
} }
object RoundState { object RoundState {
final case class Voting(votes: Map[PlayerID, String]) extends RoundState { final case class Voting(votes: Map[PlayerID, String]) extends RoundState {
def toViewFor(playerId: PlayerID): RoundStateView.Voting = RoundStateView.Voting( override def toViewFor(playerId: PlayerID): RoundStateView.Voting = RoundStateView.Voting(
myCard = votes.get(playerId), myCard = votes.get(playerId),
alreadyVoted = votes.filterKeys(id => id != playerId).keys.toList 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 { final case class Viewing(votes: Map[PlayerID, String]) extends RoundState {
def toViewFor(player: PlayerID): RoundStateView.Viewing = override def toViewFor(player: PlayerID): RoundStateView.Viewing =
RoundStateView.Viewing(votes.toList) RoundStateView.Viewing(votes.toList)
override def removePlayer(id: PlayerID): RoundState.Viewing =
RoundState.Viewing(votes.filterKeys(_ != id).toMap)
} }
} }
} }

View File

@ -8,21 +8,21 @@ object TestModels {
val birdy = Player("birdy", PlayerID(11)) val birdy = Player("birdy", PlayerID(11))
val horsey = Player("horsey", PlayerID(12)) val horsey = Player("horsey", PlayerID(12))
val testRoomBackend = Room( // val testRoomBackend = Room(
id = RoomID("testroom"), // id = RoomID("testroom"),
players = List(me, birdy, pony, horsey), // players = List(me, birdy, pony, horsey),
owner = me.id, // owner = me.id,
password = "password", // password = "password",
allowedCards = List("xs", "s", "m", "l", "xl"), // allowedCards = List("xs", "s", "m", "l", "xl"),
round = RoundState.Viewing( // round = RoundState.Viewing(
Map(me.id -> "xs", pony.id -> "l", birdy.id -> "s", horsey.id -> "m") // Map(me.id -> "xs", pony.id -> "l", birdy.id -> "s", horsey.id -> "m")
), // ),
playersPasswords = Map("me" -> "nickpassword") // nickname into password // playersPasswords = Map("me" -> "nickpassword") // nickname into password
) // )
val testSessionId = 1L // val testSessionId = 1L
val testSessions = Map(testSessionId -> (testRoomBackend.id, me.id)) // val testSessions = Map(testSessionId -> (testRoomBackend.id, me.id))
val testRooms = Map(testRoomBackend.id -> testRoomBackend) // val testRooms = Map(testRoomBackend.id -> testRoomBackend)
val testChangesList = List( val testChangesList = List(
RoomStateView( RoomStateView(

View File

@ -34,8 +34,8 @@ object TableView {
trait CardState trait CardState
case class NoCard(name: String) extends CardState case class NoCard(name: String) extends CardState
case object CardBack extends CardState case class CardBack(name: String) extends CardState
case class Open(value: String) extends CardState case class Open(name: String, value: String) extends CardState
def getPlayerCardType( def getPlayerCardType(
id: PlayerID, id: PlayerID,
@ -46,36 +46,46 @@ object TableView {
state match { state match {
case isOpen: RoundStateView.Voting => case isOpen: RoundStateView.Voting =>
if (myId == id) { if (myId == id) {
isOpen.myCard.fold(NoCard(name))(vote => Open(vote)) isOpen.myCard.fold(NoCard(name))(vote => Open(name, vote))
} else isOpen.alreadyVoted.find(_ == id).fold(NoCard(name))(_ => CardBack) } else isOpen.alreadyVoted.find(_ == id).fold(NoCard(name))(_ => CardBack(name))
case isClosed: RoundStateView.Viewing => case isClosed: RoundStateView.Viewing =>
isClosed.votes isClosed.votes
.find(_._1 == id) .find(_._1 == id)
.fold { .fold {
g.console.error(s"missing vote for player $name") g.console.error(s"missing vote for player $name")
Open("error") Open(name, "error")
} { case (_, vote) => Open(vote) } } { case (_, vote) => Open(name, vote) }
} }
} }
def renderPlayerCard(state: Signal[CardState]): Element = { def renderPlayerCard(state: Signal[CardState]): Element = {
val cardTypeStyle = state.map { val cardTypeStyle = state.map {
case NoCard(_) => "bg-green-100 text-black border-2 border-black" case NoCard(_) => "bg-green-100 text-black border-2 border-black"
case CardBack => "bg-green-500 border-4 border-green-700" case CardBack(_) => "bg-green-500 border-4 border-green-700"
case Open(_) => "text-black bg-gray-50 border-black border-2" case Open(_, _) => "text-black bg-gray-50 border-black border-2"
} }
div( div(
className := "w-20 h-40 m-1 rounded flex justify-center items-center m-3", className := "w-20 h-40 m-1 rounded flex flex-col justify-center items-center m-3",
className <-- cardTypeStyle, className <-- cardTypeStyle,
// the diagonal card value \ place text
div( div(
className := "-rotate-45 text-xl", className := "-rotate-45 text-xl",
child.text <-- state.map { child.text <-- state.map {
case NoCard(name) => name case NoCard(name) => name
case CardBack => "" case CardBack(name) => name
case Open(vote) => vote case Open(_, vote) => vote
}
),
// name under viewing the votes
div(
className := "text-xl",
child.text <-- state.map {
case Open(name, _) => name
case _ => ""
} }
) )
) )
} }