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

samsmithnz / PuzzleSolver / 4398149475

pending completion
4398149475

Pull #52

github

GitHub
Merge 0d7412dab into a11a49d0f
Pull Request #52: Resolving paths from crossing

950 of 1044 branches covered (91.0%)

Branch coverage included in aggregate %.

182 of 182 new or added lines in 6 files covered. (100.0%)

1664 of 1769 relevant lines covered (94.06%)

1041712.92 hits per line

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

78.1
/src/PuzzleSolver/Board.cs
1
using PuzzleSolver.Actions;
2
using PuzzleSolver.Entities;
3
using PuzzleSolver.Images;
4
using PuzzleSolver.Map;
5
using SixLabors.ImageSharp.PixelFormats;
6
using System.Collections.Generic;
7
using System.Linq;
8
using System.Numerics;
9

10
namespace PuzzleSolver
11
{
12
    public class Board
13
    {
14
        public string[,] Map { get; set; }
177✔
15

16
        //Color Palette
17
        public List<Rgb24> ColorPalette { get; set; }
16✔
18

19
        //Pieces
20
        public Vector2 UnsortedPiecesLocation { get; set; }
10✔
21
        public Queue<Piece> UnsortedPieces { get; set; }
305✔
22
        public List<Piece> SortedPieces { get; set; }
75✔
23
        public List<SortedDropZone> SortedDropZones { get; set; }
305✔
24

25
        //Characters
26
        public List<Robot> Robots { get; set; }
239✔
27

28
        private Dictionary<int, int> _RobotProgress = new Dictionary<int, int>();
8✔
29

30
        //Constructor
31
        public Board(string[,] map,
8✔
32
            Vector2 unsortedPiecesLocation,
8✔
33
            List<Rgb24> colorPalette,
8✔
34
            List<Piece> unsortedPieceList,
8✔
35
            List<SortedDropZone> sortedDropZones,
8✔
36
            List<Robot> robots)
8✔
37
        {
8✔
38
            Map = map;
8✔
39
            UnsortedPiecesLocation = unsortedPiecesLocation;
8✔
40
            ColorPalette = colorPalette;
8✔
41
            UnsortedPieces = new Queue<Piece>();
8✔
42
            ImageColorGroups imageProcessing = new ImageColorGroups(ColorPalette);
8✔
43
            for (int i = 0; i < unsortedPieceList.Count; i++)
144✔
44
            {
64✔
45
                Piece piece = unsortedPieceList[i];
64✔
46
                piece.ImageStats = imageProcessing.ProcessStatsForImage(null, piece.Image);
64✔
47
                UnsortedPieces.Enqueue(piece);
64✔
48
            }
64✔
49
            SortedDropZones = sortedDropZones;
8✔
50
            SortedPieces = new List<Piece>();
8✔
51
            Robots = robots;
8✔
52
        }
8✔
53

54
        public TimeLine RunRobots2()
55
        {
×
56
            TimeLine timeline = new TimeLine();
×
57
            //Create a dictonary to track robot turn progress over time
58
            Dictionary<int, int> robotProgress = new Dictionary<int, int>();
×
59
            foreach (Robot robot in Robots)
×
60
            {
×
61
                robotProgress.Add(robot.RobotId, 0);
×
62
            }
×
63

64
            //Need to loop through all unsorted pieces until they are sorted
65
            while (UnsortedPieces.Count > 0)
×
66
            {
×
67
                //Sort the progress list to find the robot with the least number of turns - this is the robot who should pick up next
68
                List<KeyValuePair<int, int>> orderedRobotProgress = robotProgress.OrderBy(x => x.Value).ToList();
×
69
                //For each robot
70
                foreach (Robot robot in Robots)
×
71
                {
×
72
                    switch (robot.RobotStatus)
×
73
                    {
74
                        case RobotStatus.RobotStatusEnum.LookingForJob:
75
                            robot.RobotStatus = RobotStatus.RobotStatusEnum.MovingToPickupLocation;
×
76
                            break;
×
77
                        case RobotStatus.RobotStatusEnum.MovingToPickupLocation:
78
                            //If there are unsorted pieces, move to pickup
79
                            RobotAction robotActionPickup = new RobotAction();
×
80
                            robotActionPickup.RobotPickupStartingLocation = robot.Location;
×
81
                            PathFindingResult pathFindingResultForPickup = FindPickupPathToLocation(robot, robot.PickupLocation, timeline);
×
82
                            robotActionPickup.RobotPickupEndingLocation = pathFindingResultForPickup.Path.Last();
×
83
                            robot.Location = pathFindingResultForPickup.Path.Last();
×
84
                            if (robot.Location == robot.PickupLocation)
×
85
                            {
×
86
                                robot.RobotStatus = RobotStatus.RobotStatusEnum.PickingUpPackage;
×
87
                            }
×
88
                            break;
×
89
                        case RobotStatus.RobotStatusEnum.PickingUpPackage:
90
                            //If we are at the pickup location, and there are pieces, pick up the piece
91
                            RobotAction robotActionDropoff = new RobotAction();
×
92

93
                            // Process the unsorted piece to work out where it goes
94
                            Vector2? destinationLocation = null;
×
95
                            foreach (SortedDropZone sortedDropZone in SortedDropZones)
×
96
                            {
×
97
                                if (sortedDropZone.Color == robot.Piece.ImageStats.TopColorGroupColor)
×
98
                                {
×
99
                                    destinationLocation = sortedDropZone.Location;
×
100
                                    break;
×
101
                                }
102
                            }
×
103
                            if (destinationLocation == null)
×
104
                            {
×
105
                                throw new System.Exception("Destination not found for piece " + robot.Piece.Id);
×
106
                            }
107

108
                            //Get the best adjacent location to the destination
109
                            Vector2? pathDestinationLocation = destinationLocation;
×
110
                            if (destinationLocation != null)
×
111
                            {
×
112
                                Vector2? adjacentLocation = GetAdjacentLocation((Vector2)destinationLocation, Map, SortedDropZones);
×
113
                                if (adjacentLocation != null)
×
114
                                {
×
115
                                    pathDestinationLocation = (Vector2)adjacentLocation;
×
116
                                    robotActionDropoff.RobotDropoffStartingLocation = robot.Location;
×
117

118
                                    PathFindingResult pathFindingResultForDropoff = FindPickupPathToLocation(robot, (Vector2)pathDestinationLocation, timeline);
×
119
                                    robot.RobotStatus = RobotStatus.RobotStatusEnum.MovingToPickupLocation;
×
120
                                    robotActionDropoff.RobotDropoffEndingLocation = pathFindingResultForDropoff.Path.Last();
×
121
                                    robot.Location = pathFindingResultForDropoff.Path.Last();
×
122
                                }
×
123
                            }
×
124
                            if (robot.Location == pathDestinationLocation)
×
125
                            {
×
126
                                robot.RobotStatus = RobotStatus.RobotStatusEnum.MovingToDeliveryLocation;
×
127
                            }
×
128
                            break;
×
129
                        case RobotStatus.RobotStatusEnum.MovingToDeliveryLocation:
130
                            //If the piece is picked up, move to dropoff
131
                            break;
×
132
                        case RobotStatus.RobotStatusEnum.DeliveringPackage:
133
                            //If we are at the dropoff location, drop off the piece
134

135

136
                            //If the piece is dropped off, move to pickup
137
                            break;
×
138
                    }
139
                }
×
140
            }
×
141

142
            return timeline;
×
143
        }
×
144

145
        public PathFindingResult FindPathFindingWithTimeline(string[,] map, Vector2 startLocation, Vector2 endLocation, int robotId, List<Robot> robots, TimeLine timeline)
146
        {
111✔
147
            //Get the path
148
            PathFindingResult pathFindingResult = PathFinding.FindPath(map, startLocation, endLocation);
111✔
149

150
            if (robots.Count > 1)
111✔
151
            {
40✔
152
                //Get the robot turn
153
                int turn = _RobotProgress[robotId];
40✔
154

155
                //Check the timeline to see if there are conflicts
156
                //Look at every turn
157
                for (int i = turn; i <= timeline.Turns.Count - 1; i++)
300✔
158
                {
110✔
159
                    //Look at every robot action in that turn
160
                    foreach (RobotTurnAction robotTurnAction in timeline.Turns[i].RobotActions)
550✔
161
                    {
110✔
162
                        //Only look at robots that aren't this one
163
                        if (robotTurnAction.RobotId != robotId)
110✔
164
                        {
110✔
165
                            if (pathFindingResult != null &&
110✔
166
                                pathFindingResult.Path.Count > 0 &&
110✔
167
                                robotTurnAction.Movement != null &&
110✔
168
                                robotTurnAction.Movement.Count > 0)
110✔
169
                            {
84✔
170
                                //Loop through the path
171
                                for (int k = 0; k < pathFindingResult.Path.Count - 1; k++)
536✔
172
                                {
209✔
173
                                    if (pathFindingResult.Path[k].X == robotTurnAction.Movement[0].X &&
209✔
174
                                        pathFindingResult.Path[k].Y == robotTurnAction.Movement[0].Y)
209✔
175
                                    {
25✔
176
                                        //Add a wait action to the path
177
                                        if (k == 0)
25✔
178
                                        {
9✔
179
                                            pathFindingResult.Path.Insert(0, startLocation);
9✔
180
                                        }
9✔
181
                                        else
182
                                        {
16✔
183
                                            pathFindingResult.Path.Insert(k, new Vector2(pathFindingResult.Path[k - 1].X, pathFindingResult.Path[k - 1].Y));
16✔
184
                                        }
16✔
185
                                        break;
25✔
186
                                    }
187
                                }
184✔
188
                            }
84✔
189
                        }
110✔
190
                    }
110✔
191
                }
110✔
192
            }
40✔
193

194
            return pathFindingResult;
111✔
195
        }
111✔
196

197
        public PathFindingResult FindPickupPathToLocation(Robot robot, Vector2 destination, TimeLine timeline)
198
        {
×
199
            PathFindingResult pathFindingResult = null;
×
200
            if (robot.Location != destination)
×
201
            {
×
202
                robot.RobotStatus = RobotStatus.RobotStatusEnum.MovingToPickupLocation;
×
203
                //Move the robot to the pickup zone - By doing this first we ensure we don't pick up a piece until we are there.
204
                //Vector2 currentRobotLocation = robot.Location;
205
                //Vector2 pickupLocation = robot.PickupLocation;
206

207
                // Move to unsorted pile
208
                //robotAction.RobotPickupStartingLocation = currentRobotLocation;
209
                PathFindingResult pathFindingResultForPickup = FindPathFindingWithTimeline(Map, robot.Location, robot.PickupLocation, robot.RobotId, Robots, timeline);
×
210
                if (pathFindingResultForPickup != null && pathFindingResultForPickup.Path.Any())
×
211
                {
×
212
                    //Move robot
213
                    pathFindingResult = pathFindingResultForPickup;
×
214
                    //currentRobotLocation = pathFindingResultForPickup.Path.Last();
215
                }
×
216
                //robotAction.RobotPickupEndingLocation = currentRobotLocation;
217
                //robot.Location = currentRobotLocation;
218
            }
×
219
            return pathFindingResult;
×
220
        }
×
221

222
        public TimeLine RunRobots()
223
        {
6✔
224
            TimeLine timeline = new TimeLine();
6✔
225

226
            //Create a dictonary to track robot turn progress over time
227
            foreach (Robot robot in Robots)
34✔
228
            {
8✔
229
                _RobotProgress.Add(robot.RobotId, 0);
8✔
230
            }
8✔
231

232
            //Need to loop through all unsorted pieces until they are sorted
233
            while (UnsortedPieces.Count > 0)
110✔
234
            {
104✔
235
                //Sort the progress list to find the robot with the least number of turns - this is the robot who should pick up next
236
                List<KeyValuePair<int, int>> orderedRobotProgress = _RobotProgress.OrderBy(x => x.Value).ToList();
244✔
237
                //For each robot
238
                foreach (Robot robot in Robots)
456✔
239
                {
124✔
240
                    //Find the robot with the least progress, and then break
241
                    if (robot.Piece == null && orderedRobotProgress[0].Key == robot.RobotId)
124!
242
                    {
104✔
243
                        RobotAction robotAction = new RobotAction();
104✔
244
                        Piece piece = null;
104✔
245
                        //See if the robot needs to move to the pickup zone
246
                        if (robot.Location != robot.PickupLocation)
104✔
247
                        {
48✔
248
                            robot.RobotStatus = RobotStatus.RobotStatusEnum.MovingToPickupLocation;
48✔
249
                            //Move the robot to the pickup zone - By doing this first we ensure we don't pick up a piece until we are there.
250
                            Vector2 currentRobotLocation = robot.Location;
48✔
251
                            Vector2 pickupLocation = robot.PickupLocation;
48✔
252

253
                            // Move to unsorted pile
254
                            robotAction.RobotPickupStartingLocation = currentRobotLocation;
48✔
255
                            if (currentRobotLocation != pickupLocation)
48✔
256
                            {
48✔
257
                                PathFindingResult pathFindingResultForPickup = FindPathFindingWithTimeline(Map, currentRobotLocation, pickupLocation, robot.RobotId, Robots, timeline);
48✔
258
                                if (pathFindingResultForPickup != null && pathFindingResultForPickup.Path.Any())
48!
259
                                {
48✔
260
                                    //Move robot
261
                                    robotAction.PathToPickup = pathFindingResultForPickup;
48✔
262
                                    currentRobotLocation = pathFindingResultForPickup.Path.Last();
48✔
263
                                }
48✔
264
                            }
48✔
265
                            robotAction.RobotPickupEndingLocation = currentRobotLocation;
48✔
266
                            robot.Location = currentRobotLocation;
48✔
267
                        }
48✔
268
                        //Else do the pickup, dropoff and delivery
269
                        else if (robot.Piece == null && UnsortedPieces.Count > 0)
56!
270
                        {
56✔
271
                            piece = UnsortedPieces.Dequeue();
56✔
272
                            robotAction = GetRobotAction(robot, piece, timeline);
56✔
273
                        }
56✔
274
                        ////Robot is holding the piece
275
                        //else if (robot.Piece != null)
276
                        //{
277
                        //    robotAction = GetRobotAction(robot, robot.Piece);
278
                        //    if (robot.Location != robotAction.RobotDropoffEndingLocation)
279
                        //    {
280
                        //        //need to find a dropoff path
281
                        //    }
282
                        //    else
283
                        //    {
284
                        //        //is at the dropoff point
285
                        //    }
286
                        //}
287

288
                        //process the robot action
289
                        if (robotAction != null)
104✔
290
                        {
104✔
291
                            int turn = _RobotProgress[robot.RobotId];
104✔
292
                            int turnsNeeded = 0;
104✔
293

294
                            //move to pickup
295
                            if (robotAction.PathToPickup != null)
104✔
296
                            {
48✔
297
                                turnsNeeded += robotAction.PathToPickup.Path.Count;
48✔
298
                            }
48✔
299
                            //pickup piece
300
                            if (robotAction.PickupAction != null)
104✔
301
                            {
56✔
302
                                turnsNeeded++;
56✔
303
                            }
56✔
304
                            //move to drop off
305
                            if (robotAction.PathToDropoff != null)
104✔
306
                            {
56✔
307
                                turnsNeeded += robotAction.PathToDropoff.Path.Count;
56✔
308
                            }
56✔
309
                            //drop off piece
310
                            if (robotAction.DropoffAction != null)
104✔
311
                            {
56✔
312
                                turnsNeeded++;
56✔
313
                            }
56✔
314
                            //Initialize the turns needed for this robot to complete it's turn
315
                            for (int j = turn; j < turn + turnsNeeded; j++)
1,058✔
316
                            {
425✔
317
                                if (timeline.Turns.Any(t => t.TurnNumber == j + 1) == false)
13,390✔
318
                                {
334✔
319
                                    timeline.Turns.Add(new Turn(j + 1));
334✔
320
                                }
334✔
321
                            }
425✔
322

323
                            //Now populate the turns with the pickup path
324
                            int pickupCounter = 0;
104✔
325
                            if (robotAction.PathToPickup != null &&
104✔
326
                                robotAction.PathToPickup.Path != null &&
104✔
327
                                robotAction.PathToPickup.Path.Count > 0)
104✔
328
                            {
48✔
329
                                pickupCounter++;
48✔
330
                                timeline.Turns[turn].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.MovingToPickupLocation, null)
48✔
331
                                {
48✔
332
                                    Movement = new List<Vector2>() { robotAction.RobotPickupStartingLocation, robotAction.PathToPickup.Path[0] }
48✔
333
                                });
48✔
334
                                for (int j = 1; j <= robotAction.PathToPickup.Path.Count - 1; j++)
278✔
335
                                {
91✔
336
                                    pickupCounter++;
91✔
337
                                    timeline.Turns[turn + j].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.MovingToPickupLocation, null)
91✔
338
                                    {
91✔
339
                                        Movement = new List<Vector2>() { robotAction.PathToPickup.Path[j - 1], robotAction.PathToPickup.Path[j] }
91✔
340
                                    });
91✔
341
                                }
91✔
342
                            }
48✔
343

344
                            if (robotAction.PickupAction != null)
104✔
345
                            {
56✔
346
                                timeline.Turns[pickupCounter + turn].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.PickingUpPackage, piece.Id)
56✔
347
                                {
56✔
348
                                    PickupAction = robotAction.PickupAction
56✔
349
                                });
56✔
350
                                pickupCounter++;
56✔
351
                                robot.Location = robotAction.RobotPickupEndingLocation;
56✔
352
                            }
56✔
353

354
                            //Now populate the turns with the dropoff path
355
                            int dropoffCounter = 0;
104✔
356
                            if (robotAction.PathToDropoff != null &&
104✔
357
                                robotAction.PathToDropoff.Path != null &&
104✔
358
                                robotAction.PathToDropoff.Path.Count > 0)
104✔
359
                            {
55✔
360
                                dropoffCounter++;
55✔
361
                                timeline.Turns[pickupCounter + turn].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.MovingToDeliveryLocation, piece.Id)
55✔
362
                                {
55✔
363
                                    Movement = new List<Vector2>() { robotAction.RobotDropoffStartingLocation, robotAction.PathToDropoff.Path[0] }
55✔
364
                                });
