• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Scala-Robotics-Simulator / PPS-22-srs / #507

02 Sep 2025 12:18PM UTC coverage: 54.612% (+8.1%) from 46.492%
#507

push

github

davidcohenDC
refactor: update GridDSL and tests to use IO for simulation execution

3 of 3 new or added lines in 2 files covered. (100.0%)

22 existing lines in 5 files now uncovered.

1563 of 2862 relevant lines covered (54.61%)

7.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

52.43
/src/main/scala/io/github/srs/utils/SimulationDefaults.scala
1
package io.github.srs.utils
2

3
import java.awt.Color
4
import java.util.UUID
5

6
import scala.concurrent.duration.{ DurationInt, FiniteDuration }
7

8
import cats.effect.unsafe.implicits.global
9
import io.github.srs.model.entity.*
10
import io.github.srs.model.entity.dynamicentity.Robot
11
import io.github.srs.model.entity.dynamicentity.actuator.{ Actuator, Wheel as ActWheel }
12
import io.github.srs.model.entity.dynamicentity.behavior.Policy
13
import io.github.srs.model.entity.dynamicentity.sensor.*
14
import io.github.srs.model.environment.Environment
15
import cats.effect.IO
16
import io.github.srs.model.illumination.LightMap
17
import io.github.srs.model.illumination.engine.SquidLibFovEngine
18
import io.github.srs.model.illumination.model.ScaleFactor
19

20
object SimulationDefaults:
21

×
22
  object Illumination:
23

3✔
24
    val GridThreshold = 10_000
25
    val LightThreshold = 2
8✔
26

5✔
27
    object Occlusion:
28
      val FullRotation: Double = 90.0
3✔
29
      val AlmostZero: Double = 1e-6
8✔
30

5✔
31
  object Behaviors:
32

×
33
    object Prioritized:
34
      val DangerDist: Double = 0.40
3✔
35
      val LightThreshold: Double = 0.05
8✔
36

5✔
37
    object Phototaxis:
38
      val Epsilon: Double = 1e-9
3✔
39
      val MinForwardBias: Double = 0.4
8✔
40
      val TurnGain: Double = 1.0
4✔
41

5✔
42
    object ObstacleAvoidance:
43
      val CruiseSpeed: Double = 0.35
3✔
44
      val WarnSpeed: Double = 0.15
8✔
45
      val WarnTurnSpeed: Double = 0.55
4✔
46
      val BackBoost: Double = 0.20
4✔
47
      val SafeDist: Double = 0.5
4✔
48
      val CriticalDist: Double = 0.35
4✔
49

5✔
50
    object RandomWalk:
51
      val MinForwardFactor: Double = 0.35
3✔
52
      val MaxForwardExtra: Double = 0.35
8✔
53
      val MinTurnOfBase: Double = 0.35
4✔
54
      val MaxTurnOfBase: Double = 1.15
4✔
55
      val TurnExponent: Double = 1.2
4✔
56
      val PivotBoostProb: Double = 0.20
4✔
57
      val PivotBoostAbs: Double = 0.15
4✔
58

5✔
59
  end Behaviors
60

61
  object UI:
62

×
63
    object SimulationViewConstants:
64
      val IdDisplayLength = 8
×
65
      val PositionDecimals = 2
×
66
      val OrientationDecimals = 1
×
67
      val DefaultRobotInfo = "Select a robot to view details"
×
68
      val StopConfirmMessage = "Are you sure you want to stop the simulation?\n\nClick Yes to stop, No to continue."
×
69
      val StopConfirmTitle = "Stop Simulation"
×
70

×
71
    object Colors:
72
      @inline private def rgb(r: Int, g: Int, b: Int) = new java.awt.Color(r, g, b)
×
73
      @inline private def rgba(r: Int, g: Int, b: Int, a: Int) = new java.awt.Color(r, g, b, a)
×
74
      def backgroundLight: Color = rgb(250, 250, 250)
