-
Notifications
You must be signed in to change notification settings - Fork 162
Expand file tree
/
Copy pathPackingService.cs
More file actions
96 lines (81 loc) · 3.47 KB
/
Copy pathPackingService.cs
File metadata and controls
96 lines (81 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using CromulentBisgetti.ContainerPacking.Algorithms;
using CromulentBisgetti.ContainerPacking.Entities;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace CromulentBisgetti.ContainerPacking
{
/// <summary>
/// The container packing service.
/// </summary>
public static class PackingService
{
/// <summary>
/// Attempts to pack the specified containers with the specified items using the specified algorithms.
/// </summary>
/// <param name="containers">The list of containers to pack.</param>
/// <param name="itemsToPack">The items to pack.</param>
/// <param name="algorithmTypeIDs">The list of algorithm type IDs to use for packing.</param>
/// <returns>A container packing result with lists of the packed and unpacked items.</returns>
public static List<ContainerPackingResult> Pack(List<Container> containers, List<Item> itemsToPack, List<int> algorithmTypeIDs)
{
Object sync = new Object { };
List<ContainerPackingResult> result = new List<ContainerPackingResult>();
Parallel.ForEach(containers, container =>
{
ContainerPackingResult containerPackingResult = new ContainerPackingResult();
containerPackingResult.ContainerID = container.ID;
Parallel.ForEach(algorithmTypeIDs, algorithmTypeID =>
{
IPackingAlgorithm algorithm = GetPackingAlgorithmFromTypeID(algorithmTypeID);
// Until I rewrite the algorithm with no side effects, we need to clone the item list
// so the parallel updates don't interfere with each other.
List<Item> items = new List<Item>();
itemsToPack.ForEach(item =>
{
items.Add(new Item(item.ID, item.Dim1, item.Dim2, item.Dim3, item.Quantity));
});
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
AlgorithmPackingResult algorithmResult = algorithm.Run(container, items);
stopwatch.Stop();
algorithmResult.PackTimeInMilliseconds = stopwatch.ElapsedMilliseconds;
decimal containerVolume = container.Length * container.Width * container.Height;
decimal itemVolumePacked = algorithmResult.PackedItems.Sum(i => i.Volume);
decimal itemVolumeUnpacked = algorithmResult.UnpackedItems.Sum(i => i.Volume);
algorithmResult.PercentContainerVolumePacked = Math.Round(itemVolumePacked / containerVolume * 100, 2);
var totalPackedVolume = itemVolumePacked + itemVolumeUnpacked;
algorithmResult.PercentItemVolumePacked = totalPackedVolume == 0 ? 0 : Math.Round(itemVolumePacked / totalPackedVolume * 100, 2);
lock (sync)
{
containerPackingResult.AlgorithmPackingResults.Add(algorithmResult);
}
});
containerPackingResult.AlgorithmPackingResults = containerPackingResult.AlgorithmPackingResults.OrderBy(r => r.AlgorithmName).ToList();
lock (sync)
{
result.Add(containerPackingResult);
}
});
return result;
}
/// <summary>
/// Gets the packing algorithm from the specified algorithm type ID.
/// </summary>
/// <param name="algorithmTypeID">The algorithm type ID.</param>
/// <returns>An instance of a packing algorithm implementing AlgorithmBase.</returns>
/// <exception cref="System.Exception">Invalid algorithm type.</exception>
public static IPackingAlgorithm GetPackingAlgorithmFromTypeID(int algorithmTypeID)
{
switch (algorithmTypeID)
{
case (int)AlgorithmType.EB_AFIT:
return new EB_AFIT();
default:
throw new Exception("Invalid algorithm type.");
}
}
}
}