55✔
365
                                for (int j = 1; j <= robotAction.PathToDropoff.Path.Count - 1; j++)
348✔
366
                                {
119✔
367
                                    dropoffCounter++;
119✔
368
                                    timeline.Turns[pickupCounter + turn + j].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.MovingToDeliveryLocation, piece.Id)
119✔
369
                                    {
119✔
370
                                        Movement = new List<Vector2>() { robotAction.PathToDropoff.Path[j - 1], robotAction.PathToDropoff.Path[j] }
119✔
371
                                    });
119✔
372
                                }
119✔
373
                            }
55✔
374

375
                            if (robotAction.DropoffAction != null)
104✔
376
                            {
56✔
377
                                robotAction.DropoffAction.DestinationPieceCount = GetPieceCount(robotAction.DropoffAction.Location);
56✔
378
                                timeline.Turns[pickupCounter + dropoffCounter + turn].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.DeliveringPackage, piece.Id)
56✔
379
                                {
56✔
380
                                    DropoffAction = robotAction.DropoffAction
56✔
381
                                });
56✔
382
                                dropoffCounter++;
56✔
383
                                robot.Location = robotAction.RobotDropoffEndingLocation;
56✔
384
                            }
56✔
385
                            _RobotProgress[robot.RobotId] += pickupCounter + dropoffCounter;