×
75
      def backgroundMedium: Color = rgb(245, 245, 245)
×
76
      def border: Color = rgb(200, 200, 200)
×
77
      def text: Color = rgb(60, 60, 60)
×
78
      def obstacleGradientStart: Color = rgb(120, 120, 120)
×
79
      def obstacleGradientEnd: Color = rgb(80, 80, 80)
×
80
      def obstacleBorder: Color = rgb(60, 60, 60)
×
81
      def robotDefault: Color = rgb(100, 150, 255)
×
82
      def robotDefaultDark: Color = rgb(50, 100, 200)
×
83
      def robotDefaultBorder: Color = rgb(0, 50, 150)
×
84
      def robotSelected: Color = rgb(255, 100, 100)
×
85
      def robotSelectedDark: Color = rgb(200, 50, 50)
×
86
      def robotSelectedBorder: Color = rgb(150, 0, 0)
×
87
      def robotShadow: Color = rgba(0, 0, 0, 50)
×
88
      def lightCenter: Color = rgba(255, 255, 200, 200)
×
89
      def lightEdge: Color = rgba(255, 140, 0, 80)
×
90
      def buttonHover: Color = rgb(230, 230, 230)
×
91
      def buttonPressed: Color = rgb(220, 235, 250)
×
92
      def timeDisplay: Color = rgb(50, 50, 50)
×
93

×
94
    end Colors
95

96
    object Fonts:
97
      val FontSize = 12
×
98
      val TitleSize = 12
×
99

×
100
    object Spacing:
101
      val StandardPadding = 10
×
102
      val InnerPadding = 5
×
103
      val ComponentGap = 10
×
104

×
105
    object Dimensions:
106
      val ButtonWidth = 150
×
107
      val ButtonHeight = 30
×
108
      val RobotListWidth = 250
×
109
      val RobotListHeight = 300
×
110
      val InfoAreaRows = 6
×
111
      val InfoAreaColumns = 25
×
112

×
113
    object Strokes:
114
      val ObstacleStroke = 1.5f
×
115
      val RobotShadowStroke = 3f
×
116

×
117
    object Icons:
118
      val Play = "\u25B6"
×
119
      val Stop = "\u23F9"
×
120
      val Pause = "\u23F8"
×
121
  end UI
×
122

123
  val Duration: Option[Long] = None
124
  val Seed: Option[Long] = None
8✔
125
  val DebugMode = false
4✔
126
  val BinarySearchDurationThreshold: FiniteDuration = 1.microseconds
4✔
127

15✔
128
  /**
129
   * Alternative light map configurations for different use cases
130
   */
131
  object LightMapConfigs:
132

3✔
133
    /**
134
     * Default light map with caching enabled Uses scale factor 10 for a good balance of performance and precision
135
     */
136
    lazy val BaseLightMap: LightMap[IO] =
137
      LightMap
11✔
138
        .create[IO](ScaleFactor.default, SquidLibFovEngine)
30✔
139
        .unsafeRunSync()
19✔
140

68✔
141
    /**
142
     * High-precision light map for detailed rendering Uses scale factor 100 for maximum precision.
143
     *
144
     * @return
145
     *   A [[LightMap]] configured for high precision, or the default light map if the scale factor is invalid.
146
     */
147
    def HPLightMap: LightMap[IO] =
148
      ScaleFactor
×
149
        .validate(80)
×
150
        .map { scale =>
×
151
          LightMap
×
152
            .create[IO](scale, SquidLibFovEngine)
153
            .unsafeRunSync()
154
        }
155
        .getOrElse(BaseLightMap)
×
156

×
157
    /**
158
     * Fast light map for real-time simulation Uses scale factor 5 for maximum performance.
159
     *
160
     * @return
161
     *   A [[LightMap]] configured for fast computation, or the default light map if the scale factor is invalid.
162
     */
163
    def fastLightMap: LightMap[IO] =
