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

samsmithnz / PuzzleSolver / 4409137003

pending completion
4409137003

Pull #52

github

GitHub
Merge 8274f7578 into 2c1e44de1
Pull Request #52: Resolving paths from crossing

978 of 1040 branches covered (94.04%)

Branch coverage included in aggregate %.

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

1734 of 1772 relevant lines covered (97.86%)

1042948.56 hits per line

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

93.57
/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; }
197✔
15

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

19
        //Pieces
20
        public Vector2 UnsortedPiecesLocation { get; set; }
12✔
21
        public Queue<Piece> UnsortedPieces { get; set; }
338✔
22
        public List<Piece> SortedPieces { get; set; }
85✔
23
        public List<SortedDropZone> SortedDropZones { get; set; }
337✔
24

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

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

30
        //Constructor
31
        public Board(string[,] map,
10✔
32
            Vector2 unsortedPiecesLocation,
10✔
33
            List<Rgb24> colorPalette,
10✔
34
            List<Piece> unsortedPieceList,
10✔
35
            List<SortedDropZone> sortedDropZones,
10✔
36
            List<Robot> robots)
10✔
37
        {
10✔
38
            Map = map;
10✔
39
            UnsortedPiecesLocation = unsortedPiecesLocation;
10✔
40
            ColorPalette = colorPalette;
10✔
41
            UnsortedPieces = new Queue<Piece>();
10✔
42
            ImageColorGroups imageProcessing = new ImageColorGroups(ColorPalette);
10✔
43
            for (int i = 0; i < unsortedPieceList.Count; i++)
160✔
44
            {
70✔
45
                Piece piece = unsortedPieceList[i];
70✔
46
                piece.ImageStats = imageProcessing.ProcessStatsForImage(null, piece.Image);
70✔
47
                UnsortedPieces.Enqueue(piece);
70✔
48
            }
70✔
49
            SortedDropZones = sortedDropZones;
10✔
50
            SortedPieces = new List<Piece>();
10✔
51
            Robots = robots;
10✔
52
        }
10✔
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
        {
123✔
147
            //Get the robot turn
148
            int turn = _RobotProgress[robotId];
123✔
149

150
            //Get the path
151
            string[,] mapWithAllPaths = (string[,])map.Clone();
123✔
152
            foreach (Robot robot in robots)
719✔
153
            {
175✔
154
                if (robot.RobotId != robotId)
175✔
155
                {
52✔
156
                    mapWithAllPaths[(int)robot.PickupLocation.X, (int)robot.PickupLocation.Y] = "P";
52✔
157
                }
52✔
158
            }
175✔
159
            if (timeline.Turns.Count > 0 && timeline.Turns.Count <= turn)
123✔
160
            {
76✔
161
                foreach (RobotTurnAction robotTurnAction in timeline.Turns[turn - 1].RobotActions)
396✔
162
                {
84✔
163
                    if (robotTurnAction.PathRemaining != null &&
84✔
164
                        robotTurnAction.PathRemaining.Count > 0)
84✔
165
                    {
41✔
166
                        foreach (Vector2 pathLocation in robotTurnAction.PathRemaining)
205✔
167
                        {
41✔
168
                            mapWithAllPaths[(int)pathLocation.X, (int)pathLocation.Y] = "X";
41✔
169
                        }
41✔
170
                    }
41✔
171
                }
84✔
172
            }
76✔
173
            PathFindingResult pathFindingResult = PathFinding.FindPath(mapWithAllPaths, startLocation, endLocation);
123✔
174

175
            if (pathFindingResult != null &&
123✔
176
                pathFindingResult.Path.Count > 0 && 
123✔
177
                robots.Count > 1)
123✔
178
            {
52✔
179
                //Check the timeline to see if there are conflicts
180
                //Look at every turn
181
                for (int i = turn; i <= timeline.Turns.Count - 1; i++)
358✔
182
                {
127✔
183
                    //Look at every robot action in that turn
184
                    foreach (RobotTurnAction robotTurnAction in timeline.Turns[i].RobotActions)
635✔
185
                    {
127✔
186
                        //Only look at robots that aren't this one
187
                        if (robotTurnAction.RobotId != robotId)
127✔
188
                        {
127✔
189
                            if (robotTurnAction.Movement != null &&
127✔
190
                                robotTurnAction.Movement.Count > 0)
127✔
191
                            {
96✔
192
                                //Loop through the path
193
                                for (int k = 0; k < pathFindingResult.Path.Count - 1; k++)
668✔
194
                                {
269✔
195
                                    //Check that the location the robot is moving too isn't the destination of another robot
196
                                    if ((pathFindingResult.Path[k].X == robotTurnAction.Movement[0].X &&
269✔
197
                                        pathFindingResult.Path[k].Y == robotTurnAction.Movement[0].Y) ||
269✔
198
                                        (pathFindingResult.Path[k].X == robotTurnAction.Movement[1].X &&
269✔
199
                                        pathFindingResult.Path[k].Y == robotTurnAction.Movement[1].Y))
269✔
200
                                    {
31✔
201
                                        //Add a wait action to the path
202
                                        if (k == 0)
31✔
203
                                        {
9✔
204
                                            pathFindingResult.Path.Insert(0, startLocation);
9✔
205
                                        }
9✔
206
                                        else
207
                                        {
22✔
208
                                            pathFindingResult.Path.Insert(k, new Vector2(pathFindingResult.Path[k - 1].X, pathFindingResult.Path[k - 1].Y));
22✔
209
                                        }
22✔
210
                                        break;
31✔
211
                                    }
212
                                }
238✔
213
                            }
96✔
214
                        }
127✔
215
                    }
127✔
216
                }
127✔
217
            }
52✔
218

219
            return pathFindingResult;
123✔
220
        }