104✔
386
                        }
104✔
387
                        break;
104✔
388
                    }
389
                }
20✔
390
            }
104✔
391

392
            //Move the robots back to the start location
393
            foreach (Robot robot in Robots)
34✔
394
            {
8✔
395
                if (robot.Location != robot.PickupLocation)
8✔
396
                {
7✔
397
                    RobotAction robotAction = new RobotAction();
7✔
398
                    //Move the robot to the pickup zone - By doing this first we ensure we don't pick up a piece until we are there.
399
                    Vector2 currentRobotLocation = robot.Location;
7✔
400
                    Vector2 pickupLocation = robot.PickupLocation;
7✔
401

402
                    // Move to unsorted pile
403
                    robotAction.RobotPickupStartingLocation = currentRobotLocation;
7✔
404
                    if (currentRobotLocation != pickupLocation)
7✔
405
                    {
7✔
406
                        PathFindingResult pathFindingResultForPickup = FindPathFindingWithTimeline(Map, currentRobotLocation, pickupLocation, robot.RobotId, Robots, timeline);
7✔
407
                        if (pathFindingResultForPickup != null && pathFindingResultForPickup.Path.Any())
7!
408
                        {
7✔
409
                            //Move robot
410
                            robotAction.PathToPickup = pathFindingResultForPickup;
7✔
411
                            currentRobotLocation = pathFindingResultForPickup.Path.Last();
7✔
412
                        }
7✔
413
                    }
7✔
414
                    robotAction.RobotPickupEndingLocation = currentRobotLocation;
7✔
415
                    robot.Location = currentRobotLocation;
7✔
416

417
                    //process the robot action
418
                    if (robotAction != null)
7✔
419
                    {
7✔
420
                        int turn = _RobotProgress[robot.RobotId];
7✔
421
                        int turnsNeeded = 0;
7✔
422

423
                        //move to pickup
424
                        if (robotAction.PathToPickup != null)
7✔
425
                        {
7✔
426
                            turnsNeeded += robotAction.PathToPickup.Path.Count;
7✔
427
                        }
7✔
428
                        //Initialize the turns needed for this robot to complete it's turn
429
                        for (int j = turn; j < turn + turnsNeeded; j++)
70✔
430
                        {
28✔
431
                            if (timeline.Turns.Any(t => t.TurnNumber == j + 1) == false)
1,535✔
432
                            {
17✔
433
                                timeline.Turns.Add(new Turn(j + 1));
17✔
434
                            }
17✔
435
                        }
28✔
436

437
                        //Now populate the turns with the pickup path
438
                        int pickupCounter = 0;
7✔
439
                        if (robotAction.PathToPickup != null &&
7!
440
                            robotAction.PathToPickup.Path != null &&
7✔
441
                            robotAction.PathToPickup.Path.Count > 0)
7✔
442
                        {
7✔
443
                            pickupCounter++;
7✔
444
                            timeline.Turns[turn].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.MovingToPickupLocation, null)
7✔
445
                            {
7✔
446
                                Movement = new List<Vector2>() { robotAction.RobotPickupStartingLocation, robotAction.PathToPickup.Path[0] }
7✔
447
                            });
7✔
448
                            for (int j = 1; j <= robotAction.PathToPickup.Path.Count - 1; j++)
56✔
449
                            {
21✔
450
                                pickupCounter++;
21✔
451
                                timeline.Turns[turn + j].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.MovingToPickupLocation, null)
21✔
452
                                {
21✔
453
                                    Movement = new List<Vector2>() { robotAction.PathToPickup.Path[j - 1], robotAction.PathToPickup.Path[j] }
21✔
454
                                });
21✔
455
                            }