164
      ScaleFactor
×
165
        .validate(10)
×
166
        .map { scale =>
×
167
          LightMap
×
168
            .create[IO](scale, SquidLibFovEngine)
169
            .unsafeRunSync()
170
        }
171
        .getOrElse(BaseLightMap)
×
172

×
173
    /**
174
     * Custom light map with specific scale factor Curried for better composition.
175
     *
176
     * @param scaleFactor
177
     *   The desired scale factor (cells per meter).
178
     * @return
179
     *   A [[LightMap]] configured with the specified scale factor, or the default light map if the scale factor is
180
     *   invalid.
181
     */
182
    def withScale(scaleFactor: Int): LightMap[IO] =
183
      ScaleFactor
×
184
        .validate(scaleFactor)
×
185
        .map { scale =>
×
186
          LightMap
×
187
            .create[IO](scale, SquidLibFovEngine)
188
            .unsafeRunSync()
189
        }
190
        .getOrElse(BaseLightMap)
×
191

×
192
  end LightMapConfigs
193

194
  object SimulationConfig:
195
    val MaxCount = 10_000
×
196

×
197
  object Environment:
198
    val DefaultWidth: Int = 10
3✔
199
    val MinWidth: Int = 1
8✔
200
    val MaxWidth: Int = 500
4✔
201

4✔
202
    val DefaultHeight: Int = 10
203
    val MinHeight: Int = 1
4✔
204
    val MaxHeight: Int = 500
4✔
205

4✔
206
    val DefaultEntities: Set[Entity] = Set.empty
207
    val MaxEntities: Int = 200
10✔
208

5✔
209
  object StaticEntity:
210

×
211
    object Obstacle:
212
      val DefaultId: UUID = UUID.fromString("00000000-0000-0000-0000-000000000000")
3✔
213
      val DefaultPosition: Point2D = (0.0, 0.0)
13✔
214
      val DefaultOrientation: Orientation = Orientation(0.0)
8✔
215
      val DefaultWidth: Double = 1.0
10✔
216
      val DefaultHeight: Double = 1.0
4✔
217

5✔
218
    object Light:
219
      val DefaultId: UUID = UUID.fromString("00000000-0000-0000-0000-000000000001")
3✔
220
      val DefaultPosition: Point2D = (0.0, 0.0)
13✔
221
      val DefaultOrientation: Orientation = Orientation(0.0)
8✔
222
      val DefaultRadius: Double = 0.05
10✔
223
      val DefaultIlluminationRadius: Double = 1.0
4✔
224
      val DefaultIntensity: Double = 1.0
4✔
225
      val DefaultAttenuation: Double = 1.0
4✔
226

5✔
227
    object Boundary:
228
      val DefaultPosition: Point2D = (0.0, 0.0)
3✔
229
      val DefaultOrientation: Orientation = Orientation(0.0)
12✔
230
      val DefaultWidth: Double = 1.0
10✔
231
      val DefaultHeight: Double = 1.0
4✔
232

5✔
233
  end StaticEntity
234

235
  object DynamicEntity:
236
    val ZeroSpeed: Double = 0.0
3✔
237
    val MinSpeed: Double = -1.0
8✔
238
    val MaxSpeed: Double = 1.0
4✔
239
    val HalfSpeed: Double = 0.5
4✔
240

5✔
241
    object Actuator:
242

×
243
      object DifferentialWheelMotor:
244
        val DefaultWheel: ActWheel = ActWheel()
3✔
245

22✔
246
        object Wheel:
247
          val DefaultSpeed: Double = 1.0
3✔
248
          val DefaultShape: ShapeType.Circle = ShapeType.Circle(0.1)
8✔
249
          val MinSpeed: Double = -1.0
6✔
250
          val MaxSpeed: Double = 1.0
4✔
251

5✔
252
    object Sensor:
253

×
254
      object ProximitySensor:
255
        val DefaultOffset: Double = 0.0