123✔
221

222
        //public PathFindingResult FindPickupPathToLocation(Robot robot, Vector2 destination, TimeLine timeline)
223
        //{
224
        //    PathFindingResult pathFindingResult = null;
225
        //    if (robot.Location != destination)
226
        //    {
227
        //        robot.RobotStatus = RobotStatus.RobotStatusEnum.MovingToPickupLocation;
228
        //        //Move the robot to the pickup zone - By doing this first we ensure we don't pick up a piece until we are there.
229
        //        //Vector2 currentRobotLocation = robot.Location;
230
        //        //Vector2 pickupLocation = robot.PickupLocation;
231

232
        //        // Move to unsorted pile
233
        //        //robotAction.RobotPickupStartingLocation = currentRobotLocation;
234
        //        PathFindingResult pathFindingResultForPickup = FindPathFindingWithTimeline(Map, robot.Location, robot.PickupLocation, robot.RobotId, Robots, timeline);
235
        //        if (pathFindingResultForPickup != null && pathFindingResultForPickup.Path.Any())
236
        //        {
237
        //            //Move robot
238
        //            pathFindingResult = pathFindingResultForPickup;
239
        //            //currentRobotLocation = pathFindingResultForPickup.Path.Last();
240
        //        }
241
        //        //robotAction.RobotPickupEndingLocation = currentRobotLocation;
242
        //        //robot.Location = currentRobotLocation;
243
        //    }
244
        //    return pathFindingResult;
245
        //}
246

247
        public TimeLine RunRobots()
