diff --git a/src/main/scala/floodsim/model/cell/Cell.scala b/src/main/scala/floodsim/model/cell/Cell.scala index d87a681..59e341d 100644 --- a/src/main/scala/floodsim/model/cell/Cell.scala +++ b/src/main/scala/floodsim/model/cell/Cell.scala @@ -1,26 +1,27 @@ package floodsim.model.cell -import floodsim.model.* - -enum CellType: - case HouseWithConcrete, HouseWithGrass, Square, Field +import floodsim.model.grid.Coordinate sealed trait Cell: + def coordinate: Coordinate def dimensions: Double def waterVolume: Double def obstacles: Seq[Obstacle] def altitude: Double def absorption: AbsorptionRate.AbsorptionRate def cellType: CellType + def physics: CellPhysics def waterHeight: Double = - CellPhysics.calculateWaterHeight(dimensions, waterVolume, obstacles) + physics.calculateWaterHeight(dimensions, waterVolume, obstacles) def waterSpeed: Double = - CellPhysics.calculateWaterSpeed(dimensions, obstacles) + physics.calculateWaterSpeed(dimensions, obstacles) def updateWater(newWaterVolume: Double): Cell = - val (absorbedWater, newAbsorption) = CellPhysics.calculateAbsorption(waterVolume, absorption) + val (absorbedWater, newAbsorption) = + physics.calculateAbsorption(waterVolume, absorption) + withUpdatedValues( waterVolume = waterVolume - absorbedWater + newWaterVolume, absorption = newAbsorption @@ -28,63 +29,32 @@ sealed trait Cell: def totalHeight: Double = altitude + waterHeight + def asSymbol: String = cellType.symbol + protected def withUpdatedValues(waterVolume: Double, absorption: AbsorptionRate.AbsorptionRate): Cell -private final case class CellImpl( +final private case class BaseCell( + coordinate: Coordinate, dimensions: Double, waterVolume: Double, obstacles: Seq[Obstacle], altitude: Double, absorption: AbsorptionRate.AbsorptionRate, - cellType: CellType + cellType: CellType, + physics: CellPhysics ) extends Cell: protected def withUpdatedValues(waterVolume: Double, absorption: AbsorptionRate.AbsorptionRate): Cell = copy(waterVolume = math.max(0.0, waterVolume), absorption = absorption) object Cell: - private val ConcreteAbsorption: AbsorptionRate.AbsorptionRate = AbsorptionRate(0.2) - private val GrassAbsorption: AbsorptionRate.AbsorptionRate = AbsorptionRate(0.5) - private val SquareAbsorption: AbsorptionRate.AbsorptionRate = AbsorptionRate(0.6) - private val FieldAbsorption: AbsorptionRate.AbsorptionRate = AbsorptionRate(0.9) - - final class Builder private[Cell] ( - val dimensions: Double, - val altitude: Double, - val obstacles: Seq[Obstacle], - val absorption: AbsorptionRate.AbsorptionRate, - val waterVolume: Double, - val cellType: CellType - ): - def withObstacles(obstacles: Seq[Obstacle]): Builder = - new Builder(dimensions, altitude, obstacles, absorption, waterVolume, cellType) - - def withWaterVolume(waterVolume: Double): Builder = - new Builder(dimensions, altitude, obstacles, absorption, waterVolume, cellType) - - def withAbsorption(absorption: AbsorptionRate.AbsorptionRate): Builder = - new Builder(dimensions, altitude, obstacles, absorption, waterVolume, cellType) - - def build: Cell = CellImpl( - dimensions = dimensions, - waterVolume = waterVolume, - obstacles = obstacles, - altitude = altitude, - absorption = absorption, - cellType = cellType - ) - - def apply(cellType: CellType, dimensions: Double, altitude: Double): Builder = - val absorption = cellType match - case CellType.HouseWithConcrete => ConcreteAbsorption - case CellType.HouseWithGrass => GrassAbsorption - case CellType.Square => SquareAbsorption - case CellType.Field => FieldAbsorption - - new Builder( + def apply(cellType: CellType, dimensions: Double, altitude: Double, coordinate: Coordinate): Cell = + BaseCell( + coordinate = coordinate, dimensions = dimensions, - altitude = altitude, - obstacles = Seq.empty, - absorption = absorption, waterVolume = 0.0, - cellType = cellType + obstacles = Seq.empty, + altitude = altitude, + absorption = cellType.defaultAbsorption, + cellType = cellType, + physics = DefaultCellPhysics ) diff --git a/src/main/scala/floodsim/model/cell/CellPhysics.scala b/src/main/scala/floodsim/model/cell/CellPhysics.scala index 2ab79dd..4e983c2 100644 --- a/src/main/scala/floodsim/model/cell/CellPhysics.scala +++ b/src/main/scala/floodsim/model/cell/CellPhysics.scala @@ -2,10 +2,18 @@ package floodsim.model.cell import scala.math.* -object CellPhysics: - val AbsorptionFactor: Double = 0.1 - val AbsorptionDecayFactor: Double = 0.01 - val MaxWaterSpeed: Double = 10.0 +trait CellPhysics: + def calculateWaterHeight(dimensions: Double, waterVolume: Double, obstacles: Seq[Obstacle]): Double + def calculateWaterSpeed(dimensions: Double, obstacles: Seq[Obstacle]): Double + def calculateAbsorption( + waterVolume: Double, + absorption: AbsorptionRate.AbsorptionRate + ): (Double, AbsorptionRate.AbsorptionRate) + +object DefaultCellPhysics extends CellPhysics: + private val AbsorptionFactor: Double = 0.1 + private val AbsorptionDecayFactor: Double = 0.01 + private val MaxWaterSpeed: Double = 10.0 def calculateWaterHeight(dimensions: Double, waterVolume: Double, obstacles: Seq[Obstacle]): Double = if waterVolume <= 0 then 0.0 diff --git a/src/main/scala/floodsim/model/cell/CellType.scala b/src/main/scala/floodsim/model/cell/CellType.scala new file mode 100644 index 0000000..ac28800 --- /dev/null +++ b/src/main/scala/floodsim/model/cell/CellType.scala @@ -0,0 +1,7 @@ +package floodsim.model.cell + +enum CellType(val symbol: String, val defaultAbsorption: AbsorptionRate.AbsorptionRate): + case HouseWithConcrete extends CellType("C", AbsorptionRate(0.2)) + case HouseWithGrass extends CellType("G", AbsorptionRate(0.5)) + case Square extends CellType("S", AbsorptionRate(0.6)) + case Field extends CellType("F", AbsorptionRate(0.9)) diff --git a/src/test/scala/floodsim/model/cell/CellPhysicsTest.scala b/src/test/scala/floodsim/model/cell/CellPhysicsTest.scala index d98e8c2..6e1b967 100644 --- a/src/test/scala/floodsim/model/cell/CellPhysicsTest.scala +++ b/src/test/scala/floodsim/model/cell/CellPhysicsTest.scala @@ -5,83 +5,107 @@ import org.scalatest.matchers.should.Matchers class CellPhysicsTest extends AnyFlatSpec with Matchers: - val dimensions = 10.0 - val smallObstacle: Obstacle = Obstacle(10.0, 3.0) - val largeObstacle: Obstacle = Obstacle(50.0, 5.0) - - "CellPhysics" should "calculate water height correctly with no obstacles" in { - val waterVolume = 100.0 - val obstacles = Seq.empty[Obstacle] - val height = CellPhysics.calculateWaterHeight(dimensions, waterVolume, obstacles) - val expectedHeight = waterVolume / (dimensions * dimensions) - height should be(expectedHeight) + "DefaultCellPhysics" should "calculate zero water height when water volume is zero or negative" in { + val physics = DefaultCellPhysics + val dimensions = 10.0 + val obstacles = Seq.empty[Obstacle] + physics.calculateWaterHeight(dimensions, 0.0, obstacles) shouldBe 0.0 + physics.calculateWaterHeight(dimensions, -1.0, obstacles) shouldBe 0.0 } - it should "calculate water height correctly with obstacles" in { - val waterVolume = 100.0 - val obstacles = Seq(smallObstacle) - val height = CellPhysics.calculateWaterHeight(dimensions, waterVolume, obstacles) - val availableArea = dimensions * dimensions - smallObstacle.surface - val expectedHeight = waterVolume / availableArea - height should be(expectedHeight) + it should "calculate correct water height with no obstacles" in { + val physics = DefaultCellPhysics + val dimensions = 10.0 + val waterVolume = 100.0 + val obstacles = Seq.empty[Obstacle] + // Area = 10*10 = 100, height = volume/area = 100/100 = 1.0 + physics.calculateWaterHeight(dimensions, waterVolume, obstacles) shouldBe 1.0 } - it should "return zero height when no water" in { - val waterVolume = 0.0 - val obstacles = Seq(smallObstacle) - val height = CellPhysics.calculateWaterHeight(dimensions, waterVolume, obstacles) - height should be(0.0) + it should "calculate correct water height with obstacles" in { + val physics = DefaultCellPhysics + val dimensions = 10.0 + val waterVolume = 100.0 + val obstacles = Seq( + Obstacle(20.0, 5.0), + Obstacle(10.0, 3.0) + ) + // Area = 10*10 - 20 - 10 = 70, height = volume/area = 100/70 = 1.428... + physics.calculateWaterHeight(dimensions, waterVolume, obstacles) shouldBe (100.0 / 70.0) } - it should "handle edge case when all area is occupied by obstacles" in { - val waterVolume = 100.0 - val fullObstacle = Obstacle(dimensions * dimensions, 10.0) - val height = CellPhysics.calculateWaterHeight(dimensions, waterVolume, Seq(fullObstacle)) - height should be(0.0) + it should "return zero water height when obstacles cover entire area" in { + val physics = DefaultCellPhysics + val dimensions = 10.0 + val waterVolume = 100.0 + val obstacles = Seq( + Obstacle(100.0, 5.0) // Covers entire area + ) + physics.calculateWaterHeight(dimensions, waterVolume, obstacles) shouldBe 0.0 } - it should "calculate max water speed with no obstacles" in { - val obstacles = Seq.empty[Obstacle] - val speed = CellPhysics.calculateWaterSpeed(dimensions, obstacles) - speed should be(CellPhysics.MaxWaterSpeed) + it should "calculate maximum water speed with no obstacles" in { + val physics = DefaultCellPhysics + val dimensions = 10.0 + val obstacles = Seq.empty[Obstacle] + physics.calculateWaterSpeed(dimensions, obstacles) shouldBe 10.0 } it should "calculate reduced water speed with obstacles" in { - val obstacles = Seq(smallObstacle) - val speed = CellPhysics.calculateWaterSpeed(dimensions, obstacles) - val totalObstacleSurface = smallObstacle.surface - val cellArea = dimensions * dimensions - val expectedSpeed = (1.0 - (totalObstacleSurface / cellArea)) * CellPhysics.MaxWaterSpeed - speed should be(expectedSpeed) + val physics = DefaultCellPhysics + val dimensions = 10.0 + val obstacles = Seq( + Obstacle(25.0, 3.0) // 25% of area + ) + // obstacleFactor = 1.0 - (25.0 / 100.0) = 0.75, speed = 0.75 * 10.0 = 7.5 + physics.calculateWaterSpeed(dimensions, obstacles) shouldBe 7.5 + } + + it should "calculate zero water speed when obstacles cover entire area" in { + val physics = DefaultCellPhysics + val dimensions = 10.0 + val obstacles = Seq( + Obstacle(100.0, 5.0), // Covers entire area + Obstacle(50.0, 3.0) // This doesn't matter as we cap at 1.0 + ) + physics.calculateWaterSpeed(dimensions, obstacles) shouldBe 0.0 } - it should "calculate zero water speed when all area is blocked" in { - val fullObstacle = Obstacle(dimensions * dimensions, 10.0) - val speed = CellPhysics.calculateWaterSpeed(dimensions, Seq(fullObstacle)) - speed should be(0.0) + it should "not absorb water when absorption rate is zero" in { + val physics = DefaultCellPhysics + val waterVolume = 100.0 + val absorption = AbsorptionRate(0.0) + val (absorbedWater, newAbsorption) = physics.calculateAbsorption(waterVolume, absorption) + absorbedWater shouldBe 0.0 + newAbsorption.value shouldBe 0.0 } - it should "calculate absorption correctly" in { - val waterVolume = 100.0 - val absorption = AbsorptionRate(0.5) - val (absorbed, newAbsorption) = CellPhysics.calculateAbsorption(waterVolume, absorption) - val expectedAbsorbed = absorption.value * CellPhysics.AbsorptionFactor - absorbed should be(expectedAbsorbed) - val expectedNewAbsorption = absorption.value - (expectedAbsorbed * CellPhysics.AbsorptionDecayFactor) - newAbsorption.value should be(expectedNewAbsorption) + it should "absorb water correctly and decrease absorption rate" in { + val physics = DefaultCellPhysics + val waterVolume = 100.0 + val absorption = AbsorptionRate(0.5) + // maxAbsorption = 0.5 * 0.1 = 0.05 + // absorbedWater = min(100.0, 0.05) = 0.05 + // newAbsorption = 0.5 - (0.05 * 0.01) = 0.5 - 0.0005 = 0.4995 + val (absorbedWater, newAbsorption) = physics.calculateAbsorption(waterVolume, absorption) + newAbsorption.value shouldBe 0.4995 +- 0.0001 } - it should "not absorb more water than available" in { - val waterVolume = 0.01 - val absorption = AbsorptionRate(0.5) - val (absorbed, _) = CellPhysics.calculateAbsorption(waterVolume, absorption) - absorbed should be <= waterVolume + it should "absorb only available water if less than max absorption" in { + val physics = DefaultCellPhysics + val waterVolume = 0.02 + val absorption = AbsorptionRate(0.5) + // maxAbsorption = 0.5 * 0.1 = 0.05 + // absorbedWater = min(0.02, 0.05) = 0.02 + // newAbsorption = 0.5 - (0.02 * 0.01) = 0.5 - 0.0002 = 0.4998 + val (absorbedWater, newAbsorption) = physics.calculateAbsorption(waterVolume, absorption) + newAbsorption.value shouldBe 0.4998 +- 0.0001 } - it should "not absorb when absorption rate is zero" in { - val waterVolume = 100.0 - val absorption = AbsorptionRate(0.0) - val (absorbed, newAbsorption) = CellPhysics.calculateAbsorption(waterVolume, absorption) - absorbed should be(0.0) - newAbsorption.value should be(0.0) + it should "not change absorption rate when no water is absorbed" in { + val physics = DefaultCellPhysics + val waterVolume = 0.0 + val absorption = AbsorptionRate(0.5) + val (absorbedWater, newAbsorption) = physics.calculateAbsorption(waterVolume, absorption) + newAbsorption.value shouldBe 0.5 } diff --git a/src/test/scala/floodsim/model/cell/CellTest.scala b/src/test/scala/floodsim/model/cell/CellTest.scala index ca99531..10f2077 100644 --- a/src/test/scala/floodsim/model/cell/CellTest.scala +++ b/src/test/scala/floodsim/model/cell/CellTest.scala @@ -1,147 +1,104 @@ package floodsim.model.cell +import floodsim.model.grid.Coordinate import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers class CellTest extends AnyFlatSpec with Matchers: - val dimensions = 10.0 - val altitude = 5.0 - val smallObstacle: Obstacle = Obstacle(10.0, 3.0) - val largeObstacle: Obstacle = Obstacle(50.0, 5.0) - - "Cell Builder" should "create a house with concrete correctly" in { - val cell = Cell(CellType.HouseWithConcrete, dimensions, altitude).build - cell.dimensions should be(dimensions) - cell.altitude should be(altitude) - cell.waterVolume should be(0.0) - cell.absorption.value should be(0.2) - cell.cellType should be(CellType.HouseWithConcrete) - } - - it should "create a house with grass correctly" in { - val cell = Cell(CellType.HouseWithGrass, dimensions, altitude).build - cell.dimensions should be(dimensions) - cell.altitude should be(altitude) - cell.waterVolume should be(0.0) - cell.absorption.value should be(0.5) - cell.cellType should be(CellType.HouseWithGrass) - } - - it should "create a square correctly" in { - val cell = Cell(CellType.Square, dimensions, altitude).build - cell.dimensions should be(dimensions) - cell.altitude should be(altitude) - cell.waterVolume should be(0.0) - cell.obstacles should be(empty) - cell.absorption.value should be(0.6) - cell.cellType should be(CellType.Square) - } - - it should "create a field correctly" in { - val cell = Cell(CellType.Field, dimensions, altitude).build - cell.dimensions should be(dimensions) - cell.altitude should be(altitude) - cell.waterVolume should be(0.0) - cell.obstacles should be(empty) - cell.absorption.value should be(0.9) - cell.cellType should be(CellType.Field) - } - - it should "allow adding obstacles" in { - val cell = Cell(CellType.HouseWithConcrete, dimensions, altitude) - .withObstacles(Seq(smallObstacle, largeObstacle)) - .build - cell.obstacles should contain theSameElementsAs Seq(smallObstacle, largeObstacle) - } - - it should "allow setting initial water volume" in { - val initialWater = 50.0 - val cell = Cell(CellType.Field, dimensions, altitude) - .withWaterVolume(initialWater) - .build - cell.waterVolume should be(initialWater) - } - - "Cell water management" should "calculate correct water height" in { - val waterVolume = 100.0 - val cell = Cell(CellType.Field, dimensions, altitude) - .withWaterVolume(waterVolume) - .build - val expectedHeight = waterVolume / (dimensions * dimensions) - cell.waterHeight should be(expectedHeight) - } - - it should "calculate correct water speed" in { - val cell = Cell(CellType.HouseWithConcrete, dimensions, altitude) - .withObstacles(Seq(smallObstacle)) - .build - val expectedSpeed = (1.0 - (smallObstacle.surface / (dimensions * dimensions))) * 10.0 - cell.waterSpeed should be(expectedSpeed) - } - - it should "calculate total height as sum of altitude and water height" in { - val waterVolume = 100.0 - val cell = Cell(CellType.Field, dimensions, altitude) - .withWaterVolume(waterVolume) - .build - val expectedTotalHeight = altitude + cell.waterHeight - cell.totalHeight should be(expectedTotalHeight) - } - - it should "update water volume correctly" in { - val initialWater = 100.0 - val addedWater = 50.0 - val cell = Cell(CellType.Field, dimensions, altitude) - .withWaterVolume(initialWater) - .build - val updatedCell = cell.updateWater(addedWater) - val (absorbedWater, _) = CellPhysics.calculateAbsorption(initialWater, cell.absorption) - val expectedWater = initialWater - absorbedWater + addedWater - updatedCell.waterVolume should be(expectedWater) - } - - it should "decrease absorption rate when water is absorbed" in { - val initialWater = 100.0 - val cell = Cell(CellType.Field, dimensions, altitude) - .withWaterVolume(initialWater) - .build - val initialAbsorption = cell.absorption.value - val updatedCell = cell.updateWater(0.0) - updatedCell.absorption.value should be < initialAbsorption + "Cell companion object" should "create a Cell with default values" in { + val coordinate = Coordinate(1, 2) + val cellType = CellType.Field + val dimensions = 10.0 + val altitude = 5.0 + val cell = Cell(cellType, dimensions, altitude, coordinate) + cell.coordinate shouldBe coordinate + cell.dimensions shouldBe dimensions + cell.waterVolume shouldBe 0.0 + cell.obstacles shouldBe empty + cell.altitude shouldBe altitude + cell.absorption shouldBe cellType.defaultAbsorption + cell.cellType shouldBe cellType + cell.physics shouldBe DefaultCellPhysics } - it should "preserve cell type after water update" in { - val cell = Cell(CellType.HouseWithGrass, dimensions, altitude).build - val updatedCell = cell.updateWater(50.0) - updatedCell.cellType should be(CellType.HouseWithGrass) - } - - it should "handle zero and negative water volumes" in { - val cell = Cell(CellType.Field, dimensions, altitude) - .withWaterVolume(10.0) - .build - val updatedCell = cell.updateWater(-20.0) // Try to remove more water than exists - updatedCell.waterVolume should be(0.0) // Should clamp to zero - } - - "Different cell types" should "have appropriate absorption rates" in { - val concreteCell = Cell(CellType.HouseWithConcrete, dimensions, altitude).build - val grassCell = Cell(CellType.HouseWithGrass, dimensions, altitude).build - val squareCell = Cell(CellType.Square, dimensions, altitude).build - val fieldCell = Cell(CellType.Field, dimensions, altitude).build - concreteCell.absorption.value should be < grassCell.absorption.value - grassCell.absorption.value should be < squareCell.absorption.value - squareCell.absorption.value should be < fieldCell.absorption.value - } - - "Cell builder" should "be chainable" in { - val cell = Cell(CellType.HouseWithConcrete, dimensions, altitude) - .withObstacles(Seq(smallObstacle)) - .withWaterVolume(50.0) - .withAbsorption(AbsorptionRate(0.3)) - .build - cell.obstacles should contain(smallObstacle) - cell.waterVolume should be(50.0) - cell.absorption.value should be(0.3) - } +"Cell" should "calculate water height correctly" in { + val cell = Cell( + CellType.Field, + dimensions = 10.0, + altitude = 5.0, + coordinate = Coordinate(0, 0) + ) + val cellWithWater = cell.updateWater(100.0) + cellWithWater.waterHeight shouldBe 1.0 // 100 / (10*10) = 1.0 +} + +it should "calculate water speed correctly" in { + val cell = Cell( + CellType.Field, + dimensions = 10.0, + altitude = 5.0, + coordinate = Coordinate(0, 0) + ) + cell.waterSpeed shouldBe 10.0 // MaxWaterSpeed +} + +it should "calculate total height correctly" in { + val cell = Cell( + CellType.Field, + dimensions = 10.0, + altitude = 5.0, + coordinate = Coordinate(0, 0) + ) + val cellWithWater = cell.updateWater(100.0) // 1.0 water height + cellWithWater.totalHeight shouldBe 6.0 // altitude(5.0) + waterHeight(1.0) +} + +it should "return the cell type symbol" in { + val concreteCell = Cell(CellType.HouseWithConcrete, 10.0, 5.0, Coordinate(0, 0)) + concreteCell.asSymbol shouldBe "C" +} + +it should "update water volume correctly with absorption" in { + val cell = Cell( + CellType.Field, // Field has absorption of 0.9 + dimensions = 10.0, + altitude = 5.0, + coordinate = Coordinate(0, 0) + ) + val initialWaterVolume = 50.0 + val cellWithWater = cell.updateWater(initialWaterVolume) + val additionalWater = 10.0 + val updatedCell = cellWithWater.updateWater(additionalWater) + updatedCell.waterVolume should be > cellWithWater.waterVolume + updatedCell.waterVolume should be < (cellWithWater.waterVolume + additionalWater) + updatedCell.absorption.value should be < cellWithWater.absorption.value +} + +it should "handle negative resulting water volumes" in { + val cell = Cell( + CellType.Field, + dimensions = 10.0, + altitude = 5.0, + coordinate = Coordinate(0, 0) + ) + val cellWithWater = cell.updateWater(5.0) + val updatedCell = cellWithWater.updateWater(-10.0) + updatedCell.waterVolume shouldBe 0.0 +} + +it should "preserve all properties except water volume and absorption when updating water" in { + val coordinate = Coordinate(1, 2) + val cellType = CellType.Field + val dimensions = 10.0 + val altitude = 5.0 + val cell = Cell(cellType, dimensions, altitude, coordinate) + val updatedCell = cell.updateWater(20.0) + updatedCell.waterVolume should not be cell.waterVolume + updatedCell.coordinate shouldBe cell.coordinate + updatedCell.dimensions shouldBe cell.dimensions + updatedCell.obstacles shouldBe cell.obstacles + updatedCell.altitude shouldBe cell.altitude + updatedCell.cellType shouldBe cell.cellType + updatedCell.physics shouldBe cell.physics +} diff --git a/src/test/scala/floodsim/model/cell/CellTypeTest.scala b/src/test/scala/floodsim/model/cell/CellTypeTest.scala new file mode 100644 index 0000000..e543ad9 --- /dev/null +++ b/src/test/scala/floodsim/model/cell/CellTypeTest.scala @@ -0,0 +1,24 @@ +package floodsim.model.cell + +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers + +class CellTypeTest extends AnyFlatSpec with Matchers: + + "CellType" should "have all required cell types defined" in { + CellType.values.length shouldBe 4 + CellType.values should contain allOf ( + CellType.HouseWithConcrete, + CellType.HouseWithGrass, + CellType.Square, + CellType.Field + ) + } + + it should "be comparable with equals" in { + val concrete1 = CellType.HouseWithConcrete + val concrete2 = CellType.HouseWithConcrete + val grass = CellType.HouseWithGrass + concrete1 shouldBe concrete2 + concrete1 should not be grass + } diff --git a/src/test/scala/floodsim/model/cell/ObstacleTest.scala b/src/test/scala/floodsim/model/cell/ObstacleTest.scala index 9e52ff9..6d1a705 100644 --- a/src/test/scala/floodsim/model/cell/ObstacleTest.scala +++ b/src/test/scala/floodsim/model/cell/ObstacleTest.scala @@ -5,11 +5,17 @@ import org.scalatest.matchers.should.Matchers class ObstacleTest extends AnyFlatSpec with Matchers: - "An Obstacle" should "store surface and height correctly" in { + "An Obstacle" should "store surface correctly" in { val surface = 10.0 val height = 5.0 val obstacle = Obstacle(surface, height) obstacle.surface should be(surface) + } + + it should "store height correctly" in { + val surface = 10.0 + val height = 5.0 + val obstacle = Obstacle(surface, height) obstacle.height should be(height) } diff --git a/src/test/scala/floodsim/model/grid/GridElementTest.scala b/src/test/scala/floodsim/model/grid/GridElementTest.scala deleted file mode 100644 index ceed79a..0000000 --- a/src/test/scala/floodsim/model/grid/GridElementTest.scala +++ /dev/null @@ -1,90 +0,0 @@ -package floodsim.model.grid - -import floodsim.model.cell.{Cell, CellType} -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class GridElementTest extends AnyFlatSpec with Matchers: - - val dimensions = 10.0 - val altitude = 5.0 - - "A CellElement" should "provide correct symbol for HouseWithConcrete" in { - val cell = Cell(CellType.HouseWithConcrete, dimensions, altitude).build - val element = CellElement(cell, Coordinate(0, 0)) - element.asSymbol should be("H") - } - - it should "provide correct symbol for HouseWithGrass" in { - val cell = Cell(CellType.HouseWithGrass, dimensions, altitude).build - val element = CellElement(cell, Coordinate(0, 0)) - element.asSymbol should be("h") - } - - it should "provide correct symbol for Square" in { - val cell = Cell(CellType.Square, dimensions, altitude).build - val element = CellElement(cell, Coordinate(0, 0)) - element.asSymbol should be("S") - } - - it should "provide correct symbol for Field" in { - val cell = Cell(CellType.Field, dimensions, altitude).build - val element = CellElement(cell, Coordinate(0, 0)) - element.asSymbol should be("F") - } - - it should "return new instance with updated coordinate when withCoordinate is called" in { - val cell = Cell(CellType.Field, dimensions, altitude).build - val element = CellElement(cell, Coordinate(0, 0)) - val newElement = element.withCoordinate(Coordinate(1, 1)) - - newElement should not be theSameInstanceAs(element) - newElement.coordinate should be(Coordinate(1, 1)) - newElement.element should be theSameInstanceAs element.element - } - - "A WeatherElement" should "provide correct symbol for ClearSky" in { - val weather = floodsim.model.weather.ClearSky - val element = WeatherElement(weather, Coordinate(0, 0)) - element.asSymbol should be(" ") - } - - it should "provide correct symbol for LightClouds" in { - val weather = floodsim.model.weather.LightClouds - val element = WeatherElement(weather, Coordinate(0, 0)) - element.asSymbol should be(".") - } - - it should "provide correct symbol for HeavyClouds" in { - val weather = floodsim.model.weather.HeavyClouds - val element = WeatherElement(weather, Coordinate(0, 0)) - element.asSymbol should be(":") - } - - it should "provide correct symbol for LightRain" in { - val weather = floodsim.model.weather.LightRain - val element = WeatherElement(weather, Coordinate(0, 0)) - element.asSymbol should be("`") - } - - it should "provide correct symbol for HeavyRain" in { - val weather = floodsim.model.weather.HeavyRain - val element = WeatherElement(weather, Coordinate(0, 0)) - element.asSymbol should be("~") - } - - it should "provide correct symbol for IntenseSun" in { - val weather = floodsim.model.weather.IntenseSun - val element = WeatherElement(weather, Coordinate(0, 0)) - element.asSymbol should be("*") - } - - it should "return new instance with updated coordinate when withCoordinate is called" in { - val weather = floodsim.model.weather.ClearSky - val element = WeatherElement(weather, Coordinate(0, 0)) - val newElement = element.withCoordinate(Coordinate(1, 1)) - - newElement should not be theSameInstanceAs(element) - newElement.coordinate should be(Coordinate(1, 1)) - newElement.element should be theSameInstanceAs element.element - }