This repository has been archived by the owner on Apr 2, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bb70b43
commit 698f394
Showing
19 changed files
with
1,447 additions
and
975 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,24 @@ | ||
# METAR | ||
# METAR Parser for Swift | ||
|
||
This is a simple regular expression based METAR parser. | ||
SwiftMETAR provides a simple way to parse METARs into Swift types. | ||
|
||
## Usage Example | ||
|
||
``` swift | ||
let metar = METAR(rawMETAR: "EGLL 290420Z AUTO 05005KT 020V090 7000 R04/1300VP2000U OVC005 09/08 Q1024 TEMPO BKN004") | ||
import METAR | ||
|
||
let metar = METAR("EGLL 290420Z AUTO 05005KT 020V090 7000 R04/1300VP2000U OVC005 09/08 Q1024 TEMPO BKN004") | ||
print(metar?.visibility?.measurement) // Prints: Optional(7000.0 m) | ||
print(metar?.temperature?.measurement) // Prints: Optional(9.0 °C) | ||
print(metar?.qnh?.measurement) // Prints: Optional(1024.0 hPa) | ||
print(metar?.wind?.speed.measurement) // Prints: Optional(5.0 kn) | ||
print(metar?.runwayVisualRanges) // Prints: Optional([Runway 04: 1300.0 m – >2000.0 m Increasing]) | ||
``` | ||
|
||
## Contribution | ||
|
||
If you'd like to contribute, please feel free to create a PR. | ||
|
||
## License | ||
|
||
SwiftMETAR is available under the MIT license. See the LICENSE file for more info. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// | ||
// CloudLayer.swift | ||
// | ||
// | ||
// Created by Jonathan Downing on 12/4/20. | ||
// | ||
|
||
import Foundation | ||
|
||
public struct CloudLayer: Hashable { | ||
|
||
public enum Coverage { | ||
case few | ||
case scattered | ||
case broken | ||
case overcast | ||
case skyObscured | ||
case notReported | ||
} | ||
|
||
public enum SignificantCloudType { | ||
case cumulonimbus | ||
case toweringCumulus | ||
} | ||
|
||
public var coverage: Coverage | ||
public var height: Measurement<UnitLength>? | ||
public var significantCloudType: SignificantCloudType? | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// | ||
// DirectionalVisibility.swift | ||
// | ||
// | ||
// Created by Jonathan Downing on 12/5/20. | ||
// | ||
|
||
public struct DirectionalVisibility: Hashable { | ||
|
||
public enum Direction { | ||
case north | ||
case northEast | ||
case east | ||
case southEast | ||
case south | ||
case southWest | ||
case west | ||
case northWest | ||
} | ||
|
||
public var visibility: Visibility | ||
public var direction: Direction | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// | ||
// NOAAFlightRules.swift | ||
// | ||
// | ||
// Created by Jonathan Downing on 12/4/20. | ||
// | ||
|
||
public enum ICAOFlightRules { | ||
|
||
/// Visual Meteorlogical Conditions | ||
/// | ||
/// Applicable when either are true: | ||
/// - Ceiling is greater than or equal to 1,500 feet. | ||
/// - Visibility is greater than or equal to 5,000 meters. | ||
case vmc | ||
|
||
/// Instrument Meteorlogical Conditions | ||
/// | ||
/// Applicable when either are true: | ||
/// - Ceiling is less than 1,500 feet. | ||
/// - Visibility is less than 5,000 meters. | ||
case imc | ||
|
||
} | ||
|
||
public enum NOAAFlightRules { | ||
|
||
/// Visual Flight Rules | ||
/// | ||
/// Applicable when both are true: | ||
/// - Ceiling is greater than 3,000 feet | ||
/// - Visibility is greater than 5 miles | ||
case vfr | ||
|
||
/// Marginal Visual Flight Rules | ||
/// | ||
/// Applicable when either are true: | ||
/// - Ceiling is greater than or equal to 1,000 feet and less than or equal to 3,000 feet | ||
/// - Visibility is greater than or equal to 3 miles and less than or equal to 5 miles. | ||
case mvfr | ||
|
||
/// Instrument Flight Rules | ||
/// | ||
/// Applicable when either are true: | ||
/// - Ceiling is greater than or equal to 500 feet and less than 1,000 feet | ||
/// - Visibility is greater than or equal to 1 mile and less than 3 miles. | ||
case ifr | ||
|
||
/// Low Instrument Flight Rules | ||
/// | ||
/// Applicable when either are true: | ||
/// - Ceiling is less than 500 feet | ||
/// - Visibility is less than 1 mile | ||
case lifr | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// | ||
// METAR+Ceiling.swift | ||
// | ||
// | ||
// Created by Jonathan Downing on 07/01/2017. | ||
// | ||
|
||
import Foundation | ||
|
||
extension METAR { | ||
|
||
var ceiling: Measurement<UnitLength> { | ||
var ceiling: Double = .greatestFiniteMagnitude | ||
for layer in cloudLayers { | ||
guard layer.coverage == .overcast || layer.coverage == .skyObscured || layer.coverage == .broken else { | ||
continue | ||
} | ||
guard let height = layer.height?.converted(to: .feet).value else { | ||
continue | ||
} | ||
if ceiling > height { | ||
ceiling = height | ||
} | ||
} | ||
return .init(value: ceiling, unit: .feet) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// | ||
// METAR+Date.swift | ||
// | ||
// | ||
// Created by Jonathan Downing on 12/6/20. | ||
// | ||
|
||
import Foundation | ||
|
||
extension METAR { | ||
|
||
/// The date the report was issued. | ||
/// | ||
/// Since METARs only encode day, hour, and minute information—the date from this property is the | ||
/// most recent date in the past matching those date components. If the METAR is recent, this should | ||
/// not be a problem. | ||
public var date: Date { | ||
date(relativeTo: Date()) | ||
} | ||
|
||
func date(relativeTo referenceDate: Date) -> Date { | ||
let calendar = Calendar(identifier: .gregorian) | ||
|
||
var dateComponents = self.dateComponents | ||
dateComponents.year = calendar.component(.year, from: referenceDate) | ||
dateComponents.month = calendar.component(.month, from: referenceDate) | ||
|
||
guard var date = calendar.date(from: dateComponents) else { return .distantPast } | ||
|
||
if date > referenceDate { | ||
dateComponents.month! -= 1 | ||
date = calendar.date(from: dateComponents) ?? .distantPast | ||
} | ||
|
||
return date | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// | ||
// File.swift | ||
// | ||
// | ||
// Created by Jonathan Downing on 12/6/20. | ||
// | ||
|
||
import Foundation | ||
|
||
extension METAR { | ||
|
||
public var icaoFlightRules: ICAOFlightRules? { | ||
if ceiling.converted(to: .feet).value < 1500 { | ||
return .imc | ||
} | ||
if let visibility = visibility?.measurement.converted(to: .meters).value { | ||
return visibility < 5000 ? .imc : .vmc | ||
} | ||
return .vmc | ||
} | ||
|
||
public var noaaFlightRules: NOAAFlightRules? { | ||
if ceiling.converted(to: .feet).value < 500 { | ||
return .lifr | ||
} | ||
if let visibility = visibility?.measurement.converted(to: .miles).value, visibility < 1 { | ||
return .lifr | ||
} | ||
if ceiling.converted(to: .feet).value < 1000 { | ||
return .ifr | ||
} | ||
if let visibility = visibility?.measurement.converted(to: .miles).value, visibility < 3 { | ||
return .ifr | ||
} | ||
if ceiling.converted(to: .feet).value <= 3000 { | ||
return .mvfr | ||
} | ||
if let visibility = visibility?.measurement.converted(to: .miles).value, visibility <= 5 { | ||
return .mvfr | ||
} | ||
if let visibility = visibility?.measurement.converted(to: .miles).value, visibility > 5, ceiling.converted(to: .feet).value > 3000 { | ||
return .vfr | ||
} | ||
if isCeilingAndVisibilityOK { | ||
return .vfr | ||
} | ||
return nil | ||
} | ||
|
||
} |
Oops, something went wrong.