248
        {
8✔
249
            TimeLine timeline = new TimeLine();
8✔
250

251
            //Create a dictonary to track robot turn progress over time
252
            foreach (Robot robot in Robots)
48✔
253
            {
12✔
254
                _RobotProgress.Add(robot.RobotId, 0);
12✔
255
            }
12✔
256

257
            //Need to loop through all unsorted pieces until they are sorted
258
            while (UnsortedPieces.Count > 0)
121✔
259
            {
113✔
260
                //Sort the progress list to find the robot with the least number of turns - this is the robot who should pick up next
261
                List<KeyValuePair<int, int>> orderedRobotProgress = _RobotProgress.OrderBy(x => x.Value).ToList();
271✔
262
                //For each robot
263
                foreach (Robot robot in Robots)
500✔
264
                {
137✔
265
                    //Find the robot with the least progress, and then break
266
                    if (robot.Piece == null && orderedRobotProgress[0].Key == robot.RobotId)
137!
267
                    {
113✔
268
                        RobotAction robotAction = new RobotAction(robot.RobotId);
113✔
269
                        Piece piece = null;
113✔
270
                        //See if the robot needs to move to the pickup zone
271
                        if (robot.Location != robot.PickupLocation)
113✔
272
                        {
51✔
273
                            robot.RobotStatus = RobotStatus.RobotStatusEnum.MovingToPickupLocation;
51✔
274
                            //Move the robot to the pickup zone - By doing this first we ensure we don't pick up a piece until we are there.
275
                            Vector2 currentRobotLocation = robot.Location;
51✔
276
                            Vector2 pickupLocation = robot.PickupLocation;
51✔
277

278
                            // Move to unsorted pile
279
                            robotAction.RobotPickupStartingLocation = currentRobotLocation;
51✔
280
                            if (currentRobotLocation != pickupLocation)
51✔
281
                            {
51✔
282
                                PathFindingResult pathFindingResultForPickup = FindPathFindingWithTimeline(Map, currentRobotLocation, pickupLocation, robot.RobotId, Robots, timeline);
51✔
283
                                if (pathFindingResultForPickup != null && pathFindingResultForPickup.Path.Any())
51!
284
                                {
51✔
285
                                    //Move robot
286
                                    robotAction.PathToPickup = pathFindingResultForPickup;
51✔
287
                                    currentRobotLocation = pathFindingResultForPickup.Path.Last();
51✔
288
                                }
51✔
289
                                else
290
                                {
×
291
                                    int g = 0;
×
292
                                }
×
293
                            }
51✔
294
                            robotAction.RobotPickupEndingLocation = currentRobotLocation;
51✔
295
                            robot.Location = currentRobotLocation;
51✔
296
                        }
51✔
297
                        //Else do the pickup, dropoff and delivery
298
                        else if (robot.Piece == null && UnsortedPieces.Count > 0)
62!
299
                        {
62✔
300
                            piece = UnsortedPieces.Dequeue();
62✔
301
                            robotAction = GetRobotAction(robot, piece, timeline);
62✔
302
                        }
62✔
303
                        ////Robot is holding the piece
304
                        //else if (robot.Piece != null)
305
                        //{
306
                        //    robotAction = GetRobotAction(robot, robot.Piece);
307
                        //    if (robot.Location != robotAction.RobotDropoffEndingLocation)
308
                        //    {
309
                        //        //need to find a dropoff path
310
                        //    }
311
                        //    else
312
                        //    {
313
                        //        //is at the dropoff point
314
                        //    }
315
                        //}
316

317
                        //process the robot action
318
                        if (robotAction != null)
113✔
319
                        {
113✔
320
                            int turn = _RobotProgress[robot.RobotId];
113✔
321
                            int turnsNeeded = 0;
113✔
322

323
                            //move to pickup
324
                            if (robotAction.PathToPickup != null)
113✔
325
                            {
51✔
326
                                turnsNeeded += robotAction.PathToPickup.Path.Count;
51✔
327
                            }
51✔
328
                            //pickup piece
329
                            if (robotAction.PickupAction != null)
113✔
330
                            {
62✔
331
                                turnsNeeded++;
62✔
332
                            }
62✔
333
                            //move to drop off
334
                            if (robotAction.PathToDropoff != null)
113✔
335
                            {
62✔
336
                                turnsNeeded += robotAction.PathToDropoff.Path.Count;
62✔
337
                            }
62✔
338
                            //drop off piece
339
                            if (robotAction.DropoffAction != null)
113✔
340
                            {
62✔
341
                                turnsNeeded++;
62✔
342
                            }
62✔
343
                            //Initialize the turns needed for this robot to complete it's turn
344
                            for (int j = turn; j < turn + turnsNeeded; j++)
1,134✔
345
                            {
454✔
346
                                if (timeline.Turns.Any(t => t.TurnNumber == j + 1) == false)
13,759✔
347
                                {
350✔
348
                                    timeline.Turns.Add(new Turn(j + 1));
350✔
349
                                }
350✔
350
                            }
454✔
351

352
                            //Now populate the turns with the pickup path
353
                            int pickupCounter = 0;
113✔
354
                            if (robotAction.PathToPickup != null &&
113✔
355
                                robotAction.PathToPickup.Path != null &&
113✔
356
                                robotAction.PathToPickup.Path.Count > 0)
113✔
357
                            {
51✔
358
                                Robot robotPathRemaining = GetRobot(robotAction.RobotId);
51✔
359
                                if (robotPathRemaining != null)
51✔
360
                                {
51✔
361
                                    robotPathRemaining.RobotPath = new Queue<Vector2>(robotAction.PathToPickup.Path);
51✔
362
                                }
51✔
363
                                pickupCounter++;
51✔
364
                                timeline.Turns[turn].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.MovingToPickupLocation, null)
51✔
365
                                {
51✔
366
                                    Movement = new List<Vector2>() { robotAction.RobotPickupStartingLocation, robotAction.PathToPickup.Path[0] },
51✔
367
                                    PathRemaining = robotPathRemaining.RobotPath.ToList()
51✔
368
                                });
51✔
369
                                robotPathRemaining.RobotPath.Dequeue();
51✔
370
                                for (int j = 1; j <= robotAction.PathToPickup.Path.Count - 1; j++)
304✔
371
                                {
101✔
372
                                    pickupCounter++;
101✔
373
                                    timeline.Turns[turn + j].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.MovingToPickupLocation, null)
101✔
374
                                    {
101✔
375
                                        Movement = new List<Vector2>() { robotAction.PathToPickup.Path[j - 1], robotAction.PathToPickup.Path[j] },
101✔
376
                                        PathRemaining = robotPathRemaining.RobotPath.ToList()
101✔
377
                                    });
101✔
378
                                    robotPathRemaining.RobotPath.Dequeue();
101✔
379
                                }
101✔
380
                            }
51✔
381

382
                            if (robotAction.PickupAction != null)
113✔
383
                            {
62✔
384
                                timeline.Turns[pickupCounter + turn].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.PickingUpPackage, piece.Id)
62✔
385
                                {
62✔
386
                                    PickupAction = robotAction.PickupAction
62✔
387
                                });