21✔
456
                        }
7✔
457
                        _RobotProgress[robot.RobotId] += pickupCounter;
7✔
458
                    }
7✔
459
                }
7✔
460
            }
8✔
461

462
            return timeline;
6✔
463
        }
6✔
464

465
        public int GetPieceCount(Vector2 dropOfflocation)
466
        {
114✔
467
            int pieceCount = 0;
114✔
468
            foreach (SortedDropZone sortedDropZone in SortedDropZones)
1,084✔
469
            {
428✔
470
                if (sortedDropZone.Location == dropOfflocation)
428✔
471
                {
114✔
472
                    pieceCount = sortedDropZone.Count;
114✔
473
                    break;
114✔
474
                }
475
            }
314✔
476
            return pieceCount;
114✔
477
        }
114✔
478

479
        private Vector2? GetAdjacentLocation(Vector2 destinationLocation, string[,] map, List<SortedDropZone> sortedDropZones)
480
        {
56✔
481
            Vector2? adjacentLocation = null;
56✔
482
            if (destinationLocation != null)
56✔
483
            {
56✔
484
                if (destinationLocation.X == 0)
56✔
485
                {
43✔
486
                    //it's a right location drop-off
487
                    adjacentLocation = new Vector2((int)destinationLocation.X + 1, (int)destinationLocation.Y);
43✔
488
                }
43✔
489
                else if (destinationLocation.X == map.GetUpperBound(0))
13✔
490
                {
1✔
491
                    //it's a left location drop-off
492
                    adjacentLocation = new Vector2((int)destinationLocation.X - 1, (int)destinationLocation.Y);
1✔
493
                }
1✔
494
                else if (destinationLocation.Y == 0)
12✔
495
                {
5✔
496
                    //it's a top location drop-off
497
                    adjacentLocation = new Vector2((int)destinationLocation.X, (int)destinationLocation.Y + 1);
5✔
498
                }
5✔
499
                else if (destinationLocation.Y == map.GetUpperBound(1))
7✔
500
                {
7✔
501
                    //it's a bottom location drop-off
502
                    adjacentLocation = new Vector2((int)destinationLocation.X, (int)destinationLocation.Y - 1);
7✔
503
                }
7✔
504
            }
56✔
505
            return adjacentLocation;
56✔
506
        }