3✔
256
        val DefaultRange: Double = 1.0
8✔
257

5✔
258
    object Robot:
259

3✔
260
      val DefaultMaxRetries = 10
261

8✔
262
      val DefaultId: UUID = UUID.fromString("00000000-0000-0000-0000-000000000002")
263
      val DefaultPosition: Point2D = (0.0, 0.0)
9✔
264
      val DefaultShape: ShapeType.Circle = ShapeType.Circle(0.25)
8✔
265
      val DefaultOrientation: Orientation = Orientation(0.0)
6✔
266
      val DefaultActuators: Seq[Actuator[Robot]] = Seq.empty
10✔
267
      val DefaultSensors: Vector[Sensor[Robot, Environment]] = Vector.empty
11✔
268
      val MinRadius: Double = 0.01
10✔
269
      val MaxRadius: Double = 0.5
4✔
270

4✔
271
      val SelectionStroke: Float = 3f
272
      val NormalStroke: Float = 1f
2✔
273
      val ArrowLengthFactor: Double = 0.6
2✔
274
      val ArrowWidthFactor: Double = 0.3
2✔
275
      val MinArrowWidth: Float = 2f
2✔
276

2✔
277
      val StdProximitySensors: Vector[Sensor[Robot, Environment]] = Vector(
278
        ProximitySensor(Orientation(0.0)),
6✔
279
        ProximitySensor(Orientation(45.0)),
26✔
280
        ProximitySensor(Orientation(90.0)),
18✔
281
        ProximitySensor(Orientation(135.0)),
18✔
282
        ProximitySensor(Orientation(180.0)),
18✔
283
        ProximitySensor(Orientation(225.0)),
18✔
284
        ProximitySensor(Orientation(270.0)),
18✔
285
        ProximitySensor(Orientation(315.0)),
18✔
286
      )
18✔
287

3✔
288
      val StdLightSensors: Vector[Sensor[Robot, Environment]] = Vector(
289
        LightSensor(Orientation(0.0)),
6✔
290
        LightSensor(Orientation(45.0)),
20✔
291
        LightSensor(Orientation(90.0)),
12✔
292
        LightSensor(Orientation(135.0)),
12✔
293
        LightSensor(Orientation(180.0)),
12✔
294
        LightSensor(Orientation(225.0)),
12✔
295
        LightSensor(Orientation(270.0)),
12✔
296
        LightSensor(Orientation(315.0)),
12✔
297
      )
12✔
298
      val DefaultPolicy: Policy = Policy.AlwaysForward
3✔
299
    end Robot
5✔
300
  end DynamicEntity
301

302
  object GridDSL:
303
    val ObstacleSize: Double = 0.999999
3✔
304
    val IncrementToCenterPos: Point2D = Point2D(0.5, 0.5)
8✔
305

12✔
306
  object Fields:
UNCOV
307

×
308
    object Simulation:
309
      val Self: String = "simulation"
3✔
310
      val Duration: String = "duration"
8✔
311
      val Seed: String = "seed"
4✔
312

5✔
313
    object Environment:
314
      val Self: String = "environment"
3✔
315
      val Width: String = "width"
8✔
316
      val Height: String = "height"
4✔
317
      val Entities: String = "entities"
4✔
318

5✔
319
    object Entity:
320
      val Id: String = "id"
3✔
321
      val Position: String = "position"
8✔
322
      val X: String = "x"
4✔
323
      val Y: String = "y"
2✔
324
      val Orientation: String = "orientation"
2✔
325

5✔
326
      object StaticEntity:
UNCOV
327

×
328
        object Obstacle:
329
          val Self: String = "obstacle"
3✔
330
          val Width: String = "width"
8✔
331
          val Height: String = "height"
4✔
332

5✔
333
        object Light:
334
          val Self: String = "light"
3✔
335
          val Radius: String = "radius"
8✔
336
          val IlluminationRadius: String = "illuminationRadius"