62✔
388
                                pickupCounter++;
62✔
389
                                robot.Location = robotAction.RobotPickupEndingLocation;
62✔
390
                            }
62✔
391

392
                            //Now populate the turns with the dropoff path
393
                            int dropoffCounter = 0;
113✔
394
                            if (robotAction.PathToDropoff != null &&
113✔
395
                                robotAction.PathToDropoff.Path != null &&
113✔
396
                                robotAction.PathToDropoff.Path.Count > 0)
113✔
397
                            {
61✔
398
                                Robot robotPathRemaining = GetRobot(robotAction.RobotId);
61✔
399
                                if (robotPathRemaining != null)
61✔
400
                                {
61✔
401
                                    robotPathRemaining.RobotPath = new Queue<Vector2>(robotAction.PathToDropoff.Path);
61✔
402
                                }
61✔
403
                                dropoffCounter++;
61✔
404
                                timeline.Turns[pickupCounter + turn].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.MovingToDeliveryLocation, piece.Id)
61✔
405
                                {
61✔
406
                                    Movement = new List<Vector2>() { robotAction.RobotDropoffStartingLocation, robotAction.PathToDropoff.Path[0] },
61✔
407
                                    PathRemaining = robotPathRemaining.RobotPath.ToList()
61✔
408
                                });
61✔
409
                                robotPathRemaining.RobotPath.Dequeue();
61✔
410
                                for (int j = 1; j <= robotAction.PathToDropoff.Path.Count - 1; j++)
356✔
411
                                {
117✔
412
                                    dropoffCounter++;
117✔
413
                                    timeline.Turns[pickupCounter + turn + j].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.MovingToDeliveryLocation, piece.Id)
117✔
414
                                    {
117✔
415
                                        Movement = new List<Vector2>() { robotAction.PathToDropoff.Path[j - 1], robotAction.PathToDropoff.Path[j] },
117✔
416
                                        PathRemaining = robotPathRemaining.RobotPath.ToList()
117✔
417
                                    });
117✔
418
                                    robotPathRemaining.RobotPath.Dequeue();
117✔
419
                                }
117✔
420
                            }
61✔
421

422
                            if (robotAction.DropoffAction != null)
113✔
423
                            {
62✔
424
                                robotAction.DropoffAction.DestinationPieceCount = GetPieceCount(robotAction.DropoffAction.Location);
62✔
425
                                timeline.Turns[pickupCounter + dropoffCounter + turn].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.DeliveringPackage, piece.Id)
62✔
426
                                {
62✔
427
                                    DropoffAction = robotAction.DropoffAction
62✔
428
                                });
62✔
429
                                dropoffCounter++;
62✔
430
                                robot.Location = robotAction.RobotDropoffEndingLocation;
