"DepotSafety.bist" package: com.ecodepot.storage; "DepotSafety class responsibilities:

@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"