"DepotSafety.bist"
package: com.ecodepot.storage;
"DepotSafety class responsibilities:
- allocates storage drums to available storage space,
- applies depot safety policies during storage allocation.
@author Copyright 2004 Nikolas S. Boyd. All rights reserved."
Object subclass: DepotSafety
metaclass: [
"allocating storage space"
"Allocates drums to depot storage buildings that contain hazardous chemicals of a certain kind.
Returns the resulting allocations."
allocate: drumCount containing: hazard [
prospects := StorageAllocation prospectsContaining: hazard.
allocations := self distribute: drumCount over: prospects. "initial naive allocations"
allocations isEmpty ifTrue: [ ^allocations ]. "done if no allocations were possible"
vulnerabilities := self vulnerable: allocations with: prospects.
vulnerabilities isEmpty ifTrue: [ ^allocations ]. "done if no (new) vulnerabilities exist"
^self reduce: vulnerabilities using: prospects producing: allocations
]
"Distributes drums over some allocations based on their storage capacity.
Returns the allocations to which drums were assigned."
distribute: drumCount over: allocations [
result := OrderedCollection new.
totalCapacity := StorageAllocation capacityOfBuildings: allocations.
allocations inject: (drumCount min: totalCapacity)
into: [ :remainingDrums :allocation |
remainingDrums = 0 ifTrue: [ ^result ].
result add: allocation.
allocation remainderAfterConsumingSome: remainingDrums ].
^result "should never reach here, but ..."
]
"reducing vulnerability"
"Returns those allocations that make the depot vulnerable with other prospects."
vulnerable: allocations with: prospects [
^allocations select: [ :allocation |
allocation makesDepotVulnerableWith: prospects ]
]
"Reduces the drums assigned to some vulnerable allocations by transfering a single drum
from each to another prospective allocation which has some remaining storage capacity.
Adds each resulting prospect to the final allocations and returns the resulting allocations."
reduce: vulnerabilities using: prospects producing: allocations [
availableProspects := self safeStorageProspects: prospects.
[ availableProspects isEmpty or: [ vulnerabilities isEmpty ]] whileFalse: [
allocations add: (self reduce: vulnerabilities using: availableProspects removeFirst).
].
^allocations
]
"Reduces the drums assigned to some full allocations by transfering a single drum
from each to another prospective allocation which has some remaining storage capacity.
Returns the resulting prospective allocation."
reduce: vulnerabilities using: availableProspect [
((availableProspect remainingStorageCapacity - 1) min: vulnerabilities size)
timesRepeat: [ vulnerabilities removeFirst transferDrums: 1 to: availableProspect ].
^availableProspect
]
"ensuring safety"
"Returns the prospects that have safe storage capacity."
safeStorageProspects: allocations [
^allocations select: [ :allocation | allocation fillsBuilding not ]
]
"Returns the building vulnerability perimeter distance."
vulnerabilityPerimeter [
^Meter distance: 5.0
]
]
class: [
] "DepotSafety"