62✔
431
                            }
62✔
432
                            _RobotProgress[robot.RobotId] += pickupCounter + dropoffCounter;
113✔
433
                        }
113✔
434
                        break;
113✔
435
                    }
436
                }
24✔
437
            }
113✔
438

439
            //Move the robots back to the start location
440
            foreach (Robot robot in Robots)
48✔
441
            {
12✔
442
                if (robot.Location != robot.PickupLocation)
12✔
443
                {
10✔
444
                    RobotAction robotAction = new RobotAction(robot.RobotId);
10✔
445
                    //Move the robot to the pickup zone - By doing this first we ensure we don't pick up a piece until we are there.
446
                    Vector2 currentRobotLocation = robot.Location;
10✔
447
                    Vector2 pickupLocation = robot.PickupLocation;
10✔
448

449
                    // Move to unsorted pile
450
                    robotAction.RobotPickupStartingLocation = currentRobotLocation;
10✔
451
                    if (currentRobotLocation != pickupLocation)
10✔
452
                    {
10✔
453
                        PathFindingResult pathFindingResultForPickup = FindPathFindingWithTimeline(Map, currentRobotLocation, pickupLocation, robot.RobotId, Robots, timeline);
10✔
454
                        if (pathFindingResultForPickup != null && pathFindingResultForPickup.Path.Any())
10!
455
                        {
10✔
456
                            //Move robot
457
                            robotAction.PathToPickup = pathFindingResultForPickup;
10✔
458
                            currentRobotLocation = pathFindingResultForPickup.Path.Last();
10✔
459
                        }
10✔
460
                        else
461
                        {
×
462
                            int g = 0;
×
463
                        }
×
464
                    }
10✔
465
                    robotAction.RobotPickupEndingLocation = currentRobotLocation;
10✔
466
                    robot.Location = currentRobotLocation;
10✔
467

468
                    //process the robot action
469
                    if (robotAction != null)
10✔
470
                    {
10✔
471
                        int turn = _RobotProgress[robot.RobotId];
10✔
472
                        int turnsNeeded = 0;
10✔
473

474
                        //move to pickup
475
                        if (robotAction.PathToPickup != null)
10✔
476
                        {
10✔
477
                            turnsNeeded += robotAction.PathToPickup.Path.Count;
10✔
478
                        }
10✔
479
                        //Initialize the turns needed for this robot to complete it's turn
480
                        for (int j = turn; j < turn + turnsNeeded; j++)
82✔
481
                        {
31✔
482
                            if (timeline.Turns.Any(t => t.TurnNumber == j + 1) == false)
1,584✔
483
                            {
20✔
484
                                timeline.Turns.Add(new Turn(j + 1));
20✔
485
                            }
20✔
486
                        }
31✔
487

488
                        //Now populate the turns with the pickup path
489
                        int pickupCounter = 0;
10✔
490
                        if (robotAction.PathToPickup != null &&
10!
491
                            robotAction.PathToPickup.Path != null &&
10✔
492
                            robotAction.PathToPickup.Path.Count > 0)
10✔
493
                        {
10✔
494
                            Robot robotPathRemaining = GetRobot(robotAction.RobotId);
10✔
495
                            if (robotPathRemaining != null)
10✔
496
                            {
10✔
497
                                robotPathRemaining.RobotPath = new Queue<Vector2>(robotAction.PathToPickup.Path);
10✔
498
                            }
10✔
499
                            pickupCounter++;
10✔
500
                            timeline.Turns[turn].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.MovingToPickupLocation, null)
10✔
501
                            {
10✔
502
                                Movement = new List<Vector2>() { robotAction.RobotPickupStartingLocation, robotAction.PathToPickup.Path[0] },
10✔
503
                                PathRemaining = robotPathRemaining.RobotPath.ToList()
10✔
504
                            });
10✔
505
                            robotPathRemaining.RobotPath.Dequeue();
10✔
506
                            for (int j = 1; j <= robotAction.PathToPickup.Path.Count - 1; j++)
62✔
507
                            {
21✔
508
                                pickupCounter++;
21✔
509
                                timeline.Turns[turn + j].RobotActions.Add(new RobotTurnAction(robot.RobotId, RobotStatus.RobotStatusEnum.MovingToPickupLocation, null)
21✔
510
                                {
21✔
511
                                    Movement = new List<Vector2>() { robotAction.PathToPickup.Path[j - 1], robotAction.PathToPickup.Path[j] },
21✔
512
                                    PathRemaining = robotPathRemaining.RobotPath.ToList()
21✔
513
                                });
21✔
514
                                robotPathRemaining.RobotPath.Dequeue();
21✔
515
                            }
21✔
516
                        }
10✔
517
                        _RobotProgress[robot.RobotId] += pickupCounter;
10✔
518
                    }
10✔
519
                }
10✔
520
            }
12✔
521

522
            return timeline;
8✔
523
        }
8✔
524

525
        private Robot GetRobot(int robotId)
526
        {
122✔
527
            Robot result = null;
122✔
528
            foreach (Robot robot in Robots)
544✔
529
            {
150✔
530
                if (robot.RobotId == robotId)
150✔
531
                {
122✔
532
                    result = robot;
122✔
533
                    break;
122✔
534
                }
535
            }
28✔
536
            return result;
122✔
537
        }
122✔
538

539
        public int GetPieceCount(Vector2 dropOfflocation)
540
        {
126✔
541
            int pieceCount = 0;
126✔
542
            foreach (SortedDropZone sortedDropZone in SortedDropZones)
1,164✔
543
            {
456✔
544
                if (sortedDropZone.Location == dropOfflocation)
456✔
545
                {
126✔
546
                    pieceCount = sortedDropZone.Count;
126✔
547
                    break;
126✔
548
                }
549
            }
330✔
550
            return pieceCount;
126✔
551
        }
126✔
552

553
        private Vector2? GetAdjacentLocation(Vector2 destinationLocation, string[,] map, List<SortedDropZone> sortedDropZones)
554
        {
62✔
555
            Vector2? adjacentLocation = null;
62✔
556
            if (destinationLocation != null)
62✔
557
            {
62✔
558
                if (destinationLocation.X == 0)
62✔
559
                {
47✔
560
                    //it's a right location drop-off
561
                    adjacentLocation = new Vector2((int)destinationLocation.X + 1, (int)destinationLocation.Y);
47✔
562
                }
47✔
563
                else if (destinationLocation.X == map.GetUpperBound(0))
15✔
564
                {
1✔
565
                    //it's a left location drop-off
566
                    adjacentLocation = new Vector2((int)destinationLocation.X - 1, (int)destinationLocation.Y);
1✔
567
                }
1✔
568
                else if (destinationLocation.Y == 0)
14✔
569
                {
7✔
570
                    //it's a top location drop-off
571
                    adjacentLocation = new Vector2((int)destinationLocation.X, (int)destinationLocation.Y + 1);
7✔
572
                }
7✔
573
                else if (destinationLocation.Y == map.GetUpperBound(1))
7✔
574
                {
7✔
575
                    //it's a bottom location drop-off
576
                    adjacentLocation = new Vector2((int)destinationLocation.X, (int)destinationLocation.Y - 1);
7✔
577
                }
7✔
578
            }
62✔
579
            return adjacentLocation;
62✔
580
        }
62✔
581

582
        private RobotAction GetRobotAction(Robot robot, Piece piece, TimeLine timeline)
