168 lines
3.9 KiB
Swift
168 lines
3.9 KiB
Swift
import Foundation
|
|
|
|
extension String {
|
|
func paddedLeft(totalLen: Int) -> String {
|
|
let needed = totalLen - count
|
|
|
|
guard needed > 0 else {
|
|
return self
|
|
}
|
|
|
|
return String(repeating: " ", count: needed) + self
|
|
}
|
|
}
|
|
|
|
class FCNode {
|
|
let name: String
|
|
let weight: Int
|
|
|
|
var coverage: Double {
|
|
didSet {
|
|
if oldValue != coverage {
|
|
parent?.updateCoverage()
|
|
}
|
|
}
|
|
}
|
|
|
|
weak var parent: FCNode?
|
|
var children = [FCNode]()
|
|
|
|
init(name: String, weight: Int = 1, coverage: Double = 0) {
|
|
self.name = name
|
|
self.weight = weight
|
|
self.coverage = coverage
|
|
}
|
|
|
|
func addChildren(_ children: [FCNode]) {
|
|
for child in children {
|
|
child.parent = self
|
|
}
|
|
|
|
self.children += children
|
|
|
|
updateCoverage()
|
|
}
|
|
|
|
func show(level: Int = 0) {
|
|
let indent = level * 4
|
|
let nameLen = name.count + indent
|
|
|
|
print(name.paddedLeft(totalLen: nameLen), terminator: "")
|
|
print("|".paddedLeft(totalLen: 32 - nameLen), terminator: "")
|
|
print(String(format: " %3d |", weight), terminator: "")
|
|
print(String(format: " %8.6f |", coverage))
|
|
|
|
for child in children {
|
|
child.show(level: level + 1)
|
|
}
|
|
}
|
|
|
|
func updateCoverage() {
|
|
let v1 = children.reduce(0.0, { $0 + $1.coverage * Double($1.weight) })
|
|
let v2 = children.reduce(0.0, { $0 + Double($1.weight) })
|
|
|
|
coverage = v1 / v2
|
|
}
|
|
}
|
|
|
|
let houses = [
|
|
FCNode(name: "house1", weight: 40),
|
|
FCNode(name: "house2", weight: 60)
|
|
]
|
|
|
|
let house1 = [
|
|
FCNode(name: "bedrooms", weight: 1, coverage: 0.25),
|
|
FCNode(name: "bathrooms"),
|
|
FCNode(name: "attic", weight: 1, coverage: 0.75),
|
|
FCNode(name: "kitchen", weight: 1, coverage: 0.1),
|
|
FCNode(name: "living_rooms"),
|
|
FCNode(name: "basement"),
|
|
FCNode(name: "garage"),
|
|
FCNode(name: "garden", weight: 1, coverage: 0.8)
|
|
]
|
|
|
|
let house2 = [
|
|
FCNode(name: "upstairs"),
|
|
FCNode(name: "groundfloor"),
|
|
FCNode(name: "basement")
|
|
]
|
|
|
|
let h1Bathrooms = [
|
|
FCNode(name: "bathroom1", weight: 1, coverage: 0.5),
|
|
FCNode(name: "bathroom2"),
|
|
FCNode(name: "outside_lavatory", weight: 1, coverage: 1.0)
|
|
]
|
|
|
|
let h1LivingRooms = [
|
|
FCNode(name: "lounge"),
|
|
FCNode(name: "dining_room"),
|
|
FCNode(name: "conservatory"),
|
|
FCNode(name: "playroom", weight: 1, coverage: 1.0)
|
|
]
|
|
|
|
let h2Upstairs = [
|
|
FCNode(name: "bedrooms"),
|
|
FCNode(name: "bathroom"),
|
|
FCNode(name: "toilet"),
|
|
FCNode(name: "attics", weight: 1, coverage: 0.6)
|
|
]
|
|
|
|
let h2Groundfloor = [
|
|
FCNode(name: "kitchen"),
|
|
FCNode(name: "living_rooms"),
|
|
FCNode(name: "wet_room_&_toilet"),
|
|
FCNode(name: "garage"),
|
|
FCNode(name: "garden", weight: 1, coverage: 0.9),
|
|
FCNode(name: "hot_tub_suite", weight: 1, coverage: 1.0)
|
|
]
|
|
|
|
let h2Basement = [
|
|
FCNode(name: "cellars", weight: 1, coverage: 1.0),
|
|
FCNode(name: "wine_cellar", weight: 1, coverage: 1.0),
|
|
FCNode(name: "cinema", weight: 1, coverage: 0.75)
|
|
]
|
|
|
|
let h2UpstairsBedrooms = [
|
|
FCNode(name: "suite_1"),
|
|
FCNode(name: "suite_2"),
|
|
FCNode(name: "bedroom_3"),
|
|
FCNode(name: "bedroom_4")
|
|
]
|
|
|
|
let h2GroundfloorLivingRooms = [
|
|
FCNode(name: "lounge"),
|
|
FCNode(name: "dining_room"),
|
|
FCNode(name: "conservatory"),
|
|
FCNode(name: "playroom")
|
|
]
|
|
|
|
let cleaning = FCNode(name: "cleaning")
|
|
|
|
house1[1].addChildren(h1Bathrooms)
|
|
house1[4].addChildren(h1LivingRooms)
|
|
houses[0].addChildren(house1)
|
|
|
|
h2Upstairs[0].addChildren(h2UpstairsBedrooms)
|
|
house2[0].addChildren(h2Upstairs)
|
|
h2Groundfloor[1].addChildren(h2GroundfloorLivingRooms)
|
|
house2[1].addChildren(h2Groundfloor)
|
|
house2[2].addChildren(h2Basement)
|
|
houses[1].addChildren(house2)
|
|
|
|
cleaning.addChildren(houses)
|
|
|
|
let top = cleaning.coverage
|
|
|
|
print("Top Coverage: \(String(format: "%8.6f", top))")
|
|
print("Name Hierarchy | Weight | Coverage |")
|
|
|
|
cleaning.show()
|
|
|
|
h2Basement[2].coverage = 1.0
|
|
|
|
let diff = cleaning.coverage - top
|
|
|
|
print("\nIf the coverage of the Cinema node were increased from 0.75 to 1.0")
|
|
print("the top level coverage would increase by ")
|
|
print("\(String(format: "%8.6f", diff)) to \(String(format: "%8.6f", top))")
|