4✔
337
          val Intensity: String = "intensity"
4✔
338
          val Attenuation: String = "attenuation"
4✔
339

5✔
340
      object DynamicEntity:
UNCOV
341

×
342
        object Robot:
343
          val Self: String = "robot"
3✔
344
          val Radius: String = "radius"
8✔
345
          val Speed: String = "speed"
4✔
346
          val WithProximitySensors: String = "withProximitySensors"
4✔
347
          val WithLightSensors: String = "withLightSensors"
4✔
348
          val Behavior: String = "behavior"
4✔
349
    end Entity
5✔
350
  end Fields
351

352
  object Layout:
353
    val SplitPaneWeight: Double = 0.8
×
354
    val SplitPaneLocation: Double = 0.8
×
355

×
356
  object Frame:
357
    val MinWidth = 800
×
358
    val MinHeight = 600
×
359
    val PrefWidth = 1200
×
UNCOV
360
    val PrefHeight = 720
×
361
    val SplitWeight = 0.8
×
362
    val CanvasBorder: Int = 2
×
363

×
364
  object Canvas:
365
    val BorderSize = 2
×
366
    val MinZoom = 0.2
×
367
    val MaxZoom = 5.0
×
368
    val ZoomInFactor = 1.2
×
369
    val ZoomOutFactor = 0.8
×
370
    val DesiredLabelPixels = 40.0
×
371
    val GridStrokeWidth = 1f
×
372
    val LabelDesiredPx: Double = 40.0
×
373
    val MinLightSize: Int = 12
×
374
    val LightStroke: Float = 2f
×
UNCOV
375
    val LabelBottomOffset: Int = 4
×
376
    val LabelYOffset: Int = 12
×
377
    val LabelXOffset: Int = 2
×
378

×
379
    val LabelStepSequence: List[Int] = List(1, 2, 5)
380
    val LabelScaleBase: Int = 10
×
381
    val DiameterFactor: Double = 2.0
×
382

×
383
    object Sensors:
384
      val LineStrokeWidth: Float = 1.0f
×
UNCOV
385
      val DotSize: Int = 3
×
386

×
387
    object LightFX:
388

×
389
      val GradientFraction0: Float = 0f
UNCOV
390
      val GradientFraction1: Float = 0.55f
×
391
      val GradientFraction2: Float = 0.9f
×
392
      val GradientFraction3: Float = 1f
×
UNCOV
393

×
394
      val CoreFractionStart: Float = 0f
395
      val CoreFractionEnd: Float = 1f
×
396

×
397
      val GradientRadiusDivisor: Float = 2f
398
      val MinLightPixels: Int = 1
×
399
      val PostGlowAlpha: Float = 0.015f
×
400

×
401
      val RingStrokeWidth: Float = 0.8f
402
      val RingStrokeMiterLimit: Float = 10f
×
UNCOV
403
      val RingStrokeDash1: Float = 4f
×
404
      val RingStrokeDash2: Float = 6f
×
405
      val RingStrokeDashPhase: Float = 0f
×
406

×
407
      val GradientColor: Array[Color] = Array(
408
        new Color(255, 200, 0, 28),
×
409
        new Color(255, 180, 0, 16),
×
UNCOV
410
        new Color(255, 160, 0, 6),
×
UNCOV
411
        new Color(255, 140, 0, 0),
×
UNCOV
412
      )
×
413

×
414
    end LightFX
415

416
    object Arrow:
417
      val TriangleVertices: Int = 3
×
418

×
419
    object RobotBody:
UNCOV
420
      val GradientFractionStart: Float = 0f
×
UNCOV
421
      val GradientFractionEnd: Float = 1f
×
422

×
423
  end Canvas
424

425
  object ControlsPanel:
UNCOV
426
    val StartStopButtonText: String = "Start/Stop"
×
UNCOV
427

×
428
end SimulationDefaults
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc