@@ -26,13 +26,6 @@ import Foundation
2626/// └── ... (similar structure)
2727/// ```
2828///
29- /// ## Shared Data
30- ///
31- /// Some data tables are shared between G1 and G2+ models:
32- /// - Vref speeds
33- /// - Ice-contaminated landing data
34- /// - Contamination adjustments
35- /// - Enroute climb data
3629struct DataTableLoader {
3730
3831 private let bundle : Bundle
@@ -43,8 +36,14 @@ struct DataTableLoader {
4336 return bundle. resourceURL!. appending ( component: directory, directoryHint: . isDirectory)
4437 }
4538
46- private var g1DataURL : URL {
47- bundle. resourceURL!. appending ( component: " Data/g1 " , directoryHint: . isDirectory)
39+ /// Fallback URL for G2+ aircraft to use G2 data when G2+ data is not available.
40+ private var fallbackDataURL : URL ? {
41+ switch aircraftType {
42+ case . g2Plus, . g2( true ) :
43+ return bundle. resourceURL!. appending ( component: " Data/g2 " , directoryHint: . isDirectory)
44+ default :
45+ return nil
46+ }
4847 }
4948
5049 init ( bundle: Bundle = Bundle ( for: BasePerformanceModel . self) , aircraftType: AircraftType ) {
@@ -63,21 +62,19 @@ struct DataTableLoader {
6362 }
6463
6564 func loadLandingRunData( landingPrefix: String ) throws -> DataTable {
66- let fromG1 = landingPrefix == " 50 ice "
67- return try loadDataTable ( path: " landing/ \( landingPrefix) /ground run.csv " , fromG1: fromG1)
65+ try loadDataTable ( path: " landing/ \( landingPrefix) /ground run.csv " )
6866 }
6967
7068 func loadLandingDistanceData( landingPrefix: String ) throws -> DataTable {
71- let fromG1 = landingPrefix == " 50 ice "
72- return try loadDataTable ( path: " landing/ \( landingPrefix) /total distance.csv " , fromG1: fromG1)
69+ try loadDataTable ( path: " landing/ \( landingPrefix) /total distance.csv " )
7370 }
7471
7572 func loadVrefData( ) throws -> DataTable {
76- try loadDataTable ( path: " vref/50.csv " , fromG1 : true )
73+ try loadDataTable ( path: " vref/50.csv " )
7774 }
7875
7976 func loadVrefData( vrefPrefix: String ) throws -> DataTable {
80- try loadDataTable ( path: " vref/ \( vrefPrefix) .csv " , fromG1 : true )
77+ try loadDataTable ( path: " vref/ \( vrefPrefix) .csv " )
8178 }
8279
8380 func loadTakeoffClimbGradientData( ) throws -> DataTable {
@@ -96,17 +93,17 @@ struct DataTableLoader {
9693
9794 func loadEnrouteClimbGradientData( iceContaminated: Bool ) throws -> DataTable {
9895 let subdir = iceContaminated ? " ice contaminated " : " normal "
99- return try loadDataTable ( path: " enroute climb/ \( subdir) /gradient.csv " , fromG1 : true )
96+ return try loadDataTable ( path: " enroute climb/ \( subdir) /gradient.csv " )
10097 }
10198
10299 func loadEnrouteClimbRateData( iceContaminated: Bool ) throws -> DataTable {
103100 let subdir = iceContaminated ? " ice contaminated " : " normal "
104- return try loadDataTable ( path: " enroute climb/ \( subdir) /rate.csv " , fromG1 : true )
101+ return try loadDataTable ( path: " enroute climb/ \( subdir) /rate.csv " )
105102 }
106103
107104 func loadEnrouteClimbSpeedData( iceContaminated: Bool ) throws -> DataTable {
108105 let subdir = iceContaminated ? " ice contaminated " : " normal "
109- return try loadDataTable ( path: " enroute climb/ \( subdir) /speed.csv " , fromG1 : true )
106+ return try loadDataTable ( path: " enroute climb/ \( subdir) /speed.csv " )
110107 }
111108
112109 // MARK: - Adjustment Factor Data Tables
@@ -140,77 +137,49 @@ struct DataTableLoader {
140137 }
141138
142139 func loadLandingRunHeadwindData( landingPrefix: String ) throws -> DataTable {
143- let fromG1 = landingPrefix == " 50 ice "
144- return try loadDataTable (
145- path: " landing/ \( landingPrefix) /ground run - headwind factor.csv " ,
146- fromG1: fromG1
147- )
140+ try loadDataTable ( path: " landing/ \( landingPrefix) /ground run - headwind factor.csv " )
148141 }
149142
150143 func loadLandingRunTailwindData( landingPrefix: String ) throws -> DataTable {
151- let fromG1 = landingPrefix == " 50 ice "
152- return try loadDataTable (
153- path: " landing/ \( landingPrefix) /ground run - tailwind factor.csv " ,
154- fromG1: fromG1
155- )
144+ try loadDataTable ( path: " landing/ \( landingPrefix) /ground run - tailwind factor.csv " )
156145 }
157146
158147 func loadLandingRunDownhillData( landingPrefix: String ) throws -> DataTable {
159- let fromG1 = landingPrefix == " 50 ice "
160- return try loadDataTable (
161- path: " landing/ \( landingPrefix) /ground run - downhill factor.csv " ,
162- fromG1: fromG1
163- )
148+ try loadDataTable ( path: " landing/ \( landingPrefix) /ground run - downhill factor.csv " )
164149 }
165150
166151 func loadLandingRunUphillData( landingPrefix: String ) throws -> DataTable {
167- let fromG1 = landingPrefix == " 50 ice "
168- return try loadDataTable (
169- path: " landing/ \( landingPrefix) /ground run - uphill factor.csv " ,
170- fromG1: fromG1
171- )
152+ try loadDataTable ( path: " landing/ \( landingPrefix) /ground run - uphill factor.csv " )
172153 }
173154
174155 func loadLandingDistanceHeadwindData( landingPrefix: String ) throws -> DataTable {
175- let fromG1 = landingPrefix == " 50 ice "
176- return try loadDataTable (
177- path: " landing/ \( landingPrefix) /total distance - headwind factor.csv " ,
178- fromG1: fromG1
179- )
156+ try loadDataTable ( path: " landing/ \( landingPrefix) /total distance - headwind factor.csv " )
180157 }
181158
182159 func loadLandingDistanceTailwindData( landingPrefix: String ) throws -> DataTable {
183- let fromG1 = landingPrefix == " 50 ice "
184- return try loadDataTable (
185- path: " landing/ \( landingPrefix) /total distance - tailwind factor.csv " ,
186- fromG1: fromG1
187- )
160+ try loadDataTable ( path: " landing/ \( landingPrefix) /total distance - tailwind factor.csv " )
188161 }
189162
190163 func loadLandingDistanceUnpavedData( landingPrefix: String ) throws -> DataTable {
191- let fromG1 = landingPrefix == " 50 ice "
192- return try loadDataTable (
193- path: " landing/ \( landingPrefix) /total distance - unpaved factor.csv " ,
194- fromG1: fromG1
195- )
164+ try loadDataTable ( path: " landing/ \( landingPrefix) /total distance - unpaved factor.csv " )
196165 }
197166
198167 // MARK: - Contamination Data Tables
199168
200169 func loadCompactSnowLandingData( ) throws -> DataTable {
201- try loadDataTable ( path: " landing/contamination/compact snow.csv " , fromG1 : true )
170+ try loadDataTable ( path: " landing/contamination/compact snow.csv " )
202171 }
203172
204173 func loadDrySnowLandingData( ) throws -> DataTable {
205- try loadDataTable ( path: " landing/contamination/dry snow.csv " , fromG1 : true )
174+ try loadDataTable ( path: " landing/contamination/dry snow.csv " )
206175 }
207176
208177 func loadSlushLandingData( ) throws -> DataTable {
209- try loadDataTable ( path: " landing/contamination/slush, wet snow.csv " , fromG1 : true )
178+ try loadDataTable ( path: " landing/contamination/slush, wet snow.csv " )
210179 }
211180
212181 func loadWaterLandingData( ) throws -> DataTable {
213- try loadDataTable ( path: " landing/contamination/water.csv " , fromG1 : true )
182+ try loadDataTable ( path: " landing/contamination/water.csv " )
214183 }
215184
216185 // Alias methods for contamination data (used by TabularPerformanceModelG2+)
@@ -232,8 +201,21 @@ struct DataTableLoader {
232201
233202 // MARK: - Helper Functions
234203
235- private func loadDataTable( path: String , fromG1: Bool = false ) throws -> DataTable {
236- let url = fromG1 ? g1DataURL. appending ( path: path) : dataURL. appending ( path: path)
204+ private func loadDataTable( path: String ) throws -> DataTable {
205+ let url = dataURL. appending ( path: path)
206+
207+ // Try primary location first
208+ if FileManager . default. fileExists ( atPath: url. path) {
209+ return try DataTable ( fileURL: url)
210+ }
211+
212+ // Fall back to G2 data for G2+ aircraft if primary doesn't exist
213+ if let fallbackURL = fallbackDataURL {
214+ let fallback = fallbackURL. appending ( path: path)
215+ return try DataTable ( fileURL: fallback)
216+ }
217+
218+ // No fallback available, throw original error
237219 return try DataTable ( fileURL: url)
238220 }
239221}
0 commit comments