56✔
507

508
        private RobotAction GetRobotAction(Robot robot, Piece piece, TimeLine timeline)
509
        {
56✔
510
            RobotAction robotAction = new RobotAction();
56✔
511

512
            Vector2 currentRobotLocation = robot.Location;
56✔
513
            Vector2 pickupLocation = robot.PickupLocation;
56✔
514

515
            // Move to unsorted pile
516
            robotAction.RobotPickupStartingLocation = currentRobotLocation;
56✔
517
            if (currentRobotLocation != pickupLocation)
56!
518
            {
×
519
                robot.RobotStatus = RobotStatus.RobotStatusEnum.MovingToPickupLocation;
×
520
                PathFindingResult pathFindingResultForPickup = FindPathFindingWithTimeline(Map, currentRobotLocation, pickupLocation, robot.RobotId, Robots, timeline);
×
521
                if (pathFindingResultForPickup != null && pathFindingResultForPickup.Path.Any())
×
522
                {
×
523
                    //Move robot
524
                    robotAction.PathToPickup = pathFindingResultForPickup;
×
525
                    currentRobotLocation = pathFindingResultForPickup.Path.Last();
×
526
                }
×
527
            }
×
528
            robotAction.RobotPickupEndingLocation = currentRobotLocation;
56✔
529

530
            // Pickup an unsorted piece from the unsorted pile
531
            if (robot.Piece != null)
56!
532
            {
×
533
                throw new System.Exception("Piece " + robot.Piece.Id + " was not delivered");
×
534
            }
535
            robot.RobotStatus = RobotStatus.RobotStatusEnum.PickingUpPackage;
56✔
536
            robot.Piece = piece;
56✔
537
            robotAction.PieceId = piece.Id;
56✔
538
            robotAction.PickupAction = new ObjectInteraction()
56✔
539
            {
56✔
540
                Location = piece.Location
56✔
541
            };
56✔
542

543
            // Process the unsorted piece to work out where it goes
544
            Vector2? destinationLocation = null;
56✔
545
            foreach (SortedDropZone sortedDropZone in SortedDropZones)
538✔
546
            {
213✔
547
                if (sortedDropZone.Color == robot.Piece.ImageStats.TopColorGroupColor)
213✔
548
                {
56✔
549
                    destinationLocation = sortedDropZone.Location;
56✔
550
                    break;
56✔
551
                }
552
            }
157✔
553
            if (destinationLocation == null)
56!
554
            {
×
555
                throw new System.Exception("Destination not found for piece " + piece.Id);
×
556
            }
557

558
            //Get the best adjacent location to the destination
559
            Vector2? pathDestinationLocation = destinationLocation;
56✔
560
            if (destinationLocation != null)
56✔
561
            {
56✔
562
                Vector2? adjacentLocation = GetAdjacentLocation((Vector2)destinationLocation, Map, SortedDropZones);
56✔
563
                if (adjacentLocation != null)
56✔
564
                {
56✔
565
                    pathDestinationLocation = (Vector2)adjacentLocation;
56✔
566
                }
56✔
567
            }
56✔
568

569
            // Move the sorted piece to the correct pile
570
            robotAction.RobotDropoffStartingLocation = currentRobotLocation;
56✔
571
            if (destinationLocation != null && pathDestinationLocation != null)
56!
572
            {
56✔
573
                robot.RobotStatus = RobotStatus.RobotStatusEnum.MovingToDeliveryLocation;
56✔
574
                //now find the path
575
                PathFindingResult pathFindingResultForDropoff = FindPathFindingWithTimeline(Map, currentRobotLocation, (Vector2)pathDestinationLocation, robot.RobotId, Robots, timeline);
56✔
576
                if (pathFindingResultForDropoff != null && pathFindingResultForDropoff.Path.Count >= 0)
56!
577
                {
56✔
578
                    //Move robot
579
                    robotAction.PathToDropoff = pathFindingResultForDropoff;
56✔
580
                    robotAction.DropoffAction = new ObjectInteraction()
56✔
581
                    {
56✔
582
                        Location = (Vector2)destinationLocation
56✔
583
                    };
56✔
584
                    //Move the piece from the robot to the sorted pile
585
                    robot.RobotStatus = RobotStatus.RobotStatusEnum.DeliveringPackage;
56✔
586
                    robot.Piece.Location = robotAction.DropoffAction.Location;
56✔
587
                    SortedPieces.Add(robot.Piece);
56✔
588
                    foreach (SortedDropZone sortedDropZone in SortedDropZones)
538✔
589
                    {
213✔
590
                        if (sortedDropZone.Location == destinationLocation)
213!
591
                        {
56✔
592
                            sortedDropZone.Count++;
56✔
593
                            break;
56✔
594
                        }
595
                    }
157✔
596
                    robot.Piece = null;
56✔
597
                    robotAction.DropoffPieceCount = GetPieceCount(robotAction.DropoffAction.Location);
56✔
598
                    if (pathFindingResultForDropoff.Path.Count > 0)
56✔
599
                    {
55✔
600
                        currentRobotLocation = pathFindingResultForDropoff.Path.Last();
55✔
601
                    }
55✔
602
                }
56✔
603
            }
56✔
604
            robot.RobotStatus = RobotStatus.RobotStatusEnum.LookingForJob;
56✔
605
            robotAction.RobotDropoffEndingLocation = currentRobotLocation;
56✔
606

607
            return robotAction;
56✔
608
        }
56✔
609
    }
610
}
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

© 2025 Coveralls, Inc