7 Commits

Author SHA1 Message Date
LQ63
9191012aaf Merge pull request 'FixedIssues' (#35) from fixissues into development
All checks were successful
Build and Test (KnockOutWhist) TeamCity build finished
Reviewed-on: #35
2024-11-21 22:01:04 +01:00
LQ63
1a7e48864b Fixed TuiMain
All checks were successful
Build and Test (KnockOutWhist) TeamCity build finished
2024-11-21 21:54:16 +01:00
LQ63
6ef9e95cb8 Changed TuiMain so that it isn't smelly anymore
All checks were successful
Build and Test (KnockOutWhist) TeamCity build finished
2024-11-21 21:50:26 +01:00
c94e37f63e Reduced complexity
All checks were successful
Build and Test (KnockOutWhist) TeamCity build finished
2024-11-21 21:29:16 +01:00
LQ63
be4e00af44 Reduced smelly code
All checks were successful
Build and Test (KnockOutWhist) TeamCity build finished
2024-11-21 21:17:53 +01:00
LQ63
ebea37aece Merge remote-tracking branch 'refs/remotes/origin/development' into fixissues
# Conflicts:
#	src/main/scala/de/knockoutwhist/control/PlayerControl.scala
#	src/main/scala/de/knockoutwhist/control/RoundControl.scala
#	src/main/scala/de/knockoutwhist/control/TrickControl.scala
2024-11-21 21:16:04 +01:00
LQ63
47169bdb8b changed a name to match the given regex by sonarqube
All checks were successful
Build and Test (KnockOutWhist) TeamCity build finished
2024-11-21 12:25:22 +01:00
17 changed files with 325 additions and 315 deletions

View File

@@ -14,7 +14,7 @@ object KnockOutWhist {
*/
private[knockoutwhist] var DEBUG_MODE_VAR: Boolean = false
def DEBUG_MODE = DEBUG_MODE_VAR
def debugmode = DEBUG_MODE_VAR
def main(args: Array[String]): Unit = {
if(!TUIMain.initial) throw new IllegalStateException("Game could not be started.")

View File

@@ -1,19 +1,12 @@
package de.knockoutwhist.control
import de.knockoutwhist.KnockOutWhist
import de.knockoutwhist.cards.{Card, CardManager}
import de.knockoutwhist.control.RoundControl.controlRound
import de.knockoutwhist.events.*
import de.knockoutwhist.events.ERROR_STATUS.{IDENTICAL_NAMES, INVALID_NAME_FORMAT, INVALID_NUMBER_OF_PLAYERS, WRONG_CARD}
import de.knockoutwhist.events.ERROR_STATUS.{IDENTICAL_NAMES, INVALID_NAME_FORMAT, INVALID_NUMBER_OF_PLAYERS}
import de.knockoutwhist.events.GLOBAL_STATUS.*
import de.knockoutwhist.events.PLAYER_STATUS.{SHOW_NOT_PLAYED, SHOW_WON_PLAYER_TRICK}
import de.knockoutwhist.events.ROUND_STATUS.{PLAYERS_OUT, SHOW_START_ROUND, WON_ROUND}
import de.knockoutwhist.events.round.ShowCurrentTrickEvent
import de.knockoutwhist.events.util.DelayEvent
import de.knockoutwhist.player.Player
import de.knockoutwhist.rounds.{Match, Round, Trick}
import de.knockoutwhist.rounds.Match
import de.knockoutwhist.utils.CustomPlayerQueue
import de.knockoutwhist.utils.Implicits.*
import scala.compiletime.uninitialized
import scala.io.StdIn
@@ -51,10 +44,9 @@ object MatchControl {
def controlMatch(): Player = {
val matchImpl = Match(playerQueue.toList)
while (!isOver(matchImpl)) {
val roundImpl = controlRound(matchImpl)
controlRound(matchImpl)
}
val winner = finalizeMatch(matchImpl)
val playerwinner = winner.name
ControlHandler.invoke(ShowGlobalStatus(SHOW_FINISHED_MATCH, winner))
winner
}

View File

@@ -2,68 +2,59 @@ package de.knockoutwhist.control
import de.knockoutwhist.KnockOutWhist
import de.knockoutwhist.cards.{Card, CardManager, Suit}
import de.knockoutwhist.control.PlayerControl
import de.knockoutwhist.events.ERROR_STATUS.{INVALID_INPUT, INVALID_NUMBER, NOT_A_NUMBER}
import de.knockoutwhist.events.GLOBAL_STATUS.{SHOW_TIE, SHOW_TIE_TIE, SHOW_TIE_WINNER}
import de.knockoutwhist.events.PLAYER_STATUS.{SHOW_DOG_PLAY_CARD, SHOW_PLAY_CARD, SHOW_TIE_NUMBERS, SHOW_TRUMPSUIT_OPTIONS, SHOW_TURN}
import de.knockoutwhist.events.PLAYER_STATUS.*
import de.knockoutwhist.events.cards.{RenderHandEvent, ShowTieCardsEvent}
import de.knockoutwhist.events.directional.{RequestCardEvent, RequestDogPlayCardEvent, RequestNumberEvent, RequestPickTrumpsuitEvent}
import de.knockoutwhist.events.util.DelayEvent
import de.knockoutwhist.events.{ShowErrorStatus, ShowGlobalStatus, ShowPlayerStatus}
import de.knockoutwhist.player.Player
import de.knockoutwhist.rounds.Round
import de.knockoutwhist.ui.tui.TUIMain
import de.knockoutwhist.utils.DelayHandler
import de.knockoutwhist.utils.events.EventHandler
import scala.annotation.tailrec
import scala.collection.mutable
import scala.collection.mutable.ListBuffer
import scala.io.StdIn.readLine
import scala.util.{Failure, Success}
import scala.util.control.Breaks.*
object PlayerControl {
@tailrec
def playCard(player: Player): Card = {
ControlHandler.invoke(ShowPlayerStatus(SHOW_TURN, player))
ControlHandler.invoke(DelayEvent(3000L))
ControlHandler.invoke(ShowPlayerStatus(SHOW_PLAY_CARD, player))
ControlHandler.invoke(RenderHandEvent(player.currentHand().get, true))
ControlHandler.invoke(RequestCardEvent(player.currentHand().get)) match {
case Success(value) => {
case Success(value) =>
value
}
case Failure(exception) => {
case Failure(exception) =>
ControlHandler.invoke(ShowErrorStatus(INVALID_NUMBER))
playCard(player)
}
}
}
@tailrec
def dogplayCard(player: Player, round: Round): Option[Card] = {
ControlHandler.invoke(ShowPlayerStatus(SHOW_TURN, player))
ControlHandler.invoke(DelayEvent(3000L))
ControlHandler.invoke(ShowPlayerStatus(SHOW_DOG_PLAY_CARD, player, RoundControl.dogNeedsToPlay(round)))
ControlHandler.invoke(RenderHandEvent(player.currentHand().get, false))
ControlHandler.invoke(RequestDogPlayCardEvent(player.currentHand().get, RoundControl.dogNeedsToPlay(round))) match {
case Success(value) => {
case Success(value) =>
value
}
case Failure(exception) => {
case Failure(exception) =>
ControlHandler.invoke(ShowErrorStatus(INVALID_INPUT))
dogplayCard(player, round)
}
}
}
def determineWinnerTie(players: List[Player]): Player = {
determineWinnerTieText(players, true)
determineWinnerTie(players, true)
}
@tailrec
private def determineWinnerTieText(players: List[Player], tieMessage: Boolean): Player = {
if (!KnockOutWhist.DEBUG_MODE) CardManager.shuffleAndReset()
private def determineWinnerTie(players: List[Player], tieMessage: Boolean): Player = {
if (!KnockOutWhist.debugmode) CardManager.shuffleAndReset()
if (tieMessage) ControlHandler.invoke(ShowGlobalStatus(SHOW_TIE))
var currentStep = 0
var remaining = CardManager.cardContainer.size - (players.length - 1)
@@ -84,14 +75,17 @@ object PlayerControl {
}
}
ControlHandler.invoke(ShowTieCardsEvent(cut.toList))
evaluateTieWinner(cut)
}
var currentHighest: Card = null
private def evaluateTieWinner(cut: mutable.HashMap[Player, Card]): Player = {
val winner: ListBuffer[Player] = ListBuffer()
var currentHighest: Card = null
for ((player, card) <- cut) {
if (currentHighest == null) {
currentHighest = card
winner += player
}else {
} else {
val compared = card.cardValue.ordinal.compareTo(currentHighest.cardValue.ordinal)
if (compared > 0) {
currentHighest = card
@@ -107,20 +101,19 @@ object PlayerControl {
return winner.head
}
ControlHandler.invoke(ShowGlobalStatus(SHOW_TIE_TIE))
determineWinnerTieText(winner.toList, false)
determineWinnerTie(winner.toList, false)
}
@tailrec
def pickNextTrumpsuit(player: Player): Suit = {
ControlHandler.invoke(ShowPlayerStatus(SHOW_TRUMPSUIT_OPTIONS, player))
ControlHandler.invoke(RenderHandEvent(player.currentHand().get, false))
ControlHandler.invoke(RequestPickTrumpsuitEvent()) match {
case Success(value) => {
case Success(value) =>
value
}
case Failure(exception) => {
case Failure(exception) =>
ControlHandler.invoke(ShowErrorStatus(INVALID_NUMBER))
pickNextTrumpsuit(player)
}
}
}
}

View File

@@ -3,23 +3,21 @@ package de.knockoutwhist.control
import de.knockoutwhist.KnockOutWhist
import de.knockoutwhist.cards.CardManager
import de.knockoutwhist.control.MatchControl.playerQueue
import de.knockoutwhist.player.Player
import de.knockoutwhist.rounds.{Match, Round, Trick}
import de.knockoutwhist.utils.Implicits.*
import de.knockoutwhist.control.RoundControl
import de.knockoutwhist.control.TrickControl.controlTrick
import de.knockoutwhist.events.ROUND_STATUS.{PLAYERS_OUT, SHOW_START_ROUND, WON_ROUND}
import de.knockoutwhist.events.ShowRoundStatus
import de.knockoutwhist.events.util.DelayEvent
import de.knockoutwhist.player.Player
import de.knockoutwhist.rounds.{Match, Round}
import de.knockoutwhist.utils.Implicits.*
object RoundControl {
def isOver(round: Round): Boolean = {
round.players_in.map(_.currentHand()).count(_.get.cards.isEmpty) == round.players_in.size
round.playersin.map(_.currentHand()).count(_.get.cards.isEmpty) == round.playersin.size
}
def dogNeedsToPlay(round: Round): Boolean = {
round.players_in.filter(!_.doglife).map(_.currentHand()).exists(_.get.cards.isEmpty)
round.playersin.filter(!_.doglife).map(_.currentHand()).exists(_.get.cards.isEmpty)
}
def finalizeRound(round: Round, matchImpl: Match,force: Boolean = false): (Player, Round) = {
@@ -36,7 +34,7 @@ object RoundControl {
var playersOut = round.firstRound
? List()
|: round.players_in.filter(!tricksMapped.contains(_))
|: round.playersin.filter(!tricksMapped.contains(_))
if (playersOut.nonEmpty && !matchImpl.dogLife) {
matchImpl.dogLife = true
@@ -52,31 +50,31 @@ object RoundControl {
? winners.head
|: PlayerControl.determineWinnerTie(winners.toList)
val finalRound = Round(round.trumpSuit, matchImpl, round.tricklist, round.players_in, playersOut, winner, round.firstRound)
val finalRound = Round(round.trumpSuit, matchImpl, round.tricklist, round.playersin, playersOut, winner, round.firstRound)
matchImpl.roundlist += finalRound
(winner, finalRound)
}
def remainingPlayers(round: Round): List[Player] = {
if (round.players_out == null) {
return round.players_in
if (round.playersout == null) {
return round.playersin
}
round.players_in.filter(!round.players_out.contains(_))
round.playersin.filter(!round.playersout.contains(_))
}
def create_round(matchImpl: Match): Round = {
def createround(matchImpl: Match): Round = {
val remainingPlayer = matchImpl.roundlist.isEmpty ? matchImpl.totalplayers |: RoundControl.remainingPlayers(matchImpl.roundlist.last)
provideCards(matchImpl, remainingPlayer)
if (matchImpl.roundlist.isEmpty) {
val random_trumpsuit = CardManager.nextCard().suit
matchImpl.current_round = Some(new Round(random_trumpsuit, matchImpl, remainingPlayer, true))
val randomTrumpsuit = CardManager.nextCard().suit
matchImpl.current_round = Some(new Round(randomTrumpsuit, matchImpl, remainingPlayer, true))
} else {
val winner = matchImpl.roundlist.last.winner
val trumpsuit = PlayerControl.pickNextTrumpsuit(winner)
matchImpl.current_round = Some(new Round(trumpsuit, matchImpl, remainingPlayer, false))
}
matchImpl.number_of_cards -= 1
matchImpl.numberofcards -= 1
matchImpl.current_round.get
}
@@ -84,7 +82,7 @@ object RoundControl {
if (MatchControl.isOver(matchImpl)) {
return null
}
create_round(matchImpl)
createround(matchImpl)
}
@@ -97,9 +95,9 @@ object RoundControl {
val (roundWinner, finalRound) = RoundControl.finalizeRound(roundImpl, matchImpl)
ControlHandler.invoke(ShowRoundStatus(WON_ROUND, finalRound, roundWinner))
ControlHandler.invoke(DelayEvent(5000L))
if (finalRound.players_out.nonEmpty) {
if (finalRound.playersout.nonEmpty) {
ControlHandler.invoke(ShowRoundStatus(PLAYERS_OUT, finalRound))
finalRound.players_out.foreach(p => {
finalRound.playersout.foreach(p => {
playerQueue.remove(p)
})
}
@@ -109,11 +107,11 @@ object RoundControl {
private def provideCards(matchImpl: Match, players: List[Player]): Int = {
if (!KnockOutWhist.DEBUG_MODE) CardManager.shuffleAndReset()
if (!KnockOutWhist.debugmode) CardManager.shuffleAndReset()
var hands = 0
for (player <- players) {
if (!player.doglife) {
player.provideHand(CardManager.createHand(matchImpl.number_of_cards))
player.provideHand(CardManager.createHand(matchImpl.numberofcards))
} else {
player.provideHand(CardManager.createHand(1))
}

View File

@@ -5,11 +5,11 @@ import de.knockoutwhist.cards.Card
import de.knockoutwhist.control.MatchControl.playerQueue
import de.knockoutwhist.events.ERROR_STATUS.WRONG_CARD
import de.knockoutwhist.events.PLAYER_STATUS.{SHOW_NOT_PLAYED, SHOW_WON_PLAYER_TRICK}
import de.knockoutwhist.events.{ShowErrorStatus, ShowPlayerStatus}
import de.knockoutwhist.events.round.ShowCurrentTrickEvent
import de.knockoutwhist.events.util.DelayEvent
import de.knockoutwhist.rounds.{Round, Trick}
import de.knockoutwhist.events.{ShowErrorStatus, ShowPlayerStatus}
import de.knockoutwhist.player.Player
import de.knockoutwhist.rounds.{Round, Trick}
object TrickControl {
@@ -17,11 +17,11 @@ object TrickControl {
if (trick.finished) {
throw new IllegalStateException("This trick is already finished")
} else {
if (trick.get_first_card().isEmpty) {
trick.set_first_card(card)
if (trick.getfirstcard().isEmpty) {
trick.setfirstcard(card)
trick.cards += (card -> player)
true
} else if (card.suit == trick.get_first_card().getOrElse(card).suit) { // Wert aus Option extrahieren
} else if (card.suit == trick.getfirstcard().getOrElse(card).suit) { // Wert aus Option extrahieren
trick.cards += (card -> player)
true
} else if (card.suit == round.trumpSuit) {
@@ -39,7 +39,7 @@ object TrickControl {
if (trick.cards.keys.exists(_.suit == round.trumpSuit)) {
trick.cards.keys.filter(_.suit == round.trumpSuit).maxBy(_.cardValue.ordinal) //stream
} else {
trick.cards.keys.filter(_.suit == trick.get_first_card().get.suit).maxBy(_.cardValue.ordinal) //stream
trick.cards.keys.filter(_.suit == trick.getfirstcard().get.suit).maxBy(_.cardValue.ordinal) //stream
}
}
val winningPlayer = trick.cards(winningCard)
@@ -48,9 +48,9 @@ object TrickControl {
(winningPlayer, finalTrick)
}
def create_trick(round: Round): Trick = {
def createtrick(round: Round): Trick = {
val trick = new Trick(round)
round.set_current_trick(trick)
round.setcurrenttrick(trick)
trick
}
@@ -84,14 +84,14 @@ object TrickControl {
if (RoundControl.isOver(roundImpl)) {
return null
}
create_trick(roundImpl)
createtrick(roundImpl)
}
private[control] def controlSuitplayed(trick: Trick, player: Player): Card = {
var card = PlayerControl.playCard(player)
if (trick.get_first_card().isDefined) {
val firstCard = trick.get_first_card().get
while (!(firstCard.suit == card.suit)) {
if (trick.getfirstcard().isDefined) {
val firstCard = trick.getfirstcard().get
while (firstCard.suit != card.suit) {
var hasSuit = false
for (cardInHand <- player.currentHand().get.cards) {
if (cardInHand.suit == firstCard.suit) {

View File

@@ -5,6 +5,6 @@ import de.knockoutwhist.utils.events.ReturnableEvent
import scala.util.Try
case class RequestDogPlayCardEvent(hand: Hand, needs_to_play: Boolean) extends ReturnableEvent[Try[Option[Card]]] {
case class RequestDogPlayCardEvent(hand: Hand, needstoplay: Boolean) extends ReturnableEvent[Try[Option[Card]]] {
override def id: String = "RequestDogPlayCardEvent"
}

View File

@@ -1,6 +1,6 @@
package de.knockoutwhist.events.directional
import de.knockoutwhist.utils.events.{SimpleEvent, ReturnableEvent}
import de.knockoutwhist.utils.events.{ReturnableEvent, SimpleEvent}
import scala.io.StdIn
import scala.util.Try

View File

@@ -1,20 +1,18 @@
package de.knockoutwhist.rounds
import de.knockoutwhist.KnockOutWhist
import de.knockoutwhist.cards.CardManager
import de.knockoutwhist.player.Player
import de.knockoutwhist.utils.Implicits.*
import scala.collection.mutable.ListBuffer
import de.knockoutwhist.utils.Implicits._
case class Match(totalplayers: List[Player], var number_of_cards: Int = 7) {
case class Match(totalplayers: List[Player], var numberofcards: Int = 7) {
val roundlist: ListBuffer[Round] = ListBuffer[Round]()
var current_round: Option[Round] = None
var dogLife = false
override def toString: String = {
s"${totalplayers}, ${number_of_cards}"
s"$totalplayers, $numberofcards"
}
}

View File

@@ -1,29 +1,29 @@
package de.knockoutwhist.rounds
import de.knockoutwhist.KnockOutWhist
import de.knockoutwhist.cards.{CardManager, Suit}
import de.knockoutwhist.cards.Suit
import de.knockoutwhist.player.Player
import de.knockoutwhist.utils.Implicits.*
import scala.collection.mutable
import scala.collection.mutable.ListBuffer
case class Round (trumpSuit: Suit, matchImpl: Match, tricklist: ListBuffer[Trick], players_in: List[Player], players_out: List[Player] = null, winner: Player = null, firstRound: Boolean) {
def this(trumpSuit: Suit, matchImpl: Match, players_in: List[Player], firstRound: Boolean) = {
this(trumpSuit, matchImpl, ListBuffer[Trick](), players_in, firstRound = firstRound)
case class Round (trumpSuit: Suit, matchImpl: Match, tricklist: ListBuffer[Trick], playersin: List[Player], playersout: List[Player] = null, winner: Player = null, firstRound: Boolean) {
def this(trumpSuit: Suit, matchImpl: Match, playersin: List[Player], firstRound: Boolean) = {
this(trumpSuit, matchImpl, ListBuffer[Trick](), playersin, firstRound = firstRound)
}
private var current_trick: Option[Trick] = None
private var currenttrick: Option[Trick] = None
def get_current_trick(): Option[Trick] = {
current_trick
def getcurrenttrick(): Option[Trick] = {
currenttrick
}
def set_current_trick(trick: Trick): Unit = {
current_trick = Some(trick)
def setcurrenttrick(trick: Trick): Unit = {
currenttrick = Some(trick)
}
override def toString: String = {
s"$trumpSuit, $tricklist, $players_in, $players_out, $winner, $firstRound"
s"$trumpSuit, $tricklist, $playersin, $playersout, $winner, $firstRound"
}

View File

@@ -1,7 +1,6 @@
package de.knockoutwhist.rounds
import de.knockoutwhist.cards.Card
import de.knockoutwhist.cards.Suit
import de.knockoutwhist.player.Player
import scala.collection.mutable
@@ -14,14 +13,14 @@ case class Trick (round: Round, cards: mutable.HashMap[Card, Player], winner: Pl
}
private var first_card: Option[Card] = None // statt als Parameter im Konstruktor
def set_first_card(card: Card): Option[Card] = {
def setfirstcard(card: Card): Option[Card] = {
if(first_card.isDefined) {
throw new IllegalStateException("This trick is already finished")
}
first_card = Some(card)
first_card
}
def get_first_card(): Option[Card] = first_card
def getfirstcard(): Option[Card] = first_card
override def toString: String = {
s"$cards, $winner, $finished"

View File

@@ -25,205 +25,27 @@ object TUIMain extends EventListener with UI {
override def listen[R](event: ReturnableEvent[R]): Option[R] = {
event match {
case event: RenderHandEvent =>
TUICards.renderHandEvent(event.hand, event.showNumbers).foreach(println)
Some(true)
renderhandmethod(event)
case event: ShowTieCardsEvent =>
val a: Array[String] = Array("", "", "", "", "", "", "", "")
for ((player,card) <- event.card) {
val playerNameLength = player.name.length
a(0) += " " + player.name + ":" + (" " * (playerNameLength - 1))
val rendered = TUICards.renderCardAsString(card)
a(1) += " " + rendered(0)
a(2) += " " + rendered(1)
a(3) += " " + rendered(2)
a(4) += " " + rendered(3)
a(5) += " " + rendered(4)
a(6) += " " + rendered(5)
a(7) += " " + rendered(6)
}
a.foreach(println)
Some(true)
showtiecardseventmethod(event)
case event: ShowGlobalStatus =>
event.status match {
case SHOW_TIE =>
println("It's a tie! Let's cut to determine the winner.")
Some(true)
case SHOW_TIE_WINNER =>
if(event.objects.length != 1 || !event.objects.head.isInstanceOf[Player]) {
None
} else {
println(s"${event.objects.head.asInstanceOf[Player].name} wins the cut!")
Some(true)
}
case SHOW_TIE_TIE =>
println("It's a tie again! Let's cut again.")
Some(true)
case SHOW_START_MATCH =>
TUIUtil.clearConsole()
println("Starting a new match...")
TUIUtil.clearConsole(2)
Some(true)
case SHOW_TYPE_PLAYERS =>
println("Please enter the names of the players, separated by a comma.")
Some(true)
case SHOW_FINISHED_MATCH =>
if (event.objects.length != 1 || !event.objects.head.isInstanceOf[Player]) {
None
} else {
TUIUtil.clearConsole()
println(s"The match is over. The winner is ${event.objects.head.asInstanceOf[Player]}")
Some(true)
}
}
showglobalstatusmethod(event)
case event: ShowPlayerStatus =>
val player = event.player
event.status match {
case SHOW_TURN =>
println("It's your turn, " + player.name + ".")
Some(true)
case SHOW_PLAY_CARD =>
println("Which card do you want to play?")
Some(true)
case SHOW_DOG_PLAY_CARD =>
if(event.objects.length != 1 || !event.objects.head.isInstanceOf[Boolean]) {
None
} else {
println("You are using your dog life. Do you want to play your final card now?")
if (event.objects.head.asInstanceOf[Boolean]) {
println("You have to play your final card this round!")
println("Please enter y to play your final card.")
Some(true)
} else {
println("Please enter y/n to play your final card.")
Some(true)
}
}
case SHOW_TIE_NUMBERS =>
if(event.objects.length != 1 || !event.objects.head.isInstanceOf[Int]) {
None
} else {
println(s"${player.name} enter a number between 1 and ${event.objects.head.asInstanceOf[Int]}.")
Some(true)
}
case SHOW_TRUMPSUIT_OPTIONS =>
println("Which suit do you want to pick as the next trump suit?")
println("1: Hearts")
println("2: Diamonds")
println("3: Clubs")
println("4: Spades")
println()
Some(true)
case SHOW_NOT_PLAYED =>
println(s"Player ${event.player} decided to not play his card")
Some(true)
case SHOW_WON_PLAYER_TRICK =>
println(s"${event.player.name} won the trick.")
TUIUtil.clearConsole(2)
Some(true)
}
showplayerstatusmethod(event)
case event: ShowRoundStatus =>
event.status match {
case SHOW_START_ROUND =>
TUIUtil.clearConsole()
println(s"Starting a new round. The trump suit is ${event.currentRound.trumpSuit}.")
TUIUtil.clearConsole(2)
Some(true)
case WON_ROUND =>
if (event.objects.length != 1 || !event.objects.head.isInstanceOf[Player]) {
None
} else {
println(s"${event.objects.head.asInstanceOf[Player].name} won the round.")
Some(true)
}
case PLAYERS_OUT =>
println("The following players are out of the game:")
event.currentRound.players_out.foreach(p => {
println(p.name)
})
Some(true)
}
showroundstatusmethod(event)
case event: ShowErrorStatus =>
event.status match {
case INVALID_NUMBER =>
println("Please enter a valid number.")
Some(true)
case NOT_A_NUMBER =>
println("Please enter a valid number.")
Some(true)
case INVALID_INPUT =>
println("Please enter a valid input")
Some(true)
case INVALID_NUMBER_OF_PLAYERS =>
println("Please enter at least two names.")
Some(true)
case IDENTICAL_NAMES =>
println("Please enter unique names.")
Some(true)
case INVALID_NAME_FORMAT =>
println("Please enter valid names. Those can not be empty, shorter than 2 or longer then 10 characters.")
Some(true)
case WRONG_CARD =>
if(event.objects.length != 1 || !event.objects.head.isInstanceOf[Card]) {
None
} else {
println(f"You have to play a card of suit: ${event.objects.head.asInstanceOf[Card].suit}\n")
Some(true)
}
}
showerrstatmet(event)
case event: RequestNumberEvent =>
Some(Try {
val input = readLine()
val number = input.toInt
if (number < event.min || number > event.max) {
throw new IllegalArgumentException(s"Number must be between ${event.min} and ${event.max}")
}
number
})
reqnumbereventmet(event)
case event: RequestCardEvent =>
Some(Try {
val card = readLine().toInt - 1
if (card < 0 || card >= event.hand.cards.length) {
throw new IllegalArgumentException(s"Number has to be between 1 and ${event.hand.cards.length}")
} else {
event.hand.cards(card)
}
})
reqcardeventmet(event)
case event: RequestDogPlayCardEvent =>
Some(Try {
val card = readLine()
if (card.equalsIgnoreCase("y")) {
Some(event.hand.cards.head)
} else if (card.equalsIgnoreCase("n") && !event.needs_to_play) {
None
} else {
throw new IllegalArgumentException("Didn't want to play card but had to")
}
}
)
reqdogeventmet(event)
case event: RequestPickTrumpsuitEvent =>
Some(Try {
val suit = readLine().toInt
suit match {
case 1 => Suit.Hearts
case 2 => Suit.Diamonds
case 3 => Suit.Clubs
case 4 => Suit.Spades
case _ => throw IllegalArgumentException("Didn't enter a number between 1 and 4")
}
})
reqpicktevmet()
case event: ShowCurrentTrickEvent =>
TUIUtil.clearConsole()
val sb = new StringBuilder()
sb.append("Current Trick:\n")
sb.append("Trump-Suit: " + event.round.trumpSuit + "\n")
if (event.trick.get_first_card().isDefined) {
sb.append(s"Suit to play: ${event.trick.get_first_card().get.suit}\n")
}
for ((card, player) <- event.trick.cards) {
sb.append(s"${player.name} played ${card.toString}\n")
}
println(sb.toString())
Some(true)
showcurtrevmet(event)
case _ => None
}
}
@@ -231,13 +53,14 @@ object TUIMain extends EventListener with UI {
object TUICards {
def renderCardAsString(card: Card): Vector[String] = {
val lines = "│ │"
if (card.cardValue == CardValue.Ten) {
return Vector(
s"┌─────────┐",
s"${cardColour(card.suit)}${Console.BOLD}${card.cardValue.cardType()}${Console.RESET}",
"│ │",
lines,
s"${cardColour(card.suit)}${Console.BOLD}${card.suit.cardType()}${Console.RESET}",
"│ │",
lines,
s"${cardColour(card.suit)}${Console.BOLD}${card.cardValue.cardType()}${Console.RESET}",
s"└─────────┘"
)
@@ -245,9 +68,9 @@ object TUIMain extends EventListener with UI {
Vector(
s"┌─────────┐",
s"${cardColour(card.suit)}${Console.BOLD}${card.cardValue.cardType()}${Console.RESET}",
"│ │",
lines,
s"${cardColour(card.suit)}${Console.BOLD}${card.suit.cardType()}${Console.RESET}",
"│ │",
lines,
s"${cardColour(card.suit)}${Console.BOLD}${card.cardValue.cardType()}${Console.RESET}",
s"└─────────┘"
)
@@ -315,5 +138,215 @@ object TUIMain extends EventListener with UI {
initial
}
}
private def renderhandmethod(event: RenderHandEvent): Option[Boolean] = {
TUICards.renderHandEvent(event.hand, event.showNumbers).foreach(println)
Some(true)
}
private def showtiecardseventmethod(event: ShowTieCardsEvent): Option[Boolean] = {
val a: Array[String] = Array("", "", "", "", "", "", "", "")
for ((player, card) <- event.card) {
val playerNameLength = player.name.length
a(0) += " " + player.name + ":" + (" " * (playerNameLength - 1))
val rendered = TUICards.renderCardAsString(card)
a(1) += " " + rendered(0)
a(2) += " " + rendered(1)
a(3) += " " + rendered(2)
a(4) += " " + rendered(3)
a(5) += " " + rendered(4)
a(6) += " " + rendered(5)
a(7) += " " + rendered(6)
}
a.foreach(println)
Some(true)
}
private def showglobalstatusmethod(event: ShowGlobalStatus): Option[Boolean] = {
event.status match {
case SHOW_TIE =>
println("It's a tie! Let's cut to determine the winner.")
Some(true)
case SHOW_TIE_WINNER =>
if (event.objects.length != 1 || !event.objects.head.isInstanceOf[Player]) {
None
} else {
println(s"${event.objects.head.asInstanceOf[Player].name} wins the cut!")
Some(true)
}
case SHOW_TIE_TIE =>
println("It's a tie again! Let's cut again.")
Some(true)
case SHOW_START_MATCH =>
TUIUtil.clearConsole()
println("Starting a new match...")
TUIUtil.clearConsole(2)
Some(true)
case SHOW_TYPE_PLAYERS =>
println("Please enter the names of the players, separated by a comma.")
Some(true)
case SHOW_FINISHED_MATCH =>
if (event.objects.length != 1 || !event.objects.head.isInstanceOf[Player]) {
None
} else {
TUIUtil.clearConsole()
println(s"The match is over. The winner is ${event.objects.head.asInstanceOf[Player]}")
Some(true)
}
}
}
private def showplayerstatusmethod(event: ShowPlayerStatus): Option[Boolean] = {
val player = event.player
event.status match {
case SHOW_TURN =>
println("It's your turn, " + player.name + ".")
Some(true)
case SHOW_PLAY_CARD =>
println("Which card do you want to play?")
Some(true)
case SHOW_DOG_PLAY_CARD =>
if (event.objects.length != 1 || !event.objects.head.isInstanceOf[Boolean]) {
None
} else {
println("You are using your dog life. Do you want to play your final card now?")
if (event.objects.head.asInstanceOf[Boolean]) {
println("You have to play your final card this round!")
println("Please enter y to play your final card.")
Some(true)
} else {
println("Please enter y/n to play your final card.")
Some(true)
}
}
case SHOW_TIE_NUMBERS =>
if (event.objects.length != 1 || !event.objects.head.isInstanceOf[Int]) {
None
} else {
println(s"${player.name} enter a number between 1 and ${event.objects.head.asInstanceOf[Int]}.")
Some(true)
}
case SHOW_TRUMPSUIT_OPTIONS =>
println("Which suit do you want to pick as the next trump suit?")
println("1: Hearts")
println("2: Diamonds")
println("3: Clubs")
println("4: Spades")
println()
Some(true)
case SHOW_NOT_PLAYED =>
println(s"Player ${event.player} decided to not play his card")
Some(true)
case SHOW_WON_PLAYER_TRICK =>
println(s"${event.player.name} won the trick.")
TUIUtil.clearConsole(2)
Some(true)
}
}
private def showroundstatusmethod(event: ShowRoundStatus): Option[Boolean] = {
event.status match {
case SHOW_START_ROUND =>
TUIUtil.clearConsole()
println(s"Starting a new round. The trump suit is ${event.currentRound.trumpSuit}.")
TUIUtil.clearConsole(2)
Some(true)
case WON_ROUND =>
if (event.objects.length != 1 || !event.objects.head.isInstanceOf[Player]) {
None
} else {
println(s"${event.objects.head.asInstanceOf[Player].name} won the round.")
Some(true)
}
case PLAYERS_OUT =>
println("The following players are out of the game:")
event.currentRound.playersout.foreach(p => {
println(p.name)
})
Some(true)
}
}
private def showerrstatmet(event: ShowErrorStatus): Option[Boolean] = {
event.status match {
case INVALID_NUMBER =>
println("Please enter a valid number.")
Some(true)
case NOT_A_NUMBER =>
println("Please enter a number.")
Some(true)
case INVALID_INPUT =>
println("Please enter a valid input")
Some(true)
case INVALID_NUMBER_OF_PLAYERS =>
println("Please enter at least two names.")
Some(true)
case IDENTICAL_NAMES =>
println("Please enter unique names.")
Some(true)
case INVALID_NAME_FORMAT =>
println("Please enter valid names. Those can not be empty, shorter than 2 or longer then 10 characters.")
Some(true)
case WRONG_CARD =>
if (event.objects.length != 1 || !event.objects.head.isInstanceOf[Card]) {
None
} else {
println(f"You have to play a card of suit: ${event.objects.head.asInstanceOf[Card].suit}\n")
Some(true)
}
}
}
private def reqnumbereventmet(event: RequestNumberEvent): Option[Try[Int]] = {
Some(Try {
val input = readLine()
val number = input.toInt
if (number < event.min || number > event.max) {
throw new IllegalArgumentException(s"Number must be between ${event.min} and ${event.max}")
}
number
})
}
private def reqcardeventmet(event: RequestCardEvent): Option[Try[Card]] = {
Some(Try {
val card = readLine().toInt - 1
if (card < 0 || card >= event.hand.cards.length) {
throw new IllegalArgumentException(s"Number has to be between 1 and ${event.hand.cards.length}")
} else {
event.hand.cards(card)
}
})
}
private def reqdogeventmet(event: RequestDogPlayCardEvent): Option[Try[Option[Card]]]= {
Some(Try {
val card = readLine()
if (card.equalsIgnoreCase("y")) {
Some(event.hand.cards.head)
} else if (card.equalsIgnoreCase("n") && !event.needstoplay) {
None
} else {
throw new IllegalArgumentException("Didn't want to play card but had to")
}
}
)
}
private def reqpicktevmet(): Option[Try[Suit]] = {
Some(Try {
val suit = readLine().toInt
suit match {
case 1 => Suit.Hearts
case 2 => Suit.Diamonds
case 3 => Suit.Clubs
case 4 => Suit.Spades
case _ => throw IllegalArgumentException("Didn't enter a number between 1 and 4")
}
})
}
private def showcurtrevmet(event: ShowCurrentTrickEvent): Option[Boolean] = {
TUIUtil.clearConsole()
val sb = new StringBuilder()
sb.append("Current Trick:\n")
sb.append("Trump-Suit: " + event.round.trumpSuit + "\n")
if (event.trick.getfirstcard().isDefined) {
sb.append(s"Suit to play: ${event.trick.getfirstcard().get.suit}\n")
}
for ((card, player) <- event.trick.cards) {
sb.append(s"${player.name} played ${card.toString}\n")
}
println(sb.toString())
Some(true)
}
}

View File

@@ -1,9 +1,9 @@
package de.knockoutwhist.cards
import de.knockoutwhist.utils.events.EventHandler
import de.knockoutwhist.cards.CardValue.{Ace, Ten}
import de.knockoutwhist.events.cards.RenderHandEvent
import de.knockoutwhist.testutils.TestUtil
import de.knockoutwhist.ui.tui.TUIMain.TUICards.renderCardAsString
import de.knockoutwhist.utils.events.EventHandler
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

View File

@@ -1,14 +1,11 @@
package de.knockoutwhist.control
import de.knockoutwhist.cards.CardManager
import de.knockoutwhist.cards.CardValue.Ace
import de.knockoutwhist.cards.Suit.Hearts
import de.knockoutwhist.cards.{Card, CardValue, Hand, Suit}
import de.knockoutwhist.control.{MatchControl, RoundControl, TrickControl}
import de.knockoutwhist.cards.*
import de.knockoutwhist.player.Player
import de.knockoutwhist.rounds.{Match, Round, Trick}
import de.knockoutwhist.testutils.TestUtil
import de.knockoutwhist.ui.tui.TUIMain
import de.knockoutwhist.utils.CustomPlayerQueue
import org.scalatest.matchers.must.Matchers
import org.scalatest.matchers.should.Matchers.{should, shouldBe}

View File

@@ -1,7 +1,7 @@
package de.knockoutwhist.control
import de.knockoutwhist.cards.{CardManager, Hand}
import de.knockoutwhist.cards.Suit.*
import de.knockoutwhist.cards.{CardManager, Hand}
import de.knockoutwhist.control.PlayerControl
import de.knockoutwhist.player.Player
import de.knockoutwhist.rounds.Round

View File

@@ -3,11 +3,11 @@ package de.knockoutwhist.events
import de.knockoutwhist.KnockOutWhist
import de.knockoutwhist.cards.CardValue.{Queen, Two}
import de.knockoutwhist.cards.Suit.Hearts
import de.knockoutwhist.cards.{Card, CardManager, CardValue, Hand, Suit}
import de.knockoutwhist.cards.*
import de.knockoutwhist.control.{RoundControl, TrickControl}
import de.knockoutwhist.events.ERROR_STATUS.*
import de.knockoutwhist.events.GLOBAL_STATUS.*
import de.knockoutwhist.events.PLAYER_STATUS.*
import de.knockoutwhist.events.ERROR_STATUS.*
import de.knockoutwhist.events.ROUND_STATUS.*
import de.knockoutwhist.events.cards.{RenderHandEvent, ShowTieCardsEvent}
import de.knockoutwhist.events.directional.{RequestCardEvent, RequestDogPlayCardEvent, RequestNumberEvent, RequestPickTrumpsuitEvent}
@@ -197,8 +197,8 @@ class TestAllEvent extends AnyWordSpec with Matchers {
val player2 = Player("Peter")
val listplayers = List(player1, player2)
val match1 = Match(listplayers)
val round = RoundControl.create_round(match1)
val trick = TrickControl.create_trick(round)
val round = RoundControl.createround(match1)
val trick = TrickControl.createtrick(round)
TrickControl.playCard(trick, round, Card(CardValue.Ten, Suit.Spades), player1)
val event = ShowCurrentTrickEvent(round, trick)
"be able to get created" in {
@@ -355,7 +355,7 @@ class TestAllEvent extends AnyWordSpec with Matchers {
"The show round status event" should {
TestUtil.disableDelay()
val round = Round(trumpSuit = Hearts, matchImpl = null, tricklist = ListBuffer(), players_in = null, firstRound = false, players_out = List(Player("Foo")))
val round = Round(trumpSuit = Hearts, matchImpl = null, tricklist = ListBuffer(), playersin = null, firstRound = false, playersout = List(Player("Foo")))
var event: ShowRoundStatus = null
"be able to be created" in {
event = ShowRoundStatus(SHOW_START_ROUND, round)

View File

@@ -23,9 +23,9 @@ class MatchTests extends AnyWordSpec with Matchers{
val player2 = Player("Peter")
val player_list = List(player1, player2)
val match1 = Match(player_list)
val round1 = RoundControl.create_round(match1)
val round1 = RoundControl.createround(match1)
val trumpsuit = round1.trumpSuit
val trick1 = TrickControl.create_trick(round1)
val trick1 = TrickControl.createtrick(round1)
val playedcard1 = TestUtil.simulateInput("1\n") {
PlayerControl.playCard(player1)
}
@@ -40,10 +40,10 @@ class MatchTests extends AnyWordSpec with Matchers{
val rtrick1 = TrickControl.wonTrick(trick1, round1)
RoundControl.finalizeRound(round1, match1, true)
val round2 = TestUtil.simulateInput("1\n") {
RoundControl.create_round(match1)
RoundControl.createround(match1)
}
TestUtil.enableDebugMode()
val trick2: Trick = TrickControl.create_trick(round2)
val trick2: Trick = TrickControl.createtrick(round2)
val playedcard3 = TestUtil.simulateInput("1\n") {
PlayerControl.playCard(player1)
}
@@ -53,7 +53,7 @@ class MatchTests extends AnyWordSpec with Matchers{
}
TrickControl.playCard(trick2, round2, playedcard4, player2)
"be able to return the current trick of the round" in {
round2.get_current_trick().get should be(trick2)
round2.getcurrenttrick().get should be(trick2)
}
val rtrick2 = TrickControl.wonTrick(trick2, round2)
"return false if the round isn't over" in {
@@ -69,9 +69,9 @@ class MatchTests extends AnyWordSpec with Matchers{
}
RoundControl.finalizeRound(round2, match1, true)
val round3 = TestUtil.simulateInput("1\n") {
RoundControl.create_round(match1)
RoundControl.createround(match1)
}
val trick3 = TrickControl.create_trick(round3)
val trick3 = TrickControl.createtrick(round3)
val playedcard5 = TestUtil.simulateInput("1\n") {
PlayerControl.playCard(player1)
}
@@ -92,7 +92,7 @@ class MatchTests extends AnyWordSpec with Matchers{
"return false when no round has been completed" in {
CardManager.shuffleAndReset()
val match3 = Match(List(Player("Gunter")))
RoundControl.create_round(match3)
RoundControl.createround(match3)
MatchControl.isOver(match3) shouldBe false
}
"return true if one player is remaining after a round has been played" in {
@@ -100,16 +100,16 @@ class MatchTests extends AnyWordSpec with Matchers{
MatchControl.isOver(match1) shouldBe true
}
val round4 = TestUtil.simulateInput("1\n") {
RoundControl.create_round(match1)
RoundControl.createround(match1)
}
val trick4 = TrickControl.create_trick(round4)
val trick4 = TrickControl.createtrick(round4)
val playedcard7 = Card(CardValue.Ace, Suit.Hearts)
val playedcard8 = Card(CardValue.Two, Suit.Hearts)
TrickControl.playCard(trick4, round4, playedcard7, player1)
TrickControl.playCard(trick4, round4, playedcard8, player2)
TrickControl.wonTrick(trick4, round4)
val trick5 = TrickControl.create_trick(round4)
val trick5 = TrickControl.createtrick(round4)
TrickControl.playCard(trick5, round4, playedcard8, player1)
TrickControl.playCard(trick5, round4, playedcard7, player2)
TrickControl.wonTrick(trick5, round4)
@@ -119,7 +119,7 @@ class MatchTests extends AnyWordSpec with Matchers{
}
val round5 = TestUtil.simulateInput("1\n") {
RoundControl.create_round(match1)
RoundControl.createround(match1)
}
"error out if a round is finalized without any tricks played" in {
assertThrows[IllegalStateException] {

View File

@@ -20,8 +20,8 @@ class TrickTests extends AnyWordSpec with Matchers {
val card2 = Card(CardValue.Two, Suit.Clubs)
val trick = new Trick(round)
TrickControl.playCard(trick, round, card, player)
trick.get_first_card().isEmpty shouldBe false
trick.get_first_card().get shouldBe card
trick.getfirstcard().isEmpty shouldBe false
trick.getfirstcard().get shouldBe card
}
"be able to return no first card when none was played" in {
val player = Player("Gunter")
@@ -29,7 +29,7 @@ class TrickTests extends AnyWordSpec with Matchers {
val playerlist = List(player, player2)
val round = new Round(Suit.Diamonds, Match(playerlist), playerlist, false)
val trick = new Trick(round)
trick.get_first_card().isEmpty shouldBe true
trick.getfirstcard().isEmpty shouldBe true
}
"be able to tell who won the trick" in {
val playerlist = List(Player("Gunter"))
@@ -89,7 +89,7 @@ class TrickTests extends AnyWordSpec with Matchers {
val round = new Round(Suit.Diamonds, Match(playerlist), playerlist, false)
val card = Card(CardValue.Two, Suit.Spades)
val card2 = Card(CardValue.Ace, Suit.Spades)
val trick = TrickControl.create_trick(round)
val trick = TrickControl.createtrick(round)
TrickControl.playCard(trick, round, card, player)
TrickControl.playCard(trick, round, card2, player2) shouldBe true
}
@@ -135,9 +135,9 @@ class TrickTests extends AnyWordSpec with Matchers {
val card = Card(CardValue.Ace, Suit.Spades)
val card2 = Card(CardValue.Two, Suit.Clubs)
val trick = new Trick(round)
trick.set_first_card(card)
trick.setfirstcard(card)
assertThrows[IllegalStateException] {
trick.set_first_card(card2)
trick.setfirstcard(card2)
}
}
}