583
        {
62✔
584
            RobotAction robotAction = new RobotAction(robot.RobotId);
62✔
585

586
            Vector2 currentRobotLocation = robot.Location;
62✔
587
            Vector2 pickupLocation = robot.PickupLocation;
62✔
588

589
            // Move to unsorted pile
590
            robotAction.RobotPickupStartingLocation = currentRobotLocation;
62✔
591
            if (currentRobotLocation != pickupLocation)
62!
592
            {
×
593
                robot.RobotStatus = RobotStatus.RobotStatusEnum.MovingToPickupLocation;
×
594
                PathFindingResult pathFindingResultForPickup = FindPathFindingWithTimeline(Map, currentRobotLocation, pickupLocation, robot.RobotId, Robots, timeline);
×
595
                if (pathFindingResultForPickup != null && pathFindingResultForPickup.Path.Any())
×
596
                {
×
597
                    //Move robot
598
                    robotAction.PathToPickup = pathFindingResultForPickup;
×
599
                    currentRobotLocation = pathFindingResultForPickup.Path.Last();
×
600
                }
×
601
                else
602
                {
×
603
                    int g = 0;
×
604
                }
×
605
            }
×
606
            robotAction.RobotPickupEndingLocation = currentRobotLocation;
62✔
607

608
            // Pickup an unsorted piece from the unsorted pile
609
            if (robot.Piece != null)
62!
610
            {
×
611
                throw new System.Exception("Piece " + robot.Piece.Id + " was not delivered");
×
612
            }
613
            robot.RobotStatus = RobotStatus.RobotStatusEnum.PickingUpPackage;
62✔
614
            robot.Piece = piece;
62✔
615
            robotAction.PieceId = piece.Id;
62✔
616
            robotAction.PickupAction = new ObjectInteraction()
62✔
617
            {
62✔
618
                Location = piece.Location
62✔
619
            };
62✔
620

621
            // Process the unsorted piece to work out where it goes
622
            Vector2? destinationLocation = null;
62✔
623
            foreach (SortedDropZone sortedDropZone in SortedDropZones)
578✔
624
            {
227✔
625
                if (sortedDropZone.Color == robot.Piece.ImageStats.TopColorGroupColor)
227✔
626
                {
62✔
627
                    destinationLocation = sortedDropZone.Location;
62✔
628
                    break;
62✔
629
                }
630
            }
165✔
631
            if (destinationLocation == null)
62!
632
            {
×
633
                throw new System.Exception("Destination not found for piece " + piece.Id);
×
634
            }
635

636
            //Get the best adjacent location to the destination
637
            Vector2? pathDestinationLocation = destinationLocation;
62✔
638
            if (destinationLocation != null)
62✔
639
            {
62✔
640
                Vector2? adjacentLocation = GetAdjacentLocation((Vector2)destinationLocation, Map, SortedDropZones);
62✔
641
                if (adjacentLocation != null)
62✔
642
                {
62✔
643
                    pathDestinationLocation = (Vector2)adjacentLocation;
62✔
644
                }
62✔
645
            }
62✔
646

647
            // Move the sorted piece to the correct pile
648
            robotAction.RobotDropoffStartingLocation = currentRobotLocation;
62✔
649
            if (destinationLocation != null && pathDestinationLocation != null)
62!
650
            {
62✔
651
                robot.RobotStatus = RobotStatus.RobotStatusEnum.MovingToDeliveryLocation;
62✔
652
                //now find the path
653
                PathFindingResult pathFindingResultForDropoff = FindPathFindingWithTimeline(Map, currentRobotLocation, (Vector2)pathDestinationLocation, robot.RobotId, Robots, timeline);
62✔
654
                if (pathFindingResultForDropoff != null && pathFindingResultForDropoff.Path.Count >= 0)
62!
655
                {
62✔
656
                    //Move robot
657
                    robotAction.PathToDropoff = pathFindingResultForDropoff;
62✔
658
                    robotAction.DropoffAction = new ObjectInteraction()
62✔
659
                    {
62✔
660
                        Location = (Vector2)destinationLocation
62✔
661
                    };
62✔
662
                    //Move the piece from the robot to the sorted pile
663
                    robot.RobotStatus = RobotStatus.RobotStatusEnum.DeliveringPackage;
62✔
664
                    robot.Piece.Location = robotAction.DropoffAction.Location;
62✔
665
                    SortedPieces.Add(robot.Piece);
62✔
666
                    foreach (SortedDropZone sortedDropZone in SortedDropZones)
578✔
667
                    {
227✔
668
                        if (sortedDropZone.Location == destinationLocation)
227!
669
                        {
62✔
670
                            sortedDropZone.Count++;
62✔
671
                            break;
62✔
672
                        }
673
                    }
165✔
674
                    robot.Piece = null;
62✔
675
                    robotAction.DropoffPieceCount = GetPieceCount(robotAction.DropoffAction.Location);
62✔
676
                    if (pathFindingResultForDropoff.Path.Count > 0)
62✔
677
                    {
61✔
678
                        currentRobotLocation = pathFindingResultForDropoff.Path.Last();
61✔
679
                    }
61✔
680
                }
62✔
681
            }
62✔
682
            robot.RobotStatus = RobotStatus.RobotStatusEnum.LookingForJob;
62✔
683
            robotAction.RobotDropoffEndingLocation = currentRobotLocation;
62✔
684

685
            return robotAction;
62✔
686
        }
62✔
687
    }
688
}
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