summaryrefslogtreecommitdiff
path: root/ShedCalc/BOMController.swift
blob: be70a656cfc20b20545d96a22eb6227717632bdd (plain) (blame)
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//
//  BOMController.swift
//  ShedCalc
//
//  Created by Jacky Jack on 01/08/2026.
//
import SwiftUI
import Combine

private func roundUpPieces(_ value: Float) -> Int {
    Int(value.rounded(.up))
}

private func roundUpPieces(_ value: Double) -> Int {
    Int(value.rounded(.up))
}

struct MaterialItem: Identifiable {
    let materialName: String
    let pricePerMeter: Double
    let totalMeters: Double
    let totalPrice: Double
    let metersPerPiece: Double
    let totalPieces: Double
    
    let id = UUID()
}
class BOMController {
    
    func calcBOM(from paramModel: ParamModel) -> [MaterialItem] {
        var items: [MaterialItem] = []
        items.append(calcOSB(from: paramModel))
        items.append(calcWallTimber2x4(from: paramModel))
        items.append(calcFloorTimber2x4(from: paramModel))
        items.append(calcRoofTimber2x4(from: paramModel))
        items.append(calcRoofFelt(from: paramModel))
        items.append(calcWeatherWrap(from: paramModel))
        items.append(calcCladding(from: paramModel))
        return items
    }
    
    private func calcOSB(from paramModel: ParamModel) -> MaterialItem {
        let totalOSBarea = paramModel.floorArea()
        let OSBPrice = totalOSBarea*paramModel.OSBSheetPrice
        let OSBPricePerMeter = paramModel.OSBSheetPrice / (1.2*2.4)
        let totalPieces = roundUpPieces(totalOSBarea / (1.2*2.4))
        return MaterialItem(
            materialName: "OSB",
            pricePerMeter: Double(OSBPricePerMeter),
            totalMeters: Double(totalOSBarea),
            totalPrice: Double(totalPieces)*Double(paramModel.OSBSheetPrice),
            metersPerPiece:Double(paramModel.OSBSheetPrice),
            totalPieces: Double(totalPieces))
    }
    
    private func calcWallTimber2x4(from paramModel: ParamModel) -> MaterialItem {
        let totalLength = paramModel.totalWallBeamLength()
        let timberBeamPrice = paramModel.timberBeamPrice
        let totalPrice = totalLength*timberBeamPrice
        let pieceSize = paramModel.timberLengthSize
        let totalPieces = roundUpPieces(totalLength/pieceSize)
        return MaterialItem(
            materialName: "2x4",
            pricePerMeter: Double(timberBeamPrice),
            totalMeters: Double(totalLength),
            totalPrice: Double(totalPrice),
            metersPerPiece:Double(pieceSize),
            totalPieces: Double(totalPieces)
        )
    }
    private func calcFloorTimber2x4(from paramModel: ParamModel) -> MaterialItem {
        let joistLength = paramModel.totalJoistBeamLength() * 2
        let spacersLength = Double(paramModel.lengthBeamNum())*paramModel.beamSpace
        let timberBeamPrice = paramModel.timberBeamPrice
        let totalLength = Double(paramModel.lengthBeamNum())*paramModel.beamSpace
        let totalPrice = totalLength*timberBeamPrice
        let pieceSize = Double(paramModel.timberLengthSize)
        let totalPieces = roundUpPieces(totalLength/pieceSize)
        return MaterialItem(
            materialName: "Floor 2x4",
            pricePerMeter: Double(timberBeamPrice),
            totalMeters: Double(totalLength),
            totalPrice: Double(totalPrice),
            metersPerPiece:Double(pieceSize),
            totalPieces: Double(totalPieces)
        )
    }
    
    private func calcRoofTimber2x4(from paramModel: ParamModel) -> MaterialItem {
        let joistLength = paramModel.totalJoistBeamLength() * 2
        let spacersLength = Double(paramModel.lengthBeamNum())*paramModel.beamSpace
        let timberBeamPrice = paramModel.timberBeamPrice
        let totalLength = Double(paramModel.lengthBeamNum())*paramModel.beamSpace
        let totalPrice = totalLength*timberBeamPrice
        let pieceSize = Double(paramModel.timberLengthSize)
        let totalPieces = roundUpPieces(totalLength/pieceSize)
        return MaterialItem(
            materialName: "Roof 2x4",
            pricePerMeter: Double(timberBeamPrice),
            totalMeters: Double(totalLength),
            totalPrice: Double(totalPrice),
            metersPerPiece:Double(pieceSize),
            totalPieces: Double(totalPieces)
        )
    }
    
    private func calcRoofFelt(from paramModel: ParamModel) -> MaterialItem {
        let roofArea = paramModel.roofArea()
        let feltRollArea = Double(paramModel.feltWidth)*Double(paramModel.feltLength)
        var feltPricePerMeter:Double = 0.0
        if paramModel.feltPrice > 0.0 {
            feltPricePerMeter = Double(paramModel.feltPrice) / feltRollArea
        }
        let totalPieces = roundUpPieces(Double(roofArea)/Double(feltRollArea))
        
        let totalPrice = Double(totalPieces) * paramModel.feltPrice
        
        return MaterialItem(
            materialName: "Roof Felt",
            pricePerMeter: Double(feltPricePerMeter),
            totalMeters: Double(roofArea),
            totalPrice: Double(totalPrice),
            metersPerPiece:Double(feltRollArea),
            totalPieces: Double(totalPieces)
        )
    }
    
    private func calcWeatherWrap(from paramModel: ParamModel) -> MaterialItem {
        
        return MaterialItem(
            materialName: "Weather Wrap",
            pricePerMeter: Double(0.1),
            totalMeters: Double(0.1),
            totalPrice: Double(0.1),
            metersPerPiece:Double(0.1),
            totalPieces: Double(0.1)
        )
    }
    
    private func calcCladding(from paramModel: ParamModel) -> MaterialItem {
        let wallArea = Double(paramModel.length*paramModel.height)*2 + Double(paramModel.width*paramModel.height)*2
        let singleCladArea = paramModel.claddingLength * (Double(paramModel.claddingWidth) - paramModel.claddingOverlap)
        let claddingPieces = wallArea/singleCladArea
        let totalPieces = roundUpPieces(claddingPieces)
        let totalPrice = Double(totalPieces) * paramModel.claddingPrice
        return MaterialItem(
            materialName: "Cladding",
            pricePerMeter: Double(paramModel.claddingPrice),
            totalMeters: Double(claddingPieces*paramModel.claddingLength),
            totalPrice: Double(totalPrice),
            metersPerPiece:Double(paramModel.claddingLength),
            totalPieces: Double(totalPieces)
        )
    }
    
    private func calcBeam(from paramModel: ParamModel) -> MaterialItem {
        return MaterialItem(materialName: "2x4", pricePerMeter: 1.0, totalMeters: 10, totalPrice: 100, metersPerPiece: 1.2, totalPieces: 11.2)
    }
    
}