Skip to content

Commit

Permalink
Implement progress import validation
Browse files Browse the repository at this point in the history
  • Loading branch information
patzly committed Jan 12, 2024
1 parent 5c43ef2 commit f42a837
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ If two cards are the same and one card is different in any feature, then it is n

## License

Copyright © 2023 Matthias Elbel & Patrick Zedler. All rights reserved.
Copyright © 2024 Matthias Elbel & Patrick Zedler. All rights reserved.

[GNU General Public License version 3](https://www.gnu.org/licenses/gpl.txt)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import de.htwg.se.set.model.GameMode.{GAME_END, IN_GAME, SETTINGS}
import de.htwg.se.set.model.game.base.{Deck, Player, Triplet}
import de.htwg.se.set.model.{ICard, ITriplet}
import de.htwg.se.set.util.PrintUtil
import play.api.libs.json.JsValue
import play.api.libs.json.{JsValue, Json}

import scala.xml.Node
import scala.xml.{Node, Utility}

private class Command(controller: IController) extends ICommand(controller):

Expand Down Expand Up @@ -71,14 +71,19 @@ case class AddColumnCommand(controller: IController) extends Command(controller)
val cardsAdded = controller.game.deck.tableCards(
controller.game.columns, controller.game.tableCards, controller.game.playersCards
)
if cardsAdded.length > controller.game.tableCards.length then
val cardsAvailable = cardsAdded.length > controller.game.tableCards.length
val setsAvailable = controller.game.deck.findSets(controller.game.tableCards).nonEmpty
if cardsAvailable && controller.game.columns <= 6 then
val msg = "One column of cards added to the table."
println(msg)
controller.setMessage(msg)
controller.setTableCards(cardsAdded)
controller.changeState(SelectPlayerState(controller))
else if controller.game.deck.findSets(controller.game.tableCards).nonEmpty then
val msg = "No more cards left, but there still is at least one SET to be found!"
else if setsAvailable then
val msg = if cardsAvailable && controller.game.columns > 6 then
"Maximum number of columns reached, but there still is at least one SET to be found!"
else
"No more cards left, but there still is at least one SET to be found!"
println(PrintUtil.red(msg + "\n"))
controller.setMessage(msg)
controller.removeColumn()
Expand Down Expand Up @@ -169,8 +174,20 @@ case class ExitCommand(controller: IController) extends Command(controller):

case class LoadXmlCommand(controller: IController, node: Node) extends Command(controller):

override def execute(): Unit = controller.restoreSnapshot(Snapshot.fromXml(node, controller))
override def execute(): Unit =
val hash = (node \ "hash").text
val xmlSnapshot = (node \ "snapshot").head
if hash == Snapshot.hash(Utility.trim(xmlSnapshot).toString) then
controller.restoreSnapshot(Snapshot.fromXml(xmlSnapshot, controller))
else
println(PrintUtil.red("Invalid XML progress file!"))

case class LoadJsonCommand(controller: IController, json: JsValue) extends Command(controller):

override def execute(): Unit = controller.restoreSnapshot(Snapshot.fromJson(json, controller))
override def execute(): Unit =
val hash = (json \ "hash").get.as[String]
val jsonSnapshot = (json \ "snapshot").get
if hash == Snapshot.hash(Json.stringify(jsonSnapshot)) then
controller.restoreSnapshot(Snapshot.fromJson(jsonSnapshot, controller))
else
println(PrintUtil.red("Invalid JSON progress file!"))
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import play.api.libs.json.Json

import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Paths}
import java.security.MessageDigest
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import scala.xml.{PrettyPrinter, XML}
import scala.xml.{Elem, PrettyPrinter, Utility, XML}

case class Controller @Inject() (var settings: ISettings, var game: IGame) extends IController:

Expand Down Expand Up @@ -53,9 +54,28 @@ case class Controller @Inject() (var settings: ISettings, var game: IGame) exten
override def save(): Unit =
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm")
val date = formatter.format(LocalDateTime.now)
val name = s"set_$date"
XML.save(name + ".xml", XML.loadString(PrettyPrinter(100, 2).format(snapshot.toXml)), "UTF-8", true, null)
Files.write(Paths.get(name + ".json"), Json.prettyPrint(snapshot.toJson).getBytes(StandardCharsets.UTF_8))
val name = s"progress_$date"
saveXml(name)
saveJson(name)

private def saveXml(name: String): Unit =
val xmlSnapshot = snapshot.toXml
val hash = Snapshot.hash(Utility.trim(XML.loadString(xmlSnapshot.toString)).toString)
val xml =
<progress>
<hash>{hash}</hash>
{xmlSnapshot}
</progress>
XML.save(name + ".xml", XML.loadString(PrettyPrinter(100, 2).format(xml)), "UTF-8", true, null)

private def saveJson(name: String): Unit =
val jsonSnapshot = snapshot.toJson
val hash = Snapshot.hash(Json.stringify(jsonSnapshot))
val json = Json.obj(
"hash" -> hash,
"snapshot" -> jsonSnapshot
)
Files.write(Paths.get(name + ".json"), Json.prettyPrint(json).getBytes(StandardCharsets.UTF_8))

override def canUndo: Boolean = undoManager.canUndo

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import de.htwg.se.set.model.settings.base.Settings
import de.htwg.se.set.model.{IGame, ISettings}
import play.api.libs.json.{JsValue, Json}

import java.security.MessageDigest
import scala.xml.{Elem, Node}

case class Snapshot(settings: ISettings, game: IGame, state: IState) extends ISnapshot:
Expand Down Expand Up @@ -47,4 +48,9 @@ object Snapshot:
case "GameState" => GameState(controller)
case "GameEndState" => GameEndState(controller)
case _ => throw IllegalArgumentException("Invalid state")
Snapshot(settings, game, state)
Snapshot(settings, game, state)

def hash(input: String): String =
val md = MessageDigest.getInstance("SHA-256")
val hashBytes = md.digest(input.getBytes("UTF-8"))
hashBytes.map("%02x".format(_)).mkString
4 changes: 3 additions & 1 deletion src/main/scala/de/htwg/se/set/view/panel/MenuPanel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ case class MenuPanel(controller: IController) extends BoxPanel(Orientation.Horiz
def update(): Unit =
undoButton.enabled = controller.canUndo
redoButton.enabled = controller.canRedo
addButton.enabled = controller.game.selectedPlayer.isEmpty
val setsAvailable = controller.game.deck.findSets(controller.game.tableCards).nonEmpty
addButton.enabled = controller.game.selectedPlayer.isEmpty &&
(controller.game.columns < 6 || (controller.game.columns >= 6 && !setsAvailable))
addButton.visible = controller.settings.mode == IN_GAME && !controller.settings.singlePlayer
exitButton.visible = controller.settings.mode == IN_GAME

Expand Down

0 comments on commit f42a837

Please sign in to comment.